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 int opApply(scope int delegate(Triangle t) dg) 85 { 86 int result = 0; 87 88 foreach(i, ref f; indices) 89 { 90 Triangle tri; 91 92 tri.v[0] = vertices[f[0]]; 93 tri.v[1] = vertices[f[1]]; 94 tri.v[2] = vertices[f[2]]; 95 tri.n[0] = normals[f[0]]; 96 tri.n[1] = normals[f[1]]; 97 tri.n[2] = normals[f[2]]; 98 tri.t1[0] = texcoords[f[0]]; 99 tri.t1[1] = texcoords[f[1]]; 100 tri.t1[2] = texcoords[f[2]]; 101 tri.normal = (tri.n[0] + tri.n[1] + tri.n[2]) / 3.0f; 102 103 result = dg(tri); 104 if (result) 105 break; 106 } 107 108 return result; 109 } 110 111 void generateNormals() 112 { 113 if (normals.length == 0) 114 return; 115 116 normals[] = Vector3f(0.0f, 0.0f, 0.0f); 117 118 foreach(i, ref f; indices) 119 { 120 Vector3f v0 = vertices[f[0]]; 121 Vector3f v1 = vertices[f[1]]; 122 Vector3f v2 = vertices[f[2]]; 123 124 Vector3f p = cross(v1 - v0, v2 - v0); 125 126 normals[f[0]] += p; 127 normals[f[1]] += p; 128 normals[f[2]] += p; 129 } 130 131 foreach(i, n; normals) 132 { 133 normals[i] = n.normalized; 134 } 135 } 136 137 void prepareVAO() 138 { 139 if (!dataReady) 140 return; 141 142 glGenBuffers(1, &vbo); 143 glBindBuffer(GL_ARRAY_BUFFER, vbo); 144 glBufferData(GL_ARRAY_BUFFER, vertices.length * float.sizeof * 3, vertices.ptr, GL_STATIC_DRAW); 145 146 glGenBuffers(1, &nbo); 147 glBindBuffer(GL_ARRAY_BUFFER, nbo); 148 glBufferData(GL_ARRAY_BUFFER, normals.length * float.sizeof * 3, normals.ptr, GL_STATIC_DRAW); 149 150 glGenBuffers(1, &tbo); 151 glBindBuffer(GL_ARRAY_BUFFER, tbo); 152 glBufferData(GL_ARRAY_BUFFER, texcoords.length * float.sizeof * 2, texcoords.ptr, GL_STATIC_DRAW); 153 154 glGenBuffers(1, &eao); 155 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); 156 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length * uint.sizeof * 3, indices.ptr, GL_STATIC_DRAW); 157 158 glGenVertexArrays(1, &vao); 159 glBindVertexArray(vao); 160 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); 161 162 glEnableVertexAttribArray(VertexAttrib.Vertices); 163 glBindBuffer(GL_ARRAY_BUFFER, vbo); 164 glVertexAttribPointer(VertexAttrib.Vertices, 3, GL_FLOAT, GL_FALSE, 0, null); 165 166 glEnableVertexAttribArray(VertexAttrib.Normals); 167 glBindBuffer(GL_ARRAY_BUFFER, nbo); 168 glVertexAttribPointer(VertexAttrib.Normals, 3, GL_FLOAT, GL_FALSE, 0, null); 169 170 glEnableVertexAttribArray(VertexAttrib.Texcoords); 171 glBindBuffer(GL_ARRAY_BUFFER, tbo); 172 glVertexAttribPointer(VertexAttrib.Texcoords, 2, GL_FLOAT, GL_FALSE, 0, null); 173 174 glBindVertexArray(0); 175 176 canRender = true; 177 } 178 179 void update(double dt) 180 { 181 } 182 183 void render(RenderingContext* rc) 184 { 185 if (canRender) 186 { 187 glBindVertexArray(vao); 188 glDrawElements(GL_TRIANGLES, cast(uint)indices.length * 3, GL_UNSIGNED_INT, cast(void*)0); 189 glBindVertexArray(0); 190 } 191 } 192 } 193