📄 objectfile.java
字号:
else ng.generateNormals(gi); // Get the generated normals and indices Vector3f genNorms[] = gi.getNormals(); int genNormIndices[] = gi.getNormalIndices(); // Now we need to copy the generated normals into ObjectFile // data structures (normList and normIdxList). The variable // normIdx is the index of the index of the normal currently // being put into the list. It takes some calculation to // figure out the new index and where to put it. int normIdx = 0; // Repeat for each triangle in the smoothing group for (int i = 0 ; i < triList.size() ; i++) { // Get the coordIdxList index of the first index in this face int idx = ((Integer)triList.get(i)).intValue(); // Repeat for each vertex in the triangle for (int j = 0 ; j < 3 ; j++) { // Put the new normal's index into the index list newNormIdxArray[idx + j] = normList.size(); // Add the vertex's normal to the normal list normList.add(genNorms[genNormIndices[normIdx++]]); } } } } normIdxList = new ArrayList(coordIdxList.size()); for (int i = 0 ; i < coordIdxList.size() ; i++) { normIdxList.add(new Integer(newNormIdxArray[i])); } normArray = objectToVectorArray(normList); } // end of smoothingGroupNormals /** * Each face is converted to triangles. As each face is converted, * we look up which geometry group and smoothing group the face * belongs to. The generated triangles are added to each of these * groups, which are also being converted to a new triangle based format. * * We need to convert to triangles before normals are generated * because of smoothing groups. The faces in a smoothing group * are copied into a GeometryInfo to have their normals calculated, * and then the normals are copied out of the GeometryInfo using * GeometryInfo.getNormalIndices. As part of Normal generation, * the geometry gets converted to Triangles. So we need to convert * to triangles *before* Normal generation so that the normals we * read out of the GeometryInfo match up with the vertex data * that we sent in. If we sent in TRIANGLE_FAN data, the normal * generator would convert it to triangles and we'd read out * normals formatted for Triangle data. This would not match up * with our original Fan data, so we couldn't tell which normals * go with which vertices. */ private void convertToTriangles() { boolean triangulate = (flags & TRIANGULATE) != 0; boolean textures = !texList.isEmpty() && !texIdxList.isEmpty() && (texIdxList.size() == coordIdxList.size()); boolean normals = !normList.isEmpty() && !normIdxList.isEmpty() && (normIdxList.size() == coordIdxList.size()); int numFaces = stripCounts.size(); boolean haveSgroups = curSgroup != null; triGroups = new HashMap(50); if (haveSgroups) triSgroups = new HashMap(50); ArrayList newCoordIdxList = null; ArrayList newTexIdxList = null; ArrayList newNormIdxList = null; if (triangulate) { GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY); gi.setStripCounts(objectToIntArray(stripCounts)); gi.setCoordinates(coordArray); gi.setCoordinateIndices(objectToIntArray(coordIdxList)); if (textures) { gi.setTextureCoordinateParams(1, 2); gi.setTextureCoordinates(0, texArray); gi.setTextureCoordinateIndices(0, objectToIntArray(texIdxList)); } if (normals) { gi.setNormals(normArray); gi.setNormalIndices(objectToIntArray(normIdxList)); } gi.convertToIndexedTriangles(); // Data is now indexed triangles. Next step is to take the data // out of the GeometryInfo and put into internal data structures int coordIndicesArray[] = gi.getCoordinateIndices(); // Fix for #4366060 // Make sure triangulated geometry has the correct number of triangles int tris = 0; for (int i = 0 ; i < numFaces ; i++) tris += ((Integer)stripCounts.get(i)).intValue() - 2; if (coordIndicesArray.length != (tris * 3)) { // Model contains bad polygons that didn't triangulate into the // correct number of triangles. Fall back to "simple" triangulation triangulate = false; } else { int texIndicesArray[] = gi.getTextureCoordinateIndices(); int normIndicesArray[] = gi.getNormalIndices(); // Convert index arrays to internal ArrayList format coordIdxList.clear(); texIdxList.clear(); normIdxList.clear(); for (int i = 0 ; i < coordIndicesArray.length ; i++) { coordIdxList.add(new Integer(coordIndicesArray[i])); if (textures) texIdxList.add(new Integer(texIndicesArray[i])); if (normals) normIdxList.add(new Integer(normIndicesArray[i])); } } } if (!triangulate) { newCoordIdxList = new ArrayList(); if (textures) newTexIdxList = new ArrayList(); if (normals) newNormIdxList = new ArrayList(); } // Repeat for each face in the model - add the triangles from each // face to the Geometry and Smoothing Groups int baseVertex = 0; for (int f = 0 ; f < numFaces ; f++) { int faceSize = ((Integer)stripCounts.get(f)).intValue(); // Find out the name of the group to which this face belongs Integer curFace = new Integer(f); curGroup = (String)groups.get(curFace); // Change to a new geometry group, create if it doesn't exist curTriGroup = (ArrayList)triGroups.get(curGroup); if (curTriGroup == null) { curTriGroup = new ArrayList(); triGroups.put(curGroup, curTriGroup); } // Change to a new smoothing group, create if it doesn't exist if (haveSgroups) { curSgroup = (String)sGroups.get(curFace); if (curSgroup == null) { // Weird case - this face has no smoothing group. Happens if the // first 's' token comes after some faces have already been defined. // Assume they wanted no smoothing for these faces curSgroup = "0"; } curTriSgroup = (ArrayList)triSgroups.get(curSgroup); if (curTriSgroup == null) { curTriSgroup = new ArrayList(); triSgroups.put(curSgroup, curTriSgroup); } } if (triangulate) { // Each polygon of n vertices is now n-2 triangles for (int t = 0 ; t < faceSize - 2 ; t++) { // The groups just remember the first vertex of each triangle Integer triBaseVertex = new Integer(baseVertex); curTriGroup.add(triBaseVertex); if (haveSgroups) curTriSgroup.add(triBaseVertex); baseVertex += 3; } } else { // Triangulate simply for (int v = 0 ; v < faceSize - 2 ; v++) { // Add this triangle to the geometry group and the smoothing group Integer triBaseVertex = new Integer(newCoordIdxList.size()); curTriGroup.add(triBaseVertex); if (haveSgroups) curTriSgroup.add(triBaseVertex); newCoordIdxList.add(coordIdxList.get(baseVertex)); newCoordIdxList.add(coordIdxList.get(baseVertex + v + 1)); newCoordIdxList.add(coordIdxList.get(baseVertex + v + 2)); if (textures) { newTexIdxList.add(texIdxList.get(baseVertex)); newTexIdxList.add(texIdxList.get(baseVertex + v + 1)); newTexIdxList.add(texIdxList.get(baseVertex + v + 2)); } if (normals) { newNormIdxList.add(normIdxList.get(baseVertex)); newNormIdxList.add(normIdxList.get(baseVertex + v + 1)); newNormIdxList.add(normIdxList.get(baseVertex + v + 2)); } } baseVertex += faceSize; } } // No need to keep these around stripCounts = null; groups = null; sGroups = null; if (!triangulate) { coordIdxList = newCoordIdxList; texIdxList = newTexIdxList; normIdxList = newNormIdxList; } } // End of convertToTriangles private SceneBase makeScene() { // Create Scene to pass back SceneBase scene = new SceneBase(); BranchGroup group = new BranchGroup(); scene.setSceneGroup(group); boolean gen_norms = normList.isEmpty() || normIdxList.isEmpty() || (normIdxList.size() != coordIdxList.size()); boolean do_tex = !texList.isEmpty() && !texIdxList.isEmpty() && (texIdxList.size() == coordIdxList.size()); // Convert ArrayLists to arrays coordArray = objectToPoint3Array(coordList); if (!gen_norms) normArray = objectToVectorArray(normList); if (do_tex) texArray = objectToTexCoord2Array(texList); convertToTriangles(); if ((DEBUG & 8) != 0) { time = System.currentTimeMillis() - time; System.out.println("Convert to triangles: " + time + " ms"); time = System.currentTimeMillis(); } if ((gen_norms) && (curSgroup != null)) { smoothingGroupNormals(); gen_norms = false; if ((DEBUG & 8) != 0) { time = System.currentTimeMillis() - time; System.out.println("Smoothing group normals: " + time + " ms"); time = System.currentTimeMillis(); } } NormalGenerator ng = null; if (gen_norms) ng = new NormalGenerator(radians); Stripifier strippy = null; if ((flags & STRIPIFY) != 0) strippy = new Stripifier(); long t1 = 0, t2 = 0, t3 = 0, t4 = 0; // Each "Group" of faces in the model will be one Shape3D Iterator e = triGroups.keySet().iterator(); while (e.hasNext()) { String curname = (String)e.next(); ArrayList triList = (ArrayList)triGroups.get(curname); // Check for group with no faces if (triList.size() > 0) { GeometryInfo gi = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY); gi.setCoordinateIndices(groupIndices(coordIdxList, triList)); gi.setCoordinates(coordArray); if (do_tex) { gi.setTextureCoordinateParams(1, 2); gi.setTextureCoordinates(0, texArray); gi.setTextureCoordinateIndices(0, groupIndices(texIdxList, triList)); } if ((DEBUG & 8) != 0) time = System.currentTimeMillis(); if (gen_norms) { if ((flags & REVERSE) != 0) gi.reverse(); ng.generateNormals(gi); if ((DEBUG & 8) != 0) { t2 += System.currentTimeMillis() - time; System.out.println("Generate normals: " + t2 + " ms"); time = System.currentTimeMillis(); } } else { gi.setNormalIndices(groupIndices(normIdxList, triList)); gi.setNormals(normArray); if ((flags & REVERSE) != 0) gi.reverse(); } if ((flags & STRIPIFY) != 0) { strippy.stripify(gi); if ((DEBUG & 8) != 0) { t3 += System.currentTimeMillis() - time; System.out.println("Stripify: " + t3 + " ms"); time = System.currentTimeMillis(); } } // Put geometry into Shape3d Shape3D shape = new Shape3D(); shape.setGeometry(gi.getGeometryArray(true, true, false)); String matName = (String)groupMaterials.get(curname); materials.assignMaterial(matName, shape); group.addChild(shape); scene.addNamedObject(curname, shape); if ((DEBUG & 8) != 0) { t4 += System.currentTimeMillis() - time; System.out.println("Shape 3D: " + t4 + " ms"); time = System.currentTimeMillis(); } } } return scene; } // end of makeScene /** * The Object File is loaded from the already opened file. * To attach the model to your scene, call getSceneGroup() on * the Scene object passed back, and attach the returned * BranchGroup to your scene graph. For an example, see * j3d-examples/ObjLoad/ObjLoad.java. */ public Scene load(Reader reader) throws FileNotFoundException, IncorrectFormatException, ParsingErrorException { // ObjectFileParser does lexical analysis ObjectFileParser st = new ObjectFileParser(reader); coordList = new ArrayList(); texList = new ArrayList(); normList = new ArrayList(); coordIdxList = new ArrayList(); texIdxList = new ArrayList(); normIdxList = new ArrayList(); groups = new HashMap(50); curGroup = "default"; sGroups = new HashMap(50); curSgroup = null; stripCounts = new ArrayList(); groupMaterials = new HashMap(50); groupMaterials.put(curGroup, "default"); materials = new ObjectFileMaterials(); time = 0L; if ((DEBUG & 8) != 0) { time = System.currentTimeMillis(); } readFile(st); if ((DEBUG & 8) != 0) { time = System.currentTimeMillis() - time; System.out.println("Read file: " + time + " ms"); time = System.currentTimeMillis(); } if ((flags & RESIZE) != 0) resize(); return makeScene(); } // End of load(Reader) /** * For an .obj file loaded from a URL, set the URL where associated files * (like material properties files) will be found. * Only needs to be called to set it to a different URL * from that containing the .obj file. */ public void setBaseUrl(URL url) { baseUrl = url; } // End of setBaseUrl /** * Return the URL where files associated with this .obj file (like * material properties files) will be found. */ public URL getBaseUrl() { return baseUrl; } // End of getBaseUrl /** * Set the path where files associated with this .obj file are * located. * Only needs to be called to set it to a different directory * from that containing the .obj file. */ public void setBasePath(String pathName) { basePath = pathName; if (basePath == null || basePath == "") basePath = "." + java.io.File.separator; basePath = basePath.replace('/', java.io.File.separatorChar); basePath = basePath.replace('\\', java.io.File.separatorChar); if (!basePath.endsWith(java.io.File.separator)) basePath = basePath + java.io.File.separator; } // End of setBasePath /** * Return the path where files associated with this .obj file (like material * files) are located. */ public String getBasePath() { return basePath; } // End of getBasePath /** * Set parameters for loading the model. * Flags defined in Loader.java are ignored by the ObjectFile Loader * because the .obj file format doesn't include lights, fog, background, * behaviors, views, or sounds. However, several flags are defined * specifically for use with the ObjectFile Loader (see above). */ public void setFlags(int flags) { this.flags = flags; if ((DEBUG & 4) != 0) System.out.println("Flags = " + flags); } // End of setFlags /** * Get the parameters currently defined for loading the model. * Flags defined in Loader.java are ignored by the ObjectFile Loader * because the .obj file format doesn't include lights, fog, background, * behaviors, views, or sounds. However, several flags are defined * specifically for use with the ObjectFile Loader (see above). */ public int getFlags() { return flags; } // End of getFlags} // End of class ObjectFile// End of file ObjectFile.java
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -