vrheights

view src/mesh.cc @ 15:ffb62c8db542

added missing makefile
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 30 Oct 2015 05:40:22 +0200
parents 3f221bdc9bab
children
line source
1 #include <string.h>
2 #include "mesh.h"
3 #include "opengl.h"
5 Mesh::Mesh()
6 {
7 set_primitive(GL_TRIANGLES);
9 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
10 attrib[i].nelems = 3;
11 attrib[i].sdrloc = -1;
12 attrib[i].vbo = 0;
13 attrib[i].vbo_valid = false;
14 }
15 num_verts = 0;
17 num_idx = 0;
18 ibo = 0;
19 ibo_size = 0;
20 ibo_valid = false;
22 vbo_usage = ibo_usage = GL_STATIC_DRAW;
23 }
25 Mesh::~Mesh()
26 {
27 clear();
29 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
30 if(attrib[i].vbo) {
31 glDeleteBuffers(1, &attrib[i].vbo);
32 }
33 }
34 if(ibo) {
35 glDeleteBuffers(1, &ibo);
36 }
37 }
39 void Mesh::clear()
40 {
41 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
42 attrib[i].vbo_valid = false;
43 attrib[i].data.clear();
45 }
46 ibo_valid = false;
47 index.clear();
48 }
50 void Mesh::set_primitive(int prim)
51 {
52 if(prim == -1) {
53 this->prim = GL_TRIANGLES;
54 } else {
55 this->prim = prim;
56 }
58 switch(this->prim) {
59 case GL_TRIANGLES:
60 prim_verts = 3;
61 break;
63 case GL_QUADS:
64 prim_verts = 4;
65 break;
67 case GL_LINES:
68 prim_verts = 2;
69 break;
71 case GL_POINTS:
72 prim_verts = 1;
73 break;
75 default:
76 break;
77 }
78 }
80 void Mesh::set_attrib_location(int attr, int loc)
81 {
82 attrib[attr].sdrloc = loc;
83 }
85 float *Mesh::set_vertex_data(int attr, int nelem, int count, float *data)
86 {
87 attrib[attr].data.resize(count * nelem);
88 if(data) {
89 memcpy(&attrib[attr].data[0], data, nelem * count * sizeof(float));
90 }
92 attrib[attr].nelems = nelem;
93 attrib[attr].vbo_valid = false;
95 num_verts = count;
97 return &attrib[attr].data[0];
98 }
100 unsigned int *Mesh::set_index_data(int count, unsigned int *data)
101 {
102 index.resize(count);
103 if(data) {
104 memcpy(&index[0], data, count * sizeof(unsigned int));
105 }
107 num_idx = count;
108 ibo_valid = false;
110 return &index[0];
111 }
113 int Mesh::get_vertex_count() const
114 {
115 return num_verts;
116 }
118 float *Mesh::get_vertex_data(int attr)
119 {
120 if(attrib[attr].data.empty()) {
121 return 0;
122 }
123 return &attrib[attr].data[0];
124 }
126 const float *Mesh::get_vertex_data(int attr) const
127 {
128 if(attrib[attr].data.empty()) {
129 return 0;
130 }
131 return &attrib[attr].data[0];
132 }
134 int Mesh::get_index_count() const
135 {
136 return num_idx;
137 }
139 unsigned int *Mesh::get_index_data()
140 {
141 if(index.empty()) {
142 return 0;
143 }
144 return &index[0];
145 }
147 const unsigned int *Mesh::get_index_data() const
148 {
149 if(index.empty()) {
150 return 0;
151 }
152 return &index[0];
153 }
155 int Mesh::get_face_count() const
156 {
157 if(index.empty()) {
158 return get_vertex_count() / prim_verts;
159 }
160 return get_index_count() / prim_verts;
161 }
163 MeshFace Mesh::get_face(int idx) const
164 {
165 MeshFace face;
166 face.vcount = prim_verts;
168 int nfaces = get_face_count();
169 if(idx < 0 || idx >= nfaces) {
170 return face;
171 }
173 const Vector3 *verts = (const Vector3*)&attrib[MESH_VERTEX].data[0];
175 if(index.empty()) {
176 for(int i=0; i<3; i++) {
177 face.v[i] = verts[idx * 3 + i];
178 }
180 } else {
181 for(int i=0; i<3; i++) {
182 int vidx = index[idx * 3 + i];
183 face.v[i] = verts[vidx];
184 }
185 }
187 return face;
188 }
191 void Mesh::begin(int prim)
192 {
193 if(prim == -1) {
194 this->prim = GL_TRIANGLES;
195 } else {
196 this->prim = prim;
197 }
199 clear();
201 cur_norm_valid = false;
202 cur_tc_valid = false;
203 cur_tang_valid = false;
204 }
206 void Mesh::end()
207 {
208 }
210 void Mesh::vertex(float x, float y, float z)
211 {
212 if(cur_norm_valid) {
213 attrib[MESH_NORMAL].data.push_back(cur_norm.x);
214 attrib[MESH_NORMAL].data.push_back(cur_norm.y);
215 attrib[MESH_NORMAL].data.push_back(cur_norm.z);
216 }
217 if(cur_tc_valid) {
218 attrib[MESH_TEXCOORD].data.push_back(cur_tc.x);
219 attrib[MESH_TEXCOORD].data.push_back(cur_tc.y);
220 }
221 if(cur_tang_valid) {
222 attrib[MESH_TANGENT].data.push_back(cur_tang.x);
223 attrib[MESH_TANGENT].data.push_back(cur_tang.y);
224 attrib[MESH_TANGENT].data.push_back(cur_tang.z);
225 }
226 attrib[MESH_VERTEX].data.push_back(x);
227 attrib[MESH_VERTEX].data.push_back(y);
228 attrib[MESH_VERTEX].data.push_back(z);
229 }
231 void Mesh::normal(float x, float y, float z)
232 {
233 cur_norm = Vector3(x, y, z);
234 cur_norm_valid = true;
235 }
237 void Mesh::texcoord(float x, float y)
238 {
239 cur_tc = Vector2(x, y);
240 cur_tc_valid = true;
241 }
243 void Mesh::tangent(float x, float y, float z)
244 {
245 cur_tang = Vector3(x, y, z);
246 cur_tang_valid = true;
247 }
249 void Mesh::update_buffers()
250 {
251 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
252 if(attrib[i].vbo_valid || attrib[i].data.empty()) {
253 continue;
254 }
255 int count = (int)attrib[i].data.size();
257 float *ptr = &attrib[i].data[0];
258 // TODO: check previous size and don't resize if it's not needed
259 attrib[i].vbo_size = count * attrib[i].nelems * sizeof(float);
261 if(!attrib[i].vbo) {
262 glGenBuffers(1, &attrib[i].vbo);
263 }
265 glBindBuffer(GL_ARRAY_BUFFER, attrib[i].vbo);
266 glBufferData(GL_ARRAY_BUFFER, attrib[i].vbo_size, ptr, vbo_usage);
267 attrib[i].vbo_valid = true;
268 }
270 if(!ibo_valid && !index.empty()) {
271 unsigned int *ptr = &index[0];
272 ibo_size = index.size() * sizeof *ptr; // TODO: see above
274 if(!ibo) {
275 glGenBuffers(1, &ibo);
276 }
278 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
279 glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_size, ptr, ibo_usage);
280 ibo_valid = true;
281 }
282 }
284 void Mesh::draw() const
285 {
286 if(attrib[MESH_VERTEX].data.empty()) {
287 return;
288 }
290 ((Mesh*)this)->update_buffers();
292 bool use_norm = !attrib[MESH_NORMAL].data.empty();
293 bool use_tc = !attrib[MESH_TEXCOORD].data.empty();
294 bool use_tang = !attrib[MESH_TANGENT].data.empty();
295 int norm_loc, tc_loc, tang_loc;
297 glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_VERTEX].vbo);
298 int loc = attrib[MESH_VERTEX].sdrloc;
299 if(loc == -1) {
300 glEnableClientState(GL_VERTEX_ARRAY);
301 glVertexPointer(attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0);
302 } else {
303 glEnableVertexAttribArray(loc);
304 glVertexAttribPointer(loc, attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0, 0);
305 }
307 if(use_norm) {
308 glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_NORMAL].vbo);
309 norm_loc = attrib[MESH_NORMAL].sdrloc;
310 if(norm_loc == -1) {
311 glEnableClientState(GL_NORMAL_ARRAY);
312 glNormalPointer(GL_FLOAT, 0, 0);
313 } else {
314 glEnableVertexAttribArray(norm_loc);
315 glVertexAttribPointer(norm_loc, attrib[MESH_NORMAL].nelems, GL_FLOAT, 0, 0, 0);
316 }
317 }
319 if(use_tc) {
320 glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_TEXCOORD].vbo);
321 tc_loc = attrib[MESH_TEXCOORD].sdrloc;
322 if(tc_loc == -1) {
323 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
324 glTexCoordPointer(attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0);
325 } else {
326 glEnableVertexAttribArray(tc_loc);
327 glVertexAttribPointer(tc_loc, attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0, 0);
328 }
329 }
331 if(!attrib[MESH_TANGENT].data.empty()) {
332 glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_TANGENT].vbo);
333 tang_loc = attrib[MESH_TANGENT].sdrloc;
334 if(tang_loc != -1) {
335 glEnableVertexAttribArray(tang_loc);
336 glVertexAttribPointer(tang_loc, attrib[MESH_TANGENT].nelems, GL_FLOAT, 0, 0, 0);
337 }
338 }
340 glBindBuffer(GL_ARRAY_BUFFER, 0);
342 if(!index.empty()) {
343 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
344 glDrawElements(prim, num_idx, GL_UNSIGNED_INT, 0);
345 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
346 } else {
347 glDrawArrays(prim, 0, num_verts * 3);
348 }
350 if(use_norm) {
351 if(norm_loc == -1) {
352 glDisableClientState(GL_NORMAL_ARRAY);
353 } else {
354 glDisableVertexAttribArray(norm_loc);
355 }
356 }
357 if(use_tc) {
358 if(tc_loc == -1) {
359 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
360 } else {
361 glDisableVertexAttribArray(tc_loc);
362 }
363 }
364 if(use_tang) {
365 if(tang_loc != -1) {
366 glDisableVertexAttribArray(tang_loc);
367 }
368 }
369 }