package org.xfe.engine; import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.system.MemoryUtil; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStream; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL30.*; public class Mesh { public int vertex_count; public int vao_id; public int vbo_id; public int ebo_id; Float[] vertices; Float[] normals; Integer[] vertice_indices; Integer[] normal_indices; // Creates a new Mesh object from an wavefront .obj file public Mesh(String obj_file_path) { this.loadObj(obj_file_path); } public void loadObj(String file_path) { ArrayList temp_vertices = new ArrayList<>(); ArrayList temp_normals = new ArrayList<>(); ArrayList temp_vertice_indices = new ArrayList<>(); ArrayList temp_normal_indices = new ArrayList<>(); Scanner scanner; InputStream obj; String line; String[] face_data_temp; int[] face_data = new int[3]; int i; // Try to open the file try { obj = this.getClass().getResourceAsStream(file_path); scanner = new Scanner(obj); } catch (Exception e) { System.out.println("ERROR: OBJ File \"" + file_path + "\" not found."); e.printStackTrace(); return; } while (scanner.hasNextLine()) { line = scanner.nextLine(); String[] data = line.split(" "); switch (data[0]) { case "v": temp_vertices.add(Float.valueOf(data[1])); temp_vertices.add(Float.valueOf(data[2])); temp_vertices.add(Float.valueOf(data[3])); break; case "vn": temp_normals.add(Float.valueOf(data[1])); temp_normals.add(Float.valueOf(data[2])); temp_normals.add(Float.valueOf(data[3])); break; case "f": // Sample face data : "f 5//1 3//1 1//1" where each thing is v//normal_v for (i = 1; i < 4; i++) { face_data_temp = data[i].split("//"); temp_vertice_indices.add(Integer.parseInt(face_data_temp[0])); if (face_data_temp.length > 1) temp_normal_indices.add(Integer.parseInt(face_data_temp[1])); } break; } } this.vertices = temp_vertices.toArray(Float[]::new); this.normals = temp_normals.toArray(Float[]::new); this.vertice_indices = temp_vertice_indices.toArray(Integer[]::new); this.normal_indices = temp_normal_indices.toArray(Integer[]::new); // OBJ File has been read, setup openGL buffers init(); System.out.println(Arrays.toString(this.vertices)); } private void init() { FloatBuffer vertices_buffer = null; try { // Bind our vertices into the VBO vertices_buffer = MemoryUtil.memAllocFloat(this.vertices.length); vertex_count = this.vertices.length / 3; // Convert from our object list to the primitive float array vertices_buffer.put(ArrayUtils.toPrimitive(this.vertices)); this.vao_id = glGenVertexArrays(); glBindVertexArray(this.vao_id); this.vbo_id = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, this.vbo_id); glBufferData(GL_ARRAY_BUFFER, vertices_buffer, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); // Bind indices in EBO if (this.vertice_indices.length > 0) { // TODO : @0x01fe probably should free this (memory leaks are like bad or smthng) IntBuffer indice_buffer = MemoryUtil.memAllocInt(vertice_indices.length); indice_buffer.put(ArrayUtils.toPrimitive(vertice_indices)); ebo_id = glGenBuffers(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_id); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indice_buffer, GL_STATIC_DRAW); } glBindBuffer(GL_ARRAY_BUFFER, 0); } finally { if (vertices_buffer != null) { MemoryUtil.memFree(vertices_buffer); } } } public void cleanUp() { glDisableVertexAttribArray(0); // Delete the VBO glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(this.vbo_id); // Delete the VAO glBindVertexArray(0); glDeleteVertexArrays(this.vao_id); } }