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 34 import dagon.core.libs; 35 import dagon.core.interfaces; 36 import dagon.core.ownership; 37 38 enum VertexAttrib 39 { 40 Vertices = 0, 41 Normals = 1, 42 Texcoords = 2 43 } 44 45 class Mesh: Owner, Drawable 46 { 47 bool dataReady = false; 48 bool canRender = false; 49 50 // TODO: make these DynamicArrays 51 Vector3f[] vertices; 52 Vector3f[] normals; 53 Vector2f[] texcoords; 54 uint[3][] indices; 55 56 GLuint vao = 0; 57 GLuint vbo = 0; 58 GLuint nbo = 0; 59 GLuint tbo = 0; 60 GLuint eao = 0; 61 62 this(Owner o) 63 { 64 super(o); 65 } 66 67 ~this() 68 { 69 if (vertices.length) Delete(vertices); 70 if (normals.length) Delete(normals); 71 if (texcoords.length) Delete(texcoords); 72 if (indices.length) Delete(indices); 73 74 if (canRender) 75 { 76 glDeleteVertexArrays(1, &vao); 77 glDeleteBuffers(1, &vbo); 78 glDeleteBuffers(1, &nbo); 79 glDeleteBuffers(1, &tbo); 80 glDeleteBuffers(1, &eao); 81 } 82 } 83 84 Triangle getTriangle(size_t faceIndex) 85 { 86 uint[3] f = indices[faceIndex]; 87 Triangle tri; 88 tri.v[0] = vertices[f[0]]; 89 tri.v[1] = vertices[f[1]]; 90 tri.v[2] = vertices[f[2]]; 91 tri.n[0] = normals[f[0]]; 92 tri.n[1] = normals[f[1]]; 93 tri.n[2] = normals[f[2]]; 94 tri.t1[0] = texcoords[f[0]]; 95 tri.t1[1] = texcoords[f[1]]; 96 tri.t1[2] = texcoords[f[2]]; 97 tri.normal = (tri.n[0] + tri.n[1] + tri.n[2]) / 3.0f; 98 return tri; 99 } 100 101 int opApply(scope int delegate(Triangle t) dg) 102 { 103 int result = 0; 104 105 foreach(i, ref f; indices) 106 { 107 Triangle tri = getTriangle(i); 108 result = dg(tri); 109 if (result) 110 break; 111 } 112 113 return result; 114 } 115 116 void generateNormals() 117 { 118 if (normals.length == 0) 119 return; 120 121 normals[] = Vector3f(0.0f, 0.0f, 0.0f); 122 123 foreach(i, ref f; indices) 124 { 125 Vector3f v0 = vertices[f[0]]; 126 Vector3f v1 = vertices[f[1]]; 127 Vector3f v2 = vertices[f[2]]; 128 129 Vector3f p = cross(v1 - v0, v2 - v0); 130 131 normals[f[0]] += p; 132 normals[f[1]] += p; 133 normals[f[2]] += p; 134 } 135 136 foreach(i, n; normals) 137 { 138 normals[i] = n.normalized; 139 } 140 } 141 142 void prepareVAO() 143 { 144 if (!dataReady) 145 return; 146 147 glGenBuffers(1, &vbo); 148 glBindBuffer(GL_ARRAY_BUFFER, vbo); 149 glBufferData(GL_ARRAY_BUFFER, vertices.length * float.sizeof * 3, vertices.ptr, GL_STATIC_DRAW); 150 151 glGenBuffers(1, &nbo); 152 glBindBuffer(GL_ARRAY_BUFFER, nbo); 153 glBufferData(GL_ARRAY_BUFFER, normals.length * float.sizeof * 3, normals.ptr, GL_STATIC_DRAW); 154 155 glGenBuffers(1, &tbo); 156 glBindBuffer(GL_ARRAY_BUFFER, tbo); 157 glBufferData(GL_ARRAY_BUFFER, texcoords.length * float.sizeof * 2, texcoords.ptr, GL_STATIC_DRAW); 158 159 glGenBuffers(1, &eao); 160 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); 161 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length * uint.sizeof * 3, indices.ptr, GL_STATIC_DRAW); 162 163 glGenVertexArrays(1, &vao); 164 glBindVertexArray(vao); 165 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); 166 167 glEnableVertexAttribArray(VertexAttrib.Vertices); 168 glBindBuffer(GL_ARRAY_BUFFER, vbo); 169 glVertexAttribPointer(VertexAttrib.Vertices, 3, GL_FLOAT, GL_FALSE, 0, null); 170 171 glEnableVertexAttribArray(VertexAttrib.Normals); 172 glBindBuffer(GL_ARRAY_BUFFER, nbo); 173 glVertexAttribPointer(VertexAttrib.Normals, 3, GL_FLOAT, GL_FALSE, 0, null); 174 175 glEnableVertexAttribArray(VertexAttrib.Texcoords); 176 glBindBuffer(GL_ARRAY_BUFFER, tbo); 177 glVertexAttribPointer(VertexAttrib.Texcoords, 2, GL_FLOAT, GL_FALSE, 0, null); 178 179 glBindVertexArray(0); 180 181 canRender = true; 182 } 183 184 void update(double dt) 185 { 186 } 187 188 void render(RenderingContext* rc) 189 { 190 if (canRender) 191 { 192 glBindVertexArray(vao); 193 glDrawElements(GL_TRIANGLES, cast(uint)indices.length * 3, GL_UNSIGNED_INT, cast(void*)0); 194 glBindVertexArray(0); 195 } 196 } 197 } 198