dd73bf386f8d1d13e31df73a8680da236ac20fbb
[demo] / src / opengl / mesh-gl.cc
1 #include <GL/glew.h>
2 #include <GL/gl.h>
3 #include <gmath/gmath.h>
4
5 #include "mesh-gl.h"
6
7 MeshGL::MeshGL()
8 {
9         vao = 0;
10
11         vbo_vertices = 0;
12         vbo_normals = 0;
13         vbo_tex_coords = 0;
14         ibo = 0;
15
16         num_vertices = 0;
17         num_indices = 0;
18
19         /* draw normals */
20         nvao = nvbo = 0;
21 }
22
23 MeshGL::MeshGL(const MeshGL &mesh)
24 {
25         indices = mesh.indices;
26         vertices = mesh.vertices;
27         normals = mesh.normals;
28         tex_coords = mesh.tex_coords;
29
30         vbo_vertices = 0;
31         vbo_normals = 0;
32         vbo_tex_coords = 0;
33         ibo = 0;
34         vao = 0;
35
36         /* draw normals */
37         nvao = nvbo = 0;
38
39         /*
40          * if we set these to the actual
41          * vertices.size() and indices.size()
42          * update_vbo will have no effect
43          * */
44
45         num_vertices = 0;
46         num_indices = 0;
47 }
48
49 MeshGL &MeshGL::operator=(const MeshGL &mesh)
50 {
51         if(this == &mesh)
52                 return *this;
53
54         /* to avoid OpenGL leaks */
55         destroy_vbo();
56
57         /* what the copy constructor does */
58         indices = mesh.indices;
59         vertices = mesh.vertices;
60         normals = mesh.normals;
61         tex_coords = mesh.tex_coords;
62
63         return *this;
64 }
65
66 MeshGL::~MeshGL()
67 {
68         destroy_vbo();
69
70         vertices.clear();
71         normals.clear();
72 }
73
74 void MeshGL::draw() const
75 {
76         if(!vdata_valid) {
77                 ((MeshGL*)this)->update_vertex_data();
78         }
79         glBindVertexArray(vao);
80
81         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
82         glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, 0);
83
84         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
85         glBindVertexArray(0);
86 }
87
88 void MeshGL::draw_normals(float scale) const
89 {
90         if(!nvao) {
91                 glGenVertexArrays(1, &nvao);
92                 glBindVertexArray(nvao);
93
94                 glGenBuffers(1, &nvbo);
95                 glBindBuffer(GL_ARRAY_BUFFER, nvbo);
96                 
97                 glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(Vec3) * 2, 0, GL_STATIC_DRAW);
98                 Vec3 *data = (Vec3 *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
99
100                 for (size_t i = 0; i < normals.size(); i++)
101                 {
102                         *data++ = vertices[i];
103                         *data++ = vertices[i] + normals[i] * scale;
104                 }
105                 glUnmapBuffer(GL_ARRAY_BUFFER);
106
107                 glVertexAttribPointer(MESH_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0);
108                 glEnableVertexAttribArray(MESH_VERTEX);
109                 glBindBuffer(GL_ARRAY_BUFFER, 0);
110         } else {
111                 glBindVertexArray(nvao);
112         }
113
114         glDrawArrays(GL_LINES, 0, normals.size() * 2);
115         glBindVertexArray(0);
116 }
117
118 void MeshGL::update_vertex_data()
119 {
120         update_vbo();
121 }
122
123 void MeshGL::update_vbo()
124 {
125         if(vertices.empty()) {
126                 printf("empty vertices\n");
127                 return;
128         }
129
130         /* vao */
131         if(!vao)
132                 glGenVertexArrays(1, &vao);
133         glBindVertexArray(vao);
134
135         /* vertices */
136
137         if(!vbo_vertices)
138                 glGenBuffers(1, &vbo_vertices);
139         glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
140         if(num_vertices != (int)vertices.size())
141                 glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vec3),
142                              &vertices[0], GL_STATIC_DRAW);
143         else
144                 glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vec3),
145                                 &vertices[0]);
146         glVertexAttribPointer(MESH_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0);
147
148         /* normals */
149
150         if(!vbo_normals)
151                 glGenBuffers(1, &vbo_normals);
152         glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
153         if(num_vertices != (int)normals.size())
154                 glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(Vec3),
155                              &normals[0], GL_STATIC_DRAW);
156         else
157                 glBufferSubData(GL_ARRAY_BUFFER, 0, normals.size() * sizeof(Vec3),
158                                 &normals[0]);
159         glVertexAttribPointer(MESH_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0);
160
161         /* texture coordinates */
162
163         if(!vbo_tex_coords)
164                 glGenBuffers(1, &vbo_tex_coords);
165         glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_coords);
166         if(num_vertices != (int)tex_coords.size())
167                 glBufferData(GL_ARRAY_BUFFER, tex_coords.size() * sizeof(Vec2), &tex_coords[0], GL_STATIC_DRAW);
168         else
169                 glBufferSubData(GL_ARRAY_BUFFER, 0, tex_coords.size() * sizeof(Vec2), &tex_coords[0]);
170         glVertexAttribPointer(MESH_TEXTURE, 2, GL_FLOAT, GL_FALSE, sizeof(Vec2), 0);
171
172         num_vertices = vertices.size();
173
174         /* indices */
175
176         if(!ibo)
177                 glGenBuffers(1, &ibo);
178         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
179         if(num_indices != (int)indices.size())
180                 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * 2,
181                              &indices[0], GL_STATIC_DRAW);
182         else
183                 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * 2,
184                                 &indices[0]);
185
186         num_indices = indices.size();
187
188         glEnableVertexAttribArray(MESH_VERTEX);
189         glEnableVertexAttribArray(MESH_NORMAL);
190         glEnableVertexAttribArray(MESH_TEXTURE);
191
192         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
193         glBindBuffer(GL_ARRAY_BUFFER, 0);
194         glBindVertexArray(0);
195 }
196
197 void MeshGL::destroy_vbo()
198 {
199         if(vbo_vertices)
200                 glDeleteBuffers(1, &vbo_vertices);
201         if(vbo_normals)
202                 glDeleteBuffers(1, &vbo_normals);
203         if(vbo_tex_coords)
204                 glDeleteBuffers(1, &vbo_tex_coords);
205         if(ibo)
206                 glDeleteBuffers(1, &ibo);
207         if (vao)
208                 glDeleteVertexArrays(1, &vao);
209
210         if(nvbo)
211                 glDeleteBuffers(1, &nvbo);
212         if(nvao)
213                 glDeleteVertexArrays(1, &nvao);
214 }