goat3d

annotate src/mesh.cc @ 3:31cf61bfd29d

added todo files for tools
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 19 Aug 2013 01:10:33 +0300
parents
children cd71f0b92f44
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 }*/