//
import java.awt.*; // A VERY SIMPLE 3D RENDERER BUILT IN JAVA 1.0 - KEN PERLIN public class Shape { public final int CUBE = 0; public final int CYLINDER = 1; public final int NTYPES = 2; private int type = CUBE; // SHAPE DATA FOR A CUBE private static int[][] cubeFace = { {4,5,7,6}, {5,1,3,7}, {6,7,3,2}, {0,2,3,1}, {4,6,2,0}, {0,1,5,4} }; private static double[][] cubeVertices = { {-1,-1,-1}, { 1,-1,-1}, {-1, 1,-1}, { 1, 1,-1}, {-1,-1, 1}, { 1,-1, 1}, {-1, 1, 1}, { 1, 1, 1}, }; // SHAPE DATA FOR A PYRAMID private static int[][] pyramidFace = { }; private static double[][] pyramidVertices = { }; public int[][] face; public double[][] vertices; // CONSTRUCTOR public Shape() { Matrix.identity(matrix); useShape(cubeFace, cubeVertices); } // ALTERNATE SHAPES public void cube() { useShape(cubeFace, cubeVertices); } int cylinderFace[][][] = new int[100][][]; double cylinderVertices[][][] = new double[100][][]; public void cylinder(int n) { cylinder(n, true); } public void cylinder(int n, boolean capped) { n = Math.max(3, Math.min(99, n)); if (cylinderFace[n] == null) { cylinderFace[n] = new int[n+(capped?2:0)][]; for (int i = 0 ; i < n ; i++) { cylinderFace[n][i] = new int[4]; cylinderFace[n][i][0] = i; cylinderFace[n][i][1] = (i+1)%n; cylinderFace[n][i][2] = n + (i+1)%n; cylinderFace[n][i][3] = n + i; } if (capped) { cylinderFace[n][n ] = new int[n]; cylinderFace[n][n+1] = new int[n]; for (int i = 0 ; i < n ; i++) { cylinderFace[n][n ][i] = n-1-i; cylinderFace[n][n+1][i] = n+i; } } cylinderVertices[n] = new double[2*n][3]; for (int i = 0 ; i < n ; i++) { double theta = 2 * i * Math.PI / n; double cos = Math.cos(theta); double sin = Math.sin(theta); Vec.set(cylinderVertices[n][ i], cos, sin, -1); Vec.set(cylinderVertices[n][n+i], cos, sin, 1); } } useShape(cylinderFace[n], cylinderVertices[n]); } // PUBLIC ACCESS FUNCTIONS public void setColor(double[] src) { Vec.copy(src, color); } public void getColor(double[] dst) { Vec.copy(color, dst); } public void setTranslation(double[] src) { Vec.copy(src, translation); mustRecalc = true; } public void setRotation(double[] src) { Vec.copy(src, rotation); mustRecalc = true; } public void setScale(double[] src) { Vec.copy(src, scale); mustRecalc = true; } public void getTranslation(double[] dst) { Vec.copy(translation, dst); } public void getRotation(double[] dst) { Vec.copy(rotation, dst); } public void getScale(double[] dst) { Vec.copy(scale, dst); } public void getMatrix(double[][] m) { if (mustRecalc) { Matrix.identity(matrix); Matrix.translate(matrix, translation[0],translation[1],translation[2]); Matrix.rotateX(matrix, rotation[0]); Matrix.rotateY(matrix, rotation[1]); Matrix.rotateZ(matrix, rotation[2]); Matrix.scale(matrix, scale[0],scale[1],scale[2]); mustRecalc = false; } Matrix.copy(matrix, m); } // INTERNALLY STORED COLOR private double[] color = { 1,1,1 }; // TRANSLATION X Y Z, ROTATION X Y Z, SCALE X Y Z private double[] translation = { 0,0,0 }; private double[] rotation = { 0,0,0 }; private double[] scale = { 1,1,1 }; // INTERNALLY CALCULATED MATRIX private double[][] matrix = new double[4][4]; // NEED TO RECALCULATE MATRIX? private boolean mustRecalc = true; private void useShape(int[][] f, double[][] v) { face = f; vertices = v; } }