vrheights

view src/mesh.cc @ 8:3f221bdc9bab

mesh loading walk polys
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 03 Oct 2014 04:16:16 +0300
parents
children 25cab9e20c9c
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::draw() const
250 {
251 if(attrib[MESH_VERTEX].data.empty()) {
252 return;
253 }
255 bool use_norm = !attrib[MESH_NORMAL].data.empty();
256 bool use_tc = !attrib[MESH_TEXCOORD].data.empty();
257 bool use_tang = !attrib[MESH_TANGENT].data.empty();
258 int norm_loc, tc_loc, tang_loc;
260 const float *ptr = &attrib[MESH_VERTEX].data[0];
261 int loc = attrib[MESH_VERTEX].sdrloc;
262 if(loc == -1) {
263 glEnableClientState(GL_VERTEX_ARRAY);
264 glVertexPointer(attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, ptr);
265 } else {
266 glEnableVertexAttribArray(loc);
267 glVertexAttribPointer(loc, attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0, ptr);
268 }
270 if(use_norm) {
271 const float *ptr = &attrib[MESH_NORMAL].data[0];
272 norm_loc = attrib[MESH_NORMAL].sdrloc;
273 if(norm_loc == -1) {
274 glEnableClientState(GL_NORMAL_ARRAY);
275 glNormalPointer(GL_FLOAT, 0, ptr);
276 } else {
277 glEnableVertexAttribArray(norm_loc);
278 glVertexAttribPointer(norm_loc, attrib[MESH_NORMAL].nelems, GL_FLOAT, 0, 0, ptr);
279 }
280 }
282 if(use_tc) {
283 const float *ptr = &attrib[MESH_TEXCOORD].data[0];
284 tc_loc = attrib[MESH_TEXCOORD].sdrloc;
285 if(tc_loc == -1) {
286 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
287 glTexCoordPointer(attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, ptr);
288 } else {
289 glEnableVertexAttribArray(tc_loc);
290 glVertexAttribPointer(tc_loc, attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0, ptr);
291 }
292 }
294 if(!attrib[MESH_TANGENT].data.empty()) {
295 const float *ptr = &attrib[MESH_TANGENT].data[0];
296 tang_loc = attrib[MESH_TANGENT].sdrloc;
297 if(tang_loc != -1) {
298 glEnableVertexAttribArray(tang_loc);
299 glVertexAttribPointer(tang_loc, attrib[MESH_TANGENT].nelems, GL_FLOAT, 0, 0, ptr);
300 }
301 }
303 if(!index.empty()) {
304 glDrawElements(prim, num_idx, GL_UNSIGNED_INT, &index[0]);
305 } else {
306 glDrawArrays(prim, 0, num_verts * 3);
307 }
309 if(use_norm) {
310 if(norm_loc == -1) {
311 glDisableClientState(GL_NORMAL_ARRAY);
312 } else {
313 glDisableVertexAttribArray(norm_loc);
314 }
315 }
316 if(use_tc) {
317 if(tc_loc == -1) {
318 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
319 } else {
320 glDisableVertexAttribArray(tc_loc);
321 }
322 }
323 if(use_tang) {
324 if(tang_loc != -1) {
325 glDisableVertexAttribArray(tang_loc);
326 }
327 }
328 }