/* */ /* Create a window to display progress and results. */ scene = window.getScene(); frame = new BFrame("Validate Scene"); results = new BTextArea(10, 60); results.setEditable(false); scroll = new BScrollPane(results); progress = new BProgressBar(0, scene.getNumObjects()); progress.setShowProgressText(true); closeButton = new BButton("Cancel"); content = new BorderContainer(); content.add(scroll, BorderContainer.CENTER); content.add(progress, BorderContainer.NORTH); content.add(closeButton, BorderContainer.SOUTH, new LayoutInfo()); frame.setContent(content); frame.pack(); frame.setVisible(true); /* This function checks the coordinate system for NaNs and infinities. */ checkCoordinates(ObjectInfo info) { origin = info.coords.getOrigin(); if (Double.isNaN(origin.x) || Double.isNaN(origin.y) || Double.isNaN(origin.z)) results.append(info.name+": position is NaN\n"); if (Double.isInfinite(origin.x) || Double.isInfinite(origin.y) || Double.isInfinite(origin.z)) results.append(info.name+": position is infinite\n"); updir = info.coords.getUpDirection(); if (Double.isNaN(updir.x) || Double.isNaN(updir.y) || Double.isNaN(updir.z)) results.append(info.name+": orientation is NaN\n"); zdir = info.coords.getZDirection(); if (Double.isNaN(zdir.x) || Double.isNaN(zdir.y) || Double.isNaN(zdir.z)) results.append(info.name+": orientation is NaN\n"); } /* This function checks all the vertex positions for NaNs and infinities. */ checkMesh(ObjectInfo info) { vert = info.object.getVertices(); foundNaN = false; foundInf = false; for (int i = 0; i < vert.length; i++) { r = vert[i].r; if (Double.isNaN(r.x) || Double.isNaN(r.y) || Double.isNaN(r.z)) foundNaN = true; if (Double.isInfinite(r.x) || Double.isInfinite(r.y) || Double.isInfinite(r.z)) foundInf = true; } if (foundNaN) results.append(info.name+": vertex position is NaN\n"); if (foundInf) results.append(info.name+": vertex position is infinite\n"); } /* This is used by checkParameters(). */ checkParamValue(ObjectInfo info, TextureParameter param, value) { if (value.getClass().isArray()) { for (int i = 0; i < value.length; i++) if (!checkParamValue(info, param, value[i])) return false; return true; } if (Double.isNaN(value)) results.append(info.name+": parameter "+param.name+": value is NaN\n"); else if (Double.isInfinite(value)) results.append(info.name+": parameter "+param.name+": value is infinite\n"); else return true; return false; } /* This function checks the parameter values for NaNs and infinities. */ checkParameters(ObjectInfo info) { params = info.object.getParameters(); values = info.object.getParameterValues(); if (values == null) return; for (int i = 0; i < values.length; i++) checkParamValue(info, params[i], values[i].getValue()); } /* This function checks triangle meshes for illegal geometry. */ checkTriangleMesh(ObjectInfo info) { vert = info.object.getVertices(); edge = info.object.getEdges(); // Make a list of the edges intersecting each vertex. vertEdge = new ArrayList[vert.length]; for (int i = 0; i < vertEdge.length; i++) vertEdge[i] = new ArrayList(); for (int i = 0; i < edge.length; i++) { vertEdge[edge[i].v1].add(edge[i]); vertEdge[edge[i].v2].add(edge[i]); } // Now check for problems. foundStrayVertex = false; foundDuplicateEdge = false; foundBadBoundary = false; for (int i = 0; i < vertEdge.length; i++) { if (vertEdge[i].size() == 0) foundStrayVertex = true; numEdges = vertEdge[i].size(); boundaryCount = 0; for (int j = 0; j < numEdges; j++) { e1 = vertEdge[i].get(j); if (e1.f2 == -1) boundaryCount++; for (int k = j+1; k < numEdges; k++) { e2 = vertEdge[i].get(k); if (e1.v1 == e2.v1 && e1.v2 == e2.v2) foundDuplicateEdge = true; if (e1.v1 == e2.v2 && e1.v2 == e2.v1) foundDuplicateEdge = true; } } if (boundaryCount > 2) foundBadBoundary = true; } if (foundStrayVertex) results.append(info.name+": illegal geometry: found vertex which is not part of any face\n"); if (foundDuplicateEdge) results.append(info.name+": illegal geometry: found two edges connecting the same vertices\n"); if (foundBadBoundary) results.append(info.name+": illegal geometry: more than two boundary edges intersect one vertex\n"); } /* Run a series of checks on one object. */ checkObject(ObjectInfo info) { try { checkCoordinates(info); if (info.object instanceof Mesh) checkMesh(info); checkParameters(info); if (info.object instanceof TriangleMesh) checkTriangleMesh(info); } catch (Exception ex) { ex.printStackTrace(); results.append("Caught exception: "+ex.getMessage()); } } /* Start a new thread to check all the objects. */ processor = new Runnable() { public void run() { for (int i = 0; i < scene.getNumObjects(); i++) { progress.setProgressText("Checking "+scene.getObject(i).name); progress.setValue(i); if (Thread.interrupted()) break; checkObject(scene.getObject(i)); } progress.setValue(0); progress.setProgressText("Done validating scene.\n"); if (results.getLength() == 0) results.append("No problems found.\n"); closeButton.setText("Close"); } }; processThread = new Thread(processor); closeButton.addEventLink(CommandEvent.class, new Runnable() { public void run() { processThread.interrupt(); frame.dispose(); } }, "run"); processThread.start();