package LDraw.Support; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.HashMap; //============================================================================== // //File: LDrawVertexes.m // //Purpose: Receives primitives and transfers their vertexes into an // OpenGL-optimized object. Drawing instances of this object will // draw all the contained vertexes. // //Notes: OpenGL has historically offered several ways of submitting // vertexes, most of which proved highly suboptimal for graphics // cards. Regretfully, those were also the easiest ones to program. // // Since immediate mode is deprecated and on its way out (and // display lists with it), Bricksmith must resort to this // intermediary object which collects, packs into a buffer, and // draws all the vertexes for a model's geometry. // //Modified: 11/16/2010 Allen Smith. Creation Date. // //============================================================================== import java.util.TreeSet; import Command.LDrawLine; import Command.LDrawQuadrilateral; import Command.LDrawTriangle; import Common.Box2; import Common.Box3; import Common.Matrix4; import Common.Ray3; import Common.Vector2f; public class LDrawVertices extends LDrawDirective implements Cloneable{ /** * @uml.property name="triangles" * @uml.associationEnd multiplicity="(0 -1)" * elementType="Command.LDrawTriangle" */ ArrayList<LDrawTriangle> triangles; /** * @uml.property name="quadrilaterals" * @uml.associationEnd multiplicity="(0 -1)" * elementType="Command.LDrawQuadrilateral" */ ArrayList<LDrawQuadrilateral> quadrilaterals; /** * @uml.property name="lines" * @uml.associationEnd multiplicity="(0 -1)" elementType="Command.LDrawLine" */ ArrayList<LDrawLine> lines; /** * @uml.property name="everythingElse" * @uml.associationEnd multiplicity="(0 -1)" * elementType="LDraw.Support.LDrawDirective" */ ArrayList<LDrawDirective> everythingElse; /** * @uml.property name="acceptsNonPrimitives" */ boolean acceptsNonPrimitives; public LDrawVertices init() { super.init(); lines = new ArrayList<LDrawLine>(); triangles = new ArrayList<LDrawTriangle>(); quadrilaterals = new ArrayList<LDrawQuadrilateral>(); everythingElse = new ArrayList<LDrawDirective>(); return this; } // #pragma mark - // #pragma mark DRAWING // #pragma mark - // ========== boxTest:transform:boundsOnly:creditObject:hits: // =================== // // Purpose: Check for intersections with screen-space geometry. // // ============================================================================== public boolean boxTest(Box2 bounds, Matrix4 transform, boolean boundsOnly, LDrawDirective creditObject, TreeSet<LDrawDirective> hits) { LDrawDirective currentDirective = null; int counter = 0; // Triangles for (counter = 0; counter < triangles.size(); counter++) { currentDirective = triangles.get(counter); if (currentDirective.boxTest(bounds, transform, boundsOnly, creditObject, hits)) if (creditObject != null) return true; } // Quadrilaterals for (counter = 0; counter < quadrilaterals.size(); counter++) { currentDirective = quadrilaterals.get(counter); if (currentDirective.boxTest(bounds, transform, boundsOnly, creditObject, hits)) if (creditObject != null) return true; } // Lines for (counter = 0; counter < lines.size(); counter++) { currentDirective = lines.get(counter); if (currentDirective.boxTest(bounds, transform, boundsOnly, creditObject, hits)) if (creditObject != null) return true; } // All else for (counter = 0; counter < everythingElse.size(); counter++) { currentDirective = everythingElse.get(counter); if (currentDirective.boxTest(bounds, transform, boundsOnly, creditObject, hits)) if (creditObject != null) return true; } return false; }// end boxTest:transform:boundsOnly:creditObject:hits: // ========== // depthTest:inBox:transform:creditObject:bestObject:bestDepth:======= // // Purpose: depthTest finds the closest primitive (in screen space) // overlapping a given point, as well as its device coordinate // depth. // // ============================================================================== public void depthTest(Vector2f testPt, Box2 bounds, Matrix4 transform, LDrawDirective creditObject, ArrayList<LDrawDirective> bestObject, FloatBuffer bestDepth) { LDrawDirective currentDirective = null; int counter = 0; // Triangles for (counter = 0; counter < triangles.size(); counter++) { currentDirective = triangles.get(counter); currentDirective.depthTest(testPt, bounds, transform, creditObject, bestObject, bestDepth); } // Quadrilaterals for (counter = 0; counter < quadrilaterals.size(); counter++) { currentDirective = quadrilaterals.get(counter); currentDirective.depthTest(testPt, bounds, transform, creditObject, bestObject, bestDepth); } // Lines for (counter = 0; counter < lines.size(); counter++) { currentDirective = lines.get(counter); currentDirective.depthTest(testPt, bounds, transform, creditObject, bestObject, bestDepth); } // All else for (counter = 0; counter < everythingElse.size(); counter++) { currentDirective = everythingElse.get(counter); currentDirective.depthTest(testPt, bounds, transform, creditObject, bestObject, bestDepth); } }// end depthTest:inBox:transform:creditObject:bestObject:bestDepth: // ========== setAcceptsNonPrimitives: // ========================================== // // Purpose: Whether the receiver maintains an everythingElse array to track // non-primitive objects. // // Notes: LDrawVertexes held by an LDrawModel to draw child primitives // should not track non-primitive objects, because the model itthis // will draw them. // // LDrawVertexes owned by the PartLibrary which are surrogate // drawables for library parts *do* need to track non-primitives in // order to make sure they are drawn. // // ============================================================================== public void setAcceptsNonPrimitives(boolean flag) { if (flag == false) { // everythingElse = null; } else { everythingElse = new ArrayList<LDrawDirective>(); } } // ========== setLines:triangles:quadrilaterals:other: // ========================== // // Purpose: Sets the primitives this container will be responsible for // converting into a vertex array and drawing. // // ============================================================================== public void setLines(ArrayList<LDrawLine> linesIn, ArrayList<LDrawTriangle> trianglesIn, ArrayList<LDrawQuadrilateral> quadrilateralsIn, ArrayList<LDrawDirective> everythingElseIn) { lines.clear(); triangles.clear(); quadrilaterals.clear(); everythingElse.clear(); lines.addAll(linesIn); triangles.addAll(trianglesIn); quadrilaterals.addAll(quadrilateralsIn); if (everythingElseIn != null) everythingElse.addAll(everythingElseIn); }// end setLines:triangles:quadrilaterals:other: // ========== addDirective: // ===================================================== // // Purpose: Register a directive of an arbitrary type (type will be deduced // correctly). // // ============================================================================== public void addDirective(LDrawDirective directive) { if (LDrawLine.class.isInstance(directive)) { addLine((LDrawLine) directive); } else if (LDrawTriangle.class.isInstance(directive)) { addTriangle((LDrawTriangle) directive); } else if (LDrawQuadrilateral.class.isInstance(directive)) { addQuadrilateral((LDrawQuadrilateral) directive); } else { addOther(directive); } }// end addDirective: // ========== addLine: // ========================================================== // // Purpose: Register a line to be included in the optimized vertexes. The // object must be re-optimized now. // // ============================================================================== public void addLine(LDrawLine line) { lines.add(line); } // ========== addTriangle: // ====================================================== // // Purpose: Register a triangle to be included in the optimized vertexes. // The object must be re-optimized now. // // ============================================================================== public void addTriangle(LDrawTriangle triangle) { triangles.add(triangle); } // ========== addQuadrilateral: // ================================================= // // Purpose: Register a quadrilateral to be included in the optimized // vertexes. The object must be re-optimized now. // // ============================================================================== public void addQuadrilateral(LDrawQuadrilateral quadrilateral) { quadrilaterals.add(quadrilateral); } // ========== addOther: // ========================================================= // // Purpose: Register a other to be included in the optimized vertexes. The // object must be re-optimized now. // // ============================================================================== public void addOther(LDrawDirective other) { everythingElse.add(other); } // #pragma mark - // ========== removeDirective: // ================================================== // // Purpose: Register a directive of an arbitrary type (type will be deduced // correctly). // // ============================================================================== public void removeDirective(LDrawDirective directive) { if (LDrawLine.class.isInstance(directive)) { removeLine((LDrawLine) directive); } else if (LDrawTriangle.class.isInstance(directive)) { removeTriangle((LDrawTriangle) directive); } else if (LDrawQuadrilateral.class.isInstance(directive)) { removeQuadrilateral((LDrawQuadrilateral) directive); } else { removeOther(directive); } }// end removeDirective: // ========== removeLine: // ======================================================= // // Purpose: De-registers a line to be included in the optimized vertexes. // The object must be re-optimized now. // // ============================================================================== public void removeLine(LDrawLine line) { lines.remove(line); } // ========== removeTriangle: // =================================================== // // Purpose: De-registers a line to be included in the optimized vertexes. // The object must be re-optimized now. // // ============================================================================== public void removeTriangle(LDrawTriangle triangle) { triangles.remove(triangle); } // ========== removeQuadrilateral: // ============================================== // // Purpose: De-registers a quadrilateral to be included in the optimized // vertexes. The object must be re-optimized now. // // ============================================================================== public void removeQuadrilateral(LDrawQuadrilateral quadrilateral) { quadrilaterals.remove(quadrilateral); } // ========== removeOther: // ====================================================== // // Purpose: De-registers a other to be included in the optimized vertexes. // The object must be re-optimized now. // // ============================================================================== public void removeOther(LDrawDirective other) { everythingElse.remove(other); } public Box3 boundingBox3() { assert true : "How is this getting called?"; return Box3.getInvalidBox(); } public Object clone() throws CloneNotSupportedException{ LDrawVertices newVertices = (LDrawVertices)super.clone(); newVertices.triangles = (ArrayList<LDrawTriangle>)triangles.clone(); newVertices.lines = (ArrayList<LDrawLine>)lines.clone(); newVertices.quadrilaterals = (ArrayList<LDrawQuadrilateral>)quadrilaterals.clone(); newVertices.everythingElse = (ArrayList<LDrawDirective>)everythingElse.clone(); return newVertices; } }