📄 objectfile.java
字号:
if ((DEBUG & 32) != 0) { System.out.println(" " + vertIndex + '/' + texIndex + '/' + normIndex); } count++; } Integer faceNum = new Integer(stripCounts.size()); stripCounts.add(new Integer(count)); // Add face to current groups groups.put(faceNum, curGroup); if (curSgroup != null) sGroups.put(faceNum, curSgroup); // In case we exited early st.skipToNextLine(); } // End of readFace /** * readPartName */ void readPartName(ObjectFileParser st) { st.getToken(); // Find the Material Property of the current group String curMat = (String)groupMaterials.get(curGroup); // New faces will be added to the curGroup if (st.ttype != ObjectFileParser.TT_WORD) curGroup = "default"; else curGroup = st.sval; if ((DEBUG & 32) != 0) System.out.println(" Changed to group " + curGroup); // See if this group has Material Properties yet if (groupMaterials.get(curGroup) == null) { // It doesn't - carry over from last group groupMaterials.put(curGroup, curMat); } st.skipToNextLine(); } // End of readPartName /** * readMaterialName */ void readMaterialName(ObjectFileParser st) throws ParsingErrorException { st.getToken(); if (st.ttype == ObjectFileParser.TT_WORD) { groupMaterials.put(curGroup, new String(st.sval)); if ((DEBUG & 32) != 0) { System.out.println(" Material Property " + st.sval + " assigned to group " + curGroup); } } st.skipToNextLine(); } // End of readMaterialName /** * loadMaterialFile * * Both types of slashes are returned as tokens from our parser, * so we go through the line token by token and keep just the * last token on the line. This should be the filename without * any directory info. */ void loadMaterialFile(ObjectFileParser st) throws ParsingErrorException { String s = null; // Filenames are case sensitive st.lowerCaseMode(false); // Get name of material file (skip path) do { st.getToken(); if (st.ttype == ObjectFileParser.TT_WORD) s = st.sval; } while (st.ttype != ObjectFileParser.TT_EOL); materials.readMaterialFile(fromUrl, fromUrl ? baseUrl.toString() : basePath, s); st.lowerCaseMode(true); st.skipToNextLine(); } // End of loadMaterialFile /** * readSmoothingGroup */ void readSmoothingGroup(ObjectFileParser st) throws ParsingErrorException { st.getToken(); if (st.ttype != ObjectFileParser.TT_WORD) { st.skipToNextLine(); return; } if (st.sval.equals("off")) curSgroup = "0"; else curSgroup = st.sval; if ((DEBUG & 32) != 0) System.out.println(" Smoothing group " + curSgroup); st.skipToNextLine(); } // End of readSmoothingGroup /** * readFile * * Read the model data from the file. */ void readFile(ObjectFileParser st) throws ParsingErrorException { int t; st.getToken(); while (st.ttype != ObjectFileParser.TT_EOF) { // Print out one token for each line if ((DEBUG & 16) != 0) { System.out.print("Token "); if (st.ttype == ObjectFileParser.TT_EOL) System.out.println("EOL"); else if (st.ttype == ObjectFileParser.TT_WORD) System.out.println(st.sval); else System.out.println((char)st.ttype); } if (st.ttype == ObjectFileParser.TT_WORD) { if (st.sval.equals("v")) { readVertex(st); } else if (st.sval.equals("vn")) { readNormal(st); } else if (st.sval.equals("vt")) { readTexture(st); } else if (st.sval.equals("f")) { readFace(st); } else if (st.sval.equals("fo")) { // Not sure what the dif is readFace(st); } else if (st.sval.equals("g")) { readPartName(st); } else if (st.sval.equals("s")) { readSmoothingGroup(st); } else if (st.sval.equals("p")) { st.skipToNextLine(); } else if (st.sval.equals("l")) { st.skipToNextLine(); } else if (st.sval.equals("mtllib")) { loadMaterialFile(st); } else if (st.sval.equals("usemtl")) { readMaterialName(st); } else if (st.sval.equals("maplib")) { st.skipToNextLine(); } else if (st.sval.equals("usemap")) { st.skipToNextLine(); } else { throw new ParsingErrorException( "Unrecognized token, line " + st.lineno()); } } st.skipToNextLine(); // Get next token st.getToken(); } } // End of readFile /** * Constructor. * * @param flags The constants from above or from * com.sun.j3d.loaders.Loader, possibly "or'ed" (|) together. * @param radians Ignored if the vn token is present in the model (user * normals supplied). Otherwise, crease angle to use within smoothing * groups, or within geometry groups if the s token isn't present either. */ public ObjectFile(int flags, float radians) { setFlags(flags); this.radians = radians; } // End of ObjectFile(int, float) /** * Constructor. Crease Angle set to default of * 44 degrees (see NormalGenerator utility for details). * @param flags The constants from above or from * com.sun.j3d.loaders.Loader, possibly "or'ed" (|) together. */ public ObjectFile(int flags) { this(flags, -1.0f); } // End of ObjectFile(int) /** * Default constructor. Crease Angle set to default of * 44 degrees (see NormalGenerator utility for details). Flags * set to zero (0). */ public ObjectFile() { this(0, -1.0f); } // End of ObjectFile() /** * Takes a file name and sets the base path to the directory * containing that file. */ private void setBasePathFromFilename(String fileName) { if (fileName.lastIndexOf(java.io.File.separator) == -1) { // No path given - current directory setBasePath("." + java.io.File.separator); } else { setBasePath( fileName.substring(0, fileName.lastIndexOf(java.io.File.separator))); } } // End of setBasePathFromFilename /** * The Object File is loaded from the .obj file specified by * the filename. * 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(String filename) throws FileNotFoundException, IncorrectFormatException, ParsingErrorException { setBasePathFromFilename(filename); Reader reader = new BufferedReader(new FileReader(filename)); return load(reader); } // End of load(String) private void setBaseUrlFromUrl(URL url) throws FileNotFoundException { String u = url.toString(); String s; if (u.lastIndexOf('/') == -1) { s = url.getProtocol() + ":"; } else { s = u.substring(0, u.lastIndexOf('/') + 1); } try { baseUrl = new URL(s); } catch (MalformedURLException e) { throw new FileNotFoundException(e.getMessage()); } } // End of setBaseUrlFromUrl /** * The object file is loaded off of the web. * 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(URL url) throws FileNotFoundException, IncorrectFormatException, ParsingErrorException { BufferedReader reader; if (baseUrl == null) setBaseUrlFromUrl(url); try { reader = new BufferedReader(new InputStreamReader(url.openStream())); } catch (IOException e) { throw new FileNotFoundException(e.getMessage()); } fromUrl = true; return load(reader); } // End of load(URL) /** * getLimits * * Returns an array of Point3f which form a bounding box around the * object. Element 0 is the low value, element 1 is the high value. * See normalize() below for an example of how to use this method. */ private Point3f[] getLimits() { Point3f cur_vtx = new Point3f(); // Find the limits of the model Point3f[] limit = new Point3f[2]; limit[0] = new Point3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE); limit[1] = new Point3f(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE); for (int i = 0 ; i < coordList.size() ; i++) { cur_vtx = (Point3f)coordList.get(i); // Keep track of limits for normalization if (cur_vtx.x < limit[0].x) limit[0].x = cur_vtx.x; if (cur_vtx.x > limit[1].x) limit[1].x = cur_vtx.x; if (cur_vtx.y < limit[0].y) limit[0].y = cur_vtx.y; if (cur_vtx.y > limit[1].y) limit[1].y = cur_vtx.y; if (cur_vtx.z < limit[0].z) limit[0].z = cur_vtx.z; if (cur_vtx.z > limit[1].z) limit[1].z = cur_vtx.z; } if ((DEBUG & 64) != 0) { System.out.println("Model range: (" + limit[0].x + "," + limit[0].y + "," + limit[0].z + ") to (" + limit[1].x + "," + limit[1].y + "," + limit[1].z + ")"); } return limit; } // End of getLimits /** * Center the object and make it (-1,-1,-1) to (1,1,1). */ private void resize() { int i, j; Point3f cur_vtx = new Point3f(); float biggest_dif; Point3f[] limit = getLimits(); // Move object so it's centered on (0,0,0) Vector3f offset = new Vector3f(-0.5f * (limit[0].x + limit[1].x), -0.5f * (limit[0].y + limit[1].y), -0.5f * (limit[0].z + limit[1].z)); if ((DEBUG & 64) != 0) { System.out.println("Offset amount: (" + offset.x + "," + offset.y + "," + offset.z + ")"); } // Find the divide-by value for the normalization biggest_dif = limit[1].x - limit[0].x; if (biggest_dif < limit[1].y - limit[0].y) biggest_dif = limit[1].y - limit[0].y; if (biggest_dif < limit[1].z - limit[0].z) biggest_dif = limit[1].z - limit[0].z; biggest_dif /= 2.0f; for (i = 0 ; i < coordList.size() ; i++) { cur_vtx = (Point3f)coordList.get(i); cur_vtx.add(cur_vtx, offset); cur_vtx.x /= biggest_dif; cur_vtx.y /= biggest_dif; cur_vtx.z /= biggest_dif; // coordList.setElementAt(cur_vtx, i); } } // End of resize private int[] objectToIntArray(ArrayList inList) { int outList[] = new int[inList.size()]; for (int i = 0 ; i < inList.size() ; i++) { outList[i] = ((Integer)inList.get(i)).intValue(); } return outList; } // End of objectToIntArray private Point3f[] objectToPoint3Array(ArrayList inList) { Point3f outList[] = new Point3f[inList.size()]; for (int i = 0 ; i < inList.size() ; i++) { outList[i] = (Point3f)inList.get(i); } return outList; } // End of objectToPoint3Array private TexCoord2f[] objectToTexCoord2Array(ArrayList inList) { TexCoord2f outList[] = new TexCoord2f[inList.size()]; for (int i = 0 ; i < inList.size() ; i++) { outList[i] = (TexCoord2f)inList.get(i); } return outList; } // End of objectToTexCoord2Array private Vector3f[] objectToVectorArray(ArrayList inList) { Vector3f outList[] = new Vector3f[inList.size()]; for (int i = 0 ; i < inList.size() ; i++) { outList[i] = (Vector3f)inList.get(i); } return outList; } // End of objectToVectorArray /** * Each group is a list of indices into the model's index lists, * indicating the starting index of each triangle in the group. * This method converts those data structures * into an integer array to use with GeometryInfo. */ private int[] groupIndices(ArrayList sourceList, ArrayList group) { int indices[] = new int[group.size() * 3]; for (int i = 0 ; i < group.size() ; i++) { int j = ((Integer)group.get(i)).intValue(); indices[i * 3 + 0] = ((Integer)sourceList.get(j + 0)).intValue(); indices[i * 3 + 1] = ((Integer)sourceList.get(j + 1)).intValue(); indices[i * 3 + 2] = ((Integer)sourceList.get(j + 2)).intValue(); } return indices; } // end of groupIndices /** * smoothingGroupNormals * * Smoothing groups are groups of faces who should be grouped * together for normal calculation purposes. The faces are * put into a GeometryInfo object and normals are calculated * with a 180 degree creaseAngle (no creases) or whatever the * user has specified. The normals * are then copied out of the GeometryInfo and back into * ObjectFile data structures. */ private void smoothingGroupNormals() { NormalGenerator ng = new NormalGenerator(radians == -1.0f ? Math.PI : radians); NormalGenerator ng0 = new NormalGenerator(0.0); normList.clear(); normIdxList = null; int newNormIdxArray[] = new int[coordIdxList.size()]; Iterator e = triSgroups.keySet().iterator(); while (e.hasNext()) { String curname = (String)e.next(); ArrayList triList = (ArrayList)triSgroups.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 (curname.equals("0")) ng0.generateNormals(gi);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -