📄 objectfile.java
字号:
/* * $RCSfile: ObjectFile.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * * $Revision: 1.5 $ * $Date: 2007/02/09 17:20:10 $ * $State: Exp $ */package com.sun.j3d.loaders.objectfile;import com.sun.j3d.loaders.Scene;import com.sun.j3d.loaders.SceneBase;import com.sun.j3d.loaders.Loader;import com.sun.j3d.loaders.IncorrectFormatException;import com.sun.j3d.loaders.ParsingErrorException;import com.sun.j3d.loaders.objectfile.ObjectFileParser;import com.sun.j3d.loaders.objectfile.ObjectFileMaterials;import com.sun.j3d.utils.geometry.GeometryInfo;import com.sun.j3d.utils.geometry.NormalGenerator;import com.sun.j3d.utils.geometry.Stripifier;import java.io.FileNotFoundException;import java.io.StreamTokenizer;import java.io.Reader;import java.io.BufferedReader;import java.io.BufferedInputStream;import java.io.FileReader;import java.io.InputStreamReader;import java.io.IOException;import java.net.URL;import java.util.ArrayList;import java.util.Iterator;import java.util.HashMap;import java.util.StringTokenizer;import javax.media.j3d.*;import javax.vecmath.Color3f;import javax.vecmath.Point3f;import javax.vecmath.Vector3f;import javax.vecmath.TexCoord2f;import java.net.MalformedURLException;/** * The ObjectFile class implements the Loader interface for the Wavefront * .obj file format, a standard 3D object file format created for use with * Wavefront's Advanced Visualizer (tm) and available for purchase from * Viewpoint DataLabs, as well as other 3D model companies. Object Files * are text based * files supporting both polygonal and free-form geometry (curves * and surfaces). The Java 3D .obj file loader supports a subset of the * file format, but it is enough to load almost all commonly available * Object Files. Free-form geometry is not supported.</p> * * The Object File tokens currently supported by this loader are:</p> * <code>v <i>float</i> <i>float</i> <i>float</i></code></p> * <dl><dd>A single vertex's geometric position in space. The first vertex * listed in the file has index 1, * and subsequent vertices are numbered sequentially.</dl></p> * <code>vn <i>float</i> <i>float</i> <i>float</i></code></p> * <dl><dd>A normal. The first normal in the file is index 1, and * subsequent normals are numbered sequentially.</dl></p> * <code>vt <i>float</i> <i>float</i></code></p> * <dl><dd>A texture coordinate. The first texture coordinate in the file is * index 1, and subsequent normals are numbered sequentially.</dl></p> * <code>f <i>int</i> <i>int</i> <i>int</i> . . .</code></p> * <dl><dd><i><b>or</b></i></dl></p> * <code>f <i>int</i>/<i>int</i> <i>int</i>/<i>int</i> <i>int</i>/<i>int</i> . . .</code></p> * <dl><dd><i><b>or</i></b></dl></p> * <code>f <i>int</i>/<i>int</i>/<i>int</i> <i>int</i>/<i>int</i>/<i>int</i> <i>int</i>/<i>int</i>/<i>int</i> . . .</code></p> * <dl><dd>A polygonal face. The numbers are indexes into the arrays of * vertex positions, texture coordinates, and normals respectively. * There is no maximum number of vertices that a single polygon may * contain. The .obj file specification says that each face must * be flat and convex, but if the TRIANGULATE flag is sent to the * ObjectFile constructor, each face will be triangulated by the * Java 3D Triangulator, and therefore may be concave. * A number may be omitted if, for example, texture coordinates are * not being defined in the model. Numbers are normally positive * indexes, but may also be negative. An index of -1 means the last * member added to the respective array, -2 is the one before that, * and so on.</dl></p> * <code>g <i>name</i></code></p> * <dl><dd>Faces defined after this token will be added to the named group. * These geometry groups are returned as separated Shape3D objects * attached to the parent SceneGroup. Each named Shape3D will also * be in the Hashtable returned by Scene.getNamedObjects(). It is * legal to add faces to a group, switch to another group, and then * add more faces to the original group by reissuing the same name * with the g token. If faces are added to the model before the g * token is seen, the faces are put into the default group called * "default."</dl></p> * <code>s <i>int</i></code></p> * <dl><dd><i><b>or</i></b></dl></p> * <code>s off</code></p> * <dl><dd>If the vn token is not used in the file to specify vertex normals * for the model, this token may be used to put faces into groups * for normal calculation ("smoothing groups") in the same manner as * the 'g' token * is used to group faces geometrically. Faces in the same smoothing * group will have their normals calculated as if they are part of * the same smooth surface. To do this, we use the Java 3D NormalGenerator * utility with the creaseAngle parameter set to PI (180 degrees - * smooth shading, no creases) or to whatever the user has set the * creaseAngle. Faces in group 0 or 'off' use a * creaseAngle of zero, meaning there is no smoothing (the normal * of the face is used at all vertices giving the surface a faceted * look; there will be a * crease, or "Hard Edge," between each face in group zero). There is * also an implied hard edge <i>between</i> each smoothing group, where they * meet each other.</p> * </p> * If neither the vn nor the s token is used in the file, then normals * are calculated using the creaseAngle set in the contructor. * Normals are calculated on each geometry * group separately, meaning there will be a hard edge between each * geometry group.</dl></p> * </p> * <code>usemtl <i>name</i></code></p> * <dl><dd>The current (and subsequent) geometry groups (specified with * the 'g' token) have applied * to them the named material property. The following set of material * properties are available by default:</dl></p> * <pre> * amber amber_trans aqua aqua_filter * archwhite archwhite2 bflesh black * blondhair blue_pure bluegrey bluetint * blugrn blutan bluteal bone * bone1 bone2 brass brnhair * bronze brown brownlips brownskn * brzskin chappie charcoal deepgreen * default dkblue dkblue_pure dkbrown * dkdkgrey dkgreen dkgrey dkorange * dkpurple dkred dkteal emerald * fgreen flaqua flblack flblonde * flblue_pure flbrown fldkblue_pure fldkdkgrey * fldkgreen fldkgreen2 fldkgrey fldkolivegreen * fldkpurple fldkred flesh fleshtransparent * flgrey fllime flltbrown flltgrey * flltolivegreen flmintgreen flmustard florange * flpinegreen flpurple flred fltan * flwhite flwhite1 flyellow glass * glassblutint glasstransparent gold green * greenskn grey hair iris * jetflame lavendar lcdgreen lighttan * lighttan2 lighttan3 lighttannew lightyellow * lime lips ltbrown ltgrey * meh metal mintgrn muscle * navy_blue offwhite.cool offwhite.warm olivegreen * orange pale_green pale_pink pale_yellow * peach periwinkle pink pinktan * plasma purple red redbrick * redbrown redorange redwood rubber * ruby sand_stone sapphire shadow * ship2 silver skin sky_blue * smoked_glass tan taupe teeth * violet white yellow yellow_green * yellowbrt yelloworng * </pre> * <code>mtllib <i>filename</i></code></p> * <dl><dd>Load material properties from the named file. Materials * with the same name as the predefined materials above will override * the default value. Any directory path information in (filename) * is ignored. The .mtl files are assumed to be in the same directory * as the .obj file. If they are in a different directory, use * Loader.setBasePath() (or Loader.setBaseUrl() ). The format of the * material properties files * are as follows:</p> * <code>newmtl <i>name</i></code></p> * <dl><dd>Start the definition of a new named material property.</dl></p> * <code>Ka <i>float</i> <i>float</i> <i>float</i></code></p> * <dl><dd>Ambient color.</dl></p> * <code>Kd <i>float</i> <i>float</i> <i>float</i></code></p> * <dl><dd>Diffuse color.</dl></p> * <code>Ks <i>float</i> <i>float</i> <i>float</i></code></p> * <dl><dd>Specular color.</dl></p> * <code>illum <i>(0, 1, or 2)</i></code></p> * <dl><dd>0 to disable lighting, 1 for ambient & diffuse only (specular * color set to black), 2 for full lighting.</dl></p> * <code>Ns <i>float</i></code></p> * <dl><dd>Shininess (clamped to 1.0 - 128.0).</dl></p> * <code>map_Kd <i>filename</i></code></p> * <dl><dd>Texture map. Supports .rgb, .rgba, .int, .inta, .sgi, and * .bw files in addition to those supported by * <a href="../../utils/image/TextureLoader.html">TextureLoader</a>. * </dl></dl></p> */public class ObjectFile implements Loader { // 0=Input file assumed good // 1=Input file checked for inconsistencies // 2=path names // 4=flags // 8=Timing Info // 16=Tokens // 32=Token details (use with 16) // 64=limits of model coordinates private static final int DEBUG = 0; /** * Flag sent to constructor. The object's vertices will be changed * so that the object is centered at (0,0,0) and the coordinate * positions are all in the range of (-1,-1,-1) to (1,1,1). */ public static final int RESIZE = LOAD_SOUND_NODES << 1; /** * Flag sent to constructor. The Shape3D object will be created * by using the GeometryInfo POLYGON_ARRAY primitive, causing * them to be Triangulated by GeometryInfo. Use * this if you suspect concave or other non-behaving polygons * in your model. */ public static final int TRIANGULATE = RESIZE << 1; /** * Flag sent to constructor. Use if the vertices in your .obj * file were specified with clockwise winding (Java 3D wants * counter-clockwise) so you see the back of the polygons and * not the front. Calls GeometryInfo.reverse(). */ public static final int REVERSE = TRIANGULATE << 1; /** * Flag sent to contructor. After normals are generated the data * will be analyzed to find triangle strips. Use this if your * hardware supports accelerated rendering of strips. */ public static final int STRIPIFY = REVERSE << 1; private static final char BACKSLASH = '\\'; private int flags; private String basePath = null; private URL baseUrl = null; private boolean fromUrl = false; private float radians; // First, lists of points are read from the .obj file into these arrays. . . private ArrayList coordList; // Holds Point3f private ArrayList texList; // Holds TexCoord2f private ArrayList normList; // Holds Vector3f // . . . and index lists are read into these arrays. private ArrayList coordIdxList; // Holds Integer index into coordList private ArrayList texIdxList; // Holds Integer index into texList private ArrayList normIdxList; // Holds Integer index into normList // The length of each face is stored in this array. private ArrayList stripCounts; // Holds Integer // Each face's Geometry Group membership is kept here. . . private HashMap groups; // key=Integer index into stripCounts // value=String name of group private String curGroup; // . . . and Smoothing Group membership is kept here private HashMap sGroups; // key=Integer index into stripCounts // value=String name of group private String curSgroup; // The name of each group's "usemtl" material property is kept here private HashMap groupMaterials; // key=String name of Group // value=String name of material // After reading the entire file, the faces are converted into triangles. // The Geometry Group information is converted into these structures. . . private HashMap triGroups; // key=String name of group // value=ArrayList of Integer // indices into coordIdxList private ArrayList curTriGroup; // . . . and Smoothing Group info is converted into these. private HashMap triSgroups; // key=String name of group // value=ArrayList of Integer // indices into coordIdxList private ArrayList curTriSgroup; // Finally, coordList, texList, and normList are converted to arrays for // use with GeometryInfo private Point3f coordArray[] = null; private Vector3f normArray[] = null; private TexCoord2f texArray[] = null; // Used for debugging private long time; private ObjectFileMaterials materials = null; void readVertex(ObjectFileParser st) throws ParsingErrorException { Point3f p = new Point3f(); st.getNumber(); p.x = (float)st.nval; st.getNumber(); p.y = (float)st.nval; st.getNumber(); p.z = (float)st.nval; if ((DEBUG & 32) != 0) System.out.println(" (" + p.x + "," + p.y + "," + p.z + ")"); st.skipToNextLine(); // Add this vertex to the array coordList.add(p); } // End of readVertex /** * readNormal */ void readNormal(ObjectFileParser st) throws ParsingErrorException { Vector3f p = new Vector3f(); st.getNumber(); p.x = (float)st.nval; st.getNumber(); p.y = (float)st.nval; st.getNumber(); p.z = (float)st.nval; if ((DEBUG & 32) != 0) System.out.println(" (" + p.x + "," + p.y + "," + p.z + ")"); st.skipToNextLine(); // Add this vertex to the array normList.add(p); } // End of readNormal /** * readTexture */ void readTexture(ObjectFileParser st) throws ParsingErrorException { TexCoord2f p = new TexCoord2f(); st.getNumber(); p.x = (float)st.nval; st.getNumber(); p.y = (float)st.nval; if ((DEBUG & 32) != 0) System.out.println(" (" + p.x + "," + p.y + ")"); st.skipToNextLine(); // Add this vertex to the array texList.add(p); } // End of readTexture /** * readFace * * Adds the indices of the current face to the arrays. * * ViewPoint files can have up to three arrays: Vertex Positions, * Texture Coordinates, and Vertex Normals. Each vertex can * contain indices into all three arrays. */ void readFace(ObjectFileParser st) throws ParsingErrorException { int vertIndex, texIndex = 0, normIndex = 0; int count = 0; // There are n vertices on each line. Each vertex is comprised // of 1-3 numbers separated by slashes ('/'). The slashes may // be omitted if there's only one number. st.getToken(); while (st.ttype != st.TT_EOL) { // First token is always a number (or EOL) st.pushBack(); st.getNumber(); vertIndex = (int)st.nval - 1; if (vertIndex < 0) vertIndex += coordList.size() + 1; coordIdxList.add(new Integer(vertIndex)); // Next token is a slash, a number, or EOL. Continue on slash st.getToken(); if (st.ttype == '/') { // If there's a number after the first slash, read it st.getToken(); if (st.ttype == st.TT_WORD) { // It's a number st.pushBack(); st.getNumber(); texIndex = (int)st.nval - 1; if (texIndex < 0) texIndex += texList.size() + 1; texIdxList.add(new Integer(texIndex)); st.getToken(); } // Next token is a slash, a number, or EOL. Continue on slash if (st.ttype == '/') { // There has to be a number after the 2nd slash st.getNumber(); normIndex = (int)st.nval - 1; if (normIndex < 0) normIndex += normList.size() + 1; normIdxList.add(new Integer(normIndex)); st.getToken(); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -