package eu.tankernn.gameEngine.loader.models.obj; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; import eu.tankernn.gameEngine.util.InternalFile; public class ObjLoader { public static ModelData loadOBJ(InternalFile objFile) { BufferedReader reader; try { reader = objFile.getReader(); } catch (Exception e1) { e1.printStackTrace(); return null; } String line; List vertices = new ArrayList(); List textures = new ArrayList(); List normals = new ArrayList(); List indices = new ArrayList(); try { while (true) { line = reader.readLine(); if (line.startsWith("v ")) { String[] currentLine = line.split(" "); Vector3f vertex = new Vector3f((float) Float.valueOf(currentLine[1]), (float) Float.valueOf(currentLine[2]), (float) Float.valueOf(currentLine[3])); Vertex newVertex = new Vertex(vertices.size(), vertex); vertices.add(newVertex); } else if (line.startsWith("vt ")) { String[] currentLine = line.split(" "); Vector2f texture = new Vector2f((float) Float.valueOf(currentLine[1]), (float) Float.valueOf(currentLine[2])); textures.add(texture); } else if (line.startsWith("vn ")) { String[] currentLine = line.split(" "); Vector3f normal = new Vector3f((float) Float.valueOf(currentLine[1]), (float) Float.valueOf(currentLine[2]), (float) Float.valueOf(currentLine[3])); normals.add(normal); } else if (line.startsWith("f ")) { break; } } while (line != null && line.startsWith("f ")) { String[] currentLine = line.split(" "); String[] vertex1 = currentLine[1].split("/"); String[] vertex2 = currentLine[2].split("/"); String[] vertex3 = currentLine[3].split("/"); Vertex v0 = processVertex(vertex1, vertices, indices); Vertex v1 = processVertex(vertex2, vertices, indices); Vertex v2 = processVertex(vertex3, vertices, indices); calculateTangents(v0, v1, v2, textures);//NEW line = reader.readLine(); } reader.close(); } catch (IOException e) { System.err.println("Error reading the file"); } removeUnusedVertices(vertices); float[] verticesArray = new float[vertices.size() * 3]; float[] texturesArray = new float[vertices.size() * 2]; float[] normalsArray = new float[vertices.size() * 3]; float[] tangentsArray = new float[vertices.size() * 3]; float furthest = convertDataToArrays(vertices, textures, normals, verticesArray, texturesArray, normalsArray, tangentsArray); int[] indicesArray = convertIndicesListToArray(indices); return new ModelData(verticesArray, texturesArray, normalsArray, tangentsArray, indicesArray, furthest); } //NEW private static void calculateTangents(Vertex v0, Vertex v1, Vertex v2, List textures) { Vector3f delatPos1 = Vector3f.sub(v1.getPosition(), v0.getPosition(), null); Vector3f delatPos2 = Vector3f.sub(v2.getPosition(), v0.getPosition(), null); Vector2f uv0 = textures.get(v0.getTextureIndex()); Vector2f uv1 = textures.get(v1.getTextureIndex()); Vector2f uv2 = textures.get(v2.getTextureIndex()); Vector2f deltaUv1 = Vector2f.sub(uv1, uv0, null); Vector2f deltaUv2 = Vector2f.sub(uv2, uv0, null); float r = 1.0f / (deltaUv1.x * deltaUv2.y - deltaUv1.y * deltaUv2.x); delatPos1.scale(deltaUv2.y); delatPos2.scale(deltaUv1.y); Vector3f tangent = Vector3f.sub(delatPos1, delatPos2, null); tangent.scale(r); v0.addTangent(tangent); v1.addTangent(tangent); v2.addTangent(tangent); } private static Vertex processVertex(String[] vertex, List vertices, List indices) { int index = Integer.parseInt(vertex[0]) - 1; Vertex currentVertex = vertices.get(index); int textureIndex = Integer.parseInt(vertex[1]) - 1; int normalIndex = Integer.parseInt(vertex[2]) - 1; if (!currentVertex.isSet()) { currentVertex.setTextureIndex(textureIndex); currentVertex.setNormalIndex(normalIndex); indices.add(index); return currentVertex; } else { return dealWithAlreadyProcessedVertex(currentVertex, textureIndex, normalIndex, indices, vertices); } } private static int[] convertIndicesListToArray(List indices) { int[] indicesArray = new int[indices.size()]; for (int i = 0; i < indicesArray.length; i++) { indicesArray[i] = indices.get(i); } return indicesArray; } private static float convertDataToArrays(List vertices, List textures, List normals, float[] verticesArray, float[] texturesArray, float[] normalsArray, float[] tangentsArray) { float furthestPoint = 0; for (int i = 0; i < vertices.size(); i++) { Vertex currentVertex = vertices.get(i); if (currentVertex.getLength() > furthestPoint) { furthestPoint = currentVertex.getLength(); } Vector3f position = currentVertex.getPosition(); Vector2f textureCoord = textures.get(currentVertex.getTextureIndex()); Vector3f normalVector = normals.get(currentVertex.getNormalIndex()); Vector3f tangent = currentVertex.getAverageTangent(); verticesArray[i * 3] = position.x; verticesArray[i * 3 + 1] = position.y; verticesArray[i * 3 + 2] = position.z; texturesArray[i * 2] = textureCoord.x; texturesArray[i * 2 + 1] = 1 - textureCoord.y; normalsArray[i * 3] = normalVector.x; normalsArray[i * 3 + 1] = normalVector.y; normalsArray[i * 3 + 2] = normalVector.z; tangentsArray[i * 3] = tangent.x; tangentsArray[i * 3 + 1] = tangent.y; tangentsArray[i * 3 + 2] = tangent.z; } return furthestPoint; } private static Vertex dealWithAlreadyProcessedVertex(Vertex previousVertex, int newTextureIndex, int newNormalIndex, List indices, List vertices) { if (previousVertex.hasSameTextureAndNormal(newTextureIndex, newNormalIndex)) { indices.add(previousVertex.getIndex()); return previousVertex; } else { Vertex anotherVertex = previousVertex.getDuplicateVertex(); if (anotherVertex != null) { return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex, indices, vertices); } else { Vertex duplicateVertex = previousVertex.duplicate(vertices.size());//NEW duplicateVertex.setTextureIndex(newTextureIndex); duplicateVertex.setNormalIndex(newNormalIndex); previousVertex.setDuplicateVertex(duplicateVertex); vertices.add(duplicateVertex); indices.add(duplicateVertex.getIndex()); return duplicateVertex; } } } private static void removeUnusedVertices(List vertices) { for (Vertex vertex : vertices) { vertex.averageTangents(); if (!vertex.isSet()) { vertex.setTextureIndex(0); vertex.setNormalIndex(0); } } } }