Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
310 jrf 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, 
87
			       unsigned int level, 
88
			       vector<ISectTri*>& objects, 
89
			       vector<TriAccel*>& tri_objects) 
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
      {
104
	all_objects.push_back(objects[i]);
105
	all_triaccel.push_back(tri_objects[i]);
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
      //node.is_leaf = false;
123
 
124
      int new_axis=-1;
125
      double min_cost=CGLA::BIG;
126
      int new_pos = -1;      
127
/*
128
       float max_size=0;
129
       for(i=0;i<3;i++) {
130
         if (bbox.max_corner[i]-bbox.min_corner[i]>max_size) {
131
	   max_size = bbox.max_corner[i]-bbox.min_corner[i];
132
	   new_axis=i;
133
	   new_pos = 1;
134
	 }
135
       }
136
*/
137
      for(i=0;i<3;i++) 
138
      {
139
	for(int k=1;k<TESTS;k++) 
140
	{
141
	  BBox left_bbox = bbox;
142
	  BBox right_bbox = bbox;
143
 
144
	  double center = (bbox.max_corner[i]- bbox.min_corner[i])*(double)k/(double)TESTS + bbox.min_corner[i];
145
	  node.plane = center;
146
 
147
	  left_bbox.max_corner[i] = center; 
148
	  right_bbox.min_corner[i] = center; 
149
 
150
	  // Try putting the triangles in the left and right boxes
151
	  int left_count = 0;
152
	  int right_count = 0;
153
	  for(unsigned int j=0;j<objects.size();j++) 
154
	  {
155
	    ISectTri* tri = objects[j];
156
	    left_count += left_bbox.intersect_triangle(*tri);
157
	    right_count += right_bbox.intersect_triangle(*tri);
158
	  }
159
 
160
	  if (left_count*left_bbox.area() + right_count*right_bbox.area() < min_cost) 
161
	  {
162
	    min_cost = left_count*left_bbox.area() + right_count*right_bbox.area();
163
	    new_axis = i;
164
	    new_pos = k;
165
	    right_zero = (right_count==0);
166
	    left_zero = (left_count==0);
167
	  }
168
	}
169
      }
170
      node.axis_leaf = new_axis;
171
      //	node.axis_leaf = level %3;
172
      left_node->axis_leaf = static_cast<unsigned char>(-1); //(node.axis + 1)%3;
173
      right_node->axis_leaf = static_cast<unsigned char>(-1); //(node.axis + 1)%3;
174
      // Now chose the right splitting plane
175
      BBox left_bbox = bbox;
176
      BBox right_bbox = bbox;
177
 
178
      double size = bbox.max_corner[node.axis_leaf]- bbox.min_corner[node.axis_leaf];
179
      double center = size*(double)new_pos/(double)TESTS + bbox.min_corner[node.axis_leaf];
180
      double diff = f_eps < size/8.0 ? f_eps : size/8.0;
181
 
182
      // This doesn't help that much
183
      if (left_zero) 
184
      {
185
//			cout << "Old left center: " << center;
186
	// Find min position af alle trekanter og placer center der
187
	center = bbox.max_corner[node.axis_leaf];
188
	for(unsigned int j=0;j<objects.size();j++) 
189
	{
190
	  ISectTri* tri = objects[j];
191
	  if (tri->point0[node.axis_leaf]<center)
192
	    center=tri->point0[node.axis_leaf];
193
	  if (tri->point1[node.axis_leaf]<center)
194
	    center=tri->point1[node.axis_leaf];
195
	  if (tri->point2[node.axis_leaf]<center)
196
	    center=tri->point2[node.axis_leaf];
197
	}
198
	center -= diff;
199
//			cout << "new left center: " << center << endl;
200
      }
201
      if (right_zero) 
202
      {
203
//			cout << "Old right center: " << center;
204
	// Find max position af alle trekanter og placer center der
205
	center = bbox.min_corner[node.axis_leaf];
206
	for(unsigned int j=0;j<objects.size();j++) 
207
	{
208
	  ISectTri* tri = objects[j];
209
	  if (tri->point0[node.axis_leaf]>center)
210
	    center=tri->point0[node.axis_leaf];
211
	  if (tri->point1[node.axis_leaf]>center)
212
	    center=tri->point1[node.axis_leaf];
213
	  if (tri->point2[node.axis_leaf]>center)
214
	    center=tri->point2[node.axis_leaf];
215
	}
216
	center += diff;
217
//			cout << "new right center: " << center << endl;
218
      }
219
 
220
      node.plane = center;
221
      left_bbox.max_corner[node.axis_leaf] = center; // + f_eps; 
222
      right_bbox.min_corner[node.axis_leaf] = center; // - f_eps; 
223
 
224
      // Now put the triangles in the right and left node
225
      for(i=0;i<objects.size();i++) 
226
      {
227
	ISectTri* tri = objects[i];
228
	TriAccel *tri_accel = tri_objects[i];
229
	if (left_bbox.intersect_triangle(*tri)) 
230
	{
231
	  left_objects.push_back(tri);
232
	  tri_left_objects.push_back(tri_accel);
233
	}
234
	if (right_bbox.intersect_triangle(*tri)) 
235
	{
236
	  right_objects.push_back(tri);
237
	  tri_right_objects.push_back(tri_accel);
238
	}
239
      }
311 jrf 240
    //if (left_zero||right_zero)
241
	//  cout << left_objects.size() << "," << right_objects.size() << "," << level << endl;
310 jrf 242
 
243
      objects.clear();
244
      subdivide_node(*left_node , left_bbox , level+1, left_objects, tri_left_objects);
245
      subdivide_node(*right_node, right_bbox, level+1, right_objects, tri_right_objects);
246
    }
247
  }
248
 
249
  void BSPTree::init() 
250
  {
251
    root = new BSPNode();
252
    bbox.compute_bbox(isecttris);
253
    bbox.min_corner-=Vec3f(1.0);
254
    bbox.max_corner+=Vec3f(1.0);
255
  }
256
 
257
  void BSPTree::init(vector<TriMesh*>& _trimesh, 
258
		     vector<Mat4x4f>& _transforms, 
259
		     int _max_objects, int _max_level) 
260
  {
261
    trimesh = _trimesh;
262
    transforms = _transforms;
263
    for(unsigned int i=0;i<trimesh.size();i++) 
264
    {
265
      TriMesh *mesh = trimesh[i];
266
      // Loop through all triangles and add them to intersection structure
267
      for(int j=0;j<mesh->geometry.no_faces();j++) 
268
      {
269
	Vec3i face = mesh->geometry.face(j);
270
	ISectTri new_tri;
271
	new_tri.point0 = transforms[i].mul_3D_point(mesh->geometry.vertex(face[0]));
272
	new_tri.point1 = transforms[i].mul_3D_point(mesh->geometry.vertex(face[1]));
273
	new_tri.point2 = transforms[i].mul_3D_point(mesh->geometry.vertex(face[2]));
274
	new_tri.edge0 = new_tri.point1 - new_tri.point0;
275
	new_tri.edge1 = new_tri.point2 - new_tri.point0;
276
	new_tri.mesh_id = i;
277
	new_tri.tri_id = j;
278
	isecttris.push_back(new_tri);
279
	TriAccel ta;
280
	create_tri_accel(new_tri.point0, new_tri.point1, new_tri.point2, ta);
281
	ta.mesh_id = i;
282
	ta.tri_id = j;
283
	triaccel.push_back(ta);
284
      }
285
    }
286
 
287
    max_objects = _max_objects;
288
    max_level = _max_level;
289
    init();
290
  }
291
 
292
  void BSPTree::init(TriMesh* mesh, Mat4x4f transform, 
293
		     vector<int> &trilist, 
294
		     int _max_objects, int _max_level) 
