rev |
line source |
nuclear@1
|
1 #include <stdio.h>
|
nuclear@1
|
2 #include <stdlib.h>
|
nuclear@1
|
3 #include <float.h>
|
nuclear@1
|
4 #include <assert.h>
|
nuclear@1
|
5 #include "opengl.h"
|
nuclear@1
|
6 #include "mesh.h"
|
nuclear@1
|
7 #include "xform_node.h"
|
nuclear@1
|
8 //#include "logger.h"
|
nuclear@1
|
9
|
nuclear@1
|
10 int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5 };
|
nuclear@1
|
11 unsigned int Mesh::intersect_mode = ISECT_DEFAULT;
|
nuclear@1
|
12 float Mesh::vertex_sel_dist = 0.01;
|
nuclear@1
|
13 float Mesh::vis_vecsize = 1.0;
|
nuclear@1
|
14
|
nuclear@1
|
15 Mesh::Mesh()
|
nuclear@1
|
16 {
|
nuclear@1
|
17 clear();
|
nuclear@1
|
18
|
nuclear@1
|
19 glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects);
|
nuclear@1
|
20
|
nuclear@1
|
21 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
22 vattr[i].vbo = buffer_objects[i];
|
nuclear@1
|
23 }
|
nuclear@1
|
24 ibo = buffer_objects[NUM_MESH_ATTR];
|
nuclear@1
|
25 wire_ibo = 0;
|
nuclear@1
|
26 }
|
nuclear@1
|
27
|
nuclear@1
|
28 Mesh::~Mesh()
|
nuclear@1
|
29 {
|
nuclear@1
|
30 glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects);
|
nuclear@1
|
31
|
nuclear@1
|
32 if(wire_ibo) {
|
nuclear@1
|
33 glDeleteBuffers(1, &wire_ibo);
|
nuclear@1
|
34 }
|
nuclear@1
|
35 }
|
nuclear@1
|
36
|
nuclear@1
|
37 void Mesh::set_name(const char *name)
|
nuclear@1
|
38 {
|
nuclear@1
|
39 this->name = name;
|
nuclear@1
|
40 }
|
nuclear@1
|
41
|
nuclear@1
|
42 const char *Mesh::get_name() const
|
nuclear@1
|
43 {
|
nuclear@1
|
44 return name.c_str();
|
nuclear@1
|
45 }
|
nuclear@1
|
46
|
nuclear@1
|
47 bool Mesh::has_attrib(int attr) const
|
nuclear@1
|
48 {
|
nuclear@1
|
49 if(attr < 0 || attr >= NUM_MESH_ATTR) {
|
nuclear@1
|
50 return false;
|
nuclear@1
|
51 }
|
nuclear@1
|
52
|
nuclear@1
|
53 // if neither of these is valid, then nobody has set this attribute
|
nuclear@1
|
54 return vattr[attr].vbo_valid || vattr[attr].data_valid;
|
nuclear@1
|
55 }
|
nuclear@1
|
56
|
nuclear@1
|
57 void Mesh::clear()
|
nuclear@1
|
58 {
|
nuclear@1
|
59 bones.clear();
|
nuclear@1
|
60
|
nuclear@1
|
61 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
62 vattr[i].nelem = 0;
|
nuclear@1
|
63 vattr[i].vbo_valid = false;
|
nuclear@1
|
64 vattr[i].data_valid = false;
|
nuclear@1
|
65 //vattr[i].sdr_loc = -1;
|
nuclear@1
|
66 vattr[i].data.clear();
|
nuclear@1
|
67 }
|
nuclear@1
|
68 ibo_valid = false;
|
nuclear@1
|
69 idata.clear();
|
nuclear@1
|
70
|
nuclear@1
|
71 wire_ibo_valid = false;
|
nuclear@1
|
72
|
nuclear@1
|
73 nverts = nfaces = 0;
|
nuclear@1
|
74
|
nuclear@1
|
75 /*bsph_valid = false;
|
nuclear@1
|
76 aabb_valid = false;*/
|
nuclear@1
|
77 }
|
nuclear@1
|
78
|
nuclear@1
|
79 float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data)
|
nuclear@1
|
80 {
|
nuclear@1
|
81 if(attrib < 0 || attrib >= NUM_MESH_ATTR) {
|
nuclear@1
|
82 fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@1
|
83 return 0;
|
nuclear@1
|
84 }
|
nuclear@1
|
85
|
nuclear@1
|
86 if(nverts && num != nverts) {
|
nuclear@1
|
87 fprintf(stderr, "%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts);
|
nuclear@1
|
88 return 0;
|
nuclear@1
|
89 }
|
nuclear@1
|
90 nverts = num;
|
nuclear@1
|
91
|
nuclear@1
|
92 vattr[attrib].data.clear();
|
nuclear@1
|
93 vattr[attrib].nelem = nelem;
|
nuclear@1
|
94 vattr[attrib].data.resize(num * nelem);
|
nuclear@1
|
95
|
nuclear@1
|
96 if(data) {
|
nuclear@1
|
97 memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data);
|
nuclear@1
|
98 }
|
nuclear@1
|
99
|
nuclear@1
|
100 vattr[attrib].data_valid = true;
|
nuclear@1
|
101 vattr[attrib].vbo_valid = false;
|
nuclear@1
|
102 return &vattr[attrib].data[0];
|
nuclear@1
|
103 }
|
nuclear@1
|
104
|
nuclear@1
|
105 float *Mesh::get_attrib_data(int attrib)
|
nuclear@1
|
106 {
|
nuclear@1
|
107 if(attrib < 0 || attrib >= NUM_MESH_ATTR) {
|
nuclear@1
|
108 fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@1
|
109 return 0;
|
nuclear@1
|
110 }
|
nuclear@1
|
111
|
nuclear@1
|
112 vattr[attrib].vbo_valid = false;
|
nuclear@1
|
113 return (float*)((const Mesh*)this)->get_attrib_data(attrib);
|
nuclear@1
|
114 }
|
nuclear@1
|
115
|
nuclear@1
|
116 const float *Mesh::get_attrib_data(int attrib) const
|
nuclear@1
|
117 {
|
nuclear@1
|
118 if(attrib < 0 || attrib >= NUM_MESH_ATTR) {
|
nuclear@1
|
119 fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@1
|
120 return 0;
|
nuclear@1
|
121 }
|
nuclear@1
|
122
|
nuclear@1
|
123 if(!vattr[attrib].data_valid) {
|
nuclear@1
|
124 #if GL_ES_VERSION_2_0
|
nuclear@1
|
125 fprintf(stderr, "%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__);
|
nuclear@1
|
126 return 0;
|
nuclear@1
|
127 #else
|
nuclear@1
|
128 if(!vattr[attrib].vbo_valid) {
|
nuclear@1
|
129 fprintf(stderr, "%s: unavailable attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@1
|
130 return 0;
|
nuclear@1
|
131 }
|
nuclear@1
|
132
|
nuclear@1
|
133 // local data copy is unavailable, grab the data from the vbo
|
nuclear@1
|
134 Mesh *m = (Mesh*)this;
|
nuclear@1
|
135 m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem);
|
nuclear@1
|
136
|
nuclear@1
|
137 glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo);
|
nuclear@1
|
138 void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@1
|
139 memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float));
|
nuclear@1
|
140 glUnmapBuffer(GL_ARRAY_BUFFER);
|
nuclear@1
|
141
|
nuclear@1
|
142 vattr[attrib].data_valid = true;
|
nuclear@1
|
143 #endif
|
nuclear@1
|
144 }
|
nuclear@1
|
145
|
nuclear@1
|
146 return &vattr[attrib].data[0];
|
nuclear@1
|
147 }
|
nuclear@1
|
148
|
nuclear@1
|
149 void Mesh::set_attrib(int attrib, int idx, const Vector4 &v)
|
nuclear@1
|
150 {
|
nuclear@1
|
151 float *data = get_attrib_data(attrib);
|
nuclear@1
|
152 if(data) {
|
nuclear@1
|
153 data += idx * vattr[attrib].nelem;
|
nuclear@1
|
154 for(int i=0; i<vattr[attrib].nelem; i++) {
|
nuclear@1
|
155 data[i] = v[i];
|
nuclear@1
|
156 }
|
nuclear@1
|
157 }
|
nuclear@1
|
158 }
|
nuclear@1
|
159
|
nuclear@1
|
160 Vector4 Mesh::get_attrib(int attrib, int idx) const
|
nuclear@1
|
161 {
|
nuclear@1
|
162 Vector4 v(0.0, 0.0, 0.0, 1.0);
|
nuclear@1
|
163 const float *data = get_attrib_data(attrib);
|
nuclear@1
|
164 if(data) {
|
nuclear@1
|
165 data += idx * vattr[attrib].nelem;
|
nuclear@1
|
166 for(int i=0; i<vattr[attrib].nelem; i++) {
|
nuclear@1
|
167 v[i] = data[i];
|
nuclear@1
|
168 }
|
nuclear@1
|
169 }
|
nuclear@1
|
170 return v;
|
nuclear@1
|
171 }
|
nuclear@1
|
172
|
nuclear@1
|
173 unsigned int *Mesh::set_index_data(int num, const unsigned int *indices)
|
nuclear@1
|
174 {
|
nuclear@1
|
175 int nidx = nfaces * 3;
|
nuclear@1
|
176 if(nidx && num != nidx) {
|
nuclear@1
|
177 fprintf(stderr, "%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx);
|
nuclear@1
|
178 return 0;
|
nuclear@1
|
179 }
|
nuclear@1
|
180 nfaces = num / 3;
|
nuclear@1
|
181
|
nuclear@1
|
182 idata.clear();
|
nuclear@1
|
183 idata.resize(num);
|
nuclear@1
|
184
|
nuclear@1
|
185 if(indices) {
|
nuclear@1
|
186 memcpy(&idata[0], indices, num * sizeof *indices);
|
nuclear@1
|
187 }
|
nuclear@1
|
188
|
nuclear@1
|
189 idata_valid = true;
|
nuclear@1
|
190 ibo_valid = false;
|
nuclear@1
|
191
|
nuclear@1
|
192 return &idata[0];
|
nuclear@1
|
193 }
|
nuclear@1
|
194
|
nuclear@1
|
195 unsigned int *Mesh::get_index_data()
|
nuclear@1
|
196 {
|
nuclear@1
|
197 ibo_valid = false;
|
nuclear@1
|
198 return (unsigned int*)((const Mesh*)this)->get_index_data();
|
nuclear@1
|
199 }
|
nuclear@1
|
200
|
nuclear@1
|
201 const unsigned int *Mesh::get_index_data() const
|
nuclear@1
|
202 {
|
nuclear@1
|
203 if(!idata_valid) {
|
nuclear@1
|
204 #if GL_ES_VERSION_2_0
|
nuclear@1
|
205 fprintf(stderr, "%s: can't read back index data in CrippledGL ES\n", __FUNCTION__);
|
nuclear@1
|
206 return 0;
|
nuclear@1
|
207 #else
|
nuclear@1
|
208 if(!ibo_valid) {
|
nuclear@1
|
209 fprintf(stderr, "%s: indices unavailable\n", __FUNCTION__);
|
nuclear@1
|
210 return 0;
|
nuclear@1
|
211 }
|
nuclear@1
|
212
|
nuclear@1
|
213 // local data copy is unavailable, gram the data from the ibo
|
nuclear@1
|
214 Mesh *m = (Mesh*)this;
|
nuclear@1
|
215 int nidx = nfaces * 3;
|
nuclear@1
|
216 m->idata.resize(nidx);
|
nuclear@1
|
217
|
nuclear@1
|
218 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@1
|
219 void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@1
|
220 memcpy(&m->idata[0], data, nidx * sizeof(unsigned int));
|
nuclear@1
|
221 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
nuclear@1
|
222
|
nuclear@1
|
223 idata_valid = true;
|
nuclear@1
|
224 #endif
|
nuclear@1
|
225 }
|
nuclear@1
|
226
|
nuclear@1
|
227 return &idata[0];
|
nuclear@1
|
228 }
|
nuclear@1
|
229
|
nuclear@1
|
230 void Mesh::append(const Mesh &mesh)
|
nuclear@1
|
231 {
|
nuclear@1
|
232 unsigned int idxoffs = nverts;
|
nuclear@1
|
233
|
nuclear@1
|
234 nverts += mesh.nverts;
|
nuclear@1
|
235 nfaces += mesh.nfaces;
|
nuclear@1
|
236
|
nuclear@1
|
237 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
238 if(has_attrib(i) && mesh.has_attrib(i)) {
|
nuclear@1
|
239 // force validating the data arrays
|
nuclear@1
|
240 get_attrib_data(i);
|
nuclear@1
|
241 mesh.get_attrib_data(i);
|
nuclear@1
|
242
|
nuclear@1
|
243 // append the mesh data
|
nuclear@1
|
244 vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end());
|
nuclear@1
|
245 }
|
nuclear@1
|
246 }
|
nuclear@1
|
247
|
nuclear@1
|
248 if(ibo_valid || idata_valid) {
|
nuclear@1
|
249 // make index arrays valid
|
nuclear@1
|
250 get_index_data();
|
nuclear@1
|
251 mesh.get_index_data();
|
nuclear@1
|
252
|
nuclear@1
|
253 size_t orig_sz = idata.size();
|
nuclear@1
|
254
|
nuclear@1
|
255 idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end());
|
nuclear@1
|
256
|
nuclear@1
|
257 // fixup all the new indices
|
nuclear@1
|
258 for(size_t i=orig_sz; i<idata.size(); i++) {
|
nuclear@1
|
259 idata[i] += idxoffs;
|
nuclear@1
|
260 }
|
nuclear@1
|
261 }
|
nuclear@1
|
262
|
nuclear@1
|
263 // fuck everything
|
nuclear@1
|
264 wire_ibo_valid = false;
|
nuclear@1
|
265 /*aabb_valid = false;
|
nuclear@1
|
266 bsph_valid = false;*/
|
nuclear@1
|
267 }
|
nuclear@1
|
268
|
nuclear@1
|
269 // assemble a complete vertex by adding all the useful attributes
|
nuclear@1
|
270 void Mesh::vertex(float x, float y, float z)
|
nuclear@1
|
271 {
|
nuclear@1
|
272 cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f);
|
nuclear@1
|
273 vattr[MESH_ATTR_VERTEX].data_valid = true;
|
nuclear@1
|
274 vattr[MESH_ATTR_VERTEX].nelem = 3;
|
nuclear@1
|
275
|
nuclear@1
|
276 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
277 if(vattr[i].data_valid) {
|
nuclear@1
|
278 for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) {
|
nuclear@1
|
279 vattr[i].data.push_back(cur_val[i][j]);
|
nuclear@1
|
280 }
|
nuclear@1
|
281 }
|
nuclear@1
|
282 vattr[i].vbo_valid = false;
|
nuclear@1
|
283 }
|
nuclear@1
|
284
|
nuclear@1
|
285 if(idata_valid) {
|
nuclear@1
|
286 idata.clear();
|
nuclear@1
|
287 }
|
nuclear@1
|
288 ibo_valid = idata_valid = false;
|
nuclear@1
|
289 }
|
nuclear@1
|
290
|
nuclear@1
|
291 void Mesh::normal(float nx, float ny, float nz)
|
nuclear@1
|
292 {
|
nuclear@1
|
293 cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f);
|
nuclear@1
|
294 vattr[MESH_ATTR_NORMAL].data_valid = true;
|
nuclear@1
|
295 vattr[MESH_ATTR_NORMAL].nelem = 3;
|
nuclear@1
|
296 }
|
nuclear@1
|
297
|
nuclear@1
|
298 void Mesh::tangent(float tx, float ty, float tz)
|
nuclear@1
|
299 {
|
nuclear@1
|
300 cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f);
|
nuclear@1
|
301 vattr[MESH_ATTR_TANGENT].data_valid = true;
|
nuclear@1
|
302 vattr[MESH_ATTR_TANGENT].nelem = 3;
|
nuclear@1
|
303 }
|
nuclear@1
|
304
|
nuclear@1
|
305 void Mesh::texcoord(float u, float v, float w)
|
nuclear@1
|
306 {
|
nuclear@1
|
307 cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f);
|
nuclear@1
|
308 vattr[MESH_ATTR_TEXCOORD].data_valid = true;
|
nuclear@1
|
309 vattr[MESH_ATTR_TEXCOORD].nelem = 3;
|
nuclear@1
|
310 }
|
nuclear@1
|
311
|
nuclear@1
|
312 void Mesh::boneweights(float w1, float w2, float w3, float w4)
|
nuclear@1
|
313 {
|
nuclear@1
|
314 cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4);
|
nuclear@1
|
315 vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true;
|
nuclear@1
|
316 vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4;
|
nuclear@1
|
317 }
|
nuclear@1
|
318
|
nuclear@1
|
319 void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4)
|
nuclear@1
|
320 {
|
nuclear@1
|
321 cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4);
|
nuclear@1
|
322 vattr[MESH_ATTR_BONEIDX].data_valid = true;
|
nuclear@1
|
323 vattr[MESH_ATTR_BONEIDX].nelem = 4;
|
nuclear@1
|
324 }
|
nuclear@1
|
325
|
nuclear@1
|
326 /// static function
|
nuclear@1
|
327 void Mesh::set_attrib_location(int attr, int loc)
|
nuclear@1
|
328 {
|
nuclear@1
|
329 if(attr < 0 || attr >= NUM_MESH_ATTR) {
|
nuclear@1
|
330 return;
|
nuclear@1
|
331 }
|
nuclear@1
|
332 Mesh::global_sdr_loc[attr] = loc;
|
nuclear@1
|
333 }
|
nuclear@1
|
334
|
nuclear@1
|
335 /// static function
|
nuclear@1
|
336 int Mesh::get_attrib_location(int attr)
|
nuclear@1
|
337 {
|
nuclear@1
|
338 if(attr < 0 || attr >= NUM_MESH_ATTR) {
|
nuclear@1
|
339 return -1;
|
nuclear@1
|
340 }
|
nuclear@1
|
341 return Mesh::global_sdr_loc[attr];
|
nuclear@1
|
342 }
|
nuclear@1
|
343
|
nuclear@1
|
344 /// static function
|
nuclear@1
|
345 void Mesh::clear_attrib_locations()
|
nuclear@1
|
346 {
|
nuclear@1
|
347 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
348 Mesh::global_sdr_loc[i] = -1;
|
nuclear@1
|
349 }
|
nuclear@1
|
350 }
|
nuclear@1
|
351
|
nuclear@1
|
352 /// static function
|
nuclear@1
|
353 void Mesh::set_vis_vecsize(float sz)
|
nuclear@1
|
354 {
|
nuclear@1
|
355 Mesh::vis_vecsize = sz;
|
nuclear@1
|
356 }
|
nuclear@1
|
357
|
nuclear@1
|
358 float Mesh::get_vis_vecsize()
|
nuclear@1
|
359 {
|
nuclear@1
|
360 return Mesh::vis_vecsize;
|
nuclear@1
|
361 }
|
nuclear@1
|
362
|
nuclear@1
|
363 void Mesh::apply_xform(const Matrix4x4 &xform)
|
nuclear@1
|
364 {
|
nuclear@1
|
365 Matrix4x4 dir_xform = xform;
|
nuclear@1
|
366 dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f;
|
nuclear@1
|
367 dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f;
|
nuclear@1
|
368 dir_xform[3][3] = 1.0f;
|
nuclear@1
|
369
|
nuclear@1
|
370 apply_xform(xform, dir_xform);
|
nuclear@1
|
371 }
|
nuclear@1
|
372
|
nuclear@1
|
373 void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform)
|
nuclear@1
|
374 {
|
nuclear@1
|
375 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@1
|
376 Vector4 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@1
|
377 set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform));
|
nuclear@1
|
378
|
nuclear@1
|
379 if(has_attrib(MESH_ATTR_NORMAL)) {
|
nuclear@1
|
380 Vector3 n = get_attrib(MESH_ATTR_NORMAL, i);
|
nuclear@1
|
381 set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform));
|
nuclear@1
|
382 }
|
nuclear@1
|
383 if(has_attrib(MESH_ATTR_TANGENT)) {
|
nuclear@1
|
384 Vector3 t = get_attrib(MESH_ATTR_TANGENT, i);
|
nuclear@1
|
385 set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform));
|
nuclear@1
|
386 }
|
nuclear@1
|
387 }
|
nuclear@1
|
388 }
|
nuclear@1
|
389
|
nuclear@1
|
390 int Mesh::add_bone(XFormNode *bone)
|
nuclear@1
|
391 {
|
nuclear@1
|
392 int idx = bones.size();
|
nuclear@1
|
393 bones.push_back(bone);
|
nuclear@1
|
394 return idx;
|
nuclear@1
|
395 }
|
nuclear@1
|
396
|
nuclear@1
|
397 const XFormNode *Mesh::get_bone(int idx) const
|
nuclear@1
|
398 {
|
nuclear@1
|
399 if(idx < 0 || idx >= (int)bones.size()) {
|
nuclear@1
|
400 return 0;
|
nuclear@1
|
401 }
|
nuclear@1
|
402 return bones[idx];
|
nuclear@1
|
403 }
|
nuclear@1
|
404
|
nuclear@1
|
405 int Mesh::get_bones_count() const
|
nuclear@1
|
406 {
|
nuclear@1
|
407 return (int)bones.size();
|
nuclear@1
|
408 }
|
nuclear@1
|
409
|
nuclear@1
|
410 void Mesh::draw() const
|
nuclear@1
|
411 {
|
nuclear@1
|
412 ((Mesh*)this)->update_buffers();
|
nuclear@1
|
413
|
nuclear@1
|
414 if(!vattr[MESH_ATTR_VERTEX].vbo_valid) {
|
nuclear@1
|
415 fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__);
|
nuclear@1
|
416 return;
|
nuclear@1
|
417 }
|
nuclear@1
|
418 if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
|
nuclear@1
|
419 fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
|
nuclear@1
|
420 return;
|
nuclear@1
|
421 }
|
nuclear@1
|
422
|
nuclear@1
|
423 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
424 int loc = global_sdr_loc[i];
|
nuclear@1
|
425 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@1
|
426 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@1
|
427 glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@1
|
428 glEnableVertexAttribArray(loc);
|
nuclear@1
|
429 }
|
nuclear@1
|
430 }
|
nuclear@1
|
431 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@1
|
432
|
nuclear@1
|
433 if(ibo_valid) {
|
nuclear@1
|
434 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@1
|
435 glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0);
|
nuclear@1
|
436 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@1
|
437 } else {
|
nuclear@1
|
438 glDrawArrays(GL_TRIANGLES, 0, nverts);
|
nuclear@1
|
439 }
|
nuclear@1
|
440
|
nuclear@1
|
441 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
442 int loc = global_sdr_loc[i];
|
nuclear@1
|
443 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@1
|
444 glDisableVertexAttribArray(loc);
|
nuclear@1
|
445 }
|
nuclear@1
|
446 }
|
nuclear@1
|
447 }
|
nuclear@1
|
448
|
nuclear@1
|
449 void Mesh::draw_wire() const
|
nuclear@1
|
450 {
|
nuclear@1
|
451 ((Mesh*)this)->update_wire_ibo();
|
nuclear@1
|
452
|
nuclear@1
|
453 if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) {
|
nuclear@1
|
454 fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__);
|
nuclear@1
|
455 return;
|
nuclear@1
|
456 }
|
nuclear@1
|
457 if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
|
nuclear@1
|
458 fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
|
nuclear@1
|
459 return;
|
nuclear@1
|
460 }
|
nuclear@1
|
461
|
nuclear@1
|
462 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
463 int loc = global_sdr_loc[i];
|
nuclear@1
|
464 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@1
|
465 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@1
|
466 glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@1
|
467 glEnableVertexAttribArray(loc);
|
nuclear@1
|
468 }
|
nuclear@1
|
469 }
|
nuclear@1
|
470 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@1
|
471
|
nuclear@1
|
472 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo);
|
nuclear@1
|
473 glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0);
|
nuclear@1
|
474 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@1
|
475
|
nuclear@1
|
476 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
477 int loc = global_sdr_loc[i];
|
nuclear@1
|
478 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@1
|
479 glDisableVertexAttribArray(loc);
|
nuclear@1
|
480 }
|
nuclear@1
|
481 }
|
nuclear@1
|
482 }
|
nuclear@1
|
483
|
nuclear@1
|
484 void Mesh::draw_vertices() const
|
nuclear@1
|
485 {
|
nuclear@1
|
486 ((Mesh*)this)->update_buffers();
|
nuclear@1
|
487
|
nuclear@1
|
488 if(!vattr[MESH_ATTR_VERTEX].vbo_valid) {
|
nuclear@1
|
489 fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__);
|
nuclear@1
|
490 return;
|
nuclear@1
|
491 }
|
nuclear@1
|
492 if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
|
nuclear@1
|
493 fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
|
nuclear@1
|
494 return;
|
nuclear@1
|
495 }
|
nuclear@1
|
496
|
nuclear@1
|
497 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
498 int loc = global_sdr_loc[i];
|
nuclear@1
|
499 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@1
|
500 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@1
|
501 glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@1
|
502 glEnableVertexAttribArray(loc);
|
nuclear@1
|
503 }
|
nuclear@1
|
504 }
|
nuclear@1
|
505 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@1
|
506
|
nuclear@1
|
507 glDrawArrays(GL_POINTS, 0, nverts);
|
nuclear@1
|
508
|
nuclear@1
|
509 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
510 int loc = global_sdr_loc[i];
|
nuclear@1
|
511 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@1
|
512 glDisableVertexAttribArray(loc);
|
nuclear@1
|
513 }
|
nuclear@1
|
514 }
|
nuclear@1
|
515 }
|
nuclear@1
|
516
|
nuclear@1
|
517 void Mesh::draw_normals() const
|
nuclear@1
|
518 {
|
nuclear@1
|
519 #ifdef USE_OLDGL
|
nuclear@1
|
520 int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX];
|
nuclear@1
|
521 Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@1
|
522 Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL);
|
nuclear@1
|
523
|
nuclear@1
|
524 if(!varr || !norm || vert_loc < 0) {
|
nuclear@1
|
525 return;
|
nuclear@1
|
526 }
|
nuclear@1
|
527
|
nuclear@1
|
528 glBegin(GL_LINES);
|
nuclear@1
|
529 for(size_t i=0; i<nverts; i++) {
|
nuclear@1
|
530 glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z);
|
nuclear@1
|
531 Vector3 end = varr[i] + norm[i] * vis_vecsize;
|
nuclear@1
|
532 glVertexAttrib3f(vert_loc, end.x, end.y, end.z);
|
nuclear@1
|
533 }
|
nuclear@1
|
534 glEnd();
|
nuclear@1
|
535
|
nuclear@1
|
536 #endif // USE_OLDGL
|
nuclear@1
|
537 }
|
nuclear@1
|
538
|
nuclear@1
|
539 void Mesh::draw_tangents() const
|
nuclear@1
|
540 {
|
nuclear@1
|
541 #ifdef USE_OLDGL
|
nuclear@1
|
542 int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX];
|
nuclear@1
|
543 Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@1
|
544 Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT);
|
nuclear@1
|
545
|
nuclear@1
|
546 if(!varr || !tang || vert_loc < 0) {
|
nuclear@1
|
547 return;
|
nuclear@1
|
548 }
|
nuclear@1
|
549
|
nuclear@1
|
550 glBegin(GL_LINES);
|
nuclear@1
|
551 for(size_t i=0; i<nverts; i++) {
|
nuclear@1
|
552 glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z);
|
nuclear@1
|
553 Vector3 end = varr[i] + tang[i] * vis_vecsize;
|
nuclear@1
|
554 glVertexAttrib3f(vert_loc, end.x, end.y, end.z);
|
nuclear@1
|
555 }
|
nuclear@1
|
556 glEnd();
|
nuclear@1
|
557
|
nuclear@1
|
558 #endif // USE_OLDGL
|
nuclear@1
|
559 }
|
nuclear@1
|
560
|
nuclear@1
|
561 #if 0
|
nuclear@1
|
562 void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const
|
nuclear@1
|
563 {
|
nuclear@1
|
564 if(!aabb_valid) {
|
nuclear@1
|
565 ((Mesh*)this)->calc_aabb();
|
nuclear@1
|
566 }
|
nuclear@1
|
567 *vmin = aabb.min;
|
nuclear@1
|
568 *vmax = aabb.max;
|
nuclear@1
|
569 }
|
nuclear@1
|
570
|
nuclear@1
|
571 const AABox &Mesh::get_aabbox() const
|
nuclear@1
|
572 {
|
nuclear@1
|
573 if(!aabb_valid) {
|
nuclear@1
|
574 ((Mesh*)this)->calc_aabb();
|
nuclear@1
|
575 }
|
nuclear@1
|
576 return aabb;
|
nuclear@1
|
577 }
|
nuclear@1
|
578
|
nuclear@1
|
579 float Mesh::get_bsphere(Vector3 *center, float *rad) const
|
nuclear@1
|
580 {
|
nuclear@1
|
581 if(!bsph_valid) {
|
nuclear@1
|
582 ((Mesh*)this)->calc_bsph();
|
nuclear@1
|
583 }
|
nuclear@1
|
584 *center = bsph.center;
|
nuclear@1
|
585 *rad = bsph.radius;
|
nuclear@1
|
586 return bsph.radius;
|
nuclear@1
|
587 }
|
nuclear@1
|
588
|
nuclear@1
|
589 const Sphere &Mesh::get_bsphere() const
|
nuclear@1
|
590 {
|
nuclear@1
|
591 if(!bsph_valid) {
|
nuclear@1
|
592 ((Mesh*)this)->calc_bsph();
|
nuclear@1
|
593 }
|
nuclear@1
|
594 return bsph;
|
nuclear@1
|
595 }
|
nuclear@1
|
596
|
nuclear@1
|
597 /// static function
|
nuclear@1
|
598 void Mesh::set_intersect_mode(unsigned int mode)
|
nuclear@1
|
599 {
|
nuclear@1
|
600 Mesh::intersect_mode = mode;
|
nuclear@1
|
601 }
|
nuclear@1
|
602
|
nuclear@1
|
603 /// static function
|
nuclear@1
|
604 unsigned int Mesh::get_intersect_mode()
|
nuclear@1
|
605 {
|
nuclear@1
|
606 return Mesh::intersect_mode;
|
nuclear@1
|
607 }
|
nuclear@1
|
608
|
nuclear@1
|
609 /// static function
|
nuclear@1
|
610 void Mesh::set_vertex_select_distance(float dist)
|
nuclear@1
|
611 {
|
nuclear@1
|
612 Mesh::vertex_sel_dist = dist;
|
nuclear@1
|
613 }
|
nuclear@1
|
614
|
nuclear@1
|
615 /// static function
|
nuclear@1
|
616 float Mesh::get_vertex_select_distance()
|
nuclear@1
|
617 {
|
nuclear@1
|
618 return Mesh::vertex_sel_dist;
|
nuclear@1
|
619 }
|
nuclear@1
|
620
|
nuclear@1
|
621 /*bool Mesh::intersect(const Ray &ray, HitPoint *hit) const
|
nuclear@1
|
622 {
|
nuclear@1
|
623 assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE));
|
nuclear@1
|
624
|
nuclear@1
|
625 const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@1
|
626 const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL);
|
nuclear@1
|
627 if(!varr) {
|
nuclear@1
|
628 return false;
|
nuclear@1
|
629 }
|
nuclear@1
|
630 const unsigned int *idxarr = get_index_data();
|
nuclear@1
|
631
|
nuclear@1
|
632 // first test with the bounding box
|
nuclear@1
|
633 AABox box;
|
nuclear@1
|
634 get_aabbox(&box.min, &box.max);
|
nuclear@1
|
635 if(!box.intersect(ray)) {
|
nuclear@1
|
636 return false;
|
nuclear@1
|
637 }
|
nuclear@1
|
638
|
nuclear@1
|
639 HitPoint nearest_hit;
|
nuclear@1
|
640 nearest_hit.dist = FLT_MAX;
|
nuclear@1
|
641 nearest_hit.obj = 0;
|
nuclear@1
|
642
|
nuclear@1
|
643 if(Mesh::intersect_mode & ISECT_VERTICES) {
|
nuclear@1
|
644 // we asked for "intersections" with the vertices of the mesh
|
nuclear@1
|
645 long nearest_vidx = -1;
|
nuclear@1
|
646 float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist;
|
nuclear@1
|
647
|
nuclear@1
|
648 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@1
|
649
|
nuclear@1
|
650 if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) {
|
nuclear@1
|
651 continue;
|
nuclear@1
|
652 }
|
nuclear@1
|
653
|
nuclear@1
|
654 // project the vertex onto the ray line
|
nuclear@1
|
655 float t = dot_product(varr[i] - ray.origin, ray.dir);
|
nuclear@1
|
656 Vector3 vproj = ray.origin + ray.dir * t;
|
nuclear@1
|
657
|
nuclear@1
|
658 float dist_sq = (vproj - varr[i]).length_sq();
|
nuclear@1
|
659 if(dist_sq < thres_sq) {
|
nuclear@1
|
660 if(!hit) {
|
nuclear@1
|
661 return true;
|
nuclear@1
|
662 }
|
nuclear@1
|
663 if(t < nearest_hit.dist) {
|
nuclear@1
|
664 nearest_hit.dist = t;
|
nuclear@1
|
665 nearest_vidx = i;
|
nuclear@1
|
666 }
|
nuclear@1
|
667 }
|
nuclear@1
|
668 }
|
nuclear@1
|
669
|
nuclear@1
|
670 if(nearest_vidx != -1) {
|
nuclear@1
|
671 hitvert = varr[nearest_vidx];
|
nuclear@1
|
672 nearest_hit.obj = &hitvert;
|
nuclear@1
|
673 }
|
nuclear@1
|
674
|
nuclear@1
|
675 } else {
|
nuclear@1
|
676 // regular intersection test with polygons
|
nuclear@1
|
677
|
nuclear@1
|
678 for(unsigned int i=0; i<nfaces; i++) {
|
nuclear@1
|
679 Triangle face(i, varr, idxarr);
|
nuclear@1
|
680
|
nuclear@1
|
681 // ignore back-facing polygons if the mode flags include ISECT_FRONT
|
nuclear@1
|
682 if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) {
|
nuclear@1
|
683 continue;
|
nuclear@1
|
684 }
|
nuclear@1
|
685
|
nuclear@1
|
686 HitPoint fhit;
|
nuclear@1
|
687 if(face.intersect(ray, hit ? &fhit : 0)) {
|
nuclear@1
|
688 if(!hit) {
|
nuclear@1
|
689 return true;
|
nuclear@1
|
690 }
|
nuclear@1
|
691 if(fhit.dist < nearest_hit.dist) {
|
nuclear@1
|
692 nearest_hit = fhit;
|
nuclear@1
|
693 hitface = face;
|
nuclear@1
|
694 }
|
nuclear@1
|
695 }
|
nuclear@1
|
696 }
|
nuclear@1
|
697 }
|
nuclear@1
|
698
|
nuclear@1
|
699 if(nearest_hit.obj) {
|
nuclear@1
|
700 if(hit) {
|
nuclear@1
|
701 *hit = nearest_hit;
|
nuclear@1
|
702
|
nuclear@1
|
703 // if we are interested in the mesh and not the faces set obj to this
|
nuclear@1
|
704 if(Mesh::intersect_mode & ISECT_FACE) {
|
nuclear@1
|
705 hit->obj = &hitface;
|
nuclear@1
|
706 } else if(Mesh::intersect_mode & ISECT_VERTICES) {
|
nuclear@1
|
707 hit->obj = &hitvert;
|
nuclear@1
|
708 } else {
|
nuclear@1
|
709 hit->obj = this;
|
nuclear@1
|
710 }
|
nuclear@1
|
711 }
|
nuclear@1
|
712 return true;
|
nuclear@1
|
713 }
|
nuclear@1
|
714 return false;
|
nuclear@1
|
715 }*/
|
nuclear@1
|
716
|
nuclear@1
|
717
|
nuclear@1
|
718 // ------ private member functions ------
|
nuclear@1
|
719
|
nuclear@1
|
720 void Mesh::calc_aabb()
|
nuclear@1
|
721 {
|
nuclear@1
|
722 // the cast is to force calling the const version which doesn't invalidate
|
nuclear@1
|
723 if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) {
|
nuclear@1
|
724 return;
|
nuclear@1
|
725 }
|
nuclear@1
|
726
|
nuclear@1
|
727 aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX);
|
nuclear@1
|
728 aabb.max = -aabb.min;
|
nuclear@1
|
729
|
nuclear@1
|
730 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@1
|
731 Vector4 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@1
|
732 for(int j=0; j<3; j++) {
|
nuclear@1
|
733 if(v[j] < aabb.min[j]) {
|
nuclear@1
|
734 aabb.min[j] = v[j];
|
nuclear@1
|
735 }
|
nuclear@1
|
736 if(v[j] > aabb.max[j]) {
|
nuclear@1
|
737 aabb.max[j] = v[j];
|
nuclear@1
|
738 }
|
nuclear@1
|
739 }
|
nuclear@1
|
740 }
|
nuclear@1
|
741 aabb_valid = true;
|
nuclear@1
|
742 }
|
nuclear@1
|
743
|
nuclear@1
|
744 void Mesh::calc_bsph()
|
nuclear@1
|
745 {
|
nuclear@1
|
746 // the cast is to force calling the const version which doesn't invalidate
|
nuclear@1
|
747 if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) {
|
nuclear@1
|
748 return;
|
nuclear@1
|
749 }
|
nuclear@1
|
750
|
nuclear@1
|
751 Vector3 v;
|
nuclear@1
|
752 bsph.center = Vector3(0, 0, 0);
|
nuclear@1
|
753
|
nuclear@1
|
754 // first find the center
|
nuclear@1
|
755 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@1
|
756 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@1
|
757 bsph.center += v;
|
nuclear@1
|
758 }
|
nuclear@1
|
759 bsph.center /= (float)nverts;
|
nuclear@1
|
760
|
nuclear@1
|
761 bsph.radius = 0.0f;
|
nuclear@1
|
762 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@1
|
763 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@1
|
764 float dist_sq = (v - bsph.center).length_sq();
|
nuclear@1
|
765 if(dist_sq > bsph.radius) {
|
nuclear@1
|
766 bsph.radius = dist_sq;
|
nuclear@1
|
767 }
|
nuclear@1
|
768 }
|
nuclear@1
|
769 bsph.radius = sqrt(bsph.radius);
|
nuclear@1
|
770
|
nuclear@1
|
771 bsph_valid = true;
|
nuclear@1
|
772 }
|
nuclear@1
|
773 #endif
|
nuclear@1
|
774
|
nuclear@1
|
775 void Mesh::update_buffers()
|
nuclear@1
|
776 {
|
nuclear@1
|
777 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@1
|
778 if(has_attrib(i) && !vattr[i].vbo_valid) {
|
nuclear@1
|
779 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@1
|
780 glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW);
|
nuclear@1
|
781 vattr[i].vbo_valid = true;
|
nuclear@1
|
782 }
|
nuclear@1
|
783 }
|
nuclear@1
|
784 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@1
|
785
|
nuclear@1
|
786 if(idata_valid && !ibo_valid) {
|
nuclear@1
|
787 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@1
|
788 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW);
|
nuclear@1
|
789 ibo_valid = true;
|
nuclear@1
|
790 }
|
nuclear@1
|
791 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@1
|
792 }
|
nuclear@1
|
793
|
nuclear@1
|
794 void Mesh::update_wire_ibo()
|
nuclear@1
|
795 {
|
nuclear@1
|
796 update_buffers();
|
nuclear@1
|
797
|
nuclear@1
|
798 if(wire_ibo_valid) {
|
nuclear@1
|
799 return;
|
nuclear@1
|
800 }
|
nuclear@1
|
801
|
nuclear@1
|
802 if(!wire_ibo) {
|
nuclear@1
|
803 glGenBuffers(1, &wire_ibo);
|
nuclear@1
|
804 }
|
nuclear@1
|
805
|
nuclear@1
|
806 unsigned int *wire_idxarr = new unsigned int[nfaces * 6];
|
nuclear@1
|
807 unsigned int *dest = wire_idxarr;
|
nuclear@1
|
808
|
nuclear@1
|
809 if(ibo_valid) {
|
nuclear@1
|
810 // we're dealing with an indexed mesh
|
nuclear@1
|
811 const unsigned int *idxarr = ((const Mesh*)this)->get_index_data();
|
nuclear@1
|
812
|
nuclear@1
|
813 for(unsigned int i=0; i<nfaces; i++) {
|
nuclear@1
|
814 *dest++ = idxarr[0];
|
nuclear@1
|
815 *dest++ = idxarr[1];
|
nuclear@1
|
816 *dest++ = idxarr[1];
|
nuclear@1
|
817 *dest++ = idxarr[2];
|
nuclear@1
|
818 *dest++ = idxarr[2];
|
nuclear@1
|
819 *dest++ = idxarr[0];
|
nuclear@1
|
820 idxarr += 3;
|
nuclear@1
|
821 }
|
nuclear@1
|
822 } else {
|
nuclear@1
|
823 // not an indexed mesh ...
|
nuclear@1
|
824 for(unsigned int i=0; i<nfaces; i++) {
|
nuclear@1
|
825 int vidx = i * 3;
|
nuclear@1
|
826 *dest++ = vidx;
|
nuclear@1
|
827 *dest++ = vidx + 1;
|
nuclear@1
|
828 *dest++ = vidx + 1;
|
nuclear@1
|
829 *dest++ = vidx + 2;
|
nuclear@1
|
830 *dest++ = vidx + 2;
|
nuclear@1
|
831 *dest++ = vidx;
|
nuclear@1
|
832 }
|
nuclear@1
|
833 }
|
nuclear@1
|
834
|
nuclear@1
|
835 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo);
|
nuclear@1
|
836 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW);
|
nuclear@1
|
837 delete [] wire_idxarr;
|
nuclear@1
|
838 wire_ibo_valid = true;
|
nuclear@1
|
839 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@1
|
840 }
|
nuclear@1
|
841
|
nuclear@1
|
842
|
nuclear@1
|
843 // ------ class Triangle ------
|
nuclear@1
|
844 Triangle::Triangle()
|
nuclear@1
|
845 {
|
nuclear@1
|
846 normal_valid = false;
|
nuclear@1
|
847 id = -1;
|
nuclear@1
|
848 }
|
nuclear@1
|
849
|
nuclear@1
|
850 Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2)
|
nuclear@1
|
851 {
|
nuclear@1
|
852 v[0] = v0;
|
nuclear@1
|
853 v[1] = v1;
|
nuclear@1
|
854 v[2] = v2;
|
nuclear@1
|
855 normal_valid = false;
|
nuclear@1
|
856 id = -1;
|
nuclear@1
|
857 }
|
nuclear@1
|
858
|
nuclear@1
|
859 Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr)
|
nuclear@1
|
860 {
|
nuclear@1
|
861 if(idxarr) {
|
nuclear@1
|
862 v[0] = varr[idxarr[n * 3]];
|
nuclear@1
|
863 v[1] = varr[idxarr[n * 3 + 1]];
|
nuclear@1
|
864 v[2] = varr[idxarr[n * 3 + 2]];
|
nuclear@1
|
865 } else {
|
nuclear@1
|
866 v[0] = varr[n * 3];
|
nuclear@1
|
867 v[1] = varr[n * 3 + 1];
|
nuclear@1
|
868 v[2] = varr[n * 3 + 2];
|
nuclear@1
|
869 }
|
nuclear@1
|
870 normal_valid = false;
|
nuclear@1
|
871 id = n;
|
nuclear@1
|
872 }
|
nuclear@1
|
873
|
nuclear@1
|
874 void Triangle::calc_normal()
|
nuclear@1
|
875 {
|
nuclear@1
|
876 normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized();
|
nuclear@1
|
877 normal_valid = true;
|
nuclear@1
|
878 }
|
nuclear@1
|
879
|
nuclear@1
|
880 const Vector3 &Triangle::get_normal() const
|
nuclear@1
|
881 {
|
nuclear@1
|
882 if(!normal_valid) {
|
nuclear@1
|
883 ((Triangle*)this)->calc_normal();
|
nuclear@1
|
884 }
|
nuclear@1
|
885 return normal;
|
nuclear@1
|
886 }
|
nuclear@1
|
887
|
nuclear@1
|
888 void Triangle::transform(const Matrix4x4 &xform)
|
nuclear@1
|
889 {
|
nuclear@1
|
890 v[0].transform(xform);
|
nuclear@1
|
891 v[1].transform(xform);
|
nuclear@1
|
892 v[2].transform(xform);
|
nuclear@1
|
893 normal_valid = false;
|
nuclear@1
|
894 }
|
nuclear@1
|
895
|
nuclear@1
|
896 void Triangle::draw() const
|
nuclear@1
|
897 {
|
nuclear@1
|
898 Vector3 n[3];
|
nuclear@1
|
899 n[0] = get_normal();
|
nuclear@1
|
900 n[1] = get_normal();
|
nuclear@1
|
901 n[2] = get_normal();
|
nuclear@1
|
902
|
nuclear@1
|
903 int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX);
|
nuclear@1
|
904 int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL);
|
nuclear@1
|
905
|
nuclear@1
|
906 glEnableVertexAttribArray(vloc);
|
nuclear@1
|
907 glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x);
|
nuclear@1
|
908 glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x);
|
nuclear@1
|
909
|
nuclear@1
|
910 glDrawArrays(GL_TRIANGLES, 0, 3);
|
nuclear@1
|
911
|
nuclear@1
|
912 glDisableVertexAttribArray(vloc);
|
nuclear@1
|
913 glDisableVertexAttribArray(nloc);
|
nuclear@1
|
914 CHECKGLERR;
|
nuclear@1
|
915 }
|
nuclear@1
|
916
|
nuclear@1
|
917 void Triangle::draw_wire() const
|
nuclear@1
|
918 {
|
nuclear@1
|
919 static const int idxarr[] = {0, 1, 1, 2, 2, 0};
|
nuclear@1
|
920 int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX);
|
nuclear@1
|
921
|
nuclear@1
|
922 glEnableVertexAttribArray(vloc);
|
nuclear@1
|
923 glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x);
|
nuclear@1
|
924
|
nuclear@1
|
925 glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr);
|
nuclear@1
|
926
|
nuclear@1
|
927 glDisableVertexAttribArray(vloc);
|
nuclear@1
|
928 CHECKGLERR;
|
nuclear@1
|
929 }
|
nuclear@1
|
930
|
nuclear@1
|
931 Vector3 Triangle::calc_barycentric(const Vector3 &pos) const
|
nuclear@1
|
932 {
|
nuclear@1
|
933 Vector3 norm = get_normal();
|
nuclear@1
|
934
|
nuclear@1
|
935 float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm));
|
nuclear@1
|
936 if(area_sq < 1e-5) {
|
nuclear@1
|
937 return Vector3(0, 0, 0);
|
nuclear@1
|
938 }
|
nuclear@1
|
939
|
nuclear@1
|
940 float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm));
|
nuclear@1
|
941 float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm));
|
nuclear@1
|
942 float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm));
|
nuclear@1
|
943
|
nuclear@1
|
944 return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq);
|
nuclear@1
|
945 }
|
nuclear@1
|
946
|
nuclear@1
|
947 /*bool Triangle::intersect(const Ray &ray, HitPoint *hit) const
|
nuclear@1
|
948 {
|
nuclear@1
|
949 Vector3 normal = get_normal();
|
nuclear@1
|
950
|
nuclear@1
|
951 float ndotdir = dot_product(ray.dir, normal);
|
nuclear@1
|
952 if(fabs(ndotdir) < 1e-4) {
|
nuclear@1
|
953 return false;
|
nuclear@1
|
954 }
|
nuclear@1
|
955
|
nuclear@1
|
956 Vector3 vertdir = v[0] - ray.origin;
|
nuclear@1
|
957 float t = dot_product(normal, vertdir) / ndotdir;
|
nuclear@1
|
958
|
nuclear@1
|
959 Vector3 pos = ray.origin + ray.dir * t;
|
nuclear@1
|
960 Vector3 bary = calc_barycentric(pos);
|
nuclear@1
|
961
|
nuclear@1
|
962 if(bary.x + bary.y + bary.z > 1.00001) {
|
nuclear@1
|
963 return false;
|
nuclear@1
|
964 }
|
nuclear@1
|
965
|
nuclear@1
|
966 if(hit) {
|
nuclear@1
|
967 hit->dist = t;
|
nuclear@1
|
968 hit->pos = ray.origin + ray.dir * t;
|
nuclear@1
|
969 hit->normal = normal;
|
nuclear@1
|
970 hit->obj = this;
|
nuclear@1
|
971 }
|
nuclear@1
|
972 return true;
|
nuclear@1
|
973 }*/
|