📄 readerobj.java
字号:
//===========================================================================//=-------------------------------------------------------------------------=//= Module history: =//= - August 8 2005 - David Diaz: Original base version =//= - May 18 2006 - David Diaz: bug fixes =//= - May 22 2006 - David Diaz/Oscar Chavarro: documentation added =//= - November 13 2006 - Oscar Chavarro: re-structured and tested =//= - November 19 2006 - Oscar Chavarro: re-structured and tested - using =//= private class _ReaderObjVertex and simplified TriangleMesh design =//= - May 4 2007 - Oscar Chavarro: added support for not well formed objs =//===========================================================================package vsdk.toolkit.io.geometry;// Java basic classesimport java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.NoSuchElementException;import java.util.StringTokenizer;// VitralSDK classesimport vsdk.toolkit.common.ColorRgb;import vsdk.toolkit.common.Matrix4x4;import vsdk.toolkit.common.Triangle;import vsdk.toolkit.common.Vertex;import vsdk.toolkit.common.Vector3D;import vsdk.toolkit.media.RGBAImage;import vsdk.toolkit.environment.Background;import vsdk.toolkit.environment.Camera;import vsdk.toolkit.environment.Material;import vsdk.toolkit.environment.Light;import vsdk.toolkit.environment.geometry.Geometry;import vsdk.toolkit.environment.geometry.TriangleMesh;import vsdk.toolkit.environment.geometry.TriangleMeshGroup;import vsdk.toolkit.environment.scene.SimpleBody;import vsdk.toolkit.environment.scene.SimpleScene;import vsdk.toolkit.io.image.ImageNotRecognizedException;import vsdk.toolkit.io.image.ImagePersistence;import vsdk.toolkit.io.PersistenceElement;//===========================================================================/**Class _ReaderObjVertex contains indexes to different Arrays inside a ReaderObj.The objective of this class is to provide a temporary mapping between originalinformation in an Alias Wavefront Object file (.obj) and VSDK's TriangleMeshrepresentation. It is used only by the ReaderObj class for format conversionof geometric data.*/class _ReaderObjVertex extends PersistenceElement{ public int vertexPositionIndex; public int vertexNormalIndex; public int vertexTextureCoordinateIndex; public _ReaderObjVertex() { vertexPositionIndex = -1; vertexNormalIndex = -1; vertexTextureCoordinateIndex = -1; } public _ReaderObjVertex(_ReaderObjVertex other) { vertexPositionIndex = other.vertexPositionIndex; vertexTextureCoordinateIndex = other.vertexTextureCoordinateIndex; vertexNormalIndex = other.vertexNormalIndex; } public boolean equals(Object alien) { if ( !(alien instanceof _ReaderObjVertex) ) return false; _ReaderObjVertex other = (_ReaderObjVertex)alien; if ( other.vertexPositionIndex != this.vertexPositionIndex || other.vertexNormalIndex != this.vertexNormalIndex || other.vertexTextureCoordinateIndex != this.vertexTextureCoordinateIndex ) { return false; } return true; } public String toString() { return "Vertex " + vertexPositionIndex + " / " + vertexNormalIndex + " / " + vertexTextureCoordinateIndex; }}//===========================================================================/**The class ReaderObj provides wavefront obj loading functionality. Wavefrontobj is a 3d object format used to describe polygon meshes; it is capable ofstoring vertex, vertex normal, vertex texture, faces, material, texture andother maps information.By the use of extensions, it has the potential to describe more information.The original Wavefront format is not well standarized, so many variationscould exist. This code currently manages only triangle faces, and interpretsother polygons to triangle fans.@todo Perhaps "ReaderObj" is not the best name for this class, as in thefuture should support exporting (writing) operations. It could be renamedto something as "PersistenceObj".*/public class ReaderObj extends PersistenceElement{ /** This method reads an Alias/Wavefront .obj file in ASCII form from the given filename. A wavefront obj file can have many objects within, so this method returns a group of objects rather than a single one. Even though a wavefront obj file has many objects, all the objects in the file share a common set of vertexes; this loader only stores for a TriangleMesh the vertexes that it uses, not all the array of vertexes. For a mesh to have a material, the matrial file has to be in the same folder as the mesh file; the same statement can be given about the textures and other maps. @todo should not recieve a filename, but a previously opened stream, to make it independent of filesystems, and generalize it to URLs or whatever other connection. */ private static TriangleMeshGroup read(String fileName) throws IOException { //- Geometric data and geometric attributes extracted from file --- ArrayList<Vector3D> vertexPositionsArray; ArrayList<Vector3D> vertexNormalsArray; ArrayList<Vector3D> vertexTextureCoordinatesArray; vertexPositionsArray = new ArrayList<Vector3D>(); vertexNormalsArray = new ArrayList<Vector3D>(); vertexTextureCoordinatesArray = new ArrayList<Vector3D>(); //- Topology data extracted from file ----------------------------- // _ReaderObjVertex[] will always be of size 3 (3 vertexes groups) ArrayList<_ReaderObjVertex[]> triangleDatasetsArray; triangleDatasetsArray = new ArrayList<_ReaderObjVertex[]>(); //- Accumulated states for currently builded geometric object ----- String nextGeometricObjectName; ArrayList<RGBAImage> nextTexturesArray; ArrayList<Material> nextMaterialsArray; nextGeometricObjectName = "OBJ_default_material"; nextTexturesArray = new ArrayList<RGBAImage>(); nextMaterialsArray = new ArrayList<Material>(); //- Aditional support data structures ----------------------------- ArrayList<TriangleMesh> meshGroup; ArrayList<ArrayList<int[]>> texture_span_triangleRange_table; ArrayList<int[]> auxInitialTextureMapping; ArrayList<int[]> material_triangleRange_table; HashMap<String, RGBAImage> texturesHashMap; HashMap<String, Material> materialsHashMap; int textureIndex; meshGroup = new ArrayList<TriangleMesh>(); texturesHashMap = new HashMap<String, RGBAImage>(); materialsHashMap = new HashMap<String, Material>(); textureIndex = 0; texture_span_triangleRange_table = new ArrayList<ArrayList<int[]>>(); auxInitialTextureMapping = new ArrayList<int[]>(); auxInitialTextureMapping.add(new int[2]); texture_span_triangleRange_table.add(auxInitialTextureMapping); material_triangleRange_table = new ArrayList<int[]>(); //- Geometry object processing from file / control ------------------- BufferedReader br; String lineOfText; br = new BufferedReader(new FileReader(fileName)); while ( (lineOfText = br.readLine()) != null ) { // Build material library if ( lineOfText.startsWith("mtllib ") ) { materialsHashMap = readMaterials(lineOfText, fileName); } // Change active material if ( lineOfText.startsWith("usemtl ") ) { // String auxMaterialName; StringTokenizer auxStringTokenizer; auxStringTokenizer = new StringTokenizer(lineOfText, " "); auxStringTokenizer.nextToken(); auxMaterialName = auxStringTokenizer.nextToken(); nextMaterialsArray.add(materialsHashMap.get(auxMaterialName)); // int auxMaterialRange[]; auxMaterialRange = new int[2]; auxMaterialRange[0] = triangleDatasetsArray.size(); auxMaterialRange[1] = nextMaterialsArray.size()-1; material_triangleRange_table.add(auxMaterialRange); } // Add a vertex if ( lineOfText.startsWith("v ") ) { vertexPositionsArray.add(readVertex(lineOfText)); } // Add a normal if ( lineOfText.startsWith("vn ") ) { vertexNormalsArray.add(readVertex(lineOfText)); } // Add a texture coordinate if ( lineOfText.startsWith("vt ") ) { vertexTextureCoordinatesArray.add( readVertexTexture(lineOfText)); } // Read faces as triangles sets if ( lineOfText.startsWith("f ") ) { try { // Note that only first 3 vertexes for each polygon are // processed ArrayList<_ReaderObjVertex[]> auxTriangleFanSet; auxTriangleFanSet = readPolygonAsTriangleFan(lineOfText); _ReaderObjVertex newVertexSet[]; for( int i = 0; i < auxTriangleFanSet.size(); i++ ) { newVertexSet = auxTriangleFanSet.get(i); triangleDatasetsArray.add(newVertexSet); } // ArrayList<int[]> actRanges; actRanges = texture_span_triangleRange_table.get(textureIndex); int[] lastRange = actRanges.get(actRanges.size()-1); lastRange[1] = triangleDatasetsArray.size(); } catch( NoSuchElementException nsee ) { } } // File specified textures management if ( lineOfText.startsWith("usemap ") ) { // Put texture in hash map or select it from hash map String auxTextureName; StringTokenizer auxStringTokenizer; auxStringTokenizer = new StringTokenizer(lineOfText, " "); auxStringTokenizer.nextToken(); auxTextureName = auxStringTokenizer.nextToken(); if ( !texturesHashMap.containsKey(auxTextureName) ) { RGBAImage auxTexture; auxTexture = obtainTextureFromFile(lineOfText, fileName); if ( auxTexture == null ) { textureIndex = 0; } else { nextTexturesArray.add(auxTexture); texture_span_triangleRange_table.add( new ArrayList<int[]>()); textureIndex = nextTexturesArray.size(); } texturesHashMap.put(auxTextureName, auxTexture); } else { RGBAImage auxTexture = texturesHashMap.get(auxTextureName); if( auxTexture == null ) { textureIndex = 0; } else if( !nextTexturesArray.contains(auxTexture) ) { nextTexturesArray.add(auxTexture); texture_span_triangleRange_table.add( new ArrayList<int[]>()); textureIndex = nextTexturesArray.size(); } else { textureIndex=nextTexturesArray.indexOf(auxTexture)+1; } } // Add selected texture to current object texture definition ArrayList<int[]> actRanges; actRanges = texture_span_triangleRange_table.get(textureIndex); int[] newRange=new int[2]; newRange[0] = triangleDatasetsArray.size(); actRanges.add(newRange); } // Object building
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -