//
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;
}
}