import java.awt.*; import java.util.ArrayList; import java.util.Iterator; // Needed for XML parser import javax.xml.parsers.*; import org.w3c.dom.*; import java.io.File; /** 3D Mesh that parses XML mesh files <P> Morgan McGuire <BR>morgan@cs.williams.edu */ public class Mesh { /** All of the triangles in this mesh, in no particular order. Triangles are stored with vertices in camera space. */ protected Array<Triangle> triArray = new Array<Triangle>(); /** @param filename Name of a mesh .xml file Based on code by Kiran Pai from http://www.developerfusion.co.uk/show/2064/ */ public Mesh(String filename) { loadXML(filename); } /** Sorts all triangles from smallest to largest average z-value. */ protected void sort() { triArray.radixSort(200, new TriangleComparator(), new TriangleEvaluator()); } /** Draws this mesh on the 3D surface. */ public void render(Graphics3D g) { sort(); //for (Triangle t : triArray) { Iterator it = triArray.iterator(); while (it.hasNext()){ Triangle t = (Triangle)it.next(); //End of what I added. t.render(g); } } /** Rotates by angle radians about the Y-axis. */ public void rotate(float angle) { float c = (float)Math.cos(angle); float s = (float)Math.sin(angle); //for (Triangle t : triArray) { Iterator it = triArray.iterator(); while (it.hasNext()){ Triangle t = (Triangle)it.next(); //End what I inserted for (int v = 0; v < 3; ++v) { float x = t.x[v]; float z = t.z[v]; t.x[v] = c * x + s * z; t.z[v] = c * z - s * x; } } } /////////////////////////////////////////////////////////////////////////////////////////// /// All Parsing Code Below Here /// /////////////////////////////////////////////////////////////////////////////////////////// private void loadXML(String filename) { try { System.out.println("Loading " + filename); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse(new File(filename)); // normalize text representation doc.getDocumentElement().normalize(); String rootName = doc.getDocumentElement().getNodeName(); assert rootName.equals("mesh") : "Not a mesh file: root = " + rootName; // Extract all faces NodeList faceList = doc.getElementsByTagName("face"); int n = faceList.getLength(); System.out.print(" Loading " + n + " faces..."); triArray.clear(); for (int i = 0; i < n; ++i) { triArray.add(readTriangle(faceList.item(i))); } System.out.println("done."); } catch (Exception e) { System.err.println("Error while parsing '" + filename + "': " + e); } } /** Extracts the color = "..." attribute from an XML node and turns it into a java.awt.Color. */ private Color readColor(Node node) { NamedNodeMap map = node.getAttributes(); return Color.decode(map.getNamedItem("color").getNodeValue()); } /** Reads the floating point value whose name is attr from an XML named map.*/ private float readFloat(NamedNodeMap map, String attr) { return Float.parseFloat(map.getNamedItem(attr).getNodeValue()); } /** Reads a triangle from an XML <face> node */ private Triangle readTriangle(Node faceNode) { Triangle tri = new Triangle(); if (faceNode.getNodeType() == Node.ELEMENT_NODE) { tri.color = readColor(faceNode); Element faceElement = (Element)faceNode; float scale = 3.0f; NodeList vertexList = faceElement.getElementsByTagName("vertex"); for (int v = 0; v < vertexList.getLength(); ++v) { NamedNodeMap attributes = vertexList.item(v).getAttributes(); tri.x[v] = readFloat(attributes, "x") * scale; tri.y[v] = readFloat(attributes, "y") * scale; tri.z[v] = readFloat(attributes, "z") * scale; } } return tri; } }