Advertisement
Guest User

Untitled

a guest
Jul 3rd, 2012
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.17 KB | None | 0 0
  1. package de.finalspace.engine.geometry;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.File;
  5. import java.io.FileNotFoundException;
  6. import java.io.FileReader;
  7. import java.util.ArrayList;
  8. import java.util.Collection;
  9. import java.util.HashSet;
  10. import java.util.List;
  11. import java.util.Set;
  12.  
  13. import de.finalspace.engine.utils.PathUtils;
  14. import de.finalspace.engine.utils.Vector3f;
  15. import de.finalspace.engine.utils.Vector4f;
  16.  
  17. public class OBJLoader {
  18.     public OBJLoader() {
  19.  
  20.     }
  21.  
  22.     public enum OBJObjectType {
  23.         None, Object, Group,
  24.     }
  25.  
  26.     public class OBJFaceIndex {
  27.         public Integer vertex;
  28.         public Integer texcoord;
  29.         public Integer normal;
  30.  
  31.         public OBJFaceIndex() {
  32.             vertex = null;
  33.             texcoord = null;
  34.             normal = null;
  35.         }
  36.  
  37.         public OBJFaceIndex(final OBJFaceIndex fi) {
  38.             vertex = fi.vertex;
  39.             texcoord = fi.texcoord;
  40.             normal = fi.normal;
  41.         }
  42.     }
  43.  
  44.     public class OBJTriangle {
  45.         private final OBJFaceIndex[] index;
  46.  
  47.         public OBJTriangle(final OBJFaceIndex index0,
  48.                 final OBJFaceIndex index1, final OBJFaceIndex index2) {
  49.             this.index = new OBJFaceIndex[3];
  50.             this.index[0] = index0;
  51.             this.index[1] = index1;
  52.             this.index[2] = index2;
  53.         }
  54.  
  55.         public OBJFaceIndex get(int i) {
  56.             return index[i];
  57.         }
  58.     }
  59.  
  60.     public class OBJFace {
  61.         private List<OBJFaceIndex> indices;
  62.         private final String materialName;
  63.  
  64.         public OBJFace(final String materialName) {
  65.             this.indices = new ArrayList<OBJFaceIndex>();
  66.             this.materialName = materialName;
  67.         }
  68.  
  69.         public void add(final OBJFaceIndex fi) {
  70.             indices.add(fi);
  71.         }
  72.  
  73.         public Collection<OBJFaceIndex> getIndices() {
  74.             return indices;
  75.         }
  76.  
  77.         public String getMaterialName() {
  78.             return materialName;
  79.         }
  80.  
  81.         public OBJTriangle[] createTriangles() {
  82.             // Create triangles from face
  83.             List<OBJTriangle> triangles = new ArrayList<OBJTriangle>();
  84.             OBJFaceIndex[] vertexindices = new OBJFaceIndex[3];
  85.             int i = 0;
  86.             for (OBJFaceIndex index : indices) {
  87.                 vertexindices[2] = new OBJFaceIndex(index);
  88.                 if (i >= 2) {
  89.                     triangles.add(new OBJTriangle(new OBJFaceIndex(
  90.                             vertexindices[0]), new OBJFaceIndex(
  91.                             vertexindices[1]), new OBJFaceIndex(
  92.                             vertexindices[2])));
  93.                 }
  94.                 if (i == 0) {
  95.                     vertexindices[0] = new OBJFaceIndex(vertexindices[2]);
  96.                 } else {
  97.                     vertexindices[1] = new OBJFaceIndex(vertexindices[2]);
  98.                 }
  99.                 i++;
  100.             }
  101.             return triangles.toArray(new OBJTriangle[] {});
  102.         }
  103.     }
  104.  
  105.     public class OBJObject {
  106.         private final OBJObjectType type;
  107.         private List<OBJFace> faces;
  108.         private final String name;
  109.  
  110.         public OBJObject(final OBJObjectType type, final String name) {
  111.             this.type = type;
  112.             this.name = name;
  113.             this.faces = new ArrayList<OBJFace>();
  114.         }
  115.  
  116.         public OBJObjectType getType() {
  117.             return type;
  118.         }
  119.  
  120.         public void addFace(final OBJFace face) {
  121.             this.faces.add(face);
  122.         }
  123.  
  124.         public Collection<OBJFace> getFaces() {
  125.             return faces;
  126.         }
  127.  
  128.         public String getName() {
  129.             return name;
  130.         }
  131.     }
  132.  
  133.     public class MaterialLibrary {
  134.  
  135.     }
  136.  
  137.     private String[] parseLine(final String line) {
  138.         String[] a = line.split(" ");
  139.         List<String> o = new ArrayList<String>();
  140.         for (String s : a) {
  141.             if (!s.isEmpty()) {
  142.                 o.add(s);
  143.             }
  144.         }
  145.         return o.toArray(new String[] {});
  146.     }
  147.  
  148.     private Vector4f getVector4(final String[] params, final int minParams) {
  149.         if (params.length >= 1 + minParams) {
  150.             String x = params.length >= 2 ? params[1] : "0.0";
  151.             String y = params.length >= 3 ? params[2] : "0.0";
  152.             String z = params.length >= 4 ? params[3] : "0.0";
  153.             String w = params.length >= 5 ? params[4] : "1.0";
  154.             return Vector4f.fromStr(x, y, z, w);
  155.         } else {
  156.             return null;
  157.         }
  158.     }
  159.  
  160.     private Vector3f getVector3(final String[] params, final int minParams) {
  161.         if (params.length >= 1 + minParams) {
  162.             String x = params.length >= 2 ? params[1] : "0.0";
  163.             String y = params.length >= 3 ? params[2] : "0.0";
  164.             String z = params.length >= 4 ? params[3] : "0.0";
  165.             return Vector3f.fromStr(x, y, z);
  166.         } else {
  167.             return null;
  168.         }
  169.     }
  170.  
  171.     /**
  172.      * <p>
  173.      * Returns index coordinate started by 0 for the given index
  174.      * </p>
  175.      *
  176.      * @param value
  177.      * @param start
  178.      * @return
  179.      */
  180.     private int calcIndex(final int value, final int start) {
  181.         if (value < 0) {
  182.             // Relative
  183.             return start + value;
  184.         } else {
  185.             // Absolute
  186.             return value - 1;
  187.         }
  188.     }
  189.  
  190.     public Mesh load(final String modelPath, final String modelName)
  191.             throws Exception {
  192.  
  193.         Mesh mesh = new Mesh();
  194.  
  195.         String objFilename = PathUtils.combine(modelPath, modelName + ".obj");
  196.         List<String> materialLibs = new ArrayList<String>();
  197.  
  198.         // Obj file must exists
  199.         File objFile = new File(objFilename);
  200.         if (!objFile.exists()) {
  201.             throw new FileNotFoundException(objFilename);
  202.         }
  203.  
  204.         List<Vector4f> vertices = new ArrayList<Vector4f>();
  205.         List<Vector3f> texcoords = new ArrayList<Vector3f>();
  206.         List<Vector3f> normals = new ArrayList<Vector3f>();
  207.         List<Vector3f> parameterSpaceVertices = new ArrayList<Vector3f>();
  208.         List<OBJObject> objects = new ArrayList<OBJObject>();
  209.  
  210.         String currentMaterialName = null;
  211.         OBJObject currentEntity = null;
  212.  
  213.         Set<String> unsupported = new HashSet<String>();
  214.  
  215.         int vertexCnt = 0;
  216.         int texcoordCnt = 0;
  217.         int normalCnt = 0;
  218.  
  219.         int lineCounter = 0;
  220.         BufferedReader reader = new BufferedReader(new FileReader(objFile));
  221.         String line = null;
  222.         while ((line = reader.readLine()) != null) {
  223.             lineCounter++;
  224.             // Skip comments
  225.             if (line.startsWith("#"))
  226.                 continue;
  227.             // Skip empty lines
  228.             if (line.isEmpty())
  229.                 continue;
  230.             // Parse line params
  231.             String[] params = parseLine(line);
  232.  
  233.             // Get material name
  234.             if (params.length > 0) {
  235.                 String identifier = params[0];
  236.                 if ("mtllib".equalsIgnoreCase(identifier) && params.length >= 2) {
  237.                     materialLibs.add(params[1]);
  238.                 } else if ("v".equalsIgnoreCase(identifier)) {
  239.                     Vector4f pos = getVector4(params, 3);
  240.                     vertices.add(pos);
  241.                     vertexCnt++;
  242.                 } else if ("vt".equalsIgnoreCase(identifier)) {
  243.                     Vector3f texcoord = getVector3(params, 1);
  244.                     texcoords.add(texcoord);
  245.                     texcoordCnt++;
  246.                 } else if ("vn".equalsIgnoreCase(identifier)) {
  247.                     Vector3f normal = getVector3(params, 3);
  248.                     normals.add(normal);
  249.                     normalCnt++;
  250.                 } else if ("vp".equalsIgnoreCase(identifier)) {
  251.                     Vector3f paramSpaceVertice = getVector3(params, 1);
  252.                     parameterSpaceVertices.add(paramSpaceVertice);
  253.                 } else if ("o".equalsIgnoreCase(identifier)
  254.                         && params.length >= 2) {
  255.                     // Named object
  256.                     currentEntity = new OBJObject(OBJObjectType.Object,
  257.                             params[1]);
  258.                     objects.add(currentEntity);
  259.                 } else if ("g".equalsIgnoreCase(identifier)
  260.                         && params.length >= 2) {
  261.                     // Group object
  262.                     currentEntity = new OBJObject(OBJObjectType.Group,
  263.                             params[1]);
  264.                     objects.add(currentEntity);
  265.                 } else if ("usemtl".equalsIgnoreCase(identifier)
  266.                         && params.length >= 2) {
  267.                     currentMaterialName = params[1];
  268.                 } else if ("f".equalsIgnoreCase(identifier)) {
  269.                     if (currentEntity == null) {
  270.                         throw new Exception("No entity for face on line: "
  271.                                 + lineCounter);
  272.                     }
  273.                     if (params.length < 4) {
  274.                         throw new Exception(
  275.                                 "Face contains insufficient indices on line: "
  276.                                         + lineCounter);
  277.                     }
  278.                     OBJFace face = new OBJFace(currentMaterialName);
  279.                     currentEntity.addFace(face);
  280.  
  281.                     for (int i = 1; i < params.length; i++) {
  282.  
  283.                         String[] indicesStr = params[i].split("\\/");
  284.                         if (indicesStr.length > 0) {
  285.                             OBJFaceIndex faceIndex = new OBJFaceIndex();
  286.                             if (indicesStr.length == 1) {
  287.                                 // Vertex only
  288.                                 faceIndex.vertex = calcIndex(
  289.                                         Integer.parseInt(indicesStr[0]),
  290.                                         vertexCnt);
  291.                             } else if (indicesStr.length == 2) {
  292.                                 // Vertex/Texcoord only
  293.                                 faceIndex.vertex = calcIndex(
  294.                                         Integer.parseInt(indicesStr[0]),
  295.                                         vertexCnt);
  296.                                 faceIndex.texcoord = calcIndex(
  297.                                         Integer.parseInt(indicesStr[1]),
  298.                                         texcoordCnt);
  299.                             } else if (indicesStr.length == 3) {
  300.                                 // Vertex/Texcoord/Normal (Texcoord may be
  301.                                 // optional
  302.                                 // - empty)
  303.                                 faceIndex.vertex = calcIndex(
  304.                                         Integer.parseInt(indicesStr[0]),
  305.                                         vertexCnt);
  306.                                 faceIndex.texcoord = !indicesStr[1].isEmpty() ? calcIndex(
  307.                                         Integer.parseInt(indicesStr[1]),
  308.                                         texcoordCnt) : -1;
  309.                                 faceIndex.normal = calcIndex(
  310.                                         Integer.parseInt(indicesStr[2]),
  311.                                         normalCnt);
  312.                             }
  313.                             face.add(faceIndex);
  314.                         } else {
  315.                             throw new Exception(
  316.                                     "No face indices found on line: "
  317.                                             + lineCounter);
  318.                         }
  319.                     }
  320.  
  321.                 } else {
  322.                     if (!unsupported.contains(identifier)) {
  323.                         unsupported.add(identifier);
  324.                     }
  325.                 }
  326.             }
  327.         }
  328.  
  329.         for (String s : unsupported) {
  330.             System.out.println("[OBJ:Warning] Unsupported identifier: " + s);
  331.         }
  332.  
  333.         System.out.println("[OBJ] " + objFilename);
  334.         System.out.println("[OBJ] " + vertexCnt + " vertices, " + texcoordCnt
  335.                 + " texcoords, " + normalCnt + " normals");
  336.         System.out.println("[OBJ] " + parameterSpaceVertices.size()
  337.                 + " parameter space vertices");
  338.         System.out.println("[OBJ] " + materialLibs.size()
  339.                 + " material libraries");
  340.         for (String s : materialLibs) {
  341.             System.out.println("[OBJ] " + "  " + s);
  342.         }
  343.         System.out.println("[OBJ] " + objects.size() + " objects");
  344.  
  345.         int faceCnt = 0;
  346.         for (OBJObject e : objects) {
  347.             faceCnt += e.getFaces().size();
  348.         }
  349.         System.out.println("[OBJ] " + faceCnt + " total faces");
  350.  
  351.         int indexCnt = 0;
  352.         for (OBJObject e : objects) {
  353.             for (OBJFace f : e.getFaces()) {
  354.                 indexCnt += f.getIndices().size();
  355.             }
  356.         }
  357.         System.out.println("[OBJ] " + indexCnt + " total indices");
  358.        
  359.         // Create mesh from loaded data
  360.         int tmp = 0;
  361.         int vertexIndex = 0;
  362.         for (OBJObject e : objects) {
  363.             for (OBJFace f : e.getFaces()) {
  364.                 OBJTriangle[] faceTriangles = f.createTriangles();
  365.  
  366.                 Face nface = new Face(vertexIndex, faceTriangles.length * 3);
  367.                 mesh.addFace(nface);
  368.  
  369.                 for (OBJTriangle triangle : faceTriangles) {
  370.                     Vector4f color = new Vector4f((float) Math.random(),
  371.                             (float) Math.random(), (float) Math.random(), 1.0f);
  372.                     for (int i = 0; i < 3; i++) {
  373.                         OBJFaceIndex faceIndex = triangle.get(i);
  374.                         Vertex nvertex = new Vertex();
  375.                         nvertex.pos = vertices.get(faceIndex.vertex); // Pos
  376.                                                                         // must
  377.                                                                         // always
  378.                                                                         // be
  379.                                                                         // exists
  380.                         nvertex.texcoord = faceIndex.texcoord != null ? texcoords
  381.                                 .get(faceIndex.texcoord) : new Vector3f();
  382.                         nvertex.normal = faceIndex.normal != null ? normals
  383.                                 .get(faceIndex.normal) : new Vector3f();
  384.                         nvertex.color = new Vector4f(color);
  385.                         int vindex = mesh.addVertex(nvertex, false);
  386.                         mesh.addIndex(vindex);
  387.                        
  388.                         vertexIndex++;
  389.                         tmp++;
  390.                        
  391.                         if (tmp > 10000) {
  392.                             System.out.println(vertexIndex);
  393.                             tmp = 0;
  394.                         }
  395.                     }
  396.                 }
  397.             }
  398.         }
  399.  
  400.         System.out.println("[MESH] " + mesh.getVertices().size() + " vertices");
  401.         System.out.println("[MESH] " + mesh.getIndices().size() + " indices");
  402.         System.out.println("[MESH] " + mesh.getFaces().size() + " faces");
  403.  
  404.         return mesh;
  405.     }
  406. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement