1 /* 2 Copyright (c) 2017-2018 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.graphics.mesh; 29 30 import dlib.core.memory; 31 import dlib.geometry.triangle; 32 import dlib.math.vector; 33 import derelict.opengl; 34 import dagon.core.interfaces; 35 import dagon.core.ownership; 36 37 enum VertexAttrib 38 { 39 Vertices = 0, 40 Normals = 1, 41 Texcoords = 2 42 } 43 44 class Mesh: Owner, Drawable 45 { 46 bool dataReady = false; 47 bool canRender = false; 48 49 // TODO: make these DynamicArrays 50 Vector3f[] vertices; 51 Vector3f[] normals; 52 Vector2f[] texcoords; 53 uint[3][] indices; 54 55 GLuint vao = 0; 56 GLuint vbo = 0; 57 GLuint nbo = 0; 58 GLuint tbo = 0; 59 GLuint eao = 0; 60 61 this(Owner o) 62 { 63 super(o); 64 } 65 66 ~this() 67 { 68 if (vertices.length) Delete(vertices); 69 if (normals.length) Delete(normals); 70 if (texcoords.length) Delete(texcoords); 71 if (indices.length) Delete(indices); 72 73 if (canRender) 74 { 75 glDeleteVertexArrays(1, &vao); 76 glDeleteBuffers(1, &vbo); 77 glDeleteBuffers(1, &nbo); 78 glDeleteBuffers(1, &tbo); 79 glDeleteBuffers(1, &eao); 80 } 81 } 82 83 int opApply(scope int delegate(Triangle t) dg) 84 { 85 int result = 0; 86 87 foreach(i, ref f; indices) 88 { 89 Triangle tri; 90 91 tri.v[0] = vertices[f[0]]; 92 tri.v[1] = vertices[f[1]]; 93 tri.v[2] = vertices[f[2]]; 94 tri.n[0] = normals[f[0]]; 95 tri.n[1] = normals[f[1]]; 96 tri.n[2] = normals[f[2]]; 97 tri.t1[0] = texcoords[f[0]]; 98 tri.t1[1] = texcoords[f[1]]; 99 tri.t1[2] = texcoords[f[2]]; 100 tri.normal = (tri.n[0] + tri.n[1] + tri.n[2]) / 3.0f; 101 102 result = dg(tri); 103 if (result) 104 break; 105 } 106 107 return result; 108 } 109 110 void prepareVAO() 111 { 112 if (!dataReady) 113 return; 114 115 glGenBuffers(1, &vbo); 116 glBindBuffer(GL_ARRAY_BUFFER, vbo); 117 glBufferData(GL_ARRAY_BUFFER, vertices.length * float.sizeof * 3, vertices.ptr, GL_STATIC_DRAW); 118 119 glGenBuffers(1, &nbo); 120 glBindBuffer(GL_ARRAY_BUFFER, nbo); 121 glBufferData(GL_ARRAY_BUFFER, normals.length * float.sizeof * 3, normals.ptr, GL_STATIC_DRAW); 122 123 glGenBuffers(1, &tbo); 124 glBindBuffer(GL_ARRAY_BUFFER, tbo); 125 glBufferData(GL_ARRAY_BUFFER, texcoords.length * float.sizeof * 2, texcoords.ptr, GL_STATIC_DRAW); 126 127 glGenBuffers(1, &eao); 128 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); 129 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length * uint.sizeof * 3, indices.ptr, GL_STATIC_DRAW); 130 131 glGenVertexArrays(1, &vao); 132 glBindVertexArray(vao); 133 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); 134 135 glEnableVertexAttribArray(VertexAttrib.Vertices); 136 glBindBuffer(GL_ARRAY_BUFFER, vbo); 137 glVertexAttribPointer(VertexAttrib.Vertices, 3, GL_FLOAT, GL_FALSE, 0, null); 138 139 glEnableVertexAttribArray(VertexAttrib.Normals); 140 glBindBuffer(GL_ARRAY_BUFFER, nbo); 141 glVertexAttribPointer(VertexAttrib.Normals, 3, GL_FLOAT, GL_FALSE, 0, null); 142 143 glEnableVertexAttribArray(VertexAttrib.Texcoords); 144 glBindBuffer(GL_ARRAY_BUFFER, tbo); 145 glVertexAttribPointer(VertexAttrib.Texcoords, 2, GL_FLOAT, GL_FALSE, 0, null); 146 147 //glBindBuffer(GL_ARRAY_BUFFER, 0); 148 //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 149 150 glBindVertexArray(0); 151 152 canRender = true; 153 } 154 155 void update(double dt) 156 { 157 } 158 159 void render(RenderingContext* rc) 160 { 161 if (canRender) 162 { 163 glBindVertexArray(vao); 164 glDrawElements(GL_TRIANGLES, cast(uint)indices.length * 3, GL_UNSIGNED_INT, cast(void*)0); 165 glBindVertexArray(0); 166 } 167 } 168 } 169