// 3D Engine // // Entity may consist of components and or triangle primatives. // // Author Matthew Caryl // Created 5.5.97 // // Although under copywrite to the author (Matthew Caryl) this code can be copied and modified for non-commercial // purposes as long as any derivatives contain this condition. package ADT; import java.awt.Color; public class Entity { // // Public interface // public Entity(Vector[] vs, int[] ts, Color[] cs, Entity[] children) { // we keep a copy of the original vertices basic_vertices = vs; // and make space for transformed vertices transformed_vertices = new Vector[basic_vertices.length]; for (int i = transformed_vertices.length - 1; i >= 0; i--) transformed_vertices[i] = new Vector(); // make triangles out of vertices and colours, and manufacture normals triangle_list = new Triangle[ts.length / 3]; for (int i = triangle_list.length - 1; i >= 0; i--) { Vector v1 = new Vector(basic_vertices[ts[3 * i + 0]]); Vector v2 = basic_vertices[ts[3 * i + 1]]; Vector v3 = new Vector(basic_vertices[ts[3 * i + 2]]); v1.subtract(v2); v3.subtract(v2); v3.cross(v1); v3.normalise(); triangle_list[i] = new Triangle(transformed_vertices[ts[3 * i + 0]], transformed_vertices[ts[3 * i + 1]], transformed_vertices[ts[3 * i + 2]], v3, cs[i]); } // copy the list of children if (children != null) { child_entities = new Entity[children.length]; for (int i = child_entities.length - 1; i >= 0; i--) { child_entities[i] = children[i]; child_entities[i].setParent(this); } } else child_entities = new Entity[0]; } public Entity() { this(new Vector[0], new int[0], new Color[0], null); } public void light(Vector light) { light_vector = light; inverse_compound_matrix.set(inverse_transform_matrix); inverse_compound_matrix.transform(light_vector, calculation_vector); calculation_vector.normalise(); for (int i = triangle_list.length - 1; i >= 0; i--) triangle_list[i].light(calculation_vector); for (int i = child_entities.length - 1; i >= 0; i--) child_entities[i].light(); } public void view(Matrix M) { compound_matrix.set(M); compound_matrix.multiply(transform_matrix); compound_matrix.transform(basic_vertices, transformed_vertices); for (int i = transformed_vertices.length - 1; i >= 0; i--) transformed_vertices[i].renormalise(); for (int i = child_entities.length - 1; i >= 0; i--) child_entities[i].view(compound_matrix); } public int listTriangles(Triangle[] ts, int number_triangles) { for (int i = triangle_list.length - 1; i >= 0; i--) if (triangle_list[i].inFront() && triangle_list[i].forwardFacing()) { ts[number_triangles] = triangle_list[i]; number_triangles++; } for (int i = child_entities.length - 1; i >= 0; i--) number_triangles = child_entities[i].listTriangles(ts, number_triangles); return number_triangles; } public void moveTo(float X, float Y, float Z) { x = X; y = Y; z = Z; transformCorrection(); } public void moveBy(float dX, float dY, float dZ) { x += dX; y += dY; z += dZ; transformCorrection(); } public void turnTo(float AX, float AY, float AZ) { ax = AX; ay = AY; az = AZ; transformCorrection(); } public void turnBy(float dAX, float dAY, float dAZ) { ax += dAX; ay += dAY; az += dAZ; transformCorrection(); } // // Protected interface // protected float x = 0f, y = 0f, z = 0f; protected float ax = 0f, ay = 0f, az = 0f; protected Matrix transform_matrix = new Matrix(); protected Matrix inverse_transform_matrix = new Matrix(); protected void transformCorrection() { transform_matrix.setRotate(ax, ay, az); transform_matrix.translateBy(x, y, z); inverse_transform_matrix.setRotate(-ax, -ay, -az); inverse_transform_matrix.translateBy(-x, -y, -z); if (parent_entity == null) { if (light_vector != null) light(light_vector); } else if (parent_entity.light_vector != null) light(); } // // Private interface // private Vector[] basic_vertices; private Vector[] transformed_vertices; private Triangle[] triangle_list; private Entity[] child_entities; private Matrix compound_matrix = new Matrix(); private Matrix inverse_compound_matrix = new Matrix(); private Vector calculation_vector = new Vector(); private Vector light_vector; private Entity parent_entity; private void setParent(Entity parent) { parent_entity = parent; } private Vector getLight() { if (light_vector != null) return light_vector; else return parent_entity.getLight(); } private void light() { inverse_compound_matrix.set(parent_entity.inverse_compound_matrix); inverse_compound_matrix.multiply(inverse_transform_matrix); inverse_compound_matrix.transform(parent_entity.getLight(), calculation_vector); calculation_vector.normalise(); for (int i = triangle_list.length - 1; i >= 0; i--) triangle_list[i].light(calculation_vector); for (int i = child_entities.length - 1; i >= 0; i--) child_entities[i].light(); } }