1 /** 2 * Retrograde Engine 3 * 4 * Authors: 5 * Mike Bierlee, m.bierlee@lostmoment.com 6 * Copyright: 2014-2021 Mike Bierlee 7 * License: 8 * This software is licensed under the terms of the MIT license. 9 * The full terms of the license can be found in the LICENSE.txt file. 10 */ 11 12 module retrograde.graphics.threedee.opengl.model; 13 14 version(Have_derelict_gl3) { 15 16 import retrograde.model; 17 import retrograde.graphics.threedee.opengl.rendering; 18 import retrograde.geometry; 19 20 import derelict.opengl3.gl3; 21 22 class OpenGlMesh { 23 public immutable Mesh mesh; 24 public GLuint vertexArrayObject; 25 public GLuint vertexBufferObject; 26 27 this(immutable Mesh mesh) { 28 this.mesh = mesh; 29 } 30 } 31 32 class OpenGlModel : Model { 33 34 private OpenGlMesh[] meshes; 35 private bool loaded; 36 37 this(immutable Mesh[] meshes) { 38 foreach (mesh ; meshes) { 39 this.meshes ~= new OpenGlMesh(mesh); 40 } 41 } 42 43 public override void loadIntoVram() { 44 if (isLoadedIntoVram()) { 45 throw new ModelLoadException("Cannot load OpenGL model into VRAM: Model has been previously loaded already. Unload model with unloadFromVram first."); 46 } 47 48 foreach (openGlMesh ; meshes) { 49 // TODO: Optimize: load as actual vertex-face data if possible 50 uint totalVertices = openGlMesh.mesh.faces.length * 3; 51 Vertex[] vertexData = []; 52 foreach(face; openGlMesh.mesh.faces) { 53 vertexData ~= openGlMesh.mesh.vertices[face.vertexIndex1]; 54 vertexData ~= openGlMesh.mesh.vertices[face.vertexIndex2]; 55 vertexData ~= openGlMesh.mesh.vertices[face.vertexIndex3]; 56 } 57 58 GLuint vertexArrayObject; 59 GLuint vertexBufferObject; 60 61 glCreateVertexArrays(1, &vertexArrayObject); 62 glCreateBuffers(1, &vertexBufferObject); 63 64 uint verticesByteSize = Vertex.sizeof * vertexData.length; 65 glNamedBufferStorage(vertexBufferObject, verticesByteSize, vertexData.ptr, 0); 66 67 glVertexArrayAttribBinding(vertexArrayObject, 0, 0); 68 glVertexArrayAttribFormat(vertexArrayObject, 0, 4, GL_FLOAT, GL_FALSE, Vertex.x.offsetof); 69 glEnableVertexArrayAttrib(vertexArrayObject, 0); 70 71 glVertexArrayAttribBinding(vertexArrayObject, 1, 0); 72 glVertexArrayAttribFormat(vertexArrayObject, 1, 4, GL_FLOAT, GL_FALSE, Vertex.r.offsetof); 73 glEnableVertexArrayAttrib(vertexArrayObject, 1); 74 75 glVertexArrayAttribBinding(vertexArrayObject, 2, 0); 76 glVertexArrayAttribFormat(vertexArrayObject, 2, 2, GL_FLOAT, GL_FALSE, Vertex.u.offsetof); 77 glEnableVertexArrayAttrib(vertexArrayObject, 2); 78 79 glVertexArrayVertexBuffer(vertexArrayObject, 0, vertexBufferObject, 0, Vertex.sizeof); 80 81 openGlMesh.vertexArrayObject = vertexArrayObject; 82 openGlMesh.vertexBufferObject = vertexBufferObject; 83 } 84 85 loaded = true; 86 } 87 88 public override void unloadFromVram() { 89 foreach (openGlMesh ; meshes) { 90 glDeleteVertexArrays(1, &openGlMesh.vertexArrayObject); 91 glDeleteBuffers(1, &openGlMesh.vertexBufferObject); 92 openGlMesh.vertexArrayObject = 0; 93 openGlMesh.vertexBufferObject = 0; 94 } 95 96 loaded = false; 97 } 98 99 public override bool isLoadedIntoVram() { 100 return loaded; 101 } 102 103 public override void draw() { 104 foreach (openGlMesh ; meshes) { 105 glBindVertexArray(openGlMesh.vertexArrayObject); 106 glDrawArrays(GL_TRIANGLES, 0, openGlMesh.mesh.faces.length * 3); 107 glBindVertexArray(0); 108 } 109 } 110 111 } 112 113 }