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