Subversion Repositories gelsvn

Rev

Rev 429 | Rev 450 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
349 awk 1
#include "CGLA/Vec3d.h"
2
#include "Geometry/TriMesh.h"
3
 
4
#include "BSPTree.h"
5
 
6
using namespace std;
7
using namespace CGLA;
8
 
9
namespace Geometry
10
{
11
  int BSPTree::node_calls;
12
  int BSPTree::tri_calls;
13
 
14
  void create_tri_accel(Vec3f A, Vec3f B, Vec3f C, TriAccel &tri_accel) 
15
  {
16
    Vec3f N = normalize(cross(B-A, C-A));
17
    // Find projection dir
18
    int k,u,v;
19
    if (fabs(N[0]) > fabs(N[1]))
20
      if (fabs(N[0]) > fabs(N[2])) 
21
    k = 0; /* X */ 
22
      else 
23
    k=2;   /* Z */
24
    else
25
      if (fabs(N[1]) > fabs(N[2])) 
26
    k = 1; /* Y */ 
27
      else 
28
    k=2;   /* Z */
29
 
30
    u = (k+1)% 3; 
31
    v = (k+2)% 3;
32
 
33
    Vec3f b = C - A;
34
    Vec3f c = B - A;
35
 
36
    double div = (b[u]*c[v]-b[v]*c[u]);
37
 
38
    tri_accel.n_u = N[u]/N[k];
39
    tri_accel.n_v = N[v]/N[k];
40
    tri_accel.n_d = dot(A, N/N[k]);
41
    tri_accel.k = k;
42
 
43
    tri_accel.b_nu = -b[v]/div;
44
    tri_accel.b_nv = b[u]/div;
45
    tri_accel.b_d = (b[v]*A[u]-b[u]*A[v])/div;
46
 
47
    tri_accel.c_nu = c[v]/div;
48
    tri_accel.c_nv = -c[u]/div;
49
    tri_accel.c_d = (c[u]*A[v]-c[v]*A[u])/div;
50
  }
51
 
52
  // Most of this file is a direct copy from Henrik's notes
53
  BSPTree::BSPTree() 
54
  {
55
    root=0;
56
    b_is_build = false;
57
  }
58
 
59
  BSPTree::~BSPTree() 
60
  {
61
    clear();        
62
  }
63
 
64
  void BSPTree::clear() 
65
  {
66
    if (root!=0) 
67
    {
68
      delete_node(root);
69
      root=0;
70
      b_is_build=false;
71
    }
72
    isecttris.clear();
73
    all_objects.clear();
74
    all_triaccel.clear();
75
  }
76
 
77
  void BSPTree::delete_node(BSPNode *node) 
78
  {
79
    if (node->left!=0)
80
      delete_node(node->left);
81
    if (node->right!=0)
82
      delete_node(node->right);
83
    delete node;
84
  }
85
 
86
  void BSPTree::subdivide_node(BSPNode &node, BBox &bbox, 
428 jrf 87
                               unsigned int level, 
88
                               vector<ISectTri*>& objects, 
89
                               vector<TriAccel*>& tri_objects) 
349 awk 90
  {
91
    const int TESTS = 2;
92
 
93
    if (objects.size()<=max_objects || level==max_level) 
94
    {
95
      node.axis_leaf = 4; // Means that this is a leaf
96
      node.plane = 0;
97
      node.left = 0;
98
      node.right = 0;
99
      node.id = all_objects.size();
100
      node.count = objects.size();
101
 
102
      for(unsigned int i = 0; i < objects.size(); ++i) 
103
      {
428 jrf 104
        all_objects.push_back(objects[i]);
105
        all_triaccel.push_back(tri_objects[i]);
349 awk 106
      }  
107
    } 
108
    else 
109
    {
110
      bool right_zero=false;
111
      bool left_zero=false;
112
      unsigned int i;
113
      BSPNode* left_node  = new BSPNode();
114
      BSPNode* right_node = new BSPNode();
115
      vector<ISectTri*> left_objects;
116
      vector<ISectTri*> right_objects;
117
      vector<TriAccel*> tri_left_objects;
118
      vector<TriAccel*> tri_right_objects;
119
 
120
      node.left = left_node;
121
      node.right = right_node;
122
 
123
      int new_axis=-1;
124
      double min_cost=CGLA::BIG;
125
      int new_pos = -1;      
126
 
127
      for(i=0;i<3;i++) 
128
      {
428 jrf 129
        for(int k=1;k<TESTS;k++) 
130
        {
131
          BBox left_bbox = bbox;
132
          BBox right_bbox = bbox;
133
 
134
          double center = (bbox.max_corner[i]- bbox.min_corner[i])*(double)k/(double)TESTS + bbox.min_corner[i];
135
          node.plane = center;
136
 
137
          left_bbox.max_corner[i] = center; 
138
          right_bbox.min_corner[i] = center; 
349 awk 139
 
428 jrf 140
          // Try putting the triangles in the left and right boxes
141
          int left_count = 0;
142
          int right_count = 0;
143
          for(unsigned int j=0;j<objects.size();j++) 
144
          {
145
            ISectTri* tri = objects[j];
146
            left_count += left_bbox.intersect_triangle(*tri);
147
            right_count += right_bbox.intersect_triangle(*tri);
148
          }
349 awk 149
 
428 jrf 150
          //double len = bbox.max_corner[i] - bbox.min_corner[i];
151
          double cost = left_count*left_bbox.area() + right_count*right_bbox.area(); // - len*len;
152
          if(cost < min_cost) 
153
          {
154
            min_cost = cost;
155
            new_axis = i;
156
            new_pos = k;
157
            right_zero = (right_count==0);
158
            left_zero = (left_count==0);
159
          }
160
        }
349 awk 161
      }
162
      node.axis_leaf = new_axis;
163
      left_node->axis_leaf = static_cast<unsigned char>(-1); 
164
      right_node->axis_leaf = static_cast<unsigned char>(-1); 
165
 
166
      // Now chose the right splitting plane
167
      BBox left_bbox = bbox;
168
      BBox right_bbox = bbox;
169
 
170
      double size = bbox.max_corner[node.axis_leaf]- bbox.min_corner[node.axis_leaf];
171
      double center = size*(double)new_pos/(double)TESTS + bbox.min_corner[node.axis_leaf];
172
      double diff = f_eps < size/8.0 ? f_eps : size/8.0;
173
 
174
      if (left_zero) 
175
      {
428 jrf 176
        // Find min position of all triangle vertices and place the center there
177
        center = bbox.max_corner[node.axis_leaf];
178
        for(unsigned int j=0;j<objects.size();j++) 
179
        {
180
          ISectTri* tri = objects[j];
181
          if (tri->point0[node.axis_leaf]<center)
182
            center=tri->point0[node.axis_leaf];
183
          if (tri->point1[node.axis_leaf]<center)
184
            center=tri->point1[node.axis_leaf];
185
          if (tri->point2[node.axis_leaf]<center)
186
            center=tri->point2[node.axis_leaf];
187
        }
188
        center -= diff;
349 awk 189
      }
190
      if (right_zero) 
191
      {
428 jrf 192
        // Find max position of all triangle vertices and place the center there
193
        center = bbox.min_corner[node.axis_leaf];
194
        for(unsigned int j=0;j<objects.size();j++) 
195
        {
196
          ISectTri* tri = objects[j];
197
          if (tri->point0[node.axis_leaf]>center)
198
            center=tri->point0[node.axis_leaf];
199
          if (tri->point1[node.axis_leaf]>center)
200
            center=tri->point1[node.axis_leaf];
201
          if (tri->point2[node.axis_leaf]>center)
202
            center=tri->point2[node.axis_leaf];
203
        }
204
        center += diff;
349 awk 205
      }
206
 
207
      node.plane = center;
208
      left_bbox.max_corner[node.axis_leaf] = center; 
209
      right_bbox.min_corner[node.axis_leaf] = center;  
210
 
211
      // Now put the triangles in the right and left node
212
      for(i=0;i<objects.size();i++) 
213
      {
428 jrf 214
        ISectTri* tri = objects[i];
215
        TriAccel *tri_accel = tri_objects[i];
216
        if (left_bbox.intersect_triangle(*tri)) 
217
        {
218
          left_objects.push_back(tri);
219
          tri_left_objects.push_back(tri_accel);
220
        }
221
        if (right_bbox.intersect_triangle(*tri)) 
222
        {
223
          right_objects.push_back(tri);
224
          tri_right_objects.push_back(tri_accel);
225
        }
349 awk 226
      }
227
    //if (left_zero||right_zero)
228
    //  cout << left_objects.size() << "," << right_objects.size() << "," << level << endl;
229
 
230
      objects.clear();
231
      subdivide_node(*left_node , left_bbox , level+1, left_objects, tri_left_objects);
232
      subdivide_node(*right_node, right_bbox, level+1, right_objects, tri_right_objects);
233
    }
234
  }
235
 
236
  void BSPTree::init() 
237
  {
238
    root = new BSPNode();
239
    bbox.compute_bbox(isecttris);
240
    bbox.min_corner-=Vec3f(1.0);
241
    bbox.max_corner+=Vec3f(1.0);
242
  }
243
 
244
  void BSPTree::init(vector<const TriMesh*>& _trimesh, 
428 jrf 245
                     vector<Mat4x4f>& _transforms, 
246
                     int _max_objects, int _max_level) 
349 awk 247
  {
248
    trimesh = _trimesh;
249
    transforms = _transforms;
250
    for(unsigned int i=0;i<trimesh.size();i++) 
251
    {
252
      const TriMesh *mesh = trimesh[i];
253
      // Loop through all triangles and add them to intersection structure
254
      for(int j=0;j<mesh->geometry.no_faces();j++) 
255
      {
428 jrf 256
        Vec3i face = mesh->geometry.face(j);
257
        ISectTri new_tri;
258
        new_tri.point0 = transforms[i].mul_3D_point(mesh->geometry.vertex(face[0]));
259
        new_tri.point1 = transforms[i].mul_3D_point(mesh->geometry.vertex(face[1]));
260
        new_tri.point2 = transforms[i].mul_3D_point(mesh->geometry.vertex(face[2]));
261
        new_tri.edge0 = new_tri.point1 - new_tri.point0;
262
        new_tri.edge1 = new_tri.point2 - new_tri.point0;
263
        new_tri.mesh_id = i;
264
        new_tri.tri_id = j;
265
        isecttris.push_back(new_tri);
266
        TriAccel ta;
267
        create_tri_accel(new_tri.point0, new_tri.point1, new_tri.point2, ta);
268
        ta.mesh_id = i;
269
        ta.tri_id = j;
270
        triaccel.push_back(ta);
349 awk 271
      }
272
    }
273
 
274
    max_objects = _max_objects;
275
    max_level = _max_level;
276
    init();
277
  }
278
 
279
  void BSPTree::init(const TriMesh* mesh, Mat4x4f transform, 
280
             vector<int> &trilist, 
281
             int _max_objects, int _max_level) 
282
  {
283
    trimesh.push_back(mesh);
284
    transforms.push_back(transform);
285
    // Loop through all triangles and add them to intersection structure
286
    for(unsigned int j=0;j<trilist.size();j++) 
287
    {
288
      Vec3i face = mesh->geometry.face(trilist[j]);
289
      ISectTri new_tri;
290
      new_tri.point0 = transform.mul_3D_point(mesh->geometry.vertex(face[0]));
291
      new_tri.point1 = transform.mul_3D_point(mesh->geometry.vertex(face[1]));
292
      new_tri.point2 = transform.mul_3D_point(mesh->geometry.vertex(face[2]));
293
      new_tri.edge0 = new_tri.point1 - new_tri.point0;
294
      new_tri.edge1 = new_tri.point2 - new_tri.point0;
295
      new_tri.mesh_id = 0;
296
      new_tri.tri_id = trilist[j];
297
      isecttris.push_back(new_tri);
298
      TriAccel ta;
299
      create_tri_accel(new_tri.point0, new_tri.point1, new_tri.point2, ta);
300
      ta.mesh_id = 0;
301
      ta.tri_id = trilist[j];
302
      triaccel.push_back(ta);
303
    }
304
 
305
    max_objects = _max_objects;
306
    max_level = _max_level;
307
    init();
308
  }
309
 
310
  void BSPTree::build() 
311
  {
312
    if (!b_is_build) 
313
    {
314
      vector<ISectTri*> objects;
315
      vector<TriAccel*> tri_objects;
316
      for(unsigned int i=0;i<isecttris.size();i++) 
317
      {
428 jrf 318
        ISectTri* tri = &isecttris[i];
319
        TriAccel* tri_accel = &triaccel[i];
320
        objects.push_back(tri);
321
        tri_objects.push_back(tri_accel);
349 awk 322
      }
323
      subdivide_node(*root, bbox, 0, objects, tri_objects);
324
      b_is_build = true;
325
    }
326
    make_fast_tree(root);
327
  }
328
 
329
  bool BSPTree::is_build() 
330
  {
331
    return b_is_build;
332
  }
333
 
334
  void BSPTree::print(BSPNode *node, int depth) 
335
  {
336
    if (node==0)
337
      return;
338
    for(int i=0;i<depth;i++)
339
      cout << " ";
340
//  cout << "axis:" << node->axis_leaf << ", count:" << node->objects.size() << ", plane:" << node->plane << ", " << endl;
341
    print(node->left, depth+1);
342
    print(node->right, depth+1);
343
  }
344
 
345
  int BSPTree::size(BSPNode *node) 
346
  {
347
    if (node==0)
348
      return 0;
349
    int s = sizeof(BSPNode);
350
    s+= node->count * sizeof(ISectTri);
351
    s+=size(node->left);
352
    s+=size(node->right);
353
    return s;
354
  }
355
 
356
  int BSPTree::size() 
357
  {
358
    return size(root);
359
  }
360
 
361
/*__declspec(align(16))*/ static const unsigned int modulo[] = {0,1,2,0,1};
362
 
363
  inline bool intersect2(Ray &ray, const TriAccel &acc, double t_max) 
364
  {
365
//  cout << "Acc: " << (int)&acc << " ";
366
//inline bool Intersect(TriAccel &acc,Ray &ray)
367
#define ku modulo[acc.k+1]
368
#define kv modulo[acc.k+2]
369
    // don’t prefetch here, assume data has already been prefetched
370
    // start high-latency division as early as possible
371
    const double nd = 1.0/((double)ray.direction[acc.k] + (double)acc.n_u * (double)ray.direction[ku] + (double)acc.n_v * (double)ray.direction[kv]);
372
    const double f = ((double)acc.n_d - (double)ray.origin[acc.k]   - (double)acc.n_u * (double)ray.origin[ku] - (double)acc.n_v * (double)ray.origin[kv]) * nd;
373
    // check for valid distance.
374
    if (!(t_max > f && f > 0.001)||ray.dist<f) return false;
375
    // compute hitpoint positions on uv plane
376
    const double hu = (ray.origin[ku] + f * ray.direction[ku]);
377
    const double hv = (ray.origin[kv] + f * ray.direction[kv]);
378
    // check first barycentric coordinate
379
    const double lambda = (hu * (double)acc.b_nu + hv * (double)acc.b_nv + (double)acc.b_d);
380
    if (lambda < 0.0) return false;
381
    // check second barycentric coordinate
382
    const double mue = (hu * (double)acc.c_nu + hv * (double)acc.c_nv + (double)acc.c_d);
383
    if (mue < 0.0) return false;
384
    // check third barycentric coordinate
385
    if (lambda+mue > 1.0) return false;
386
    // have a valid hitpoint here. store it.
387
    ray.dist = f;
388
    ray.u = lambda;
389
    ray.v = mue;
390
    ray.hit_object = (TriMesh*)acc.mesh_id;
391
    ray.hit_face_id = acc.tri_id;
392
    ray.has_hit=true;
393
    return true;
394
  }
395
 
396
  bool BSPTree::intersect_node(Ray &ray, const BSPNode &node, double t_min, double t_max) const 
397
  {
398
//    cout << node.plane << endl;
429 jrf 399
    node_calls++;    
349 awk 400
    if (node.axis_leaf==4) 
401
    {
429 jrf 402
      bool found = false; 
403
      for(int i=0; i < node.count; ++i) 
349 awk 404
      {
428 jrf 405
//        const TriAccel* tri2 = all_triaccel[node.id+i];
406
        const ISectTri* tri = all_objects[node.id+i];
407
//        if (intersect2(ray, *tri2, t_max))  
408
//          found=true;
409
        if (intersect(ray, *tri, t_max))  
410
          found=true;
349 awk 411
      }
412
      if (found)
429 jrf 413
        return true;
349 awk 414
      else 
429 jrf 415
        return false;
349 awk 416
    } 
417
    else 
418
    {
419
      BSPNode *near_node;
420
      BSPNode *far_node;
421
      if (ray.direction[node.axis_leaf]>=0) 
422
      {
428 jrf 423
        near_node = node.left;
424
        far_node = node.right;
349 awk 425
      } 
426
      else 
427
      {
428 jrf 428
        near_node = node.right;
429
        far_node = node.left;
349 awk 430
      }
431
 
432
      // In order to avoid instability
433
      double t;
434
      if (fabs(ray.direction[node.axis_leaf])<d_eps)
428 jrf 435
        t = (node.plane - ray.origin[node.axis_leaf])/d_eps;// intersect node plane;
349 awk 436
      else
428 jrf 437
        t = (node.plane - ray.origin[node.axis_leaf])/ray.direction[node.axis_leaf];// intersect node plane;
349 awk 438
 
439
      if (t>t_max) 
428 jrf 440
        return intersect_node(ray, *near_node, t_min, t_max);      
349 awk 441
      else if (t<t_min) 
428 jrf 442
        return intersect_node(ray, *far_node, t_min, t_max);
349 awk 443
      else 
444
      {
428 jrf 445
        if (intersect_node(ray, *near_node, t_min, t))
446
          return true;
447
        else 
448
          return intersect_node(ray, *far_node, t, t_max);
349 awk 449
      }
450
    }
451
  }
452
 
453
  bool BSPTree::intersect(Ray &ray) const 
454
  {
455
    double t_min, t_max;
456
    bbox.intersect_min_max(ray, t_min, t_max);
457
    if (t_min>t_max)
458
      return false;
459
 
350 awk 460
//    printf("%.2f %.2f %.2f\n", ray.dist, t_min, t_max);
461
    if (!intersect_node(ray, *root, t_min, t_max))
462
      return false;
349 awk 463
//  cout << "____" << endl;
464
//  ray.reset();
465
//  cout << "Here " << endl;
350 awk 466
//    intersect_fast_node(ray, &fast_tree[0], t_min, t_max);
467
    //  if (!ray.has_hit)
468
    //return false;
349 awk 469
    else 
470
    {
428 jrf 471
      //printf("HIT\n");
349 awk 472
 
473
      // Calculate the normal at the intersection
428 jrf 474
      ray.id = reinterpret_cast<int>(ray.hit_object);
475
      ray.hit_object = trimesh[ray.id];
476
 
477
      Vec3i face = ray.hit_object->normals.face(ray.hit_face_id);
478
      Vec3f normal0 = ray.hit_object->normals.vertex(face[0]);
479
      Vec3f normal1 = ray.hit_object->normals.vertex(face[1]);
480
      Vec3f normal2 = ray.hit_object->normals.vertex(face[2]);
481
      ray.hit_normal = transforms[ray.id].mul_3D_vector(
482
          normalize(normal0*(1 - ray.u - ray.v)
483
          +normal1*ray.u
484
          +normal2*ray.v));
485
 
486
      ray.hit_pos = ray.origin + ray.direction*ray.dist;
349 awk 487
/*
488
      Vec3i face = ray.hit_object->normals.face(ray.hit_face_id);
489
      Vec3f normal0 = ray.hit_object->normals.vertex(face[0]);
490
      Vec3f normal1 = ray.hit_object->normals.vertex(face[1]);
491
      Vec3f normal2 = ray.hit_object->normals.vertex(face[2]);
492
      ray.hit_normal = normalize(normal0*(1 - ray.u - ray.v)
493
                 +normal1*ray.u
494
                 +normal2*ray.v);
495
      ray.hit_pos = ray.origin + ray.direction*ray.dist;
496
*/
497
      return true;
498
    }
499
  }
500
 
501
  const int MAX_DEPTH=25;
502
 
503
  void BSPTree::make_fast_tree(BSPNode *node) 
504
  {
505
    fast_tree.resize(1000000); // 
506
    FastBSPNode f_node;
507
    fast_tree.push_back(f_node);
508
    push_fast_bsp_node(node,0);
509
  }
510
 
511
  void BSPTree::push_fast_bsp_node(BSPNode *node, int id) 
512
  {
513
    if (node->axis_leaf==4)  // It is a leaf
514
    {
428 jrf 515
      //assert(false);
516
      //TODO: cant compile on 64 bit gcc
354 awk 517
 
428 jrf 518
      //fast_tree[id].leaf.flagAndOffset = (unsigned int)1<<31 | (unsigned int)(&all_triaccel[node->id]);
349 awk 519
      fast_tree[id].leaf.count = node->count;
520
    } 
521
    else // It is an inner node
522
    { 
523
      FastBSPNode fnode;
524
      int p_l = fast_tree.size();
525
      fast_tree.push_back(fnode); // left
526
      fast_tree.push_back(fnode); // right
527
      push_fast_bsp_node(node->left, p_l);
528
      push_fast_bsp_node(node->right, p_l+1);
354 awk 529
 
364 jrf 530
      //assert(false);
354 awk 531
      //TODO: gcc64 bit failure
532
 
533
      //fast_tree[id].inner.flagAndOffset = (unsigned int) &fast_tree[p_l] | node->axis_leaf;
349 awk 534
      fast_tree[id].inner.splitCoordinate = node->plane;
535
      node->ref = fast_tree[id].inner.flagAndOffset;
536
    }
537
  }
538
 
539
#define ABSP_ISLEAF(n)       (n->inner.flagAndOffset & (unsigned int)1<<31)
540
#define ABSP_DIMENSION(n)    (n->inner.flagAndOffset & 0x3)
541
#define ABSP_OFFSET(n)       (n->inner.flagAndOffset & (0x7FFFFFFC))
542
#define ABSP_NEARNODE(n)     (FastBSPNode*)(ray.direction[dimension]>=0?ABSP_OFFSET(node):ABSP_OFFSET(node)+sizeof(*node))
543
#define ABSP_FARNODE(n)      (FastBSPNode*)(ray.direction[dimension]>=0?ABSP_OFFSET(node)+sizeof(*node):ABSP_OFFSET(node))
544
#define ABSP_TRIANGLENODE(n) (vector<TriAccel*>::iterator)(n->flagAndOffset & (0x7FFFFFFF))
545
 
546
  struct Stack 
547
  {
548
    FastBSPNode *node;
549
    double t_min;
550
    double t_max;
551
  };
552
 
553
  inline void IntersectAlltrianglesInLeaf(const BSPLeaf* leaf, Ray &ray, double t_max) {
554
    TriAccel** tri_acc_ptr = reinterpret_cast<TriAccel**>(leaf->flagAndOffset & (0x7FFFFFFF));
555
    vector<TriAccel*>::iterator acc = vector<TriAccel*>::iterator(tri_acc_ptr);
556
//  vector<TriAccel*>::iterator acc = ABSP_TRIANGLENODE(leaf);
557
    for(unsigned int i=0;i<leaf->count;++i)
558
      intersect2(ray, *(*acc++), t_max);
559
  }
560
 
561
  void BSPTree::intersect_fast_node(Ray &ray, const FastBSPNode *node, double t_min, double t_max) const 
562
  {
563
    Stack stack[MAX_DEPTH];
564
    int stack_id=0;
565
    double t;
566
    // Precalculate one over dir
567
    double one_over_dir[3];
568
    for(int i=0;i<3;i++) 
569
    {
570
      if (ray.direction[i]!=0)
428 jrf 571
        one_over_dir[i]=1.0/ray.direction[i];
349 awk 572
      else
428 jrf 573
        one_over_dir[i]=1.0/d_eps;
349 awk 574
    }
575
 
576
    int dimension;
577
    while(1) 
578
    {
579
      while(!ABSP_ISLEAF(node)) 
580
      {
428 jrf 581
        dimension = ABSP_DIMENSION(node);
582
        t = (node->inner.splitCoordinate - ray.origin[dimension])*one_over_dir[dimension];
583
        if (t>=t_max) 
584
          node = ABSP_NEARNODE(node);
585
        else if (t<=t_min)
586
          node = ABSP_FARNODE(node);
587
        else 
588
        {
589
          // Stack push
590
          stack[stack_id].node = ABSP_FARNODE(node);
591
          stack[stack_id].t_min = t;
592
          stack[stack_id++].t_max = t_max;
593
          // Set current node to near side
594
          node = ABSP_NEARNODE(node);
595
          t_max = t;
596
        }
349 awk 597
      }
598
 
599
      IntersectAlltrianglesInLeaf(&node->leaf, ray, t_max);
600
      if (ray.dist<t_max)
428 jrf 601
        return;
349 awk 602
      if (stack_id==0)
428 jrf 603
        return;
349 awk 604
      // Stack pop
605
 
606
      node = stack[--stack_id].node;
607
      t_min = stack[stack_id].t_min;
608
      t_max = stack[stack_id].t_max;
609
    }
610
  }
611
 
612
  bool BSPTree::intersect(Ray &ray, const ISectTri &isecttri, double t_max) const 
613
  {
614
    tri_calls++;
429 jrf 615
 
349 awk 616
    // This is the Möller-Trumbore method
429 jrf 617
    Vec3d direction(ray.direction);
618
    Vec3d edge0(isecttri.edge0);
619
    Vec3d edge1(isecttri.edge1);
349 awk 620
 
429 jrf 621
    // Ray-triangle intersection
622
    Vec3d p = cross(direction, edge1);
623
    double a = dot(edge0, p);
624
    if(a > -d_eps && a < d_eps)
349 awk 625
      return false;
429 jrf 626
 
627
    // Just delay these 
628
    Vec3d origin(ray.origin);
629
    Vec3d point0(isecttri.point0);    
630
    double f = 1.0/a;
631
    Vec3d s = origin - point0;
430 jrf 632
    double u = f*dot(s, p);
429 jrf 633
    if(u < 0.0 || u > 1.0)
349 awk 634
      return false;
429 jrf 635
 
636
    Vec3d q = cross(s, edge0);
637
    double v = f*dot(direction, q);  
638
    if(v < 0.0 || u + v > 1.0)
349 awk 639
      return false;
429 jrf 640
 
641
    double t = f*dot(edge1, q);
430 jrf 642
    if(t < f_eps || t*t < f_eps)
349 awk 643
      return false;
430 jrf 644
    if(t > t_max)
349 awk 645
      return false;
429 jrf 646
    if(t > ray.dist)
349 awk 647
      return false;
648
 
429 jrf 649
    ray.dist = t;
349 awk 650
    ray.u = u;
651
    ray.v = v;
652
    ray.hit_object = (TriMesh*)isecttri.mesh_id;
653
    ray.hit_face_id = isecttri.tri_id;
654
    ray.has_hit=true;
655
    return true; 
656
  }
657
}