tavli
diff src/mesh.cc @ 0:52e0dd47753b
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 21 Jun 2015 06:30:39 +0300 |
parents | |
children | 3fcd7b4d631f |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/mesh.cc Sun Jun 21 06:30:39 2015 +0300 1.3 @@ -0,0 +1,1190 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <float.h> 1.7 +#include <assert.h> 1.8 +#include "opengl.h" 1.9 +#include "mesh.h" 1.10 +//#include "xform_node.h" 1.11 +#include "shader.h" 1.12 + 1.13 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 1.14 + (int)SDR_ATTR_VERTEX, 1.15 + (int)SDR_ATTR_NORMAL, 1.16 + (int)SDR_ATTR_TANGENT, 1.17 + (int)SDR_ATTR_TEXCOORD, 1.18 + (int)SDR_ATTR_COLOR, 1.19 + -1, -1}; 1.20 +unsigned int Mesh::intersect_mode = ISECT_DEFAULT; 1.21 +float Mesh::vertex_sel_dist = 0.01; 1.22 +float Mesh::vis_vecsize = 1.0; 1.23 + 1.24 +Mesh::Mesh() 1.25 +{ 1.26 + clear(); 1.27 + 1.28 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 1.29 + 1.30 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.31 + vattr[i].vbo = buffer_objects[i]; 1.32 + } 1.33 + ibo = buffer_objects[NUM_MESH_ATTR]; 1.34 + wire_ibo = 0; 1.35 +} 1.36 + 1.37 +Mesh::~Mesh() 1.38 +{ 1.39 + glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects); 1.40 + 1.41 + if(wire_ibo) { 1.42 + glDeleteBuffers(1, &wire_ibo); 1.43 + } 1.44 +} 1.45 + 1.46 +Mesh::Mesh(const Mesh &rhs) 1.47 +{ 1.48 + clear(); 1.49 + 1.50 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 1.51 + 1.52 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.53 + vattr[i].vbo = buffer_objects[i]; 1.54 + } 1.55 + ibo = buffer_objects[NUM_MESH_ATTR]; 1.56 + wire_ibo = 0; 1.57 + 1.58 + clone(rhs); 1.59 +} 1.60 + 1.61 +Mesh &Mesh::operator =(const Mesh &rhs) 1.62 +{ 1.63 + if(&rhs != this) { 1.64 + clone(rhs); 1.65 + } 1.66 + return *this; 1.67 +} 1.68 + 1.69 +bool Mesh::clone(const Mesh &m) 1.70 +{ 1.71 + clear(); 1.72 + 1.73 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.74 + if(m.has_attrib(i)) { 1.75 + m.get_attrib_data(i); // force validation of the actual data on the source mesh 1.76 + 1.77 + vattr[i].nelem = m.vattr[i].nelem; 1.78 + vattr[i].data = m.vattr[i].data; // copy the actual data 1.79 + vattr[i].data_valid = true; 1.80 + } 1.81 + } 1.82 + 1.83 + if(m.is_indexed()) { 1.84 + m.get_index_data(); // again, force validation 1.85 + 1.86 + // copy the index data 1.87 + idata = m.idata; 1.88 + idata_valid = true; 1.89 + } 1.90 + 1.91 + name = m.name; 1.92 + nverts = m.nverts; 1.93 + nfaces = m.nfaces; 1.94 + 1.95 + //bones = m.bones; 1.96 + 1.97 + memcpy(cur_val, m.cur_val, sizeof cur_val); 1.98 + 1.99 + aabb = m.aabb; 1.100 + aabb_valid = m.aabb_valid; 1.101 + bsph = m.bsph; 1.102 + bsph_valid = m.bsph_valid; 1.103 + 1.104 + hitface = m.hitface; 1.105 + hitvert = m.hitvert; 1.106 + 1.107 + intersect_mode = m.intersect_mode; 1.108 + vertex_sel_dist = m.vertex_sel_dist; 1.109 + vis_vecsize = m.vis_vecsize; 1.110 + 1.111 + return true; 1.112 +} 1.113 + 1.114 +void Mesh::set_name(const char *name) 1.115 +{ 1.116 + this->name = name; 1.117 +} 1.118 + 1.119 +const char *Mesh::get_name() const 1.120 +{ 1.121 + return name.c_str(); 1.122 +} 1.123 + 1.124 +bool Mesh::has_attrib(int attr) const 1.125 +{ 1.126 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 1.127 + return false; 1.128 + } 1.129 + 1.130 + // if neither of these is valid, then nobody has set this attribute 1.131 + return vattr[attr].vbo_valid || vattr[attr].data_valid; 1.132 +} 1.133 + 1.134 +bool Mesh::is_indexed() const 1.135 +{ 1.136 + return ibo_valid || idata_valid; 1.137 +} 1.138 + 1.139 +void Mesh::clear() 1.140 +{ 1.141 + //bones.clear(); 1.142 + 1.143 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.144 + vattr[i].nelem = 0; 1.145 + vattr[i].vbo_valid = false; 1.146 + vattr[i].data_valid = false; 1.147 + //vattr[i].sdr_loc = -1; 1.148 + vattr[i].data.clear(); 1.149 + } 1.150 + ibo_valid = idata_valid = false; 1.151 + idata.clear(); 1.152 + 1.153 + wire_ibo_valid = false; 1.154 + 1.155 + nverts = nfaces = 0; 1.156 + 1.157 + bsph_valid = false; 1.158 + aabb_valid = false; 1.159 +} 1.160 + 1.161 +float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data) 1.162 +{ 1.163 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 1.164 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 1.165 + return 0; 1.166 + } 1.167 + 1.168 + if(nverts && num != nverts) { 1.169 + fprintf(stderr, "%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts); 1.170 + return 0; 1.171 + } 1.172 + nverts = num; 1.173 + 1.174 + vattr[attrib].data.clear(); 1.175 + vattr[attrib].nelem = nelem; 1.176 + vattr[attrib].data.resize(num * nelem); 1.177 + 1.178 + if(data) { 1.179 + memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data); 1.180 + } 1.181 + 1.182 + vattr[attrib].data_valid = true; 1.183 + vattr[attrib].vbo_valid = false; 1.184 + return &vattr[attrib].data[0]; 1.185 +} 1.186 + 1.187 +float *Mesh::get_attrib_data(int attrib) 1.188 +{ 1.189 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 1.190 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 1.191 + return 0; 1.192 + } 1.193 + 1.194 + vattr[attrib].vbo_valid = false; 1.195 + return (float*)((const Mesh*)this)->get_attrib_data(attrib); 1.196 +} 1.197 + 1.198 +const float *Mesh::get_attrib_data(int attrib) const 1.199 +{ 1.200 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 1.201 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 1.202 + return 0; 1.203 + } 1.204 + 1.205 + if(!vattr[attrib].data_valid) { 1.206 +#if GL_ES_VERSION_2_0 1.207 + fprintf(stderr, "%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__); 1.208 + return 0; 1.209 +#else 1.210 + if(!vattr[attrib].vbo_valid) { 1.211 + fprintf(stderr, "%s: unavailable attrib: %d\n", __FUNCTION__, attrib); 1.212 + return 0; 1.213 + } 1.214 + 1.215 + // local data copy is unavailable, grab the data from the vbo 1.216 + Mesh *m = (Mesh*)this; 1.217 + m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem); 1.218 + 1.219 + glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo); 1.220 + void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 1.221 + memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float)); 1.222 + glUnmapBuffer(GL_ARRAY_BUFFER); 1.223 + 1.224 + vattr[attrib].data_valid = true; 1.225 +#endif 1.226 + } 1.227 + 1.228 + return &vattr[attrib].data[0]; 1.229 +} 1.230 + 1.231 +void Mesh::set_attrib(int attrib, int idx, const Vector4 &v) 1.232 +{ 1.233 + float *data = get_attrib_data(attrib); 1.234 + if(data) { 1.235 + data += idx * vattr[attrib].nelem; 1.236 + for(int i=0; i<vattr[attrib].nelem; i++) { 1.237 + data[i] = v[i]; 1.238 + } 1.239 + } 1.240 +} 1.241 + 1.242 +Vector4 Mesh::get_attrib(int attrib, int idx) const 1.243 +{ 1.244 + Vector4 v(0.0, 0.0, 0.0, 1.0); 1.245 + const float *data = get_attrib_data(attrib); 1.246 + if(data) { 1.247 + data += idx * vattr[attrib].nelem; 1.248 + for(int i=0; i<vattr[attrib].nelem; i++) { 1.249 + v[i] = data[i]; 1.250 + } 1.251 + } 1.252 + return v; 1.253 +} 1.254 + 1.255 +int Mesh::get_attrib_count(int attrib) const 1.256 +{ 1.257 + return has_attrib(attrib) ? nverts : 0; 1.258 +} 1.259 + 1.260 + 1.261 +unsigned int *Mesh::set_index_data(int num, const unsigned int *indices) 1.262 +{ 1.263 + int nidx = nfaces * 3; 1.264 + if(nidx && num != nidx) { 1.265 + fprintf(stderr, "%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx); 1.266 + return 0; 1.267 + } 1.268 + nfaces = num / 3; 1.269 + 1.270 + idata.clear(); 1.271 + idata.resize(num); 1.272 + 1.273 + if(indices) { 1.274 + memcpy(&idata[0], indices, num * sizeof *indices); 1.275 + } 1.276 + 1.277 + idata_valid = true; 1.278 + ibo_valid = false; 1.279 + 1.280 + return &idata[0]; 1.281 +} 1.282 + 1.283 +unsigned int *Mesh::get_index_data() 1.284 +{ 1.285 + ibo_valid = false; 1.286 + return (unsigned int*)((const Mesh*)this)->get_index_data(); 1.287 +} 1.288 + 1.289 +const unsigned int *Mesh::get_index_data() const 1.290 +{ 1.291 + if(!idata_valid) { 1.292 +#if GL_ES_VERSION_2_0 1.293 + fprintf(stderr, "%s: can't read back index data in CrippledGL ES\n", __FUNCTION__); 1.294 + return 0; 1.295 +#else 1.296 + if(!ibo_valid) { 1.297 + fprintf(stderr, "%s: indices unavailable\n", __FUNCTION__); 1.298 + return 0; 1.299 + } 1.300 + 1.301 + // local data copy is unavailable, gram the data from the ibo 1.302 + Mesh *m = (Mesh*)this; 1.303 + int nidx = nfaces * 3; 1.304 + m->idata.resize(nidx); 1.305 + 1.306 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 1.307 + void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); 1.308 + memcpy(&m->idata[0], data, nidx * sizeof(unsigned int)); 1.309 + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 1.310 + 1.311 + idata_valid = true; 1.312 +#endif 1.313 + } 1.314 + 1.315 + return &idata[0]; 1.316 +} 1.317 + 1.318 +int Mesh::get_index_count() const 1.319 +{ 1.320 + return nfaces * 3; 1.321 +} 1.322 + 1.323 +void Mesh::append(const Mesh &mesh) 1.324 +{ 1.325 + unsigned int idxoffs = nverts; 1.326 + 1.327 + nverts += mesh.nverts; 1.328 + nfaces += mesh.nfaces; 1.329 + 1.330 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.331 + if(has_attrib(i) && mesh.has_attrib(i)) { 1.332 + // force validating the data arrays 1.333 + get_attrib_data(i); 1.334 + mesh.get_attrib_data(i); 1.335 + 1.336 + // append the mesh data 1.337 + vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end()); 1.338 + } 1.339 + } 1.340 + 1.341 + if(ibo_valid || idata_valid) { 1.342 + // make index arrays valid 1.343 + get_index_data(); 1.344 + mesh.get_index_data(); 1.345 + 1.346 + size_t orig_sz = idata.size(); 1.347 + 1.348 + idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end()); 1.349 + 1.350 + // fixup all the new indices 1.351 + for(size_t i=orig_sz; i<idata.size(); i++) { 1.352 + idata[i] += idxoffs; 1.353 + } 1.354 + } 1.355 + 1.356 + // fuck everything 1.357 + wire_ibo_valid = false; 1.358 + aabb_valid = false; 1.359 + bsph_valid = false; 1.360 +} 1.361 + 1.362 +// assemble a complete vertex by adding all the useful attributes 1.363 +void Mesh::vertex(float x, float y, float z) 1.364 +{ 1.365 + cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f); 1.366 + vattr[MESH_ATTR_VERTEX].data_valid = true; 1.367 + vattr[MESH_ATTR_VERTEX].nelem = 3; 1.368 + 1.369 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.370 + if(vattr[i].data_valid) { 1.371 + for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) { 1.372 + vattr[i].data.push_back(cur_val[i][j]); 1.373 + } 1.374 + } 1.375 + vattr[i].vbo_valid = false; 1.376 + } 1.377 + 1.378 + if(idata_valid) { 1.379 + idata.clear(); 1.380 + } 1.381 + ibo_valid = idata_valid = false; 1.382 +} 1.383 + 1.384 +void Mesh::normal(float nx, float ny, float nz) 1.385 +{ 1.386 + cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f); 1.387 + vattr[MESH_ATTR_NORMAL].data_valid = true; 1.388 + vattr[MESH_ATTR_NORMAL].nelem = 3; 1.389 +} 1.390 + 1.391 +void Mesh::tangent(float tx, float ty, float tz) 1.392 +{ 1.393 + cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f); 1.394 + vattr[MESH_ATTR_TANGENT].data_valid = true; 1.395 + vattr[MESH_ATTR_TANGENT].nelem = 3; 1.396 +} 1.397 + 1.398 +void Mesh::texcoord(float u, float v, float w) 1.399 +{ 1.400 + cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f); 1.401 + vattr[MESH_ATTR_TEXCOORD].data_valid = true; 1.402 + vattr[MESH_ATTR_TEXCOORD].nelem = 3; 1.403 +} 1.404 + 1.405 +void Mesh::boneweights(float w1, float w2, float w3, float w4) 1.406 +{ 1.407 + cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4); 1.408 + vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true; 1.409 + vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4; 1.410 +} 1.411 + 1.412 +void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4) 1.413 +{ 1.414 + cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4); 1.415 + vattr[MESH_ATTR_BONEIDX].data_valid = true; 1.416 + vattr[MESH_ATTR_BONEIDX].nelem = 4; 1.417 +} 1.418 + 1.419 +int Mesh::get_poly_count() const 1.420 +{ 1.421 + if(nfaces) { 1.422 + return nfaces; 1.423 + } 1.424 + if(nverts) { 1.425 + return nverts / 3; 1.426 + } 1.427 + return 0; 1.428 +} 1.429 + 1.430 +/// static function 1.431 +void Mesh::set_attrib_location(int attr, int loc) 1.432 +{ 1.433 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 1.434 + return; 1.435 + } 1.436 + Mesh::global_sdr_loc[attr] = loc; 1.437 +} 1.438 + 1.439 +/// static function 1.440 +int Mesh::get_attrib_location(int attr) 1.441 +{ 1.442 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 1.443 + return -1; 1.444 + } 1.445 + return Mesh::global_sdr_loc[attr]; 1.446 +} 1.447 + 1.448 +/// static function 1.449 +void Mesh::clear_attrib_locations() 1.450 +{ 1.451 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.452 + Mesh::global_sdr_loc[i] = -1; 1.453 + } 1.454 +} 1.455 + 1.456 +/// static function 1.457 +void Mesh::set_vis_vecsize(float sz) 1.458 +{ 1.459 + Mesh::vis_vecsize = sz; 1.460 +} 1.461 + 1.462 +float Mesh::get_vis_vecsize() 1.463 +{ 1.464 + return Mesh::vis_vecsize; 1.465 +} 1.466 + 1.467 +void Mesh::apply_xform(const Matrix4x4 &xform) 1.468 +{ 1.469 + Matrix4x4 dir_xform = xform; 1.470 + dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f; 1.471 + dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f; 1.472 + dir_xform[3][3] = 1.0f; 1.473 + 1.474 + apply_xform(xform, dir_xform); 1.475 +} 1.476 + 1.477 +void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform) 1.478 +{ 1.479 + for(unsigned int i=0; i<nverts; i++) { 1.480 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 1.481 + set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform)); 1.482 + 1.483 + if(has_attrib(MESH_ATTR_NORMAL)) { 1.484 + Vector3 n = get_attrib(MESH_ATTR_NORMAL, i); 1.485 + set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform)); 1.486 + } 1.487 + if(has_attrib(MESH_ATTR_TANGENT)) { 1.488 + Vector3 t = get_attrib(MESH_ATTR_TANGENT, i); 1.489 + set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform)); 1.490 + } 1.491 + } 1.492 +} 1.493 + 1.494 +void Mesh::flip() 1.495 +{ 1.496 + flip_faces(); 1.497 + flip_normals(); 1.498 +} 1.499 + 1.500 +void Mesh::flip_faces() 1.501 +{ 1.502 + if(is_indexed()) { 1.503 + unsigned int *indices = get_index_data(); 1.504 + if(!indices) return; 1.505 + 1.506 + int idxnum = get_index_count(); 1.507 + for(int i=0; i<idxnum; i+=3) { 1.508 + unsigned int tmp = indices[i + 2]; 1.509 + indices[i + 2] = indices[i + 1]; 1.510 + indices[i + 1] = tmp; 1.511 + } 1.512 + 1.513 + } else { 1.514 + Vector3 *verts = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 1.515 + if(!verts) return; 1.516 + 1.517 + int vnum = get_attrib_count(MESH_ATTR_VERTEX); 1.518 + for(int i=0; i<vnum; i+=3) { 1.519 + Vector3 tmp = verts[i + 2]; 1.520 + verts[i + 2] = verts[i + 1]; 1.521 + verts[i + 1] = tmp; 1.522 + } 1.523 + } 1.524 +} 1.525 + 1.526 +void Mesh::flip_normals() 1.527 +{ 1.528 + Vector3 *normals = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 1.529 + if(!normals) return; 1.530 + 1.531 + int num = get_attrib_count(MESH_ATTR_NORMAL); 1.532 + for(int i=0; i<num; i++) { 1.533 + normals[i] = -normals[i]; 1.534 + } 1.535 +} 1.536 + 1.537 +/* 1.538 +int Mesh::add_bone(XFormNode *bone) 1.539 +{ 1.540 + int idx = bones.size(); 1.541 + bones.push_back(bone); 1.542 + return idx; 1.543 +} 1.544 + 1.545 +const XFormNode *Mesh::get_bone(int idx) const 1.546 +{ 1.547 + if(idx < 0 || idx >= (int)bones.size()) { 1.548 + return 0; 1.549 + } 1.550 + return bones[idx]; 1.551 +} 1.552 + 1.553 +int Mesh::get_bones_count() const 1.554 +{ 1.555 + return (int)bones.size(); 1.556 +} 1.557 +*/ 1.558 + 1.559 +void Mesh::draw() const 1.560 +{ 1.561 +#ifdef GL_ES_VERSION_2_0 1.562 + if(!SdrProg::active) { 1.563 + fprintf(stderr, "%s: CrippledGL ES can't draw without a shader\n", __FUNCTION__); 1.564 + return; 1.565 + } 1.566 +#endif 1.567 + 1.568 + ((Mesh*)this)->update_buffers(); 1.569 + 1.570 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 1.571 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 1.572 + return; 1.573 + } 1.574 + 1.575 + if(SdrProg::active) { 1.576 + // rendering with shaders 1.577 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 1.578 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 1.579 + return; 1.580 + } 1.581 + 1.582 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.583 + int loc = global_sdr_loc[i]; 1.584 + if(loc >= 0 && vattr[i].vbo_valid) { 1.585 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 1.586 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 1.587 + glEnableVertexAttribArray(loc); 1.588 + } 1.589 + } 1.590 + } else { 1.591 +#ifndef GL_ES_VERSION_2_0 1.592 + // rendering with fixed-function (not available in GLES2) 1.593 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_VERTEX].vbo); 1.594 + glVertexPointer(vattr[MESH_ATTR_VERTEX].nelem, GL_FLOAT, 0, 0); 1.595 + glEnableClientState(GL_VERTEX_ARRAY); 1.596 + 1.597 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 1.598 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_NORMAL].vbo); 1.599 + glNormalPointer(GL_FLOAT, 0, 0); 1.600 + glEnableClientState(GL_NORMAL_ARRAY); 1.601 + } 1.602 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 1.603 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_TEXCOORD].vbo); 1.604 + glTexCoordPointer(vattr[MESH_ATTR_TEXCOORD].nelem, GL_FLOAT, 0, 0); 1.605 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.606 + } 1.607 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 1.608 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_COLOR].vbo); 1.609 + glColorPointer(vattr[MESH_ATTR_COLOR].nelem, GL_FLOAT, 0, 0); 1.610 + glEnableClientState(GL_COLOR_ARRAY); 1.611 + } 1.612 +#endif 1.613 + } 1.614 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.615 + 1.616 + if(ibo_valid) { 1.617 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 1.618 + glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); 1.619 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1.620 + } else { 1.621 + glDrawArrays(GL_TRIANGLES, 0, nverts); 1.622 + } 1.623 + 1.624 + if(SdrProg::active) { 1.625 + // rendered with shaders 1.626 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.627 + int loc = global_sdr_loc[i]; 1.628 + if(loc >= 0 && vattr[i].vbo_valid) { 1.629 + glDisableVertexAttribArray(loc); 1.630 + } 1.631 + } 1.632 + } else { 1.633 +#ifndef GL_ES_VERSION_2_0 1.634 + // rendered with fixed-function 1.635 + glDisableClientState(GL_VERTEX_ARRAY); 1.636 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 1.637 + glDisableClientState(GL_NORMAL_ARRAY); 1.638 + } 1.639 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 1.640 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.641 + } 1.642 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 1.643 + glDisableClientState(GL_COLOR_ARRAY); 1.644 + } 1.645 +#endif 1.646 + } 1.647 +} 1.648 + 1.649 +void Mesh::draw_wire() const 1.650 +{ 1.651 + ((Mesh*)this)->update_wire_ibo(); 1.652 + 1.653 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) { 1.654 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 1.655 + return; 1.656 + } 1.657 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 1.658 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 1.659 + return; 1.660 + } 1.661 + 1.662 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.663 + int loc = global_sdr_loc[i]; 1.664 + if(loc >= 0 && vattr[i].vbo_valid) { 1.665 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 1.666 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 1.667 + glEnableVertexAttribArray(loc); 1.668 + } 1.669 + } 1.670 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.671 + 1.672 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 1.673 + glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0); 1.674 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1.675 + 1.676 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.677 + int loc = global_sdr_loc[i]; 1.678 + if(loc >= 0 && vattr[i].vbo_valid) { 1.679 + glDisableVertexAttribArray(loc); 1.680 + } 1.681 + } 1.682 +} 1.683 + 1.684 +void Mesh::draw_vertices() const 1.685 +{ 1.686 + ((Mesh*)this)->update_buffers(); 1.687 + 1.688 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 1.689 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 1.690 + return; 1.691 + } 1.692 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 1.693 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 1.694 + return; 1.695 + } 1.696 + 1.697 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.698 + int loc = global_sdr_loc[i]; 1.699 + if(loc >= 0 && vattr[i].vbo_valid) { 1.700 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 1.701 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 1.702 + glEnableVertexAttribArray(loc); 1.703 + } 1.704 + } 1.705 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.706 + 1.707 + glDrawArrays(GL_POINTS, 0, nverts); 1.708 + 1.709 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.710 + int loc = global_sdr_loc[i]; 1.711 + if(loc >= 0 && vattr[i].vbo_valid) { 1.712 + glDisableVertexAttribArray(loc); 1.713 + } 1.714 + } 1.715 +} 1.716 + 1.717 +void Mesh::draw_normals() const 1.718 +{ 1.719 +#ifdef USE_OLDGL 1.720 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 1.721 + Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 1.722 + if(!varr || !norm) { 1.723 + return; 1.724 + } 1.725 + 1.726 + glBegin(GL_LINES); 1.727 + if(get_current_shader()) { 1.728 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 1.729 + if(vert_loc < 0) { 1.730 + glEnd(); 1.731 + return; 1.732 + } 1.733 + 1.734 + for(size_t i=0; i<nverts; i++) { 1.735 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 1.736 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 1.737 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 1.738 + } 1.739 + } else { 1.740 + for(size_t i=0; i<nverts; i++) { 1.741 + glVertex3f(varr[i].x, varr[i].y, varr[i].z); 1.742 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 1.743 + glVertex3f(end.x, end.y, end.z); 1.744 + } 1.745 + } 1.746 + glEnd(); 1.747 +#endif // USE_OLDGL 1.748 +} 1.749 + 1.750 +void Mesh::draw_tangents() const 1.751 +{ 1.752 +#ifdef USE_OLDGL 1.753 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 1.754 + Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT); 1.755 + if(!varr || !tang) { 1.756 + return; 1.757 + } 1.758 + 1.759 + glBegin(GL_LINES); 1.760 + if(get_current_shader()) { 1.761 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 1.762 + if(vert_loc < 0) { 1.763 + glEnd(); 1.764 + return; 1.765 + } 1.766 + 1.767 + for(size_t i=0; i<nverts; i++) { 1.768 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 1.769 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 1.770 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 1.771 + } 1.772 + } else { 1.773 + for(size_t i=0; i<nverts; i++) { 1.774 + glVertex3f(varr[i].x, varr[i].y, varr[i].z); 1.775 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 1.776 + glVertex3f(end.x, end.y, end.z); 1.777 + } 1.778 + } 1.779 + glEnd(); 1.780 +#endif // USE_OLDGL 1.781 +} 1.782 + 1.783 +void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const 1.784 +{ 1.785 + if(!aabb_valid) { 1.786 + ((Mesh*)this)->calc_aabb(); 1.787 + } 1.788 + *vmin = aabb.min; 1.789 + *vmax = aabb.max; 1.790 +} 1.791 + 1.792 +const AABox &Mesh::get_aabbox() const 1.793 +{ 1.794 + if(!aabb_valid) { 1.795 + ((Mesh*)this)->calc_aabb(); 1.796 + } 1.797 + return aabb; 1.798 +} 1.799 + 1.800 +float Mesh::get_bsphere(Vector3 *center, float *rad) const 1.801 +{ 1.802 + if(!bsph_valid) { 1.803 + ((Mesh*)this)->calc_bsph(); 1.804 + } 1.805 + *center = bsph.center; 1.806 + *rad = bsph.radius; 1.807 + return bsph.radius; 1.808 +} 1.809 + 1.810 +const Sphere &Mesh::get_bsphere() const 1.811 +{ 1.812 + if(!bsph_valid) { 1.813 + ((Mesh*)this)->calc_bsph(); 1.814 + } 1.815 + return bsph; 1.816 +} 1.817 + 1.818 +/// static function 1.819 +void Mesh::set_intersect_mode(unsigned int mode) 1.820 +{ 1.821 + Mesh::intersect_mode = mode; 1.822 +} 1.823 + 1.824 +/// static function 1.825 +unsigned int Mesh::get_intersect_mode() 1.826 +{ 1.827 + return Mesh::intersect_mode; 1.828 +} 1.829 + 1.830 +/// static function 1.831 +void Mesh::set_vertex_select_distance(float dist) 1.832 +{ 1.833 + Mesh::vertex_sel_dist = dist; 1.834 +} 1.835 + 1.836 +/// static function 1.837 +float Mesh::get_vertex_select_distance() 1.838 +{ 1.839 + return Mesh::vertex_sel_dist; 1.840 +} 1.841 + 1.842 +bool Mesh::intersect(const Ray &ray, HitPoint *hit) const 1.843 +{ 1.844 + assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE)); 1.845 + 1.846 + const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 1.847 + const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 1.848 + if(!varr) { 1.849 + return false; 1.850 + } 1.851 + const unsigned int *idxarr = get_index_data(); 1.852 + 1.853 + // first test with the bounding box 1.854 + AABox box; 1.855 + get_aabbox(&box.min, &box.max); 1.856 + if(!box.intersect(ray)) { 1.857 + return false; 1.858 + } 1.859 + 1.860 + HitPoint nearest_hit; 1.861 + nearest_hit.dist = FLT_MAX; 1.862 + nearest_hit.obj = 0; 1.863 + 1.864 + if(Mesh::intersect_mode & ISECT_VERTICES) { 1.865 + // we asked for "intersections" with the vertices of the mesh 1.866 + long nearest_vidx = -1; 1.867 + float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist; 1.868 + 1.869 + for(unsigned int i=0; i<nverts; i++) { 1.870 + 1.871 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) { 1.872 + continue; 1.873 + } 1.874 + 1.875 + // project the vertex onto the ray line 1.876 + float t = dot_product(varr[i] - ray.origin, ray.dir); 1.877 + Vector3 vproj = ray.origin + ray.dir * t; 1.878 + 1.879 + float dist_sq = (vproj - varr[i]).length_sq(); 1.880 + if(dist_sq < thres_sq) { 1.881 + if(!hit) { 1.882 + return true; 1.883 + } 1.884 + if(t < nearest_hit.dist) { 1.885 + nearest_hit.dist = t; 1.886 + nearest_vidx = i; 1.887 + } 1.888 + } 1.889 + } 1.890 + 1.891 + if(nearest_vidx != -1) { 1.892 + hitvert = varr[nearest_vidx]; 1.893 + nearest_hit.obj = &hitvert; 1.894 + } 1.895 + 1.896 + } else { 1.897 + // regular intersection test with polygons 1.898 + 1.899 + for(unsigned int i=0; i<nfaces; i++) { 1.900 + Triangle face(i, varr, idxarr); 1.901 + 1.902 + // ignore back-facing polygons if the mode flags include ISECT_FRONT 1.903 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) { 1.904 + continue; 1.905 + } 1.906 + 1.907 + HitPoint fhit; 1.908 + if(face.intersect(ray, hit ? &fhit : 0)) { 1.909 + if(!hit) { 1.910 + return true; 1.911 + } 1.912 + if(fhit.dist < nearest_hit.dist) { 1.913 + nearest_hit = fhit; 1.914 + hitface = face; 1.915 + } 1.916 + } 1.917 + } 1.918 + } 1.919 + 1.920 + if(nearest_hit.obj) { 1.921 + if(hit) { 1.922 + *hit = nearest_hit; 1.923 + 1.924 + // if we are interested in the mesh and not the faces set obj to this 1.925 + if(Mesh::intersect_mode & ISECT_FACE) { 1.926 + hit->obj = &hitface; 1.927 + } else if(Mesh::intersect_mode & ISECT_VERTICES) { 1.928 + hit->obj = &hitvert; 1.929 + } else { 1.930 + hit->obj = this; 1.931 + } 1.932 + } 1.933 + return true; 1.934 + } 1.935 + return false; 1.936 +} 1.937 + 1.938 + 1.939 +// ------ private member functions ------ 1.940 + 1.941 +void Mesh::calc_aabb() 1.942 +{ 1.943 + // the cast is to force calling the const version which doesn't invalidate 1.944 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 1.945 + return; 1.946 + } 1.947 + 1.948 + aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 1.949 + aabb.max = -aabb.min; 1.950 + 1.951 + for(unsigned int i=0; i<nverts; i++) { 1.952 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 1.953 + for(int j=0; j<3; j++) { 1.954 + if(v[j] < aabb.min[j]) { 1.955 + aabb.min[j] = v[j]; 1.956 + } 1.957 + if(v[j] > aabb.max[j]) { 1.958 + aabb.max[j] = v[j]; 1.959 + } 1.960 + } 1.961 + } 1.962 + aabb_valid = true; 1.963 +} 1.964 + 1.965 +void Mesh::calc_bsph() 1.966 +{ 1.967 + // the cast is to force calling the const version which doesn't invalidate 1.968 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 1.969 + return; 1.970 + } 1.971 + 1.972 + Vector3 v; 1.973 + bsph.center = Vector3(0, 0, 0); 1.974 + 1.975 + // first find the center 1.976 + for(unsigned int i=0; i<nverts; i++) { 1.977 + v = get_attrib(MESH_ATTR_VERTEX, i); 1.978 + bsph.center += v; 1.979 + } 1.980 + bsph.center /= (float)nverts; 1.981 + 1.982 + bsph.radius = 0.0f; 1.983 + for(unsigned int i=0; i<nverts; i++) { 1.984 + v = get_attrib(MESH_ATTR_VERTEX, i); 1.985 + float dist_sq = (v - bsph.center).length_sq(); 1.986 + if(dist_sq > bsph.radius) { 1.987 + bsph.radius = dist_sq; 1.988 + } 1.989 + } 1.990 + bsph.radius = sqrt(bsph.radius); 1.991 + 1.992 + bsph_valid = true; 1.993 +} 1.994 + 1.995 +void Mesh::update_buffers() 1.996 +{ 1.997 + for(int i=0; i<NUM_MESH_ATTR; i++) { 1.998 + if(has_attrib(i) && !vattr[i].vbo_valid) { 1.999 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 1.1000 + glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW); 1.1001 + vattr[i].vbo_valid = true; 1.1002 + } 1.1003 + } 1.1004 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.1005 + 1.1006 + if(idata_valid && !ibo_valid) { 1.1007 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 1.1008 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW); 1.1009 + ibo_valid = true; 1.1010 + } 1.1011 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1.1012 +} 1.1013 + 1.1014 +void Mesh::update_wire_ibo() 1.1015 +{ 1.1016 + update_buffers(); 1.1017 + 1.1018 + if(wire_ibo_valid) { 1.1019 + return; 1.1020 + } 1.1021 + 1.1022 + if(!wire_ibo) { 1.1023 + glGenBuffers(1, &wire_ibo); 1.1024 + } 1.1025 + 1.1026 + unsigned int *wire_idxarr = new unsigned int[nfaces * 6]; 1.1027 + unsigned int *dest = wire_idxarr; 1.1028 + 1.1029 + if(ibo_valid) { 1.1030 + // we're dealing with an indexed mesh 1.1031 + const unsigned int *idxarr = ((const Mesh*)this)->get_index_data(); 1.1032 + 1.1033 + for(unsigned int i=0; i<nfaces; i++) { 1.1034 + *dest++ = idxarr[0]; 1.1035 + *dest++ = idxarr[1]; 1.1036 + *dest++ = idxarr[1]; 1.1037 + *dest++ = idxarr[2]; 1.1038 + *dest++ = idxarr[2]; 1.1039 + *dest++ = idxarr[0]; 1.1040 + idxarr += 3; 1.1041 + } 1.1042 + } else { 1.1043 + // not an indexed mesh ... 1.1044 + for(unsigned int i=0; i<nfaces; i++) { 1.1045 + int vidx = i * 3; 1.1046 + *dest++ = vidx; 1.1047 + *dest++ = vidx + 1; 1.1048 + *dest++ = vidx + 1; 1.1049 + *dest++ = vidx + 2; 1.1050 + *dest++ = vidx + 2; 1.1051 + *dest++ = vidx; 1.1052 + } 1.1053 + } 1.1054 + 1.1055 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 1.1056 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW); 1.1057 + delete [] wire_idxarr; 1.1058 + wire_ibo_valid = true; 1.1059 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1.1060 +} 1.1061 + 1.1062 + 1.1063 +// ------ class Triangle ------ 1.1064 +Triangle::Triangle() 1.1065 +{ 1.1066 + normal_valid = false; 1.1067 + id = -1; 1.1068 +} 1.1069 + 1.1070 +Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2) 1.1071 +{ 1.1072 + v[0] = v0; 1.1073 + v[1] = v1; 1.1074 + v[2] = v2; 1.1075 + normal_valid = false; 1.1076 + id = -1; 1.1077 +} 1.1078 + 1.1079 +Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr) 1.1080 +{ 1.1081 + if(idxarr) { 1.1082 + v[0] = varr[idxarr[n * 3]]; 1.1083 + v[1] = varr[idxarr[n * 3 + 1]]; 1.1084 + v[2] = varr[idxarr[n * 3 + 2]]; 1.1085 + } else { 1.1086 + v[0] = varr[n * 3]; 1.1087 + v[1] = varr[n * 3 + 1]; 1.1088 + v[2] = varr[n * 3 + 2]; 1.1089 + } 1.1090 + normal_valid = false; 1.1091 + id = n; 1.1092 +} 1.1093 + 1.1094 +void Triangle::calc_normal() 1.1095 +{ 1.1096 + normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized(); 1.1097 + normal_valid = true; 1.1098 +} 1.1099 + 1.1100 +const Vector3 &Triangle::get_normal() const 1.1101 +{ 1.1102 + if(!normal_valid) { 1.1103 + ((Triangle*)this)->calc_normal(); 1.1104 + } 1.1105 + return normal; 1.1106 +} 1.1107 + 1.1108 +void Triangle::transform(const Matrix4x4 &xform) 1.1109 +{ 1.1110 + v[0].transform(xform); 1.1111 + v[1].transform(xform); 1.1112 + v[2].transform(xform); 1.1113 + normal_valid = false; 1.1114 +} 1.1115 + 1.1116 +void Triangle::draw() const 1.1117 +{ 1.1118 + Vector3 n[3]; 1.1119 + n[0] = get_normal(); 1.1120 + n[1] = get_normal(); 1.1121 + n[2] = get_normal(); 1.1122 + 1.1123 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 1.1124 + int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL); 1.1125 + 1.1126 + glEnableVertexAttribArray(vloc); 1.1127 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 1.1128 + glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x); 1.1129 + 1.1130 + glDrawArrays(GL_TRIANGLES, 0, 3); 1.1131 + 1.1132 + glDisableVertexAttribArray(vloc); 1.1133 + glDisableVertexAttribArray(nloc); 1.1134 + CHECK_GLERROR; 1.1135 +} 1.1136 + 1.1137 +void Triangle::draw_wire() const 1.1138 +{ 1.1139 + static const int idxarr[] = {0, 1, 1, 2, 2, 0}; 1.1140 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 1.1141 + 1.1142 + glEnableVertexAttribArray(vloc); 1.1143 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 1.1144 + 1.1145 + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr); 1.1146 + 1.1147 + glDisableVertexAttribArray(vloc); 1.1148 + CHECK_GLERROR; 1.1149 +} 1.1150 + 1.1151 +Vector3 Triangle::calc_barycentric(const Vector3 &pos) const 1.1152 +{ 1.1153 + Vector3 norm = get_normal(); 1.1154 + 1.1155 + float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm)); 1.1156 + if(area_sq < 1e-5) { 1.1157 + return Vector3(0, 0, 0); 1.1158 + } 1.1159 + 1.1160 + float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm)); 1.1161 + float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm)); 1.1162 + float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm)); 1.1163 + 1.1164 + return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq); 1.1165 +} 1.1166 + 1.1167 +bool Triangle::intersect(const Ray &ray, HitPoint *hit) const 1.1168 +{ 1.1169 + Vector3 normal = get_normal(); 1.1170 + 1.1171 + float ndotdir = dot_product(ray.dir, normal); 1.1172 + if(fabs(ndotdir) < 1e-4) { 1.1173 + return false; 1.1174 + } 1.1175 + 1.1176 + Vector3 vertdir = v[0] - ray.origin; 1.1177 + float t = dot_product(normal, vertdir) / ndotdir; 1.1178 + 1.1179 + Vector3 pos = ray.origin + ray.dir * t; 1.1180 + Vector3 bary = calc_barycentric(pos); 1.1181 + 1.1182 + if(bary.x + bary.y + bary.z > 1.00001) { 1.1183 + return false; 1.1184 + } 1.1185 + 1.1186 + if(hit) { 1.1187 + hit->dist = t; 1.1188 + hit->pos = ray.origin + ray.dir * t; 1.1189 + hit->normal = normal; 1.1190 + hit->obj = this; 1.1191 + } 1.1192 + return true; 1.1193 +}