diff --git a/app/build.gradle b/app/build.gradle index e3a8f95..dd7732b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,11 +26,13 @@ dependencies { implementation "org.lwjgl:lwjgl:$lwjgl_version" implementation "org.lwjgl:lwjgl-opengl:$lwjgl_version" implementation "org.lwjgl:lwjgl-glfw:$lwjgl_version" + implementation "org.lwjgl:lwjgl-assimp:$lwjgl_version" implementation "org.joml:joml:1.10.8" implementation "org.lwjgl:lwjgl::$lwjgl_natives" implementation "org.lwjgl:lwjgl-opengl::$lwjgl_natives" implementation "org.lwjgl:lwjgl-glfw::$lwjgl_natives" + implementation "org.lwjgl:lwjgl-assimp::$lwjgl_natives" } application { diff --git a/app/src/main/java/chess/view/DDDrender/ModelLoader.java b/app/src/main/java/chess/view/DDDrender/ModelLoader.java new file mode 100644 index 0000000..d77cf4c --- /dev/null +++ b/app/src/main/java/chess/view/DDDrender/ModelLoader.java @@ -0,0 +1,141 @@ +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), vertNumber); + positionVBO.AddVertexAttribPointer(VERTEX_POSITION_INDEX, VERTEX_SIZE, 0); + VertexBuffer textureVBO = new VertexBuffer(toFloatArray(positions), vertNumber); + textureVBO.AddVertexAttribPointer(VERTEX_UV_INDEX, UV_SIZE, 0); + VertexBuffer normalVBO = new VertexBuffer(toFloatArray(positions), vertNumber); + 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 List 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_ValidateDataStructure, + ""); + + List vertecies = new ArrayList<>(); + + processNode(scene.mRootNode(), scene, vertecies); + + MemoryUtil.memFree(data); + + return vertecies; + + } + +} diff --git a/app/src/main/java/chess/view/DDDrender/Window.java b/app/src/main/java/chess/view/DDDrender/Window.java index e2b8ff7..a1f6edd 100644 --- a/app/src/main/java/chess/view/DDDrender/Window.java +++ b/app/src/main/java/chess/view/DDDrender/Window.java @@ -5,6 +5,7 @@ import org.lwjgl.glfw.*; import org.lwjgl.opengl.*; import org.lwjgl.system.*; +import java.io.IOException; import java.nio.*; import static org.lwjgl.glfw.Callbacks.*; @@ -24,6 +25,11 @@ public class Window { public Window() { this.renderer = new Renderer(); this.cam = new Camera(); + try { + ModelLoader.loadModel("3d/bishop.glb"); + } catch (IOException e) { + e.printStackTrace(); + } } public static void main(String[] args) {