Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package de.finalspace.engine.geometry;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Set;
- import de.finalspace.engine.utils.PathUtils;
- import de.finalspace.engine.utils.Vector3f;
- import de.finalspace.engine.utils.Vector4f;
- public class OBJLoader {
- public OBJLoader() {
- }
- public enum OBJObjectType {
- None, Object, Group,
- }
- public class OBJFaceIndex {
- public Integer vertex;
- public Integer texcoord;
- public Integer normal;
- public OBJFaceIndex() {
- vertex = null;
- texcoord = null;
- normal = null;
- }
- public OBJFaceIndex(final OBJFaceIndex fi) {
- vertex = fi.vertex;
- texcoord = fi.texcoord;
- normal = fi.normal;
- }
- }
- public class OBJTriangle {
- private final OBJFaceIndex[] index;
- public OBJTriangle(final OBJFaceIndex index0,
- final OBJFaceIndex index1, final OBJFaceIndex index2) {
- this.index = new OBJFaceIndex[3];
- this.index[0] = index0;
- this.index[1] = index1;
- this.index[2] = index2;
- }
- public OBJFaceIndex get(int i) {
- return index[i];
- }
- }
- public class OBJFace {
- private List<OBJFaceIndex> indices;
- private final String materialName;
- public OBJFace(final String materialName) {
- this.indices = new ArrayList<OBJFaceIndex>();
- this.materialName = materialName;
- }
- public void add(final OBJFaceIndex fi) {
- indices.add(fi);
- }
- public Collection<OBJFaceIndex> getIndices() {
- return indices;
- }
- public String getMaterialName() {
- return materialName;
- }
- public OBJTriangle[] createTriangles() {
- // Create triangles from face
- List<OBJTriangle> triangles = new ArrayList<OBJTriangle>();
- OBJFaceIndex[] vertexindices = new OBJFaceIndex[3];
- int i = 0;
- for (OBJFaceIndex index : indices) {
- vertexindices[2] = new OBJFaceIndex(index);
- if (i >= 2) {
- triangles.add(new OBJTriangle(new OBJFaceIndex(
- vertexindices[0]), new OBJFaceIndex(
- vertexindices[1]), new OBJFaceIndex(
- vertexindices[2])));
- }
- if (i == 0) {
- vertexindices[0] = new OBJFaceIndex(vertexindices[2]);
- } else {
- vertexindices[1] = new OBJFaceIndex(vertexindices[2]);
- }
- i++;
- }
- return triangles.toArray(new OBJTriangle[] {});
- }
- }
- public class OBJObject {
- private final OBJObjectType type;
- private List<OBJFace> faces;
- private final String name;
- public OBJObject(final OBJObjectType type, final String name) {
- this.type = type;
- this.name = name;
- this.faces = new ArrayList<OBJFace>();
- }
- public OBJObjectType getType() {
- return type;
- }
- public void addFace(final OBJFace face) {
- this.faces.add(face);
- }
- public Collection<OBJFace> getFaces() {
- return faces;
- }
- public String getName() {
- return name;
- }
- }
- public class MaterialLibrary {
- }
- private String[] parseLine(final String line) {
- String[] a = line.split(" ");
- List<String> o = new ArrayList<String>();
- for (String s : a) {
- if (!s.isEmpty()) {
- o.add(s);
- }
- }
- return o.toArray(new String[] {});
- }
- private Vector4f getVector4(final String[] params, final int minParams) {
- if (params.length >= 1 + minParams) {
- String x = params.length >= 2 ? params[1] : "0.0";
- String y = params.length >= 3 ? params[2] : "0.0";
- String z = params.length >= 4 ? params[3] : "0.0";
- String w = params.length >= 5 ? params[4] : "1.0";
- return Vector4f.fromStr(x, y, z, w);
- } else {
- return null;
- }
- }
- private Vector3f getVector3(final String[] params, final int minParams) {
- if (params.length >= 1 + minParams) {
- String x = params.length >= 2 ? params[1] : "0.0";
- String y = params.length >= 3 ? params[2] : "0.0";
- String z = params.length >= 4 ? params[3] : "0.0";
- return Vector3f.fromStr(x, y, z);
- } else {
- return null;
- }
- }
- /**
- * <p>
- * Returns index coordinate started by 0 for the given index
- * </p>
- *
- * @param value
- * @param start
- * @return
- */
- private int calcIndex(final int value, final int start) {
- if (value < 0) {
- // Relative
- return start + value;
- } else {
- // Absolute
- return value - 1;
- }
- }
- public Mesh load(final String modelPath, final String modelName)
- throws Exception {
- Mesh mesh = new Mesh();
- String objFilename = PathUtils.combine(modelPath, modelName + ".obj");
- List<String> materialLibs = new ArrayList<String>();
- // Obj file must exists
- File objFile = new File(objFilename);
- if (!objFile.exists()) {
- throw new FileNotFoundException(objFilename);
- }
- List<Vector4f> vertices = new ArrayList<Vector4f>();
- List<Vector3f> texcoords = new ArrayList<Vector3f>();
- List<Vector3f> normals = new ArrayList<Vector3f>();
- List<Vector3f> parameterSpaceVertices = new ArrayList<Vector3f>();
- List<OBJObject> objects = new ArrayList<OBJObject>();
- String currentMaterialName = null;
- OBJObject currentEntity = null;
- Set<String> unsupported = new HashSet<String>();
- int vertexCnt = 0;
- int texcoordCnt = 0;
- int normalCnt = 0;
- int lineCounter = 0;
- BufferedReader reader = new BufferedReader(new FileReader(objFile));
- String line = null;
- while ((line = reader.readLine()) != null) {
- lineCounter++;
- // Skip comments
- if (line.startsWith("#"))
- continue;
- // Skip empty lines
- if (line.isEmpty())
- continue;
- // Parse line params
- String[] params = parseLine(line);
- // Get material name
- if (params.length > 0) {
- String identifier = params[0];
- if ("mtllib".equalsIgnoreCase(identifier) && params.length >= 2) {
- materialLibs.add(params[1]);
- } else if ("v".equalsIgnoreCase(identifier)) {
- Vector4f pos = getVector4(params, 3);
- vertices.add(pos);
- vertexCnt++;
- } else if ("vt".equalsIgnoreCase(identifier)) {
- Vector3f texcoord = getVector3(params, 1);
- texcoords.add(texcoord);
- texcoordCnt++;
- } else if ("vn".equalsIgnoreCase(identifier)) {
- Vector3f normal = getVector3(params, 3);
- normals.add(normal);
- normalCnt++;
- } else if ("vp".equalsIgnoreCase(identifier)) {
- Vector3f paramSpaceVertice = getVector3(params, 1);
- parameterSpaceVertices.add(paramSpaceVertice);
- } else if ("o".equalsIgnoreCase(identifier)
- && params.length >= 2) {
- // Named object
- currentEntity = new OBJObject(OBJObjectType.Object,
- params[1]);
- objects.add(currentEntity);
- } else if ("g".equalsIgnoreCase(identifier)
- && params.length >= 2) {
- // Group object
- currentEntity = new OBJObject(OBJObjectType.Group,
- params[1]);
- objects.add(currentEntity);
- } else if ("usemtl".equalsIgnoreCase(identifier)
- && params.length >= 2) {
- currentMaterialName = params[1];
- } else if ("f".equalsIgnoreCase(identifier)) {
- if (currentEntity == null) {
- throw new Exception("No entity for face on line: "
- + lineCounter);
- }
- if (params.length < 4) {
- throw new Exception(
- "Face contains insufficient indices on line: "
- + lineCounter);
- }
- OBJFace face = new OBJFace(currentMaterialName);
- currentEntity.addFace(face);
- for (int i = 1; i < params.length; i++) {
- String[] indicesStr = params[i].split("\\/");
- if (indicesStr.length > 0) {
- OBJFaceIndex faceIndex = new OBJFaceIndex();
- if (indicesStr.length == 1) {
- // Vertex only
- faceIndex.vertex = calcIndex(
- Integer.parseInt(indicesStr[0]),
- vertexCnt);
- } else if (indicesStr.length == 2) {
- // Vertex/Texcoord only
- faceIndex.vertex = calcIndex(
- Integer.parseInt(indicesStr[0]),
- vertexCnt);
- faceIndex.texcoord = calcIndex(
- Integer.parseInt(indicesStr[1]),
- texcoordCnt);
- } else if (indicesStr.length == 3) {
- // Vertex/Texcoord/Normal (Texcoord may be
- // optional
- // - empty)
- faceIndex.vertex = calcIndex(
- Integer.parseInt(indicesStr[0]),
- vertexCnt);
- faceIndex.texcoord = !indicesStr[1].isEmpty() ? calcIndex(
- Integer.parseInt(indicesStr[1]),
- texcoordCnt) : -1;
- faceIndex.normal = calcIndex(
- Integer.parseInt(indicesStr[2]),
- normalCnt);
- }
- face.add(faceIndex);
- } else {
- throw new Exception(
- "No face indices found on line: "
- + lineCounter);
- }
- }
- } else {
- if (!unsupported.contains(identifier)) {
- unsupported.add(identifier);
- }
- }
- }
- }
- for (String s : unsupported) {
- System.out.println("[OBJ:Warning] Unsupported identifier: " + s);
- }
- System.out.println("[OBJ] " + objFilename);
- System.out.println("[OBJ] " + vertexCnt + " vertices, " + texcoordCnt
- + " texcoords, " + normalCnt + " normals");
- System.out.println("[OBJ] " + parameterSpaceVertices.size()
- + " parameter space vertices");
- System.out.println("[OBJ] " + materialLibs.size()
- + " material libraries");
- for (String s : materialLibs) {
- System.out.println("[OBJ] " + " " + s);
- }
- System.out.println("[OBJ] " + objects.size() + " objects");
- int faceCnt = 0;
- for (OBJObject e : objects) {
- faceCnt += e.getFaces().size();
- }
- System.out.println("[OBJ] " + faceCnt + " total faces");
- int indexCnt = 0;
- for (OBJObject e : objects) {
- for (OBJFace f : e.getFaces()) {
- indexCnt += f.getIndices().size();
- }
- }
- System.out.println("[OBJ] " + indexCnt + " total indices");
- // Create mesh from loaded data
- int tmp = 0;
- int vertexIndex = 0;
- for (OBJObject e : objects) {
- for (OBJFace f : e.getFaces()) {
- OBJTriangle[] faceTriangles = f.createTriangles();
- Face nface = new Face(vertexIndex, faceTriangles.length * 3);
- mesh.addFace(nface);
- for (OBJTriangle triangle : faceTriangles) {
- Vector4f color = new Vector4f((float) Math.random(),
- (float) Math.random(), (float) Math.random(), 1.0f);
- for (int i = 0; i < 3; i++) {
- OBJFaceIndex faceIndex = triangle.get(i);
- Vertex nvertex = new Vertex();
- nvertex.pos = vertices.get(faceIndex.vertex); // Pos
- // must
- // always
- // be
- // exists
- nvertex.texcoord = faceIndex.texcoord != null ? texcoords
- .get(faceIndex.texcoord) : new Vector3f();
- nvertex.normal = faceIndex.normal != null ? normals
- .get(faceIndex.normal) : new Vector3f();
- nvertex.color = new Vector4f(color);
- int vindex = mesh.addVertex(nvertex, false);
- mesh.addIndex(vindex);
- vertexIndex++;
- tmp++;
- if (tmp > 10000) {
- System.out.println(vertexIndex);
- tmp = 0;
- }
- }
- }
- }
- }
- System.out.println("[MESH] " + mesh.getVertices().size() + " vertices");
- System.out.println("[MESH] " + mesh.getIndices().size() + " indices");
- System.out.println("[MESH] " + mesh.getFaces().size() + " faces");
- return mesh;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement