/src/org/mt4j/util/modelImporter/file3ds/Model3dsFileFactory.java

http://mt4j.googlecode.com/ · Java · 685 lines · 451 code · 111 blank · 123 comment · 74 complexity · 708825288d8de6cb9b7a5c8dd38a0f79 MD5 · raw file

  1. /***********************************************************************
  2. * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. ***********************************************************************/
  18. package org.mt4j.util.modelImporter.file3ds;
  19. import java.io.File;
  20. import java.io.FileNotFoundException;
  21. import java.io.InputStream;
  22. import java.util.ArrayList;
  23. import java.util.HashMap;
  24. import java.util.Iterator;
  25. import java.util.Map;
  26. import java.util.WeakHashMap;
  27. import mri.v3ds.Face3ds;
  28. import mri.v3ds.FaceMat3ds;
  29. import mri.v3ds.Material3ds;
  30. import mri.v3ds.Mesh3ds;
  31. import mri.v3ds.Scene3ds;
  32. import mri.v3ds.TexCoord3ds;
  33. import mri.v3ds.TextDecode3ds;
  34. import mri.v3ds.Vertex3ds;
  35. import org.mt4j.MTApplication;
  36. import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
  37. import org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh;
  38. import org.mt4j.util.MT4jSettings;
  39. import org.mt4j.util.TriangleNormalGenerator;
  40. import org.mt4j.util.logging.ILogger;
  41. import org.mt4j.util.logging.MTLoggerFactory;
  42. import org.mt4j.util.math.Tools3D;
  43. import org.mt4j.util.math.Vertex;
  44. import org.mt4j.util.modelImporter.ModelImporterFactory;
  45. import org.mt4j.util.opengl.GLTexture;
  46. import org.mt4j.util.opengl.GLTexture.EXPANSION_FILTER;
  47. import org.mt4j.util.opengl.GLTexture.SHRINKAGE_FILTER;
  48. import org.mt4j.util.opengl.GLTexture.TEXTURE_TARGET;
  49. import org.mt4j.util.opengl.GLTexture.WRAP_MODE;
  50. import org.mt4j.util.opengl.GLTextureSettings;
  51. import processing.core.PApplet;
  52. import processing.core.PImage;
  53. /**
  54. * A factory for creating Model3dsFile objects.
  55. * @author Christopher Ruff
  56. */
  57. public class Model3dsFileFactory extends ModelImporterFactory{
  58. private static final ILogger logger = MTLoggerFactory.getLogger(Model3dsFileFactory.class.getName());
  59. static{
  60. logger.setLevel(ILogger.ERROR);
  61. }
  62. private PApplet pa;
  63. private Map<String, PImage> textureCache ;
  64. /**
  65. * Load model.
  66. *
  67. * @param pa the pa
  68. * @param pathToModel the path to model
  69. * @param creaseAngle the crease angle
  70. * @param flipTextureY flip texture y
  71. * @param flipTextureX flip texture x
  72. *
  73. * @return the MT triangle meshes[]
  74. *
  75. * @throws FileNotFoundException the file not found exception
  76. */
  77. public MTTriangleMesh[] loadModelImpl(PApplet pa, String pathToModel, float creaseAngle, boolean flipTextureY, boolean flipTextureX) throws FileNotFoundException{
  78. long timeA = System.currentTimeMillis();
  79. this.pa = pa;
  80. ArrayList<MTTriangleMesh> returnMeshList = new ArrayList<MTTriangleMesh>();
  81. TriangleNormalGenerator normalGenerator = new TriangleNormalGenerator();
  82. // normalGenerator.setDebug(debug);
  83. HashMap<Integer, Group> materialIdToGroup = new HashMap<Integer, Group>();
  84. //TODO implement
  85. if (textureCache != null)
  86. textureCache.clear();
  87. textureCache = new WeakHashMap<String, PImage>();
  88. Scene3ds scene = null;
  89. try{
  90. TextDecode3ds decode = new TextDecode3ds();
  91. // int level = Scene3ds.DECODE_USED_PARAMS_AND_CHUNKS; //Scene3ds.DECODE_ALL; DECODE_USED_PARAMS, DECODE_USED_PARAMS_AND_CHUNKS
  92. int level = Scene3ds.DECODE_ALL;
  93. //LOAD all meshes from file into scene object
  94. File file = new File(pathToModel);
  95. if (file.exists()){
  96. scene = new Scene3ds(file, decode, level );
  97. }else{
  98. InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(pathToModel);
  99. if (in == null){
  100. in = pa.getClass().getResourceAsStream(pathToModel);
  101. }
  102. if (in != null){
  103. scene = new Scene3ds(in, decode, level );
  104. }else{
  105. throw new FileNotFoundException("File not found: " + file.getAbsolutePath());
  106. }
  107. }
  108. if (debug)
  109. logger.debug("\n-> Loading model: " + file.getName() + " <-");
  110. if (debug){
  111. //Go through all MATERIALS
  112. logger.debug("\nNum Scene Materials: " + scene.materials() );
  113. for( int m=0; m < scene.materials(); m++ ){
  114. Material3ds mat = scene.material( m );
  115. logger.debug(" Material " + m + ": \" " + mat.name() + "\"");
  116. }
  117. logger.debug("");
  118. }
  119. ///////// Go through all MESHES //////////////////////////
  120. for( int i=0; i<scene.meshes(); i++ ) {
  121. Mesh3ds m = scene.mesh( i );
  122. if (debug){
  123. int texMapType = m.texMapType();
  124. logger.debug("Texture coordinates provided: " + m.texCoords());
  125. logger.debug("Texture mapping type: " + texMapType);
  126. logger.debug("Mesh:" + m.name() + " Pivot:" + m.pivot());
  127. }
  128. /*
  129. XYZTrack3ds pos = m.positionTrack();
  130. RotationTrack3ds rot = m.rotationTrack();
  131. XYZTrack3ds sc = m.scaleTrack();
  132. //FIXME .track and key(i) werden nicht zur verfügung gestellt?!? aber in javadoc
  133. */
  134. if (debug){
  135. logger.debug("->Processing mesh: " + i + " of " + scene.meshes() + " Name: \"" + m.name() + "\"");
  136. logger.debug(" Num Faces: " + m.faces());
  137. logger.debug(" Num Vertices: " + m.vertices());
  138. logger.debug(" Num TextureCoordinates: " + m.texCoords());
  139. logger.debug("");
  140. }
  141. //Create the arrays needed for the cruncher
  142. Vertex[] vertices = new Vertex[m.vertices()];
  143. int[] indices = new int[m.faces()*3];
  144. int[] texCoordIndices = new int[m.faces()*3];
  145. float[][] textureCoords = new float[m.texCoords()][2];
  146. //Fill Vertices array
  147. for (int j = 0; j < m.vertices(); j++) {
  148. Vertex3ds vert = m.vertex(j);
  149. if (this.flipY){
  150. vertices[j] = new Vertex(vert.X, -vert.Y, vert.Z, -1,-1);
  151. }else{
  152. vertices[j] = new Vertex(vert.X, vert.Y, vert.Z, -1,-1);
  153. }
  154. if (m.texCoords()> j)
  155. textureCoords[j] = new float[]{m.texCoord(j).U, m.texCoord(j).V };
  156. }
  157. //Fill texcoords array
  158. for (int j = 0; j < m.texCoords(); j++) {
  159. TexCoord3ds tex = m.texCoord(j);
  160. float[] texCoord = new float[2];
  161. texCoord[0] = tex.U;
  162. texCoord[1] = tex.V;
  163. textureCoords[j] = texCoord;
  164. }
  165. //TODO so werden gleiche materials in verschiedenen meshes nicht zu einem mesh gemacht!
  166. //also müsste also ohne clear machen und dafür vertices + texcoords in einen grossen
  167. //array, dafür müssten indices aber per offset angepasst werden dass die wieder stimmen!
  168. materialIdToGroup.clear();
  169. if (m.faceMats() > 0){
  170. //List face Materials //TODO USE LOGGERS!!
  171. logger.debug(" Num Face-Materials: " + m.faceMats() );
  172. for( int n = 0; n < m.faceMats(); n++ ){
  173. FaceMat3ds fmat = m.faceMat( n );
  174. logger.debug(" FaceMat ID: " + fmat.matIndex() );
  175. logger.debug(" FaceMat indices: " + fmat.faceIndexes());
  176. int[] faceIndicesForMaterial = fmat.faceIndex();
  177. if (faceIndicesForMaterial.length <= 0){
  178. continue;
  179. }
  180. //Check if there already is a group with the same material
  181. Group group = materialIdToGroup.get(fmat.matIndex());
  182. //If not, create a new group and save it in map
  183. if (group == null){
  184. group = new Group(Integer.toString(fmat.matIndex()));
  185. materialIdToGroup.put(fmat.matIndex(), group);
  186. }
  187. //Go through all pointers to the faces for this material
  188. //and get the corresponding face
  189. for (int k : faceIndicesForMaterial) {
  190. Face3ds face = m.face(k);
  191. AFace aFace = new AFace();
  192. aFace.p0 = face.P0;
  193. aFace.p1 = face.P1;
  194. aFace.p2 = face.P2;
  195. aFace.t0 = face.P0;
  196. aFace.t1 = face.P1;
  197. aFace.t2 = face.P2;
  198. group.addFace(aFace);
  199. }
  200. }
  201. Iterator<Integer> it = materialIdToGroup.keySet().iterator();
  202. logger.debug("Mesh: " + m.name() + " Anzahl Groups:" + materialIdToGroup.keySet().size());
  203. while (it.hasNext()) {
  204. int currentGroupName = it.next();
  205. Group currentGroup = materialIdToGroup.get(currentGroupName);
  206. logger.debug("Current group: " + currentGroupName);
  207. currentGroup.compileItsOwnLists(vertices, textureCoords);
  208. //Get the new arrays
  209. Vertex[] newVertices = currentGroup.getGroupVertices();
  210. int[] newIndices = currentGroup.getIndexArray();
  211. float[][] newTextureCoords = currentGroup.getGroupTexCoords();
  212. int[] newTexIndices = currentGroup.getTexCoordIndices();
  213. logger.debug("\nGroup: \"" + currentGroup.name + "\" ->Vertices: " + currentGroup.verticesForGroup.size()+ " ->TextureCoords: " + currentGroup.texCoordsForGroup.size() + " ->Indices: " + currentGroup.indexArray.length + " ->Texcoord Indices: " + currentGroup.texCoordIndexArray.length );
  214. logger.debug("");
  215. if (vertices.length > 2){
  216. GeometryInfo geometry = null;
  217. //Load as all vertex normals smoothed if creaseAngle == 180;
  218. if (creaseAngle == 180){
  219. geometry = normalGenerator.generateSmoothNormals(pa, newVertices , newIndices, newTextureCoords, newTexIndices, creaseAngle, flipTextureY, flipTextureX);
  220. }else{
  221. geometry = normalGenerator.generateCreaseAngleNormals(pa, newVertices, newIndices, newTextureCoords, newTexIndices, creaseAngle, flipTextureY, flipTextureX);
  222. }
  223. MTTriangleMesh mesh = new MTTriangleMesh(pa, geometry);
  224. if (mesh != null){
  225. mesh.setName(m.name() + " material: " + Integer.toString(currentGroupName));
  226. //Assign texture
  227. this.assignMaterial(pathToModel, file, scene, m, currentGroupName, mesh);
  228. if (mesh.getTexture() != null){
  229. mesh.setTextureEnabled(true);
  230. }else{
  231. logger.debug("No texture could be assigned to mesh.");
  232. }
  233. returnMeshList.add(mesh);
  234. }
  235. }
  236. }
  237. }else{
  238. //If there are no materials for this mesh dont split mesh into
  239. //groups by material
  240. //Fill indices array and texcoords array (Here: vertex index = texcoord index)
  241. for( int faceIndex = 0; faceIndex < m.faces(); faceIndex++ ){
  242. Face3ds f = m.face( faceIndex );
  243. indices[faceIndex*3] = f.P0;
  244. indices[faceIndex*3+1] = f.P1;
  245. indices[faceIndex*3+2] = f.P2;
  246. texCoordIndices[faceIndex*3] = f.P0;
  247. texCoordIndices[faceIndex*3+1] = f.P1;
  248. texCoordIndices[faceIndex*3+2] = f.P2;
  249. }//for faces
  250. //Create the Mesh and set a texture
  251. if (vertices.length > 2){
  252. //Create normals for the mesh and duplicate vertices for faces that share the same
  253. //Vertex, but with different texture coordinates or different normals
  254. GeometryInfo geometry = null;
  255. //Generate normals and denormalize vertices with more than 1 texture coordinate
  256. if (creaseAngle == 180){
  257. geometry = normalGenerator.generateSmoothNormals(pa, vertices, indices, textureCoords, texCoordIndices, creaseAngle, flipTextureY, flipTextureX);
  258. }else{
  259. geometry = normalGenerator.generateCreaseAngleNormals(pa, vertices, indices, textureCoords, texCoordIndices, creaseAngle, flipTextureY, flipTextureX);
  260. }
  261. MTTriangleMesh mesh = new MTTriangleMesh(pa, geometry);
  262. mesh.setName(m.name());
  263. // this.assignMaterial(file, scene, m, sceneMaterialID, mesh);
  264. returnMeshList.add(mesh);
  265. }//end if vertices.lentgh > 2
  266. }
  267. }//for meshes
  268. // logger.debug(decode.text());
  269. }catch (Exception e) {
  270. e.printStackTrace();
  271. }
  272. materialIdToGroup.clear();
  273. long timeB = System.currentTimeMillis();
  274. long delta = timeB-timeA;
  275. logger.debug("Loaded model in: " + delta + " ms");
  276. return returnMeshList.toArray(new MTTriangleMesh[returnMeshList.size()]);
  277. }
  278. /**
  279. * Assigns the texture.
  280. * @param pathToModel
  281. * @param modelFile
  282. * @param scene
  283. * @param m
  284. * @param sceneMaterialID
  285. * @param mesh
  286. */
  287. private void assignMaterial(String pathToModel, File modelFile, Scene3ds scene, Mesh3ds m, int sceneMaterialID, MTTriangleMesh mesh){
  288. if (scene.materials() > 0){
  289. if (m.faceMats() > 0){
  290. //Just take the first material in the mesh, it could have more but we dont support more than 1 material for a mesh
  291. // materialIndexForMesh = m.faceMat(0).matIndex();
  292. Material3ds mat = scene.material(sceneMaterialID);
  293. String materialName = mat.name();
  294. if (debug)
  295. logger.debug("Material name for mesh \"" + mesh.getName() + ":-> \"" + materialName + "\"");
  296. materialName = materialName.trim();
  297. materialName = materialName.toLowerCase();
  298. //Try to load texture
  299. try {
  300. PImage cachedImage = textureCache.get(materialName);
  301. if (cachedImage != null){
  302. mesh.setTexture(cachedImage);
  303. mesh.setTextureEnabled(true);
  304. if (debug)
  305. logger.debug("->Loaded texture from CACHE : \"" + materialName + "\"");
  306. return;
  307. }
  308. if (modelFile.exists()){ //If model is loaded from local file system
  309. String modelFolder = modelFile.getParent();// pathToModel.substring(), pathToModel.lastIndexOf(File.pathSeparator)
  310. File modelFolderFile = new File (modelFolder);
  311. if (modelFolderFile.exists() && modelFolderFile.isDirectory())
  312. modelFolder = modelFolderFile.getAbsolutePath();
  313. else{
  314. modelFolder = "";
  315. }
  316. String[] suffix = new String[]{"jpg", "JPG", "tga" , "TGA", "bmp", "BMP", "png", "PNG", "tiff", "TIFF"};
  317. for (int j = 0; j < suffix.length; j++) {
  318. String suffixString = suffix[j];
  319. //Try to load and set texture to mesh
  320. String texturePath = modelFolder + MTApplication.separator + materialName + "." + suffixString;
  321. File textureFile = new File(texturePath);
  322. if (textureFile.exists()){
  323. boolean success = textureFile.renameTo(new File(texturePath));
  324. if (!success) {
  325. // File was not successfully renamed
  326. logger.debug("failed to RENAME file: " + textureFile.getAbsolutePath());
  327. }
  328. PImage texture = null;
  329. if (MT4jSettings.getInstance().isOpenGlMode()){ //TODO check if render thread
  330. PImage img = pa.loadImage(texturePath);
  331. if (Tools3D.isPowerOfTwoDimension(img)){
  332. texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.TEXTURE_2D, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
  333. }else{
  334. texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.RECTANGULAR, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
  335. // ((GLTexture)texture).setFilter(SHRINKAGE_FILTER.BilinearNoMipMaps, EXPANSION_FILTER.Bilinear);
  336. }
  337. }else{
  338. texture = pa.loadImage(texturePath);
  339. }
  340. mesh.setTexture(texture);
  341. mesh.setTextureEnabled(true);
  342. textureCache.put(materialName, texture);
  343. if (debug)
  344. logger.debug("->Loaded material texture: \"" + materialName + "\"");
  345. break;
  346. }
  347. if (j+1==suffix.length){
  348. logger.error("Couldnt load material texture: \"" + materialName + "\"");
  349. }
  350. }
  351. }else{//Probably loading from jar file
  352. PImage texture = null;
  353. String[] suffix = new String[]{"jpg", "JPG", "tga" , "TGA", "bmp", "BMP", "png", "PNG", "tiff", "TIFF"};
  354. for (String suffixString : suffix) {
  355. String modelFolder = pathToModel.substring(0, pathToModel.lastIndexOf(MTApplication.separator));
  356. String texturePath = modelFolder + MTApplication.separator + materialName + "." + suffixString;
  357. if (MT4jSettings.getInstance().isOpenGlMode()){
  358. PImage img = pa.loadImage(texturePath);
  359. if (Tools3D.isPowerOfTwoDimension(img)){
  360. texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.TEXTURE_2D, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
  361. }else{
  362. texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.RECTANGULAR, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
  363. // ((GLTexture)texture).setFilter(SHRINKAGE_FILTER.BilinearNoMipMaps, EXPANSION_FILTER.Bilinear);
  364. }
  365. }else{
  366. texture = pa.loadImage(texturePath);
  367. }
  368. mesh.setTexture(texture);
  369. mesh.setTextureEnabled(true);
  370. textureCache.put(materialName, texture);
  371. if (debug)
  372. logger.debug("->Loaded material texture: \"" + materialName + "\"");
  373. break;
  374. }
  375. }
  376. } catch (Exception e) {
  377. logger.error(e.getMessage());
  378. }
  379. }//if (m.faceMats() > 0)
  380. }//if (scene.materials() > 0)
  381. }
  382. private boolean debug = true;
  383. private boolean flipY = true;
  384. public void setDebug(boolean debug) {
  385. this.debug = debug;
  386. if (debug)
  387. logger.setLevel(ILogger.DEBUG);
  388. else
  389. logger.setLevel(ILogger.ERROR);
  390. }
  391. public void setFlipY(boolean flipY){
  392. this.flipY = flipY;
  393. }
  394. /**
  395. * A class representing one group in a .3ds file
  396. * @author C.Ruff
  397. *
  398. */
  399. private class Group{
  400. private String name;
  401. private ArrayList<AFace> faces;
  402. private ArrayList<Vertex> verticesForGroup;
  403. private HashMap<Integer, Integer> oldIndexToNewIndex;
  404. private ArrayList<float[]> texCoordsForGroup;
  405. private HashMap<Integer, Integer> oldTexIndexToNewTexIndex;
  406. private int[] indexArray;
  407. private int[] texCoordIndexArray;
  408. public Group(String name){
  409. this.name = name;
  410. faces = new ArrayList<AFace>();
  411. verticesForGroup = new ArrayList<Vertex>();
  412. oldIndexToNewIndex = new HashMap<Integer, Integer>();
  413. texCoordsForGroup = new ArrayList<float[]>();
  414. oldTexIndexToNewTexIndex = new HashMap<Integer, Integer>();
  415. indexArray = new int[0];
  416. texCoordIndexArray = new int[0];
  417. //name = "default";
  418. }
  419. public void addFace(AFace face){
  420. faces.add(face);
  421. }
  422. //Irgendwann am ende ausführen
  423. //=>für jede gruppe eigene liste von vertices on indices speichern
  424. //aus hauptlisten rausholen
  425. /**
  426. * Uses the faces attached to this group during the parsing process and the lists with
  427. * all vertex and all texture coordinates of the obj file to create arrays for this group
  428. * with vertices and texture coords that only belong to this single group.
  429. *
  430. * @param allFileVerts
  431. * @param allTexCoords
  432. */
  433. public void compileItsOwnLists(Vertex[] allFileVerts, float[][] allTexCoords){
  434. indexArray = new int[faces.size()*3];
  435. if (allTexCoords.length > 0){
  436. texCoordIndexArray = new int[faces.size()*3];
  437. }
  438. for (int i = 0; i < faces.size(); i++) {
  439. AFace currentFace = faces.get(i);
  440. Vertex v0 = allFileVerts[currentFace.p0];
  441. Vertex v1 = allFileVerts[currentFace.p1];
  442. Vertex v2 = allFileVerts[currentFace.p2];
  443. if ( allTexCoords.length > currentFace.t0
  444. && allTexCoords.length > currentFace.t1
  445. && allTexCoords.length > currentFace.t2
  446. ){
  447. float[] texV0 = allTexCoords[currentFace.t0];
  448. float[] texV1 = allTexCoords[currentFace.t1];
  449. float[] texV2 = allTexCoords[currentFace.t2];
  450. //Etwas redundant immer wieder zu machen beim gleichen vertex..whatever
  451. v0.setTexCoordU(texV0[0]);
  452. v0.setTexCoordV(texV0[1]);
  453. v1.setTexCoordU(texV1[0]);
  454. v1.setTexCoordV(texV1[1]);
  455. v2.setTexCoordU(texV2[0]);
  456. v2.setTexCoordV(texV2[1]);
  457. //Check if there is a texture index in the hashtable at the faces texture pointer
  458. //if not, create a new index = the end of thexcoords list, and put the pointer into the hash
  459. //if yes, point the faces texture pointer to the pointer in the hash
  460. //This process maps the texture coords and indices of all the groups in the obj
  461. //file to only this groups texture coord list and texture indices, the indices
  462. //are created from the index in the thex coord list when they are put in
  463. //Only the texture coordinates are added to the list that have not been adressed
  464. //in the texture indices pointers in the faces
  465. //Same texture pointers will point to the same texcoord in the list
  466. Integer oldToNewT0 = oldTexIndexToNewTexIndex.get(currentFace.t0);
  467. if (oldToNewT0 != null){
  468. currentFace.t0 = oldToNewT0;
  469. }else{
  470. int newIndex = texCoordsForGroup.size();
  471. texCoordsForGroup.add(texV0);
  472. oldTexIndexToNewTexIndex.put(currentFace.t0, newIndex);
  473. currentFace.t0 = newIndex;
  474. }
  475. Integer oldToNewT1 = oldTexIndexToNewTexIndex.get(currentFace.t1);
  476. if (oldToNewT1 != null){
  477. currentFace.t1 = oldToNewT1;
  478. }else{
  479. int newIndex = texCoordsForGroup.size();
  480. texCoordsForGroup.add(texV1);
  481. oldTexIndexToNewTexIndex.put(currentFace.t1, newIndex);
  482. currentFace.t1 = newIndex;
  483. }
  484. Integer oldToNewT2 = oldTexIndexToNewTexIndex.get(currentFace.t2);
  485. if (oldToNewT2 != null){
  486. currentFace.t2 = oldToNewT2;
  487. }else{
  488. int newIndex = texCoordsForGroup.size();
  489. texCoordsForGroup.add(texV2);
  490. oldTexIndexToNewTexIndex.put(currentFace.t2, newIndex);
  491. currentFace.t2 = newIndex;
  492. }
  493. }
  494. //Do the same for the vertices.
  495. //Create a new vertex pointer when adding the vertex to the list
  496. Integer oldToNewP0 = oldIndexToNewIndex.get(currentFace.p0);
  497. if (oldToNewP0 != null){
  498. //index of the old vertex list has already been mapped to a new one here -> use the new index in the face
  499. currentFace.p0 = oldToNewP0;
  500. }else{
  501. int newIndex = verticesForGroup.size();
  502. verticesForGroup.add(v0);
  503. //mark that the former index (for exmample 323) is now at new index (f.e. 1)
  504. oldIndexToNewIndex.put(currentFace.p0, newIndex);
  505. currentFace.p0 = newIndex;
  506. }
  507. Integer oldToNewP1 = oldIndexToNewIndex.get(currentFace.p1);
  508. if (oldToNewP1 != null){
  509. currentFace.p1 = oldToNewP1;
  510. }else{
  511. int newIndex = verticesForGroup.size();
  512. verticesForGroup.add(v1);
  513. oldIndexToNewIndex.put(currentFace.p1, newIndex);
  514. currentFace.p1 = newIndex;
  515. }
  516. Integer oldToNewP2 = oldIndexToNewIndex.get(currentFace.p2);
  517. if (oldToNewP2 != null){
  518. currentFace.p2 = oldToNewP2;
  519. }else{
  520. int newIndex = verticesForGroup.size();
  521. verticesForGroup.add(v2);
  522. oldIndexToNewIndex.put(currentFace.p2, newIndex);
  523. currentFace.p2 = newIndex;
  524. }
  525. indexArray[i*3] = currentFace.p0;
  526. indexArray[i*3+1] = currentFace.p1;
  527. indexArray[i*3+2] = currentFace.p2;
  528. if (allTexCoords.length > 0){
  529. texCoordIndexArray[i*3] = currentFace.t0;
  530. texCoordIndexArray[i*3+1] = currentFace.t1;
  531. texCoordIndexArray[i*3+2] = currentFace.t2;
  532. }
  533. }
  534. }
  535. public int[] getIndexArray() {
  536. return indexArray;
  537. }
  538. public String getName() {
  539. return name;
  540. }
  541. public int[] getTexCoordIndices() {
  542. return texCoordIndexArray;
  543. }
  544. public float[][] getGroupTexCoords() {
  545. return texCoordsForGroup.toArray(new float[this.texCoordsForGroup.size()][]);
  546. }
  547. public Vertex[] getGroupVertices() {
  548. return verticesForGroup.toArray(new Vertex[this.verticesForGroup.size()]);
  549. }
  550. }
  551. /**
  552. * A class representing a face in the obj file.
  553. * Has pointers into the vertex and the texture arrays.
  554. *
  555. * @author C.Ruff
  556. *
  557. */
  558. private class AFace{
  559. int p0;
  560. int p1;
  561. int p2;
  562. int t0;
  563. int t1;
  564. int t2;
  565. public AFace(){
  566. p0 = -1;
  567. p1 = -1;
  568. p2 = -1;
  569. t0 = 0;
  570. t1 = 0;
  571. t2 = 0;
  572. }
  573. }
  574. }