rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <float.h>
|
nuclear@0
|
4 #include <assert.h>
|
nuclear@0
|
5 #include "opengl.h"
|
nuclear@0
|
6 #include "mesh.h"
|
nuclear@0
|
7 //#include "xform_node.h"
|
nuclear@0
|
8
|
nuclear@11
|
9 #define USE_OLDGL
|
nuclear@11
|
10
|
nuclear@1
|
11 int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5, 6 };
|
nuclear@1
|
12 /*
|
nuclear@0
|
13 (int)SDR_ATTR_VERTEX,
|
nuclear@0
|
14 (int)SDR_ATTR_NORMAL,
|
nuclear@0
|
15 (int)SDR_ATTR_TANGENT,
|
nuclear@0
|
16 (int)SDR_ATTR_TEXCOORD,
|
nuclear@0
|
17 (int)SDR_ATTR_COLOR,
|
nuclear@0
|
18 -1, -1};
|
nuclear@1
|
19 */
|
nuclear@0
|
20 unsigned int Mesh::intersect_mode = ISECT_DEFAULT;
|
nuclear@0
|
21 float Mesh::vertex_sel_dist = 0.01;
|
nuclear@0
|
22 float Mesh::vis_vecsize = 1.0;
|
nuclear@0
|
23
|
nuclear@0
|
24 Mesh::Mesh()
|
nuclear@0
|
25 {
|
nuclear@0
|
26 clear();
|
nuclear@0
|
27
|
nuclear@0
|
28 glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects);
|
nuclear@0
|
29
|
nuclear@0
|
30 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
31 vattr[i].vbo = buffer_objects[i];
|
nuclear@0
|
32 }
|
nuclear@0
|
33 ibo = buffer_objects[NUM_MESH_ATTR];
|
nuclear@0
|
34 wire_ibo = 0;
|
nuclear@0
|
35 }
|
nuclear@0
|
36
|
nuclear@0
|
37 Mesh::~Mesh()
|
nuclear@0
|
38 {
|
nuclear@0
|
39 glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects);
|
nuclear@0
|
40
|
nuclear@0
|
41 if(wire_ibo) {
|
nuclear@0
|
42 glDeleteBuffers(1, &wire_ibo);
|
nuclear@0
|
43 }
|
nuclear@0
|
44 }
|
nuclear@0
|
45
|
nuclear@0
|
46 Mesh::Mesh(const Mesh &rhs)
|
nuclear@0
|
47 {
|
nuclear@0
|
48 clear();
|
nuclear@0
|
49
|
nuclear@0
|
50 glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects);
|
nuclear@0
|
51
|
nuclear@0
|
52 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
53 vattr[i].vbo = buffer_objects[i];
|
nuclear@0
|
54 }
|
nuclear@0
|
55 ibo = buffer_objects[NUM_MESH_ATTR];
|
nuclear@0
|
56 wire_ibo = 0;
|
nuclear@0
|
57
|
nuclear@0
|
58 clone(rhs);
|
nuclear@0
|
59 }
|
nuclear@0
|
60
|
nuclear@0
|
61 Mesh &Mesh::operator =(const Mesh &rhs)
|
nuclear@0
|
62 {
|
nuclear@0
|
63 if(&rhs != this) {
|
nuclear@0
|
64 clone(rhs);
|
nuclear@0
|
65 }
|
nuclear@0
|
66 return *this;
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69 bool Mesh::clone(const Mesh &m)
|
nuclear@0
|
70 {
|
nuclear@0
|
71 clear();
|
nuclear@0
|
72
|
nuclear@0
|
73 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
74 if(m.has_attrib(i)) {
|
nuclear@0
|
75 m.get_attrib_data(i); // force validation of the actual data on the source mesh
|
nuclear@0
|
76
|
nuclear@0
|
77 vattr[i].nelem = m.vattr[i].nelem;
|
nuclear@0
|
78 vattr[i].data = m.vattr[i].data; // copy the actual data
|
nuclear@0
|
79 vattr[i].data_valid = true;
|
nuclear@0
|
80 }
|
nuclear@0
|
81 }
|
nuclear@0
|
82
|
nuclear@0
|
83 if(m.is_indexed()) {
|
nuclear@0
|
84 m.get_index_data(); // again, force validation
|
nuclear@0
|
85
|
nuclear@0
|
86 // copy the index data
|
nuclear@0
|
87 idata = m.idata;
|
nuclear@0
|
88 idata_valid = true;
|
nuclear@0
|
89 }
|
nuclear@0
|
90
|
nuclear@0
|
91 name = m.name;
|
nuclear@0
|
92 nverts = m.nverts;
|
nuclear@0
|
93 nfaces = m.nfaces;
|
nuclear@0
|
94
|
nuclear@0
|
95 //bones = m.bones;
|
nuclear@0
|
96
|
nuclear@0
|
97 memcpy(cur_val, m.cur_val, sizeof cur_val);
|
nuclear@0
|
98
|
nuclear@0
|
99 aabb = m.aabb;
|
nuclear@0
|
100 aabb_valid = m.aabb_valid;
|
nuclear@0
|
101 bsph = m.bsph;
|
nuclear@0
|
102 bsph_valid = m.bsph_valid;
|
nuclear@0
|
103
|
nuclear@0
|
104 hitface = m.hitface;
|
nuclear@0
|
105 hitvert = m.hitvert;
|
nuclear@0
|
106
|
nuclear@0
|
107 intersect_mode = m.intersect_mode;
|
nuclear@0
|
108 vertex_sel_dist = m.vertex_sel_dist;
|
nuclear@0
|
109 vis_vecsize = m.vis_vecsize;
|
nuclear@0
|
110
|
nuclear@0
|
111 return true;
|
nuclear@0
|
112 }
|
nuclear@0
|
113
|
nuclear@0
|
114 void Mesh::set_name(const char *name)
|
nuclear@0
|
115 {
|
nuclear@0
|
116 this->name = name;
|
nuclear@0
|
117 }
|
nuclear@0
|
118
|
nuclear@0
|
119 const char *Mesh::get_name() const
|
nuclear@0
|
120 {
|
nuclear@0
|
121 return name.c_str();
|
nuclear@0
|
122 }
|
nuclear@0
|
123
|
nuclear@0
|
124 bool Mesh::has_attrib(int attr) const
|
nuclear@0
|
125 {
|
nuclear@0
|
126 if(attr < 0 || attr >= NUM_MESH_ATTR) {
|
nuclear@0
|
127 return false;
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@0
|
130 // if neither of these is valid, then nobody has set this attribute
|
nuclear@0
|
131 return vattr[attr].vbo_valid || vattr[attr].data_valid;
|
nuclear@0
|
132 }
|
nuclear@0
|
133
|
nuclear@0
|
134 bool Mesh::is_indexed() const
|
nuclear@0
|
135 {
|
nuclear@0
|
136 return ibo_valid || idata_valid;
|
nuclear@0
|
137 }
|
nuclear@0
|
138
|
nuclear@0
|
139 void Mesh::clear()
|
nuclear@0
|
140 {
|
nuclear@0
|
141 //bones.clear();
|
nuclear@0
|
142
|
nuclear@0
|
143 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
144 vattr[i].nelem = 0;
|
nuclear@0
|
145 vattr[i].vbo_valid = false;
|
nuclear@0
|
146 vattr[i].data_valid = false;
|
nuclear@0
|
147 //vattr[i].sdr_loc = -1;
|
nuclear@0
|
148 vattr[i].data.clear();
|
nuclear@0
|
149 }
|
nuclear@0
|
150 ibo_valid = idata_valid = false;
|
nuclear@0
|
151 idata.clear();
|
nuclear@0
|
152
|
nuclear@0
|
153 wire_ibo_valid = false;
|
nuclear@0
|
154
|
nuclear@0
|
155 nverts = nfaces = 0;
|
nuclear@0
|
156
|
nuclear@0
|
157 bsph_valid = false;
|
nuclear@0
|
158 aabb_valid = false;
|
nuclear@0
|
159 }
|
nuclear@0
|
160
|
nuclear@0
|
161 float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data)
|
nuclear@0
|
162 {
|
nuclear@0
|
163 if(attrib < 0 || attrib >= NUM_MESH_ATTR) {
|
nuclear@0
|
164 fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@0
|
165 return 0;
|
nuclear@0
|
166 }
|
nuclear@0
|
167
|
nuclear@0
|
168 if(nverts && num != nverts) {
|
nuclear@0
|
169 fprintf(stderr, "%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts);
|
nuclear@0
|
170 return 0;
|
nuclear@0
|
171 }
|
nuclear@0
|
172 nverts = num;
|
nuclear@0
|
173
|
nuclear@0
|
174 vattr[attrib].data.clear();
|
nuclear@0
|
175 vattr[attrib].nelem = nelem;
|
nuclear@0
|
176 vattr[attrib].data.resize(num * nelem);
|
nuclear@0
|
177
|
nuclear@0
|
178 if(data) {
|
nuclear@0
|
179 memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data);
|
nuclear@0
|
180 }
|
nuclear@0
|
181
|
nuclear@0
|
182 vattr[attrib].data_valid = true;
|
nuclear@0
|
183 vattr[attrib].vbo_valid = false;
|
nuclear@0
|
184 return &vattr[attrib].data[0];
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187 float *Mesh::get_attrib_data(int attrib)
|
nuclear@0
|
188 {
|
nuclear@0
|
189 if(attrib < 0 || attrib >= NUM_MESH_ATTR) {
|
nuclear@0
|
190 fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@0
|
191 return 0;
|
nuclear@0
|
192 }
|
nuclear@0
|
193
|
nuclear@0
|
194 vattr[attrib].vbo_valid = false;
|
nuclear@0
|
195 return (float*)((const Mesh*)this)->get_attrib_data(attrib);
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 const float *Mesh::get_attrib_data(int attrib) const
|
nuclear@0
|
199 {
|
nuclear@0
|
200 if(attrib < 0 || attrib >= NUM_MESH_ATTR) {
|
nuclear@0
|
201 fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@0
|
202 return 0;
|
nuclear@0
|
203 }
|
nuclear@0
|
204
|
nuclear@0
|
205 if(!vattr[attrib].data_valid) {
|
nuclear@0
|
206 #if GL_ES_VERSION_2_0
|
nuclear@0
|
207 fprintf(stderr, "%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__);
|
nuclear@0
|
208 return 0;
|
nuclear@0
|
209 #else
|
nuclear@0
|
210 if(!vattr[attrib].vbo_valid) {
|
nuclear@0
|
211 fprintf(stderr, "%s: unavailable attrib: %d\n", __FUNCTION__, attrib);
|
nuclear@0
|
212 return 0;
|
nuclear@0
|
213 }
|
nuclear@0
|
214
|
nuclear@0
|
215 // local data copy is unavailable, grab the data from the vbo
|
nuclear@0
|
216 Mesh *m = (Mesh*)this;
|
nuclear@0
|
217 m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem);
|
nuclear@0
|
218
|
nuclear@0
|
219 glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo);
|
nuclear@0
|
220 void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@0
|
221 memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float));
|
nuclear@0
|
222 glUnmapBuffer(GL_ARRAY_BUFFER);
|
nuclear@0
|
223
|
nuclear@0
|
224 vattr[attrib].data_valid = true;
|
nuclear@0
|
225 #endif
|
nuclear@0
|
226 }
|
nuclear@0
|
227
|
nuclear@0
|
228 return &vattr[attrib].data[0];
|
nuclear@0
|
229 }
|
nuclear@0
|
230
|
nuclear@0
|
231 void Mesh::set_attrib(int attrib, int idx, const Vector4 &v)
|
nuclear@0
|
232 {
|
nuclear@0
|
233 float *data = get_attrib_data(attrib);
|
nuclear@0
|
234 if(data) {
|
nuclear@0
|
235 data += idx * vattr[attrib].nelem;
|
nuclear@0
|
236 for(int i=0; i<vattr[attrib].nelem; i++) {
|
nuclear@0
|
237 data[i] = v[i];
|
nuclear@0
|
238 }
|
nuclear@0
|
239 }
|
nuclear@0
|
240 }
|
nuclear@0
|
241
|
nuclear@0
|
242 Vector4 Mesh::get_attrib(int attrib, int idx) const
|
nuclear@0
|
243 {
|
nuclear@0
|
244 Vector4 v(0.0, 0.0, 0.0, 1.0);
|
nuclear@0
|
245 const float *data = get_attrib_data(attrib);
|
nuclear@0
|
246 if(data) {
|
nuclear@0
|
247 data += idx * vattr[attrib].nelem;
|
nuclear@0
|
248 for(int i=0; i<vattr[attrib].nelem; i++) {
|
nuclear@0
|
249 v[i] = data[i];
|
nuclear@0
|
250 }
|
nuclear@0
|
251 }
|
nuclear@0
|
252 return v;
|
nuclear@0
|
253 }
|
nuclear@0
|
254
|
nuclear@0
|
255 int Mesh::get_attrib_count(int attrib) const
|
nuclear@0
|
256 {
|
nuclear@0
|
257 return has_attrib(attrib) ? nverts : 0;
|
nuclear@0
|
258 }
|
nuclear@0
|
259
|
nuclear@0
|
260
|
nuclear@0
|
261 unsigned int *Mesh::set_index_data(int num, const unsigned int *indices)
|
nuclear@0
|
262 {
|
nuclear@0
|
263 int nidx = nfaces * 3;
|
nuclear@0
|
264 if(nidx && num != nidx) {
|
nuclear@0
|
265 fprintf(stderr, "%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx);
|
nuclear@0
|
266 return 0;
|
nuclear@0
|
267 }
|
nuclear@0
|
268 nfaces = num / 3;
|
nuclear@0
|
269
|
nuclear@0
|
270 idata.clear();
|
nuclear@0
|
271 idata.resize(num);
|
nuclear@0
|
272
|
nuclear@0
|
273 if(indices) {
|
nuclear@0
|
274 memcpy(&idata[0], indices, num * sizeof *indices);
|
nuclear@0
|
275 }
|
nuclear@0
|
276
|
nuclear@0
|
277 idata_valid = true;
|
nuclear@0
|
278 ibo_valid = false;
|
nuclear@0
|
279
|
nuclear@0
|
280 return &idata[0];
|
nuclear@0
|
281 }
|
nuclear@0
|
282
|
nuclear@0
|
283 unsigned int *Mesh::get_index_data()
|
nuclear@0
|
284 {
|
nuclear@0
|
285 ibo_valid = false;
|
nuclear@0
|
286 return (unsigned int*)((const Mesh*)this)->get_index_data();
|
nuclear@0
|
287 }
|
nuclear@0
|
288
|
nuclear@0
|
289 const unsigned int *Mesh::get_index_data() const
|
nuclear@0
|
290 {
|
nuclear@0
|
291 if(!idata_valid) {
|
nuclear@0
|
292 #if GL_ES_VERSION_2_0
|
nuclear@0
|
293 fprintf(stderr, "%s: can't read back index data in CrippledGL ES\n", __FUNCTION__);
|
nuclear@0
|
294 return 0;
|
nuclear@0
|
295 #else
|
nuclear@0
|
296 if(!ibo_valid) {
|
nuclear@0
|
297 fprintf(stderr, "%s: indices unavailable\n", __FUNCTION__);
|
nuclear@0
|
298 return 0;
|
nuclear@0
|
299 }
|
nuclear@0
|
300
|
nuclear@0
|
301 // local data copy is unavailable, gram the data from the ibo
|
nuclear@0
|
302 Mesh *m = (Mesh*)this;
|
nuclear@0
|
303 int nidx = nfaces * 3;
|
nuclear@0
|
304 m->idata.resize(nidx);
|
nuclear@0
|
305
|
nuclear@0
|
306 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@0
|
307 void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@0
|
308 memcpy(&m->idata[0], data, nidx * sizeof(unsigned int));
|
nuclear@0
|
309 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
nuclear@0
|
310
|
nuclear@0
|
311 idata_valid = true;
|
nuclear@0
|
312 #endif
|
nuclear@0
|
313 }
|
nuclear@0
|
314
|
nuclear@0
|
315 return &idata[0];
|
nuclear@0
|
316 }
|
nuclear@0
|
317
|
nuclear@0
|
318 int Mesh::get_index_count() const
|
nuclear@0
|
319 {
|
nuclear@0
|
320 return nfaces * 3;
|
nuclear@0
|
321 }
|
nuclear@0
|
322
|
nuclear@0
|
323 void Mesh::append(const Mesh &mesh)
|
nuclear@0
|
324 {
|
nuclear@0
|
325 unsigned int idxoffs = nverts;
|
nuclear@0
|
326
|
nuclear@7
|
327 if(!nverts) {
|
nuclear@7
|
328 clone(mesh);
|
nuclear@7
|
329 return;
|
nuclear@7
|
330 }
|
nuclear@7
|
331
|
nuclear@0
|
332 nverts += mesh.nverts;
|
nuclear@0
|
333 nfaces += mesh.nfaces;
|
nuclear@0
|
334
|
nuclear@0
|
335 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
336 if(has_attrib(i) && mesh.has_attrib(i)) {
|
nuclear@0
|
337 // force validating the data arrays
|
nuclear@0
|
338 get_attrib_data(i);
|
nuclear@0
|
339 mesh.get_attrib_data(i);
|
nuclear@0
|
340
|
nuclear@0
|
341 // append the mesh data
|
nuclear@0
|
342 vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end());
|
nuclear@0
|
343 }
|
nuclear@0
|
344 }
|
nuclear@0
|
345
|
nuclear@0
|
346 if(ibo_valid || idata_valid) {
|
nuclear@0
|
347 // make index arrays valid
|
nuclear@0
|
348 get_index_data();
|
nuclear@0
|
349 mesh.get_index_data();
|
nuclear@0
|
350
|
nuclear@0
|
351 size_t orig_sz = idata.size();
|
nuclear@0
|
352
|
nuclear@0
|
353 idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end());
|
nuclear@0
|
354
|
nuclear@0
|
355 // fixup all the new indices
|
nuclear@0
|
356 for(size_t i=orig_sz; i<idata.size(); i++) {
|
nuclear@0
|
357 idata[i] += idxoffs;
|
nuclear@0
|
358 }
|
nuclear@0
|
359 }
|
nuclear@0
|
360
|
nuclear@0
|
361 // fuck everything
|
nuclear@0
|
362 wire_ibo_valid = false;
|
nuclear@0
|
363 aabb_valid = false;
|
nuclear@0
|
364 bsph_valid = false;
|
nuclear@0
|
365 }
|
nuclear@0
|
366
|
nuclear@0
|
367 // assemble a complete vertex by adding all the useful attributes
|
nuclear@0
|
368 void Mesh::vertex(float x, float y, float z)
|
nuclear@0
|
369 {
|
nuclear@0
|
370 cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f);
|
nuclear@0
|
371 vattr[MESH_ATTR_VERTEX].data_valid = true;
|
nuclear@0
|
372 vattr[MESH_ATTR_VERTEX].nelem = 3;
|
nuclear@0
|
373
|
nuclear@0
|
374 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
375 if(vattr[i].data_valid) {
|
nuclear@0
|
376 for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) {
|
nuclear@0
|
377 vattr[i].data.push_back(cur_val[i][j]);
|
nuclear@0
|
378 }
|
nuclear@0
|
379 }
|
nuclear@0
|
380 vattr[i].vbo_valid = false;
|
nuclear@0
|
381 }
|
nuclear@0
|
382
|
nuclear@0
|
383 if(idata_valid) {
|
nuclear@0
|
384 idata.clear();
|
nuclear@0
|
385 }
|
nuclear@0
|
386 ibo_valid = idata_valid = false;
|
nuclear@0
|
387 }
|
nuclear@0
|
388
|
nuclear@0
|
389 void Mesh::normal(float nx, float ny, float nz)
|
nuclear@0
|
390 {
|
nuclear@0
|
391 cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f);
|
nuclear@0
|
392 vattr[MESH_ATTR_NORMAL].data_valid = true;
|
nuclear@0
|
393 vattr[MESH_ATTR_NORMAL].nelem = 3;
|
nuclear@0
|
394 }
|
nuclear@0
|
395
|
nuclear@0
|
396 void Mesh::tangent(float tx, float ty, float tz)
|
nuclear@0
|
397 {
|
nuclear@0
|
398 cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f);
|
nuclear@0
|
399 vattr[MESH_ATTR_TANGENT].data_valid = true;
|
nuclear@0
|
400 vattr[MESH_ATTR_TANGENT].nelem = 3;
|
nuclear@0
|
401 }
|
nuclear@0
|
402
|
nuclear@0
|
403 void Mesh::texcoord(float u, float v, float w)
|
nuclear@0
|
404 {
|
nuclear@0
|
405 cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f);
|
nuclear@0
|
406 vattr[MESH_ATTR_TEXCOORD].data_valid = true;
|
nuclear@0
|
407 vattr[MESH_ATTR_TEXCOORD].nelem = 3;
|
nuclear@0
|
408 }
|
nuclear@0
|
409
|
nuclear@0
|
410 void Mesh::boneweights(float w1, float w2, float w3, float w4)
|
nuclear@0
|
411 {
|
nuclear@0
|
412 cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4);
|
nuclear@0
|
413 vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true;
|
nuclear@0
|
414 vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4;
|
nuclear@0
|
415 }
|
nuclear@0
|
416
|
nuclear@0
|
417 void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4)
|
nuclear@0
|
418 {
|
nuclear@0
|
419 cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4);
|
nuclear@0
|
420 vattr[MESH_ATTR_BONEIDX].data_valid = true;
|
nuclear@0
|
421 vattr[MESH_ATTR_BONEIDX].nelem = 4;
|
nuclear@0
|
422 }
|
nuclear@0
|
423
|
nuclear@0
|
424 int Mesh::get_poly_count() const
|
nuclear@0
|
425 {
|
nuclear@0
|
426 if(nfaces) {
|
nuclear@0
|
427 return nfaces;
|
nuclear@0
|
428 }
|
nuclear@0
|
429 if(nverts) {
|
nuclear@0
|
430 return nverts / 3;
|
nuclear@0
|
431 }
|
nuclear@0
|
432 return 0;
|
nuclear@0
|
433 }
|
nuclear@0
|
434
|
nuclear@0
|
435 /// static function
|
nuclear@0
|
436 void Mesh::set_attrib_location(int attr, int loc)
|
nuclear@0
|
437 {
|
nuclear@0
|
438 if(attr < 0 || attr >= NUM_MESH_ATTR) {
|
nuclear@0
|
439 return;
|
nuclear@0
|
440 }
|
nuclear@0
|
441 Mesh::global_sdr_loc[attr] = loc;
|
nuclear@0
|
442 }
|
nuclear@0
|
443
|
nuclear@0
|
444 /// static function
|
nuclear@0
|
445 int Mesh::get_attrib_location(int attr)
|
nuclear@0
|
446 {
|
nuclear@0
|
447 if(attr < 0 || attr >= NUM_MESH_ATTR) {
|
nuclear@0
|
448 return -1;
|
nuclear@0
|
449 }
|
nuclear@0
|
450 return Mesh::global_sdr_loc[attr];
|
nuclear@0
|
451 }
|
nuclear@0
|
452
|
nuclear@0
|
453 /// static function
|
nuclear@0
|
454 void Mesh::clear_attrib_locations()
|
nuclear@0
|
455 {
|
nuclear@0
|
456 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
457 Mesh::global_sdr_loc[i] = -1;
|
nuclear@0
|
458 }
|
nuclear@0
|
459 }
|
nuclear@0
|
460
|
nuclear@0
|
461 /// static function
|
nuclear@0
|
462 void Mesh::set_vis_vecsize(float sz)
|
nuclear@0
|
463 {
|
nuclear@0
|
464 Mesh::vis_vecsize = sz;
|
nuclear@0
|
465 }
|
nuclear@0
|
466
|
nuclear@0
|
467 float Mesh::get_vis_vecsize()
|
nuclear@0
|
468 {
|
nuclear@0
|
469 return Mesh::vis_vecsize;
|
nuclear@0
|
470 }
|
nuclear@0
|
471
|
nuclear@0
|
472 void Mesh::apply_xform(const Matrix4x4 &xform)
|
nuclear@0
|
473 {
|
nuclear@0
|
474 Matrix4x4 dir_xform = xform;
|
nuclear@0
|
475 dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f;
|
nuclear@0
|
476 dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f;
|
nuclear@0
|
477 dir_xform[3][3] = 1.0f;
|
nuclear@0
|
478
|
nuclear@0
|
479 apply_xform(xform, dir_xform);
|
nuclear@0
|
480 }
|
nuclear@0
|
481
|
nuclear@0
|
482 void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform)
|
nuclear@0
|
483 {
|
nuclear@0
|
484 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@0
|
485 Vector4 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@0
|
486 set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform));
|
nuclear@0
|
487
|
nuclear@0
|
488 if(has_attrib(MESH_ATTR_NORMAL)) {
|
nuclear@0
|
489 Vector3 n = get_attrib(MESH_ATTR_NORMAL, i);
|
nuclear@0
|
490 set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform));
|
nuclear@0
|
491 }
|
nuclear@0
|
492 if(has_attrib(MESH_ATTR_TANGENT)) {
|
nuclear@0
|
493 Vector3 t = get_attrib(MESH_ATTR_TANGENT, i);
|
nuclear@0
|
494 set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform));
|
nuclear@0
|
495 }
|
nuclear@0
|
496 }
|
nuclear@0
|
497 }
|
nuclear@0
|
498
|
nuclear@0
|
499 void Mesh::flip()
|
nuclear@0
|
500 {
|
nuclear@0
|
501 flip_faces();
|
nuclear@0
|
502 flip_normals();
|
nuclear@0
|
503 }
|
nuclear@0
|
504
|
nuclear@0
|
505 void Mesh::flip_faces()
|
nuclear@0
|
506 {
|
nuclear@0
|
507 if(is_indexed()) {
|
nuclear@0
|
508 unsigned int *indices = get_index_data();
|
nuclear@0
|
509 if(!indices) return;
|
nuclear@0
|
510
|
nuclear@0
|
511 int idxnum = get_index_count();
|
nuclear@0
|
512 for(int i=0; i<idxnum; i+=3) {
|
nuclear@0
|
513 unsigned int tmp = indices[i + 2];
|
nuclear@0
|
514 indices[i + 2] = indices[i + 1];
|
nuclear@0
|
515 indices[i + 1] = tmp;
|
nuclear@0
|
516 }
|
nuclear@0
|
517
|
nuclear@0
|
518 } else {
|
nuclear@0
|
519 Vector3 *verts = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@0
|
520 if(!verts) return;
|
nuclear@0
|
521
|
nuclear@0
|
522 int vnum = get_attrib_count(MESH_ATTR_VERTEX);
|
nuclear@0
|
523 for(int i=0; i<vnum; i+=3) {
|
nuclear@0
|
524 Vector3 tmp = verts[i + 2];
|
nuclear@0
|
525 verts[i + 2] = verts[i + 1];
|
nuclear@0
|
526 verts[i + 1] = tmp;
|
nuclear@0
|
527 }
|
nuclear@0
|
528 }
|
nuclear@0
|
529 }
|
nuclear@0
|
530
|
nuclear@0
|
531 void Mesh::flip_normals()
|
nuclear@0
|
532 {
|
nuclear@0
|
533 Vector3 *normals = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL);
|
nuclear@0
|
534 if(!normals) return;
|
nuclear@0
|
535
|
nuclear@0
|
536 int num = get_attrib_count(MESH_ATTR_NORMAL);
|
nuclear@0
|
537 for(int i=0; i<num; i++) {
|
nuclear@0
|
538 normals[i] = -normals[i];
|
nuclear@0
|
539 }
|
nuclear@0
|
540 }
|
nuclear@0
|
541
|
nuclear@0
|
542 /*
|
nuclear@0
|
543 int Mesh::add_bone(XFormNode *bone)
|
nuclear@0
|
544 {
|
nuclear@0
|
545 int idx = bones.size();
|
nuclear@0
|
546 bones.push_back(bone);
|
nuclear@0
|
547 return idx;
|
nuclear@0
|
548 }
|
nuclear@0
|
549
|
nuclear@0
|
550 const XFormNode *Mesh::get_bone(int idx) const
|
nuclear@0
|
551 {
|
nuclear@0
|
552 if(idx < 0 || idx >= (int)bones.size()) {
|
nuclear@0
|
553 return 0;
|
nuclear@0
|
554 }
|
nuclear@0
|
555 return bones[idx];
|
nuclear@0
|
556 }
|
nuclear@0
|
557
|
nuclear@0
|
558 int Mesh::get_bones_count() const
|
nuclear@0
|
559 {
|
nuclear@0
|
560 return (int)bones.size();
|
nuclear@0
|
561 }
|
nuclear@0
|
562 */
|
nuclear@0
|
563
|
nuclear@0
|
564 void Mesh::draw() const
|
nuclear@0
|
565 {
|
nuclear@1
|
566 int cur_sdr;
|
nuclear@1
|
567 glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
|
nuclear@1
|
568
|
nuclear@0
|
569
|
nuclear@0
|
570 ((Mesh*)this)->update_buffers();
|
nuclear@0
|
571
|
nuclear@0
|
572 if(!vattr[MESH_ATTR_VERTEX].vbo_valid) {
|
nuclear@0
|
573 fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__);
|
nuclear@0
|
574 return;
|
nuclear@0
|
575 }
|
nuclear@0
|
576
|
nuclear@1
|
577 if(cur_sdr) {
|
nuclear@0
|
578 // rendering with shaders
|
nuclear@0
|
579 if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
|
nuclear@0
|
580 fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
|
nuclear@0
|
581 return;
|
nuclear@0
|
582 }
|
nuclear@0
|
583
|
nuclear@0
|
584 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
585 int loc = global_sdr_loc[i];
|
nuclear@0
|
586 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@0
|
587 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@0
|
588 glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@0
|
589 glEnableVertexAttribArray(loc);
|
nuclear@0
|
590 }
|
nuclear@0
|
591 }
|
nuclear@0
|
592 } else {
|
nuclear@0
|
593 #ifndef GL_ES_VERSION_2_0
|
nuclear@0
|
594 // rendering with fixed-function (not available in GLES2)
|
nuclear@0
|
595 glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_VERTEX].vbo);
|
nuclear@0
|
596 glVertexPointer(vattr[MESH_ATTR_VERTEX].nelem, GL_FLOAT, 0, 0);
|
nuclear@0
|
597 glEnableClientState(GL_VERTEX_ARRAY);
|
nuclear@0
|
598
|
nuclear@0
|
599 if(vattr[MESH_ATTR_NORMAL].vbo_valid) {
|
nuclear@0
|
600 glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_NORMAL].vbo);
|
nuclear@0
|
601 glNormalPointer(GL_FLOAT, 0, 0);
|
nuclear@0
|
602 glEnableClientState(GL_NORMAL_ARRAY);
|
nuclear@0
|
603 }
|
nuclear@0
|
604 if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) {
|
nuclear@0
|
605 glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_TEXCOORD].vbo);
|
nuclear@0
|
606 glTexCoordPointer(vattr[MESH_ATTR_TEXCOORD].nelem, GL_FLOAT, 0, 0);
|
nuclear@0
|
607 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@0
|
608 }
|
nuclear@0
|
609 if(vattr[MESH_ATTR_COLOR].vbo_valid) {
|
nuclear@0
|
610 glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_COLOR].vbo);
|
nuclear@0
|
611 glColorPointer(vattr[MESH_ATTR_COLOR].nelem, GL_FLOAT, 0, 0);
|
nuclear@0
|
612 glEnableClientState(GL_COLOR_ARRAY);
|
nuclear@0
|
613 }
|
nuclear@0
|
614 #endif
|
nuclear@0
|
615 }
|
nuclear@0
|
616 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@0
|
617
|
nuclear@0
|
618 if(ibo_valid) {
|
nuclear@0
|
619 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@0
|
620 glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0);
|
nuclear@0
|
621 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@0
|
622 } else {
|
nuclear@0
|
623 glDrawArrays(GL_TRIANGLES, 0, nverts);
|
nuclear@0
|
624 }
|
nuclear@0
|
625
|
nuclear@1
|
626 if(cur_sdr) {
|
nuclear@0
|
627 // rendered with shaders
|
nuclear@0
|
628 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
629 int loc = global_sdr_loc[i];
|
nuclear@0
|
630 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@0
|
631 glDisableVertexAttribArray(loc);
|
nuclear@0
|
632 }
|
nuclear@0
|
633 }
|
nuclear@0
|
634 } else {
|
nuclear@0
|
635 #ifndef GL_ES_VERSION_2_0
|
nuclear@0
|
636 // rendered with fixed-function
|
nuclear@0
|
637 glDisableClientState(GL_VERTEX_ARRAY);
|
nuclear@0
|
638 if(vattr[MESH_ATTR_NORMAL].vbo_valid) {
|
nuclear@0
|
639 glDisableClientState(GL_NORMAL_ARRAY);
|
nuclear@0
|
640 }
|
nuclear@0
|
641 if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) {
|
nuclear@0
|
642 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@0
|
643 }
|
nuclear@0
|
644 if(vattr[MESH_ATTR_COLOR].vbo_valid) {
|
nuclear@0
|
645 glDisableClientState(GL_COLOR_ARRAY);
|
nuclear@0
|
646 }
|
nuclear@0
|
647 #endif
|
nuclear@0
|
648 }
|
nuclear@0
|
649 }
|
nuclear@0
|
650
|
nuclear@0
|
651 void Mesh::draw_wire() const
|
nuclear@0
|
652 {
|
nuclear@0
|
653 ((Mesh*)this)->update_wire_ibo();
|
nuclear@0
|
654
|
nuclear@0
|
655 if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) {
|
nuclear@0
|
656 fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__);
|
nuclear@0
|
657 return;
|
nuclear@0
|
658 }
|
nuclear@0
|
659 if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
|
nuclear@0
|
660 fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
|
nuclear@0
|
661 return;
|
nuclear@0
|
662 }
|
nuclear@0
|
663
|
nuclear@0
|
664 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
665 int loc = global_sdr_loc[i];
|
nuclear@0
|
666 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@0
|
667 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@0
|
668 glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@0
|
669 glEnableVertexAttribArray(loc);
|
nuclear@0
|
670 }
|
nuclear@0
|
671 }
|
nuclear@0
|
672 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@0
|
673
|
nuclear@0
|
674 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo);
|
nuclear@0
|
675 glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0);
|
nuclear@0
|
676 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@0
|
677
|
nuclear@0
|
678 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
679 int loc = global_sdr_loc[i];
|
nuclear@0
|
680 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@0
|
681 glDisableVertexAttribArray(loc);
|
nuclear@0
|
682 }
|
nuclear@0
|
683 }
|
nuclear@0
|
684 }
|
nuclear@0
|
685
|
nuclear@0
|
686 void Mesh::draw_vertices() const
|
nuclear@0
|
687 {
|
nuclear@0
|
688 ((Mesh*)this)->update_buffers();
|
nuclear@0
|
689
|
nuclear@0
|
690 if(!vattr[MESH_ATTR_VERTEX].vbo_valid) {
|
nuclear@0
|
691 fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__);
|
nuclear@0
|
692 return;
|
nuclear@0
|
693 }
|
nuclear@0
|
694 if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
|
nuclear@0
|
695 fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
|
nuclear@0
|
696 return;
|
nuclear@0
|
697 }
|
nuclear@0
|
698
|
nuclear@0
|
699 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
700 int loc = global_sdr_loc[i];
|
nuclear@0
|
701 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@0
|
702 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@0
|
703 glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@0
|
704 glEnableVertexAttribArray(loc);
|
nuclear@0
|
705 }
|
nuclear@0
|
706 }
|
nuclear@0
|
707 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@0
|
708
|
nuclear@0
|
709 glDrawArrays(GL_POINTS, 0, nverts);
|
nuclear@0
|
710
|
nuclear@0
|
711 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
712 int loc = global_sdr_loc[i];
|
nuclear@0
|
713 if(loc >= 0 && vattr[i].vbo_valid) {
|
nuclear@0
|
714 glDisableVertexAttribArray(loc);
|
nuclear@0
|
715 }
|
nuclear@0
|
716 }
|
nuclear@0
|
717 }
|
nuclear@0
|
718
|
nuclear@0
|
719 void Mesh::draw_normals() const
|
nuclear@0
|
720 {
|
nuclear@0
|
721 #ifdef USE_OLDGL
|
nuclear@11
|
722 int cur_sdr;
|
nuclear@11
|
723 glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
|
nuclear@11
|
724
|
nuclear@0
|
725 Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@0
|
726 Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL);
|
nuclear@0
|
727 if(!varr || !norm) {
|
nuclear@0
|
728 return;
|
nuclear@0
|
729 }
|
nuclear@0
|
730
|
nuclear@0
|
731 glBegin(GL_LINES);
|
nuclear@11
|
732 if(cur_sdr) {
|
nuclear@0
|
733 int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX];
|
nuclear@0
|
734 if(vert_loc < 0) {
|
nuclear@0
|
735 glEnd();
|
nuclear@0
|
736 return;
|
nuclear@0
|
737 }
|
nuclear@0
|
738
|
nuclear@0
|
739 for(size_t i=0; i<nverts; i++) {
|
nuclear@0
|
740 glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z);
|
nuclear@0
|
741 Vector3 end = varr[i] + norm[i] * vis_vecsize;
|
nuclear@0
|
742 glVertexAttrib3f(vert_loc, end.x, end.y, end.z);
|
nuclear@0
|
743 }
|
nuclear@0
|
744 } else {
|
nuclear@0
|
745 for(size_t i=0; i<nverts; i++) {
|
nuclear@0
|
746 glVertex3f(varr[i].x, varr[i].y, varr[i].z);
|
nuclear@0
|
747 Vector3 end = varr[i] + norm[i] * vis_vecsize;
|
nuclear@0
|
748 glVertex3f(end.x, end.y, end.z);
|
nuclear@0
|
749 }
|
nuclear@0
|
750 }
|
nuclear@0
|
751 glEnd();
|
nuclear@0
|
752 #endif // USE_OLDGL
|
nuclear@0
|
753 }
|
nuclear@0
|
754
|
nuclear@0
|
755 void Mesh::draw_tangents() const
|
nuclear@0
|
756 {
|
nuclear@0
|
757 #ifdef USE_OLDGL
|
nuclear@11
|
758 int cur_sdr;
|
nuclear@11
|
759 glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
|
nuclear@11
|
760
|
nuclear@0
|
761 Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@0
|
762 Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT);
|
nuclear@0
|
763 if(!varr || !tang) {
|
nuclear@0
|
764 return;
|
nuclear@0
|
765 }
|
nuclear@0
|
766
|
nuclear@0
|
767 glBegin(GL_LINES);
|
nuclear@11
|
768 if(cur_sdr) {
|
nuclear@0
|
769 int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX];
|
nuclear@0
|
770 if(vert_loc < 0) {
|
nuclear@0
|
771 glEnd();
|
nuclear@0
|
772 return;
|
nuclear@0
|
773 }
|
nuclear@0
|
774
|
nuclear@0
|
775 for(size_t i=0; i<nverts; i++) {
|
nuclear@0
|
776 glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z);
|
nuclear@0
|
777 Vector3 end = varr[i] + tang[i] * vis_vecsize;
|
nuclear@0
|
778 glVertexAttrib3f(vert_loc, end.x, end.y, end.z);
|
nuclear@0
|
779 }
|
nuclear@0
|
780 } else {
|
nuclear@0
|
781 for(size_t i=0; i<nverts; i++) {
|
nuclear@0
|
782 glVertex3f(varr[i].x, varr[i].y, varr[i].z);
|
nuclear@0
|
783 Vector3 end = varr[i] + tang[i] * vis_vecsize;
|
nuclear@0
|
784 glVertex3f(end.x, end.y, end.z);
|
nuclear@0
|
785 }
|
nuclear@0
|
786 }
|
nuclear@0
|
787 glEnd();
|
nuclear@0
|
788 #endif // USE_OLDGL
|
nuclear@0
|
789 }
|
nuclear@0
|
790
|
nuclear@0
|
791 void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const
|
nuclear@0
|
792 {
|
nuclear@0
|
793 if(!aabb_valid) {
|
nuclear@0
|
794 ((Mesh*)this)->calc_aabb();
|
nuclear@0
|
795 }
|
nuclear@0
|
796 *vmin = aabb.min;
|
nuclear@0
|
797 *vmax = aabb.max;
|
nuclear@0
|
798 }
|
nuclear@0
|
799
|
nuclear@0
|
800 const AABox &Mesh::get_aabbox() const
|
nuclear@0
|
801 {
|
nuclear@0
|
802 if(!aabb_valid) {
|
nuclear@0
|
803 ((Mesh*)this)->calc_aabb();
|
nuclear@0
|
804 }
|
nuclear@0
|
805 return aabb;
|
nuclear@0
|
806 }
|
nuclear@0
|
807
|
nuclear@0
|
808 float Mesh::get_bsphere(Vector3 *center, float *rad) const
|
nuclear@0
|
809 {
|
nuclear@0
|
810 if(!bsph_valid) {
|
nuclear@0
|
811 ((Mesh*)this)->calc_bsph();
|
nuclear@0
|
812 }
|
nuclear@0
|
813 *center = bsph.center;
|
nuclear@0
|
814 *rad = bsph.radius;
|
nuclear@0
|
815 return bsph.radius;
|
nuclear@0
|
816 }
|
nuclear@0
|
817
|
nuclear@0
|
818 const Sphere &Mesh::get_bsphere() const
|
nuclear@0
|
819 {
|
nuclear@0
|
820 if(!bsph_valid) {
|
nuclear@0
|
821 ((Mesh*)this)->calc_bsph();
|
nuclear@0
|
822 }
|
nuclear@0
|
823 return bsph;
|
nuclear@0
|
824 }
|
nuclear@0
|
825
|
nuclear@0
|
826 /// static function
|
nuclear@0
|
827 void Mesh::set_intersect_mode(unsigned int mode)
|
nuclear@0
|
828 {
|
nuclear@0
|
829 Mesh::intersect_mode = mode;
|
nuclear@0
|
830 }
|
nuclear@0
|
831
|
nuclear@0
|
832 /// static function
|
nuclear@0
|
833 unsigned int Mesh::get_intersect_mode()
|
nuclear@0
|
834 {
|
nuclear@0
|
835 return Mesh::intersect_mode;
|
nuclear@0
|
836 }
|
nuclear@0
|
837
|
nuclear@0
|
838 /// static function
|
nuclear@0
|
839 void Mesh::set_vertex_select_distance(float dist)
|
nuclear@0
|
840 {
|
nuclear@0
|
841 Mesh::vertex_sel_dist = dist;
|
nuclear@0
|
842 }
|
nuclear@0
|
843
|
nuclear@0
|
844 /// static function
|
nuclear@0
|
845 float Mesh::get_vertex_select_distance()
|
nuclear@0
|
846 {
|
nuclear@0
|
847 return Mesh::vertex_sel_dist;
|
nuclear@0
|
848 }
|
nuclear@0
|
849
|
nuclear@0
|
850 bool Mesh::intersect(const Ray &ray, HitPoint *hit) const
|
nuclear@0
|
851 {
|
nuclear@0
|
852 assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE));
|
nuclear@0
|
853
|
nuclear@0
|
854 const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX);
|
nuclear@0
|
855 const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL);
|
nuclear@0
|
856 if(!varr) {
|
nuclear@0
|
857 return false;
|
nuclear@0
|
858 }
|
nuclear@0
|
859 const unsigned int *idxarr = get_index_data();
|
nuclear@0
|
860
|
nuclear@0
|
861 // first test with the bounding box
|
nuclear@0
|
862 AABox box;
|
nuclear@0
|
863 get_aabbox(&box.min, &box.max);
|
nuclear@0
|
864 if(!box.intersect(ray)) {
|
nuclear@0
|
865 return false;
|
nuclear@0
|
866 }
|
nuclear@0
|
867
|
nuclear@0
|
868 HitPoint nearest_hit;
|
nuclear@0
|
869 nearest_hit.dist = FLT_MAX;
|
nuclear@0
|
870 nearest_hit.obj = 0;
|
nuclear@0
|
871
|
nuclear@0
|
872 if(Mesh::intersect_mode & ISECT_VERTICES) {
|
nuclear@0
|
873 // we asked for "intersections" with the vertices of the mesh
|
nuclear@0
|
874 long nearest_vidx = -1;
|
nuclear@0
|
875 float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist;
|
nuclear@0
|
876
|
nuclear@0
|
877 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@0
|
878
|
nuclear@0
|
879 if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) {
|
nuclear@0
|
880 continue;
|
nuclear@0
|
881 }
|
nuclear@0
|
882
|
nuclear@0
|
883 // project the vertex onto the ray line
|
nuclear@0
|
884 float t = dot_product(varr[i] - ray.origin, ray.dir);
|
nuclear@0
|
885 Vector3 vproj = ray.origin + ray.dir * t;
|
nuclear@0
|
886
|
nuclear@0
|
887 float dist_sq = (vproj - varr[i]).length_sq();
|
nuclear@0
|
888 if(dist_sq < thres_sq) {
|
nuclear@0
|
889 if(!hit) {
|
nuclear@0
|
890 return true;
|
nuclear@0
|
891 }
|
nuclear@0
|
892 if(t < nearest_hit.dist) {
|
nuclear@0
|
893 nearest_hit.dist = t;
|
nuclear@0
|
894 nearest_vidx = i;
|
nuclear@0
|
895 }
|
nuclear@0
|
896 }
|
nuclear@0
|
897 }
|
nuclear@0
|
898
|
nuclear@0
|
899 if(nearest_vidx != -1) {
|
nuclear@0
|
900 hitvert = varr[nearest_vidx];
|
nuclear@0
|
901 nearest_hit.obj = &hitvert;
|
nuclear@0
|
902 }
|
nuclear@0
|
903
|
nuclear@0
|
904 } else {
|
nuclear@0
|
905 // regular intersection test with polygons
|
nuclear@0
|
906
|
nuclear@0
|
907 for(unsigned int i=0; i<nfaces; i++) {
|
nuclear@0
|
908 Triangle face(i, varr, idxarr);
|
nuclear@0
|
909
|
nuclear@0
|
910 // ignore back-facing polygons if the mode flags include ISECT_FRONT
|
nuclear@0
|
911 if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) {
|
nuclear@0
|
912 continue;
|
nuclear@0
|
913 }
|
nuclear@0
|
914
|
nuclear@0
|
915 HitPoint fhit;
|
nuclear@0
|
916 if(face.intersect(ray, hit ? &fhit : 0)) {
|
nuclear@0
|
917 if(!hit) {
|
nuclear@0
|
918 return true;
|
nuclear@0
|
919 }
|
nuclear@0
|
920 if(fhit.dist < nearest_hit.dist) {
|
nuclear@0
|
921 nearest_hit = fhit;
|
nuclear@0
|
922 hitface = face;
|
nuclear@0
|
923 }
|
nuclear@0
|
924 }
|
nuclear@0
|
925 }
|
nuclear@0
|
926 }
|
nuclear@0
|
927
|
nuclear@0
|
928 if(nearest_hit.obj) {
|
nuclear@0
|
929 if(hit) {
|
nuclear@0
|
930 *hit = nearest_hit;
|
nuclear@0
|
931
|
nuclear@0
|
932 // if we are interested in the mesh and not the faces set obj to this
|
nuclear@0
|
933 if(Mesh::intersect_mode & ISECT_FACE) {
|
nuclear@0
|
934 hit->obj = &hitface;
|
nuclear@0
|
935 } else if(Mesh::intersect_mode & ISECT_VERTICES) {
|
nuclear@0
|
936 hit->obj = &hitvert;
|
nuclear@0
|
937 } else {
|
nuclear@0
|
938 hit->obj = this;
|
nuclear@0
|
939 }
|
nuclear@0
|
940 }
|
nuclear@0
|
941 return true;
|
nuclear@0
|
942 }
|
nuclear@0
|
943 return false;
|
nuclear@0
|
944 }
|
nuclear@0
|
945
|
nuclear@0
|
946
|
nuclear@6
|
947 // texture coordinate manipulation
|
nuclear@6
|
948 void Mesh::texcoord_apply_xform(const Matrix4x4 &xform)
|
nuclear@6
|
949 {
|
nuclear@6
|
950 if(!has_attrib(MESH_ATTR_TEXCOORD)) {
|
nuclear@6
|
951 return;
|
nuclear@6
|
952 }
|
nuclear@6
|
953
|
nuclear@6
|
954 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@6
|
955 Vector4 tc = get_attrib(MESH_ATTR_TEXCOORD, i);
|
nuclear@6
|
956 set_attrib(MESH_ATTR_TEXCOORD, i, tc.transformed(xform));
|
nuclear@6
|
957 }
|
nuclear@6
|
958 }
|
nuclear@6
|
959
|
nuclear@6
|
960 void Mesh::texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang)
|
nuclear@6
|
961 {
|
nuclear@6
|
962 if(!nverts) return;
|
nuclear@6
|
963
|
nuclear@6
|
964 if(!has_attrib(MESH_ATTR_TEXCOORD)) {
|
nuclear@6
|
965 // allocate texture coordinate attribute array
|
nuclear@6
|
966 set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts);
|
nuclear@6
|
967 }
|
nuclear@6
|
968
|
nuclear@6
|
969 Vector3 n = norm.normalized();
|
nuclear@6
|
970 Vector3 b = cross_product(n, tang).normalized();
|
nuclear@6
|
971 Vector3 t = cross_product(b, n);
|
nuclear@6
|
972
|
nuclear@6
|
973 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@6
|
974 Vector3 pos = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@6
|
975
|
nuclear@6
|
976 // distance along the tangent direction
|
nuclear@6
|
977 float u = dot_product(pos, t);
|
nuclear@6
|
978 // distance along the bitangent direction
|
nuclear@6
|
979 float v = dot_product(pos, b);
|
nuclear@6
|
980
|
nuclear@6
|
981 set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(u, v, 0, 1));
|
nuclear@6
|
982 }
|
nuclear@6
|
983 }
|
nuclear@6
|
984
|
nuclear@6
|
985 void Mesh::texcoord_gen_box()
|
nuclear@6
|
986 {
|
nuclear@6
|
987 if(!nverts || !has_attrib(MESH_ATTR_NORMAL)) return;
|
nuclear@6
|
988
|
nuclear@6
|
989 if(!has_attrib(MESH_ATTR_TEXCOORD)) {
|
nuclear@6
|
990 // allocate texture coordinate attribute array
|
nuclear@6
|
991 set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts);
|
nuclear@6
|
992 }
|
nuclear@6
|
993
|
nuclear@6
|
994 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@6
|
995 Vector3 pos = Vector3(get_attrib(MESH_ATTR_VERTEX, i)) * 0.5 + Vector3(0.5, 0.5, 0.5);
|
nuclear@6
|
996 Vector3 norm = get_attrib(MESH_ATTR_NORMAL, i);
|
nuclear@6
|
997
|
nuclear@6
|
998 float abs_nx = fabs(norm.x);
|
nuclear@6
|
999 float abs_ny = fabs(norm.y);
|
nuclear@6
|
1000 float abs_nz = fabs(norm.z);
|
nuclear@6
|
1001 int dom = abs_nx > abs_ny && abs_nx > abs_nz ? 0 : (abs_ny > abs_nz ? 1 : 2);
|
nuclear@6
|
1002
|
nuclear@6
|
1003 float uv[2], *uvptr = uv;
|
nuclear@6
|
1004 for(int j=0; j<3; j++) {
|
nuclear@6
|
1005 if(j == dom) continue; // skip dominant axis
|
nuclear@6
|
1006
|
nuclear@6
|
1007 *uvptr++ = pos[j];
|
nuclear@6
|
1008 }
|
nuclear@6
|
1009 set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(uv[0], uv[1], 0, 1));
|
nuclear@6
|
1010 }
|
nuclear@6
|
1011 }
|
nuclear@6
|
1012
|
nuclear@0
|
1013 // ------ private member functions ------
|
nuclear@0
|
1014
|
nuclear@0
|
1015 void Mesh::calc_aabb()
|
nuclear@0
|
1016 {
|
nuclear@0
|
1017 // the cast is to force calling the const version which doesn't invalidate
|
nuclear@0
|
1018 if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) {
|
nuclear@0
|
1019 return;
|
nuclear@0
|
1020 }
|
nuclear@0
|
1021
|
nuclear@0
|
1022 aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX);
|
nuclear@0
|
1023 aabb.max = -aabb.min;
|
nuclear@0
|
1024
|
nuclear@0
|
1025 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@0
|
1026 Vector4 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@0
|
1027 for(int j=0; j<3; j++) {
|
nuclear@0
|
1028 if(v[j] < aabb.min[j]) {
|
nuclear@0
|
1029 aabb.min[j] = v[j];
|
nuclear@0
|
1030 }
|
nuclear@0
|
1031 if(v[j] > aabb.max[j]) {
|
nuclear@0
|
1032 aabb.max[j] = v[j];
|
nuclear@0
|
1033 }
|
nuclear@0
|
1034 }
|
nuclear@0
|
1035 }
|
nuclear@0
|
1036 aabb_valid = true;
|
nuclear@0
|
1037 }
|
nuclear@0
|
1038
|
nuclear@0
|
1039 void Mesh::calc_bsph()
|
nuclear@0
|
1040 {
|
nuclear@0
|
1041 // the cast is to force calling the const version which doesn't invalidate
|
nuclear@0
|
1042 if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) {
|
nuclear@0
|
1043 return;
|
nuclear@0
|
1044 }
|
nuclear@0
|
1045
|
nuclear@0
|
1046 Vector3 v;
|
nuclear@0
|
1047 bsph.center = Vector3(0, 0, 0);
|
nuclear@0
|
1048
|
nuclear@0
|
1049 // first find the center
|
nuclear@0
|
1050 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@0
|
1051 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@0
|
1052 bsph.center += v;
|
nuclear@0
|
1053 }
|
nuclear@0
|
1054 bsph.center /= (float)nverts;
|
nuclear@0
|
1055
|
nuclear@0
|
1056 bsph.radius = 0.0f;
|
nuclear@0
|
1057 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@0
|
1058 v = get_attrib(MESH_ATTR_VERTEX, i);
|
nuclear@0
|
1059 float dist_sq = (v - bsph.center).length_sq();
|
nuclear@0
|
1060 if(dist_sq > bsph.radius) {
|
nuclear@0
|
1061 bsph.radius = dist_sq;
|
nuclear@0
|
1062 }
|
nuclear@0
|
1063 }
|
nuclear@0
|
1064 bsph.radius = sqrt(bsph.radius);
|
nuclear@0
|
1065
|
nuclear@0
|
1066 bsph_valid = true;
|
nuclear@0
|
1067 }
|
nuclear@0
|
1068
|
nuclear@0
|
1069 void Mesh::update_buffers()
|
nuclear@0
|
1070 {
|
nuclear@0
|
1071 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@0
|
1072 if(has_attrib(i) && !vattr[i].vbo_valid) {
|
nuclear@0
|
1073 glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo);
|
nuclear@0
|
1074 glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW);
|
nuclear@0
|
1075 vattr[i].vbo_valid = true;
|
nuclear@0
|
1076 }
|
nuclear@0
|
1077 }
|
nuclear@0
|
1078 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@0
|
1079
|
nuclear@0
|
1080 if(idata_valid && !ibo_valid) {
|
nuclear@0
|
1081 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@0
|
1082 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW);
|
nuclear@0
|
1083 ibo_valid = true;
|
nuclear@0
|
1084 }
|
nuclear@0
|
1085 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@0
|
1086 }
|
nuclear@0
|
1087
|
nuclear@0
|
1088 void Mesh::update_wire_ibo()
|
nuclear@0
|
1089 {
|
nuclear@0
|
1090 update_buffers();
|
nuclear@0
|
1091
|
nuclear@0
|
1092 if(wire_ibo_valid) {
|
nuclear@0
|
1093 return;
|
nuclear@0
|
1094 }
|
nuclear@0
|
1095
|
nuclear@0
|
1096 if(!wire_ibo) {
|
nuclear@0
|
1097 glGenBuffers(1, &wire_ibo);
|
nuclear@0
|
1098 }
|
nuclear@0
|
1099
|
nuclear@0
|
1100 unsigned int *wire_idxarr = new unsigned int[nfaces * 6];
|
nuclear@0
|
1101 unsigned int *dest = wire_idxarr;
|
nuclear@0
|
1102
|
nuclear@0
|
1103 if(ibo_valid) {
|
nuclear@0
|
1104 // we're dealing with an indexed mesh
|
nuclear@0
|
1105 const unsigned int *idxarr = ((const Mesh*)this)->get_index_data();
|
nuclear@0
|
1106
|
nuclear@0
|
1107 for(unsigned int i=0; i<nfaces; i++) {
|
nuclear@0
|
1108 *dest++ = idxarr[0];
|
nuclear@0
|
1109 *dest++ = idxarr[1];
|
nuclear@0
|
1110 *dest++ = idxarr[1];
|
nuclear@0
|
1111 *dest++ = idxarr[2];
|
nuclear@0
|
1112 *dest++ = idxarr[2];
|
nuclear@0
|
1113 *dest++ = idxarr[0];
|
nuclear@0
|
1114 idxarr += 3;
|
nuclear@0
|
1115 }
|
nuclear@0
|
1116 } else {
|
nuclear@0
|
1117 // not an indexed mesh ...
|
nuclear@0
|
1118 for(unsigned int i=0; i<nfaces; i++) {
|
nuclear@0
|
1119 int vidx = i * 3;
|
nuclear@0
|
1120 *dest++ = vidx;
|
nuclear@0
|
1121 *dest++ = vidx + 1;
|
nuclear@0
|
1122 *dest++ = vidx + 1;
|
nuclear@0
|
1123 *dest++ = vidx + 2;
|
nuclear@0
|
1124 *dest++ = vidx + 2;
|
nuclear@0
|
1125 *dest++ = vidx;
|
nuclear@0
|
1126 }
|
nuclear@0
|
1127 }
|
nuclear@0
|
1128
|
nuclear@0
|
1129 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo);
|
nuclear@0
|
1130 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW);
|
nuclear@0
|
1131 delete [] wire_idxarr;
|
nuclear@0
|
1132 wire_ibo_valid = true;
|
nuclear@0
|
1133 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@0
|
1134 }
|
nuclear@0
|
1135
|
nuclear@0
|
1136
|
nuclear@0
|
1137 // ------ class Triangle ------
|
nuclear@0
|
1138 Triangle::Triangle()
|
nuclear@0
|
1139 {
|
nuclear@0
|
1140 normal_valid = false;
|
nuclear@0
|
1141 id = -1;
|
nuclear@0
|
1142 }
|
nuclear@0
|
1143
|
nuclear@0
|
1144 Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2)
|
nuclear@0
|
1145 {
|
nuclear@0
|
1146 v[0] = v0;
|
nuclear@0
|
1147 v[1] = v1;
|
nuclear@0
|
1148 v[2] = v2;
|
nuclear@0
|
1149 normal_valid = false;
|
nuclear@0
|
1150 id = -1;
|
nuclear@0
|
1151 }
|
nuclear@0
|
1152
|
nuclear@0
|
1153 Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr)
|
nuclear@0
|
1154 {
|
nuclear@0
|
1155 if(idxarr) {
|
nuclear@0
|
1156 v[0] = varr[idxarr[n * 3]];
|
nuclear@0
|
1157 v[1] = varr[idxarr[n * 3 + 1]];
|
nuclear@0
|
1158 v[2] = varr[idxarr[n * 3 + 2]];
|
nuclear@0
|
1159 } else {
|
nuclear@0
|
1160 v[0] = varr[n * 3];
|
nuclear@0
|
1161 v[1] = varr[n * 3 + 1];
|
nuclear@0
|
1162 v[2] = varr[n * 3 + 2];
|
nuclear@0
|
1163 }
|
nuclear@0
|
1164 normal_valid = false;
|
nuclear@0
|
1165 id = n;
|
nuclear@0
|
1166 }
|
nuclear@0
|
1167
|
nuclear@0
|
1168 void Triangle::calc_normal()
|
nuclear@0
|
1169 {
|
nuclear@0
|
1170 normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized();
|
nuclear@0
|
1171 normal_valid = true;
|
nuclear@0
|
1172 }
|
nuclear@0
|
1173
|
nuclear@0
|
1174 const Vector3 &Triangle::get_normal() const
|
nuclear@0
|
1175 {
|
nuclear@0
|
1176 if(!normal_valid) {
|
nuclear@0
|
1177 ((Triangle*)this)->calc_normal();
|
nuclear@0
|
1178 }
|
nuclear@0
|
1179 return normal;
|
nuclear@0
|
1180 }
|
nuclear@0
|
1181
|
nuclear@0
|
1182 void Triangle::transform(const Matrix4x4 &xform)
|
nuclear@0
|
1183 {
|
nuclear@0
|
1184 v[0].transform(xform);
|
nuclear@0
|
1185 v[1].transform(xform);
|
nuclear@0
|
1186 v[2].transform(xform);
|
nuclear@0
|
1187 normal_valid = false;
|
nuclear@0
|
1188 }
|
nuclear@0
|
1189
|
nuclear@0
|
1190 void Triangle::draw() const
|
nuclear@0
|
1191 {
|
nuclear@0
|
1192 Vector3 n[3];
|
nuclear@0
|
1193 n[0] = get_normal();
|
nuclear@0
|
1194 n[1] = get_normal();
|
nuclear@0
|
1195 n[2] = get_normal();
|
nuclear@0
|
1196
|
nuclear@0
|
1197 int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX);
|
nuclear@0
|
1198 int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL);
|
nuclear@0
|
1199
|
nuclear@0
|
1200 glEnableVertexAttribArray(vloc);
|
nuclear@0
|
1201 glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x);
|
nuclear@0
|
1202 glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x);
|
nuclear@0
|
1203
|
nuclear@0
|
1204 glDrawArrays(GL_TRIANGLES, 0, 3);
|
nuclear@0
|
1205
|
nuclear@0
|
1206 glDisableVertexAttribArray(vloc);
|
nuclear@0
|
1207 glDisableVertexAttribArray(nloc);
|
nuclear@0
|
1208 }
|
nuclear@0
|
1209
|
nuclear@0
|
1210 void Triangle::draw_wire() const
|
nuclear@0
|
1211 {
|
nuclear@0
|
1212 static const int idxarr[] = {0, 1, 1, 2, 2, 0};
|
nuclear@0
|
1213 int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX);
|
nuclear@0
|
1214
|
nuclear@0
|
1215 glEnableVertexAttribArray(vloc);
|
nuclear@0
|
1216 glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x);
|
nuclear@0
|
1217
|
nuclear@0
|
1218 glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr);
|
nuclear@0
|
1219
|
nuclear@0
|
1220 glDisableVertexAttribArray(vloc);
|
nuclear@0
|
1221 }
|
nuclear@0
|
1222
|
nuclear@0
|
1223 Vector3 Triangle::calc_barycentric(const Vector3 &pos) const
|
nuclear@0
|
1224 {
|
nuclear@0
|
1225 Vector3 norm = get_normal();
|
nuclear@0
|
1226
|
nuclear@0
|
1227 float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm));
|
nuclear@0
|
1228 if(area_sq < 1e-5) {
|
nuclear@0
|
1229 return Vector3(0, 0, 0);
|
nuclear@0
|
1230 }
|
nuclear@0
|
1231
|
nuclear@0
|
1232 float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm));
|
nuclear@0
|
1233 float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm));
|
nuclear@0
|
1234 float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm));
|
nuclear@0
|
1235
|
nuclear@0
|
1236 return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq);
|
nuclear@0
|
1237 }
|
nuclear@0
|
1238
|
nuclear@0
|
1239 bool Triangle::intersect(const Ray &ray, HitPoint *hit) const
|
nuclear@0
|
1240 {
|
nuclear@0
|
1241 Vector3 normal = get_normal();
|
nuclear@0
|
1242
|
nuclear@0
|
1243 float ndotdir = dot_product(ray.dir, normal);
|
nuclear@0
|
1244 if(fabs(ndotdir) < 1e-4) {
|
nuclear@0
|
1245 return false;
|
nuclear@0
|
1246 }
|
nuclear@0
|
1247
|
nuclear@0
|
1248 Vector3 vertdir = v[0] - ray.origin;
|
nuclear@0
|
1249 float t = dot_product(normal, vertdir) / ndotdir;
|
nuclear@0
|
1250
|
nuclear@0
|
1251 Vector3 pos = ray.origin + ray.dir * t;
|
nuclear@0
|
1252 Vector3 bary = calc_barycentric(pos);
|
nuclear@0
|
1253
|
nuclear@0
|
1254 if(bary.x + bary.y + bary.z > 1.00001) {
|
nuclear@0
|
1255 return false;
|
nuclear@0
|
1256 }
|
nuclear@0
|
1257
|
nuclear@0
|
1258 if(hit) {
|
nuclear@0
|
1259 hit->dist = t;
|
nuclear@0
|
1260 hit->pos = ray.origin + ray.dir * t;
|
nuclear@0
|
1261 hit->normal = normal;
|
nuclear@0
|
1262 hit->obj = this;
|
nuclear@0
|
1263 }
|
nuclear@0
|
1264 return true;
|
nuclear@0
|
1265 }
|