295
  {
296
    trimesh.push_back(mesh);
297
    transforms.push_back(transform);
298
    // Loop through all triangles and add them to intersection structure
299
    for(unsigned int j=0;j<trilist.size();j++) 
300
    {
301
      Vec3i face = mesh->geometry.face(trilist[j]);
302
      ISectTri new_tri;
303
      new_tri.point0 = transform.mul_3D_point(mesh->geometry.vertex(face[0]));
304
      new_tri.point1 = transform.mul_3D_point(mesh->geometry.vertex(face[1]));
305
      new_tri.point2 = transform.mul_3D_point(mesh->geometry.vertex(face[2]));
306
      new_tri.edge0 = new_tri.point1 - new_tri.point0;
307
      new_tri.edge1 = new_tri.point2 - new_tri.point0;
308
      new_tri.mesh_id = 0;
309
      new_tri.tri_id = trilist[j];
310
      isecttris.push_back(new_tri);
311
      TriAccel ta;
312
      create_tri_accel(new_tri.point0, new_tri.point1, new_tri.point2, ta);
313
      ta.mesh_id = 0;
314
      ta.tri_id = trilist[j];
315
      triaccel.push_back(ta);
316
    }
317
 
318
    max_objects = _max_objects;
319
    max_level = _max_level;
320
    init();
321
  }
322
 
323
  void BSPTree::build() 
324
  {
325
    if (!b_is_build) 
326
    {
327
      vector<ISectTri*> objects;
328
      vector<TriAccel*> tri_objects;
329
      for(unsigned int i=0;i<isecttris.size();i++) 
330
      {
331
	ISectTri* tri = &isecttris[i];
332
	TriAccel* tri_accel = &triaccel[i];
333
	objects.push_back(tri);
334
	tri_objects.push_back(tri_accel);
335
      }
336
      subdivide_node(*root, bbox, 0, objects, tri_objects);
337
      b_is_build = true;
338
    }
339
    isecttris.clear();
340
    all_objects.clear();
341
    make_fast_tree(root);
342
  }
343
 
344
  bool BSPTree::is_build() 
345
  {
346
    return b_is_build;
347
  }
348
 
349
  void BSPTree::print(BSPNode *node, int depth) 
350
  {
351
    if (node==0)
352
      return;
353
    for(int i=0;i<depth;i++)
354
      cout << " ";
355
//	cout << "axis:" << node->axis_leaf << ", count:" << node->objects.size() << ", plane:" << node->plane << ", " << endl;
356
    print(node->left, depth+1);
357
    print(node->right, depth+1);
358
  }
359
 
360
  int BSPTree::size(BSPNode *node) 
361
  {
362
    if (node==0)
363
      return 0;
364
    int s = sizeof(BSPNode);
365
    s+= node->count * sizeof(ISectTri);
366
    s+=size(node->left);
367
    s+=size(node->right);
368
    return s;
369
  }
370
 
371
  int BSPTree::size() 
372
  {
373
    return size(root);
374
  }
375
 
376
/*__declspec(align(16))*/ static const unsigned int modulo[] = {0,1,2,0,1};
377
 
378
  inline bool intersect2(Ray &ray, const TriAccel &acc, double t_max) 
379
  {
380
//	cout << "Acc: " << (int)&acc << " ";
381
//inline bool Intersect(TriAccel &acc,Ray &ray)
382
#define ku modulo[acc.k+1]
383
#define kv modulo[acc.k+2]
384
    // don’t prefetch here, assume data has already been prefetched
385
    // start high-latency division as early as possible
386
    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]);
387
    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;
388
    // check for valid distance.
389
    if (!(t_max > f && f > f_eps)||ray.dist<f) return false;
390
    // compute hitpoint positions on uv plane
391
    const double hu = (ray.origin[ku] + f * ray.direction[ku]);
392
    const double hv = (ray.origin[kv] + f * ray.direction[kv]);
393
    // check first barycentric coordinate
394
    const double lambda = (hu * (double)acc.b_nu + hv * (double)acc.b_nv + (double)acc.b_d);
395
    if (lambda < 0.0) return false;
396
    // check second barycentric coordinate
397
    const double mue = (hu * (double)acc.c_nu + hv * (double)acc.c_nv + (double)acc.c_d);
398
    if (mue < 0.0) return false;
399
    // check third barycentric coordinate
400
    if (lambda+mue > 1.0) return false;
401
    // have a valid hitpoint here. store it.
402
    ray.dist = f;
403
    ray.u = lambda;
404
    ray.v = mue;
405
    ray.hit_object = (TriMesh*)acc.mesh_id;
406
    ray.hit_face_id = acc.tri_id;
407
    ray.has_hit=true;
408
    return true;
409
  }
410
 
411
  bool BSPTree::intersect_node(Ray &ray, const BSPNode &node, double t_min, double t_max) const 
412
  {
413
//    cout << node.plane << endl;
414
    node_calls++;
415
    static bool found;
416
    static int i;
417
 
418
    if (node.axis_leaf==4) 
419
    {
420
      found = false; 
421
      for(i=0;i<node.count;i++) 
422
      {
423
//	const TriAccel* tri2 = all_triaccel[node.id+i];
424
	const ISectTri* tri = all_objects[node.id+i];
425
//			if (intersect2(ray, *tri2, t_max))  
426
//				found=true;
427
	if (intersect(ray, *tri, t_max))  
428
	  found=true;
429
      }
430
      if (found)
431
	return true;
432
      else 
433
	return false;
434
    } 
435
    else 
436
    {
437
      BSPNode *near_node;
438
      BSPNode *far_node;
439
      if (ray.direction[node.axis_leaf]>=0) 
440
      {
441
	near_node = node.left;
442
	far_node = node.right;
443
      } 
444
      else 
445
      {
446
	near_node = node.right;
447
	far_node = node.left;
448
      }
449
 
450
      // In order to avoid instability
451
      double t;
452
      if (fabs(ray.direction[node.axis_leaf])<d_eps)
453
	t = (node.plane - ray.origin[node.axis_leaf])/d_eps;// intersect node plane;
454
      else
455
	t = (node.plane - ray.origin[node.axis_leaf])/ray.direction[node.axis_leaf];// intersect node plane;
456
 
457
      if (t>t_max) 
458
      	return intersect_node(ray, *near_node, t_min, t_max);
459
 
460
      else if (t<t_min) 
461
	return intersect_node(ray, *far_node, t_min, t_max);
462
      else 
463
      {
464
	if (intersect_node(ray, *near_node, t_min, t))
465
	  return true;
466
	else 
467
	  return intersect_node(ray, *far_node, t, t_max);
468
      }
469
    }
470
  }
471
 
472
  bool BSPTree::intersect(Ray &ray) const 
473
  {
474
    double t_min, t_max;
475
    bbox.intersect_min_max(ray, t_min, t_max);
476
    if (t_min>t_max)
477
      return false;
478
//    if (!intersect_node(ray, *root, t_min, t_max))
479
//      return false;
480
//	cout << "____" << endl;
481
//	ray.reset();
482
//	cout << "Here " << endl;
483
    intersect_fast_node(ray, &fast_tree[0], t_min, t_max);
484
    if (!ray.has_hit)
485
      return false;
486
    else 
487
    {
488
      // Calculate the normal at the intersection
489
      ray.hit_object = trimesh[(int)ray.hit_object];
490
/*
491
      Vec3i face = ray.hit_object->normals.face(ray.hit_face_id);
492
      Vec3f normal0 = ray.hit_object->normals.vertex(face[0]);
493
      Vec3f normal1 = ray.hit_object->normals.vertex(face[1]);
494
      Vec3f normal2 = ray.hit_object->normals.vertex(face[2]);
495
      ray.hit_normal = normalize(normal0*(1 - ray.u - ray.v)
496
				 +normal1*ray.u
497
				 +normal2*ray.v);
498
      ray.hit_pos = ray.origin + ray.direction*ray.dist;
499
*/
500
      return true;
501
    }
502
  }
503
 
504
  const int MAX_DEPTH=25;
505
 
506
  void BSPTree::make_fast_tree(BSPNode *node) 
507
  {
508
    fast_tree.resize(1000000); // 
509
    FastBSPNode f_node;
510
    fast_tree.push_back(f_node);
511
    push_fast_bsp_node(node,0);
512
  }
513
 
514
  void BSPTree::push_fast_bsp_node(BSPNode *node, int id) 
515
  {
516
    if (node->axis_leaf==4)  // It is a leaf
517
    {
518
      fast_tree[id].leaf.flagAndOffset = (unsigned int)1<<31 | (unsigned int)(&all_triaccel[node->id]);
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);
529
      fast_tree[id].inner.flagAndOffset = (unsigned int) &fast_tree[p_l] | node->axis_leaf;
530
      fast_tree[id].inner.splitCoordinate = node->plane;
531
      node->ref = fast_tree[id].inner.flagAndOffset;
532
    }
533
  }
534
 
535
#define ABSP_ISLEAF(n)       (n->inner.flagAndOffset & (unsigned int)1<<31)
536
#define ABSP_DIMENSION(n)    (n->inner.flagAndOffset & 0x3)
537
#define ABSP_OFFSET(n)       (n->inner.flagAndOffset & (0x7FFFFFFC))
538
#define ABSP_NEARNODE(n)     (FastBSPNode*)(ray.direction[dimension]>=0?ABSP_OFFSET(node):ABSP_OFFSET(node)+sizeof(*node))
539
#define ABSP_FARNODE(n)      (FastBSPNode*)(ray.direction[dimension]>=0?ABSP_OFFSET(node)+sizeof(*node):ABSP_OFFSET(node))
540
#define ABSP_TRIANGLENODE(n) (vector<TriAccel*>::iterator)(n->flagAndOffset & (0x7FFFFFFF))
541
 
542
  struct Stack 
543
  {
544
    FastBSPNode *node;
545
    double t_min;
546
    double t_max;
547
  };
548
 
549
  inline void IntersectAlltrianglesInLeaf(const BSPLeaf* leaf, Ray &ray, double t_max) {
550
    TriAccel** tri_acc_ptr = reinterpret_cast<TriAccel**>(leaf->flagAndOffset & (0x7FFFFFFF));
551
    vector<TriAccel*>::iterator acc = vector<TriAccel*>::iterator(tri_acc_ptr);
552
//	vector<TriAccel*>::iterator acc = ABSP_TRIANGLENODE(leaf);
553
    for(unsigned int i=0;i<leaf->count;++i)
554
      intersect2(ray, *(*acc++), t_max);
555
  }
556
 
557
  void BSPTree::intersect_fast_node(Ray &ray, const FastBSPNode *node, double t_min, double t_max) const 
558
  {
559
    Stack stack[MAX_DEPTH];
560
    int stack_id=0;
561
    double t;
562
    // Precalculate one over dir
563
    double one_over_dir[3];
564
    for(int i=0;i<3;i++) 
565
    {
566
      if (ray.direction[i]!=0)
567
	one_over_dir[i]=1.0/ray.direction[i];
568
      else
569
	one_over_dir[i]=1.0/d_eps;
570
    }
571
 
572
    int dimension;
573
    while(1) 
574
    {
575
      while(!ABSP_ISLEAF(node)) 
576
      {
577
	dimension = ABSP_DIMENSION(node);
578
	t = (node->inner.splitCoordinate - ray.origin[dimension])*one_over_dir[dimension];
579
	if (t>=t_max) 
580
	  node = ABSP_NEARNODE(node);
581
	else if (t<=t_min)
582
	  node = ABSP_FARNODE(node);
583
	else 
584
	{
585
	  // Stack push
586
	  stack[stack_id].node = ABSP_FARNODE(node);
587
	  stack[stack_id].t_min = t;
588
	  stack[stack_id++].t_max = t_max;
589
	  // Set current node to near side
590
	  node = ABSP_NEARNODE(node);
591
	  t_max = t;
592
	}
593
      }
594
 
595
      IntersectAlltrianglesInLeaf(&node->leaf, ray, t_max);
596
      if (ray.dist<t_max)
597
	return;
598
      if (stack_id==0)
599
	return;
600
      // Stack pop
601
 
602
      node = stack[--stack_id].node;
603
      t_min = stack[stack_id].t_min;
604
      t_max = stack[stack_id].t_max;
605
    }
606
  }
