public class Tube { final int X = 0; final int Y = 1; final int Z = 2; final int NX = 3; final int NY = 4; final int NZ = 5; final int U = 6; final int V = 7; int N; Material material; int[][] faces; double[][] vertices; ImageBuffer imgBuf; double[][][] texBuf; public Tube (int n) { N = 2 * n; // there are n vertices on each end of tube faces = new int[N/2][4]; for (int i = 0; i < N/2; i++) { faces[i][0] = i; faces[i][1] = (i + 1) % (N/2); faces[i][2] = i + N/2; faces[i][3] = ((i + 1) % (N/2)) + N/2; } reset(); } public void reset() { vertices = new double[N][8]; imgBuf = null; for (int i = 0; i < N/2; i++) { vertices[i][X] = Math.cos( 2*i * 2 * Math.PI / (N - 1) ); vertices[i][Y] = Math.sin( 2*i * 2 * Math.PI / (N - 1) ); vertices[i][Z] = 1; vertices[i + N/2][X] = vertices[i][X]; vertices[i + N/2][Y] = vertices[i][Y]; vertices[i + N/2][Z] = -1; vertices[i][NX] = vertices[i][X]; vertices[i][NY] = vertices[i][Y]; vertices[i][NZ] = 0; vertices[i + N/2][NX] = vertices[i][NX]; vertices[i + N/2][NY] = vertices[i][NY]; vertices[i + N/2][NZ] = vertices[i][NZ]; vertices[i][U] = i / (N/2.0); vertices[i][V] = 0; vertices[i + N/2][U] = i / (N/2.0); vertices[i + N/2][V] = 1; } } public void setMaterial(Material m) { material = m.copy(); } public void setTextureBuffer(double[][][] tb) { texBuf = tb; } public void setImageBuffer(ImageBuffer buf) { imgBuf = buf; } public void bufferTo(double[][] zBuffer, double[][][] frameBuffer, Light[] lights, double focalLength) { for (int i = 0; i < faces.length; i++) { Triangle triangle1 = makeTriangle( vertices[faces[i][0]], vertices[faces[i][1]], vertices[faces[i][2]]); triangle1.perspectiveTransform(focalLength); triangle1.viewportTransform(zBuffer.length, zBuffer[0].length); triangle1.calculateColors(lights); triangle1.bufferTo(zBuffer, frameBuffer); Triangle triangle2 = makeTriangle( vertices[faces[i][2]], vertices[faces[i][3]], vertices[faces[i][1]]); triangle2.perspectiveTransform(focalLength); triangle2.viewportTransform(zBuffer.length, zBuffer[0].length); triangle2.calculateColors(lights); triangle2.bufferTo(zBuffer, frameBuffer); } } private Triangle makeTriangle(double[] v0, double[] v1, double[] v2) { Triangle triangle = new Triangle(); double[][] vertices = { {v0[X], v0[Y], v0[Z]}, {v1[X], v1[Y], v1[Z]}, {v2[X], v2[Y], v2[Z]} }; double[][] normals = { {v0[NX], v0[NY], v0[NZ]}, {v1[NX], v1[NY], v1[NZ]}, {v2[NX], v2[NY], v2[NZ]} }; double[][] uv = { {v0[U], v0[V]}, {v1[U], v1[V]}, {v2[U], v2[V]} }; //if (normals[0][Z] < 0) { //for (int i = 0; i < normals.length; i++) //for (int j = 0; j < normals[i].length; j++) //normals[i][j] = -1 * normals[i][j]; //} triangle.setVertices(vertices); triangle.setNormals(normals); triangle.setUV(uv); triangle.setImageBuffer(imgBuf); triangle.setTextureBuffer(texBuf); triangle.setAmbientColor(material.getAmbientColor()); triangle.setDiffuseColor(material.getDiffuseColor()); triangle.setSpecularColor(material.getSpecularColor()); triangle.setSpecularPower(material.specularPower); return triangle; } public void printVertices() { System.out.println("Vertices"); for (int i = 0; i < vertices.length; i++) { System.out.println(i + ": {" + vertices[i][X] + ", " + vertices[i][Y] + ", " + vertices[i][Z] + "}"); } } public double[][] getTransformedVertices(Matrix3D t) { double[][] newVertices = new double[vertices.length][3]; for (int i = 0; i < newVertices.length; i++) { double[] point = { vertices[i][X], vertices[i][Y], vertices[i][Z] }; double[] transPoint = t.transform(point); newVertices[i][X] = transPoint[0]; newVertices[i][Y] = transPoint[1]; newVertices[i][Z] = transPoint[2]; } return newVertices; } public double[][] getNormals(double[][] v) { double[][] gradients = new double[faces.length][3]; for (int i = 0; i < faces.length; i++) { double[] v1minusv0 = { v[faces[i][1]][X] - v[faces[i][0]][X], v[faces[i][1]][Y] - v[faces[i][0]][Y], v[faces[i][1]][Z] - v[faces[i][0]][Z] }; double[] v2minusv1 = { v[faces[i][2]][X] - v[faces[i][1]][X], v[faces[i][2]][Y] - v[faces[i][1]][Y], v[faces[i][2]][Z] - v[faces[i][1]][Z] }; // cross products gradients[i][X] = v1minusv0[Y] * v2minusv1[Z] - v1minusv0[Z] * v2minusv1[Y]; gradients[i][Y] = v1minusv0[Z] * v2minusv1[X] - v1minusv0[X] * v2minusv1[Z]; gradients[i][Z] = v1minusv0[X] * v2minusv1[Y] - v1minusv0[Y] * v2minusv1[X]; } double[][] normals = new double[vertices.length][3]; for (int i = 0; i < normals.length; i++) { normals[i][X] = 0; normals[i][Y] = 0; normals[i][Z] = 0; for (int j = 0; j < faces.length; j++) { for (int k = 0; k < faces[j].length; k++) { if (faces[j][k] == i) { normals[i][X] = gradients[j][X]; normals[i][Y] = gradients[j][Y]; normals[i][Z] = gradients[j][Z]; break; } } } double magnitude = Math.sqrt( normals[i][X] * normals[i][X] + normals[i][Y] * normals[i][Y] + normals[i][Z] * normals[i][Z] ); normals[i][X] /= magnitude; normals[i][Y] /= magnitude; normals[i][Z] /= magnitude; } return normals; } public void transformedBy(Matrix3D t) { double[][] transVertices = getTransformedVertices(t); double[][] transNormals = getNormals(transVertices); for (int i = 0; i < vertices.length; i++) { vertices[i][X] = transVertices[i][X]; vertices[i][Y] = transVertices[i][Y]; vertices[i][Z] = transVertices[i][Z]; vertices[i][NX] = transNormals[i][X]; vertices[i][NY] = transNormals[i][Y]; vertices[i][NZ] = transNormals[i][Z]; } } }