f0956b4470295a593c9b6feef30ed3d7b3a2f8fd
[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         glBindVertexArray(vao);
77
78         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
79         glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, 0);
80
81         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
82         glBindVertexArray(0);
83 }
84
85 void MeshGL::draw_normals(float scale) const
86 {
87         if(!nvao) {
88                 glGenVertexArrays(1, &nvao);
89                 glBindVertexArray(nvao);
90
91                 glGenBuffers(1, &nvbo);
92                 glBindBuffer(GL_ARRAY_BUFFER, nvbo);
93                 
94                 glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(Vec3) * 2, 0, GL_STATIC_DRAW);
95                 Vec3 *data = (Vec3 *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
96
97                 for (size_t i = 0; i < normals.size(); i++)
98                 {
99                         *data++ = vertices[i];
100                         *data++ = vertices[i] + normals[i] * scale;
101                 }
102                 glUnmapBuffer(GL_ARRAY_BUFFER);
103
104                 glVertexAttribPointer(MESH_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0);
105                 glEnableVertexAttribArray(MESH_VERTEX);
106                 glBindBuffer(GL_ARRAY_BUFFER, 0);
107         } else {
108                 glBindVertexArray(nvao);
109         }
110
111         glDrawArrays(GL_LINES, 0, normals.size() * 2);
112         glBindVertexArray(0);
113 }
114
115 void MeshGL::update_vertex_data()
116 {
117         update_vbo();
118 }
119
120 void MeshGL::update_vbo()
121 {
122         if(vertices.empty()) {
123                 printf("empty vertices\n");
124                 return;
125         }
126
127         /* vao */
128         if(!vao)
129                 glGenVertexArrays(1, &vao);
130         glBindVertexArray(vao);
131
132         /* vertices */
133
134         if(!vbo_vertices)
135                 glGenBuffers(1, &vbo_vertices);
136         glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
137         if(num_vertices != (int)vertices.size())
138                 glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vec3),
139                              &vertices[0], GL_STATIC_DRAW);
140         else
141                 glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vec3),
142                                 &vertices[0]);
143         glVertexAttribPointer(MESH_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0);
144
145         /* normals */
146
147         if(!vbo_normals)
148                 glGenBuffers(1, &vbo_normals);
149         glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
150         if(num_vertices != (int)normals.size())
151                 glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(Vec3),
152                              &normals[0], GL_STATIC_DRAW);
153         else
154                 glBufferSubData(GL_ARRAY_BUFFER, 0, normals.size() * sizeof(Vec3),
155                                 &normals[0]);
156         glVertexAttribPointer(MESH_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0);
157
158         /* texture coordinates */
159
160         if(!vbo_tex_coords)
161                 glGenBuffers(1, &vbo_tex_coords);
162         glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_coords);
163         if(num_vertices != (int)tex_coords.size())
164                 glBufferData(GL_ARRAY_BUFFER, tex_coords.size() * sizeof(Vec2), &tex_coords[0], GL_STATIC_DRAW);
165         else
166                 glBufferSubData(GL_ARRAY_BUFFER, 0, tex_coords.size() * sizeof(Vec2), &tex_coords[0]);
167         glVertexAttribPointer(MESH_TEXTURE, 2, GL_FLOAT, GL_FALSE, sizeof(Vec2), 0);
168
169         num_vertices = vertices.size();
170
171         /* indices */
172
173         if(!ibo)
174                 glGenBuffers(1, &ibo);
175         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
176         if(num_indices != (int)indices.size())
177                 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * 2,
178                              &indices[0], GL_STATIC_DRAW);
179         else
180                 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * 2,
181                                 &indices[0]);
182
183         num_indices = indices.size();
184
185         glEnableVertexAttribArray(MESH_VERTEX);
186         glEnableVertexAttribArray(MESH_NORMAL);
187         glEnableVertexAttribArray(MESH_TEXTURE);
188
189         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
190         glBindBuffer(GL_ARRAY_BUFFER, 0);
191         glBindVertexArray(0);
192 }
193
194 void MeshGL::destroy_vbo()
195 {
196         if(vbo_vertices)
197                 glDeleteBuffers(1, &vbo_vertices);
198         if(vbo_normals)
199                 glDeleteBuffers(1, &vbo_normals);
200         if(vbo_tex_coords)
201                 glDeleteBuffers(1, &vbo_tex_coords);
202         if(ibo)
203                 glDeleteBuffers(1, &ibo);
204         if (vao)
205                 glDeleteVertexArrays(1, &vao);
206
207         if(nvbo)
208                 glDeleteBuffers(1, &nvbo);
209         if(nvao)
210                 glDeleteVertexArrays(1, &nvao);
211 }