package chess.view.DDDrender; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.List; import java.util.stream.IntStream; import org.lwjgl.PointerBuffer; import org.lwjgl.assimp.AIFace.Buffer; import org.lwjgl.assimp.AIMesh; import org.lwjgl.assimp.AINode; import org.lwjgl.assimp.AIScene; import org.lwjgl.assimp.AIVector3D; import org.lwjgl.assimp.Assimp; import org.lwjgl.system.MemoryUtil; import chess.view.AssetManager; public class ModelLoader { private static final int VERTEX_SIZE = 3; private static final int UV_SIZE = 2; private static final int VERTEX_POSITION_INDEX = 0; private static final int VERTEX_UV_INDEX = 1; private static final int VERTEX_NORMAL_INDEX = 2; private static float[] toFloatArray(List list) { float[] result = new float[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i); } return result; } private static int[] toIntArray(List list) { int[] result = new int[list.size()]; for (int i = 0; i < list.size(); i++) { result[i] = list.get(i); } return result; } private static VertexArray processMesh(AIMesh mesh, AIScene scene) { List positions = new ArrayList<>(); List textureCoords = new ArrayList<>(); List normals = new ArrayList<>(); List indicies = new ArrayList<>(); Buffer faces = mesh.mFaces(); int faceNumber = mesh.mNumFaces(); for (int i = 0; i < faceNumber; i++) { int offset = indicies.size(); int numIndices = faces.get(i).mNumIndices(); IntBuffer faceIndicies = faces.get(i).mIndices(); // IntStream.of(faceIndicies.array()).forEach(indicies::add); for (int j = 0; j < faceIndicies.capacity(); j++) { indicies.add(faceIndicies.get(j)); } } int vertNumber = mesh.mNumVertices(); org.lwjgl.assimp.AIVector3D.Buffer vertecies = mesh.mVertices(); for (int i = 0; i < vertNumber; i++) { AIVector3D vertex = vertecies.get(i); positions.add(vertex.x()); positions.add(vertex.y()); positions.add(vertex.z()); } org.lwjgl.assimp.AIVector3D.Buffer vertexNormals = mesh.mNormals(); for (int i = 0; i < vertNumber; i++) { AIVector3D normal = vertexNormals.get(i); normals.add(normal.x()); normals.add(normal.y()); normals.add(normal.z()); } PointerBuffer vertexTexture = mesh.mTextureCoords(); for (int i = 0; i < vertNumber; i++) { // PointerBuffer buff = mesh.mTextureCoords(); // textureCoords.add(buff.get(i).x()); // textureCoords.add(buff.get(i).y()); } VertexBuffer positionVBO = new VertexBuffer(toFloatArray(positions), VERTEX_SIZE); positionVBO.AddVertexAttribPointer(VERTEX_POSITION_INDEX, VERTEX_SIZE, 0); VertexBuffer textureVBO = new VertexBuffer(toFloatArray(textureCoords), UV_SIZE); textureVBO.AddVertexAttribPointer(VERTEX_UV_INDEX, UV_SIZE, 0); VertexBuffer normalVBO = new VertexBuffer(toFloatArray(normals), VERTEX_SIZE); normalVBO.AddVertexAttribPointer(VERTEX_NORMAL_INDEX, VERTEX_SIZE, 0); VertexArray vao = new VertexArray(new ElementBuffer(toIntArray(indicies))); vao.Bind(); vao.BindVertexBuffer(positionVBO); vao.BindVertexBuffer(textureVBO); vao.BindVertexBuffer(normalVBO); vao.Unbind(); return vao; } private static void processNode(AINode node, AIScene scene, List meshes) { for (int i = 0; i < node.mNumChildren(); i++) { AINode child = AINode.create(node.mChildren().get(i)); processNode(child, scene, meshes); } for (int i = 0; i < node.mNumMeshes(); i++) { AIMesh mesh = AIMesh.create(scene.mMeshes().get(node.mMeshes().get(i))); meshes.add(processMesh(mesh, scene)); } } public static DDDModel loadModel(String filename) throws IOException { InputStream input = AssetManager.getResource(filename); byte[] buffer = input.readAllBytes(); ByteBuffer data = MemoryUtil.memCalloc(buffer.length); data.put(buffer); data.flip(); AIScene scene = Assimp.aiImportFileFromMemory( data, Assimp.aiProcess_Triangulate | Assimp.aiProcess_PreTransformVertices | Assimp.aiProcess_GlobalScale | Assimp.aiProcess_ValidateDataStructure, ""); if (scene == null) System.err.println(Assimp.aiGetErrorString()); List vertecies = new ArrayList<>(); processNode(scene.mRootNode(), scene, vertecies); MemoryUtil.memFree(data); return new DDDModel(vertecies); } }