607
 
608
  bool BSPTree::intersect(Ray &ray, const ISectTri &isecttri, double t_max) const 
609
  {
610
    tri_calls++;
611
    // This is the Möller-Trumbore method
612
    static Vec3d direction; // = Vec3d(ray.direction);
613
    static Vec3d origin; // = Vec3d(ray.direction);
614
    static Vec3d edge1; // = Vec3d(ray.direction);
615
    static Vec3d edge0; // = Vec3d(ray.direction);
616
    static Vec3d point0; // = Vec3d(ray.direction);
617
    static Vec3d p;
618
    static Vec3d q;
619
    static Vec3d s;
620
    static Vec3f point;
621
    static double a, f, u, v, t;
622
    static double ray_dist_sq;
623
 
624
    static double dist_sq;
625
 
626
    static Vec3f found_point;
627
 
628
    direction.set((double)ray.direction[0], (double)ray.direction[1], (double)ray.direction[2]);
629
    edge0.set((double)isecttri.edge0[0], (double)isecttri.edge0[1], (double)isecttri.edge0[2]);
630
    edge1.set((double)isecttri.edge1[0], (double)isecttri.edge1[1], (double)isecttri.edge1[2]);
631
 
632
// Ray-tri intersection
633
//		const double eps = 0.001f;
634
/********* Complain!!!!!!!!!!!!!!!! *****************/		
635
	//p = cross(direction, edge1);
636
	// Why the &%¤/ is this so much faster????? - Because of MS Compiler - the intel compiler does it right!!
637
    p.set(direction[1] * edge1[2] - direction[2] * edge1[1], 
638
	  direction[2] * edge1[0] - direction[0] * edge1[2], 
639
	  direction[0] * edge1[1] - direction[1] * edge1[0]);
640
/****************************************************/
641
    a = dot(edge0,p);
642
    if (a>-d_eps && a<d_eps)
643
      return false;
644
  // Just delay these 
645
    origin.set((double)ray.origin[0], (double)ray.origin[1], (double)ray.origin[2]);
646
    point0.set((double)isecttri.point0[0], (double)isecttri.point0[1], (double)isecttri.point0[2]);
647
 
648
    f = 1.0/a;
649
    s = origin - point0;
650
    u = f*dot(s,p);
651
    if (u<0.0 || u>1.0)
652
      return false;
653
/********* Complain!!!!!!!!!!!!!!!! *****************/		
654
  //q = cross(s, edge0);
655
  // Why the &%¤/ is this so much faster?????
656
    q.set(s[1] * edge0[2] - s[2] * edge0[1], 
657
	  s[2] * edge0[0] - s[0] * edge0[2], 
658
	  s[0] * edge0[1] - s[1] * edge0[0]);
659
/****************************************************/
660
 
661
    v = f * dot(direction, q);  
662
    if (v<0.0 || u+v>1.0)
663
      return false;
664
    t = f*dot(edge1, q);
665
    if (t<0)
666
      return false;
667
    if (fabs(t)<d_eps)
668
      return false;
669
    if (t_max<t)
670
      return false;
671
    point = ray.origin + ray.direction*t;
672
 
673
    dist_sq = dot(point-ray.origin, point-ray.origin);
674
    ray_dist_sq = ray.dist * ray.dist;
675
 
676
    if (dist_sq<f_eps)
677
      return false;
678
    if (dist_sq>ray_dist_sq)
679
      return false;
680
 
681
    ray.dist = sqrt(dist_sq);
682
    ray.u = u;
683
    ray.v = v;
684
    ray.hit_object = (TriMesh*)isecttri.mesh_id;
685
    ray.hit_face_id = isecttri.tri_id;
686
    ray.has_hit=true;
687
    return true; 
688
  }
689
}