source: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbf2trv.cpp @ 2595

Revision 2595, 19.3 KB checked in by bittner, 16 years ago (diff)
Line 
1// ===================================================================
2// $Id: $
3//
4// ktbftrav.cpp
5//
6// class: CKTBTraversal
7//
8// REPLACEMENT_STRING
9//
10// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
11// Initial coding by Vlasta Havran, February 2007 (copy from kdrtrav.cpp)
12
13// GOLEM headers
14#include "ktbconf.h"
15#include "ktbtrav.h"
16#include "Intersectable.h"
17
18namespace GtpVisibilityPreprocessor {
19
20#ifdef TRV00F
21
22#ifdef _USE_HAVRAN_SSE 
23#ifdef __SSE__
24
25// Even faster - about 125,500 rays per second for single dir and 164,000 rps
26// for double dir !
27int
28CKTBTraversal::FindNearestI_16oneDir(SimpleRayContainer &rays, int offset,
29                                     int copyOffset)
30{
31  static RayPacket2x2 raypack;
32  struct SResultI {
33    Intersectable *intersectable;
34    float          tdist;   
35  };
36  static SResultI results[16];
37   
38  for (int i = 0; i < 4; i++) {
39    int k = i * 4 + offset;
40    for (int j = 0; j < 4; j++, k++) {
41      raypack.SetLoc(j, rays[k].mOrigin);
42      raypack.SetDir(j, rays[k].mDirection);     
43    }
44    // Here either use ray packet traversal or
45    // casting individual rays
46    FindNearestI(raypack);
47    k = i * 4;
48    for (int j = 0; j < 4; j++, k++) {
49      results[k].intersectable = raypack.GetObject(j);
50      results[k].tdist = raypack.GetT(j);
51    } // for j
52  } // for i
53
54  // Copy the results to the output array
55  for (int i = 0; i < 16; i++) {
56    SimpleRay::IntersectionRes[i + copyOffset].intersectable =
57      results[i].intersectable;
58    SimpleRay::IntersectionRes[i + copyOffset].tdist =
59      results[i].tdist;
60  } // for i
61  return 0;
62}
63 
64#if 0
65// This code works well 1/1/2008 - 11:00
66// The same operations for packets of rays for the same signs,
67// otherwise it is emulated by decomposition
68// of a packet to individual rays and traced individually.
69void
70CKTBTraversal::FindNearestI(RayPacket2x2 &rp)
71{
72  int m1 = _mm_movemask_ps(rp.dx4);
73  if ((m1 == 0)||(m1 == 15)) {
74  m1 = _mm_movemask_ps(rp.dy4);
75  if ((m1 == 0)||(m1 == 15)) {
76  m1 = _mm_movemask_ps(rp.dz4);
77  if ((m1 == 0)||(m1 == 15)) {
78    rp.Init();
79    // all the signs for 4 rays are the same, use
80    // ray packet traversal
81    // Compute min and max distances
82    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
83    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
84    GALIGN16 int inters[4];
85    inters[0] = inters[1] = inters[2] = inters[3] = 1;
86    SimpleRay sray[4];
87    int maxIntersections = 4;
88    unsigned int inters32 = 0xf;
89    for (int i = 0; i < 4; i++) {
90      SimpleRay::IntersectionRes[i].intersectable = 0;
91      rp.SetObject(i, 0);
92      bbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));
93      if ( (tmin4[i] >= tmax4[i]) ||
94           (tmax4[i] < 0.f) ) {
95        inters[i] = 0; // finished
96        inters32 &= ~(1 << i); // bit zero when ray is invalid
97        maxIntersections--;
98      }     
99      if (tmin4[i] < 0.f)
100        tmin4[i] = 0.f;
101      sray[i].mOrigin = rp.GetLoc(i);
102      sray[i].mDirection = rp.GetDir(i);
103    } // for i
104    if (maxIntersections == 0)
105      return;
106
107    SKTBNodeT * childNodes[2];
108    int RayDirs[3];
109    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
110    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
111    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
112    //int activeMask=_mm_movemask_ps(_mm_cmplt_ps( tmin_4, tmax_4 ))&inters32;
113    int activeMask = inters32;
114    int indexStack = 0;
115    SKTBNodeT *currNode = root;
116    unsigned int k = GetNodeType(currNode);
117    for (;;) {     
118      while (k < CKTBAxes::EE_Leaf) {
119        // the 3 operations below can be brought down to 3 simple float
120        // calculations by precomputing min/max of the inverse dir
121        const __m128 node_split = _mm_set_ps1(GetSplitValue(currNode));
122        const __m128 t4 =
123          _mm_mul_ps(_mm_sub_ps(node_split, rp.orig[k]), rp.idir[k]);
124        childNodes[0] = GetLeft(currNode);
125        childNodes[1] = GetRight(currNode);
126        int rayDir = RayDirs[k];
127        SKTBNodeT *far = childNodes[rayDir];
128        if (!(_mm_movemask_ps(_mm_cmpgt_ps(t4, tmin_4)) & activeMask))
129        {
130          currNode = far;
131          k = GetNodeType(currNode);
132          continue;
133        }
134        currNode = childNodes[rayDir ^ 0x1]; // this is near node
135        k = GetNodeType(currNode);     
136        if (!(_mm_movemask_ps(_mm_cmplt_ps( t4, tmax_4)) & activeMask))
137          continue;
138
139        // pop far node to the stack
140        stack4[indexStack].nodep = far;
141        stack4[indexStack].tmax_4 = tmax_4;
142        stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
143        // stack4[indexStack].mask = activeMask;
144        indexStack++;
145       
146        tmax_4 = _mm_min_ps(t4, tmax_4);
147        activeMask &= _mm_movemask_ps(_mm_cmplt_ps( tmin_4, tmax_4 ));
148      } // while this is an interior node
149
150      // either a leaf or a link
151      if (k == CKTBAxes::EE_Leaf) {
152        // test objects for intersection
153        if (!IsEmptyLeaf_(currNode)) {
154          // cout << "Full leaf" << endl;
155         
156          // test the objects in the full leaf against the ray   
157          for (int i = 0; i < 4; i++) {
158            if (inters[i] ) {
159              // no intersection so far !
160              SimpleRay::IntersectionRes[i].maxt =
161                tmax4[i] + Limits::Small;
162              // Test only rays that were not finished
163              if (TestFullLeaf(sray[i], currNode, i)) {
164                // intersection for this ray found
165                inters[i] = 0;
166                inters32 &= ~(1 << i);
167                rp.SetT(i, SimpleRay::IntersectionRes[i].maxt);
168                rp.SetObject(i, SimpleRay::IntersectionRes[i].intersectable);
169                // signed distance should be already set in TestFullLeaf
170                // the first object intersected was found
171                if (--maxIntersections == 0)
172                  return;
173              }
174            } // if this ray did not hit the triangle so far
175          } // for all 4 rays
176        } // full leaf
177        // pop farChild from the stack
178        // restore the current values
179        // update the minimum distance since we traverse to the next one
180
181        if (indexStack == 0)
182          return;
183        indexStack--;
184        currNode = stack4[indexStack].nodep;
185        k = GetNodeType(currNode);
186        tmin_4 = stack4[indexStack].tmin_4;
187        tmax_4 = stack4[indexStack].tmax_4;
188        activeMask = _mm_movemask_ps(_mm_cmple_ps( tmin_4, tmax_4 )) & inters32;
189        continue;
190      } // if leaf
191      // cout << "Link node was accessed" << endl;
192      assert(k == CKTBAxes::EE_Link);
193      currNode = GetLinkNode(currNode);
194      k = GetNodeType(currNode);
195    } // for
196    return;
197  }}}
198
199  // Trace ray by ray
200  SimpleRay ray;
201  for (int i = 0; i < 4; i++) {
202    ray.mOrigin = rp.GetLoc(i);
203    ray.mDirection = rp.GetDir(i);
204    FindNearestI(ray);
205    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
206    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
207    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
208  } // for
209
210  return;
211}
212#endif
213
214
215#if 1
216// This code also works well 1/1/2008 - 14:00
217// Using mask of 128-bits width - the code works as well, only a bit
218// faster than the code above
219void
220CKTBTraversal::FindNearestI(RayPacket2x2 &rp)
221{
222  int m1 = _mm_movemask_ps(rp.dx4);
223  if ((m1 == 0)||(m1 == 15)) {
224  m1 = _mm_movemask_ps(rp.dy4);
225  if ((m1 == 0)||(m1 == 15)) {
226  m1 = _mm_movemask_ps(rp.dz4);
227  if ((m1 == 0)||(m1 == 15)) {
228    rp.Init();
229    // all the signs for 4 rays are the same, use
230    // ray packet traversal
231    // Compute min and max distances
232    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
233    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
234    GALIGN16 union { unsigned int activeMask[4]; __m128 activeMask_4; };
235    GALIGN16 union { unsigned int liveMask[4]; __m128 liveMask_4; };
236    liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;
237
238    GALIGN16 SimpleRay sray[4];
239    int maxIntersections = 4;
240    // unsigned int inters32 = 0xf;
241    for (int i = 0; i < 4; i++) {
242      SimpleRay::IntersectionRes[i].intersectable = 0;
243      rp.SetObject(i, 0);
244      bbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));
245      if ( (tmin4[i] >= tmax4[i]) ||
246           (tmax4[i] < 0.f) ) {
247        liveMask[i] = 0; // finished
248        // inters32 &= ~(1 << i); // bit zero when ray is invalid
249        maxIntersections--;
250      }
251      if (tmin4[i] < 0.f)
252        tmin4[i] = 0.f;
253      sray[i].mOrigin = rp.GetLoc(i);
254      sray[i].mDirection = rp.GetDir(i);
255    } // for i
256    if (maxIntersections == 0)
257      return;
258
259    // This is the mask 128 bits witdth
260    //activeMask_4 =
261    //  _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),
262    //           _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));
263    activeMask_4 = liveMask_4;
264
265    SKTBNodeT * childNodes[2];
266    int RayDirs[4];
267    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
268    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
269    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
270    int indexStack = 0;
271    SKTBNodeT *currNode = root;
272    unsigned int k = GetNodeType(currNode);
273    for (;;) {
274      // traverse until we find a leaf
275      while (k < CKTBAxes::EE_Leaf) {
276        // the 3 operations below can be brought down to 3 simple float
277        // calculations by precomputing min/max of the inverse dir
278        // const __m128 node_split = ;
279        const __m128 t4 =
280          _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),
281                                rp.orig[k]), rp.idir[k]);
282        childNodes[0] = GetLeft(currNode);
283        childNodes[1] = GetRight(currNode);
284        int rayDir = RayDirs[k];
285        SKTBNodeT *far = childNodes[rayDir];
286        if (!_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),
287                                        activeMask_4))) {         
288          currNode = far;
289          k = GetNodeType(currNode);
290          continue;
291        }
292
293        currNode = childNodes[rayDir ^ 0x1]; // this is near node
294        k = GetNodeType(currNode);     
295        if (!_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),
296                                        activeMask_4)))
297          continue;
298
299        // pop far node to the stack
300        stack4[indexStack].nodep = far;
301        stack4[indexStack].tmax_4 = tmax_4;
302
303// Uncomenting this macro is unsafe!
304// Not convinced if for packet of 4 rays we can say that since when
305// one ray is different than the others, it could bring to wrong state
306// It is surely true for one ray when tmin < t < tmax, but for a packet
307// of rays this condition can be true only for a single ray
308//   tmin4 = max(t4, tmin4) = min(t4, tmax4)
309//#define _NOT_STORE_MINT
310
311#ifdef _NOT_STORE_MINT 
312#else
313        // store mint onto the stack
314        stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
315#endif 
316        // stack4[indexStack].mask = activeMask;
317        indexStack++;
318       
319        tmax_4 = _mm_min_ps(t4, tmax_4);
320        activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );
321      } // while this is an interior node
322
323      // either a leaf or a link
324      if (k == CKTBAxes::EE_Leaf) {
325        // test objects for intersection
326        if (!IsEmptyLeaf_(currNode)) {
327          // cout << "Full leaf" << endl;
328         
329          // test the objects in the full leaf against the ray   
330          for (int i = 0; i < 4; i++) {
331            if (liveMask[i] ) {
332              // no intersection so far !
333              SimpleRay::IntersectionRes[i].maxt =
334                tmax4[i] + Limits::Small;
335#if 0
336              // Using subroutine
337              // Test only rays that were not finished
338              if (TestFullLeaf(sray[i], currNode, i))
339#else
340              // avoiding one call
341              const ObjectContainer * const list = GetObjList(currNode);
342              int intersected = 0;
343              // iterate the whole list and find out the nearest intersection
344              ObjectContainer::const_iterator sc_end = list->end();
345              for (ObjectContainer::const_iterator sc = list->begin();
346                   sc != sc_end; sc++) {
347                // if the intersection realy lies in the node       
348                intersected |= ((*sc)->CastSimpleRay(sray[i], i));
349              } // for all objects
350              if (intersected)
351#endif         
352              {
353                // object was intersected
354                rp.SetT(i, SimpleRay::IntersectionRes[i].maxt);
355                rp.SetObject(i, SimpleRay::IntersectionRes[i].intersectable);
356                // signed distance should be already set in TestFullLeaf
357                // the first object intersected was found
358                if (--maxIntersections == 0)
359                  return;
360                // inters32 &= ~(1 << i);
361                liveMask[i] = 0;
362              }
363            } // if this ray did not hit the triangle so far
364          } // for all 4 rays
365        } // full leaf
366
367        // pop farChild from the stack
368        // restore the current values
369        // update the minimum distance since we traverse to the next one
370        do {
371          if (indexStack == 0)
372            return;
373          indexStack--;
374          currNode = stack4[indexStack].nodep;
375          k = GetNodeType(currNode);
376#ifdef _NOT_STORE_MINT
377          // this is an attempt !
378          tmin_4 = tmax_4;
379#else
380          // This surrely works
381          tmin_4 = stack4[indexStack].tmin_4;
382#endif   
383          tmax_4 = stack4[indexStack].tmax_4;
384          activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);
385        }
386        while (_mm_movemask_ps(activeMask_4) == 0);
387      }
388      else {
389        // cout << "Link node was accessed" << endl;
390        assert(k == CKTBAxes::EE_Link);
391        currNode = GetLinkNode(currNode);
392        k = GetNodeType(currNode);
393      }
394    } // for(;;)
395    return;
396  }}}
397
398  // Trace ray by ray
399  SimpleRay ray;
400  for (int i = 0; i < 4; i++) {
401    ray.mOrigin = rp.GetLoc(i);
402    ray.mDirection = rp.GetDir(i);
403    FindNearestI(ray);
404    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
405    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
406    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
407  } // for
408
409  return;
410}
411#endif
412
413// This code allows to specify the box where the ray should be traversed!
414void
415CKTBTraversal::FindNearestI(RayPacket2x2 &rp, Vector3 &boxmin, Vector3 &boxmax)
416{
417  static AxisAlignedBox3 localbox;
418  localbox.SetMin(boxmin);
419  localbox.SetMax(boxmax);
420
421  int m1 = _mm_movemask_ps(rp.dx4);
422  if ((m1 == 0)||(m1 == 15)) {
423  m1 = _mm_movemask_ps(rp.dy4);
424  if ((m1 == 0)||(m1 == 15)) {
425  m1 = _mm_movemask_ps(rp.dz4);
426  if ((m1 == 0)||(m1 == 15)) {
427    rp.Init();
428   
429    // all the signs for 4 rays are the same, use
430    // ray packet traversal
431    // Compute min and max distances
432    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
433    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
434    GALIGN16 union { unsigned int activeMask[4]; __m128 activeMask_4; };
435    GALIGN16 union { unsigned int liveMask[4]; __m128 liveMask_4; };
436    liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;
437
438    GALIGN16 SimpleRay sray[4];
439    int maxIntersections = 4;
440    // unsigned int inters32 = 0xf;
441    for (int i = 0; i < 4; i++) {
442      SimpleRay::IntersectionRes[i].intersectable = 0;
443      rp.SetObject(i, 0);
444      localbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i),
445                              &(tmin4[i]), &(tmax4[i]));
446      if ( (tmin4[i] >= tmax4[i]) ||
447           (tmax4[i] < 0.f) ) {
448        liveMask[i] = 0; // finished
449        // inters32 &= ~(1 << i); // bit zero when ray is invalid
450        maxIntersections--;
451      }
452      if (tmin4[i] < 0.f)
453        tmin4[i] = 0.f;
454      sray[i].mOrigin = rp.GetLoc(i);
455      sray[i].mDirection = rp.GetDir(i);
456    } // for i
457    if (maxIntersections == 0)
458      return;
459
460    // This is the mask 128 bits witdth
461    //activeMask_4 =
462    //  _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),
463    //           _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));
464    activeMask_4 = liveMask_4;
465
466    SKTBNodeT * childNodes[2];
467    int RayDirs[4];
468    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
469    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
470    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
471    int indexStack = 0;
472    SKTBNodeT *currNode = root;
473    unsigned int k = GetNodeType(currNode);
474    for (;;) {
475      // traverse until we find a leaf
476      while (k < CKTBAxes::EE_Leaf) {
477        // the 3 operations below can be brought down to 3 simple float
478        // calculations by precomputing min/max of the inverse dir
479        // const __m128 node_split = ;
480        const __m128 t4 =
481          _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),
482                                rp.orig[k]), rp.idir[k]);
483        childNodes[0] = GetLeft(currNode);
484        childNodes[1] = GetRight(currNode);
485        int rayDir = RayDirs[k];
486        SKTBNodeT *far = childNodes[rayDir];
487        if (!_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),
488                                        activeMask_4))) {         
489          currNode = far;
490          k = GetNodeType(currNode);
491          continue;
492        }
493
494        currNode = childNodes[rayDir ^ 0x1]; // this is near node
495        k = GetNodeType(currNode);     
496        if (!_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),
497                                        activeMask_4)))
498          continue;
499
500        // pop far node to the stack
501        stack4[indexStack].nodep = far;
502        stack4[indexStack].tmax_4 = tmax_4;
503
504// Uncomenting this macro is unsafe!
505// Not convinced if for packet of 4 rays we can say that since when
506// one ray is different than the others, it could bring to wrong state
507// It is surely true for one ray when tmin < t < tmax, but for a packet
508// of rays this condition can be true only for a single ray
509//   tmin4 = max(t4, tmin4) = min(t4, tmax4)
510#undef _NOT_STORE_MINT 
511//#define _NOT_STORE_MINT
512
513#ifdef _NOT_STORE_MINT 
514#else
515        // store mint onto the stack
516        stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
517#endif 
518        // stack4[indexStack].mask = activeMask;
519        indexStack++;
520       
521        tmax_4 = _mm_min_ps(t4, tmax_4);
522        activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );
523      } // while this is an interior node
524
525      // either a leaf or a link
526      if (k == CKTBAxes::EE_Leaf) {
527        // test objects for intersection
528        if (!IsEmptyLeaf_(currNode)) {
529          // cout << "Full leaf" << endl;
530         
531          // test the objects in the full leaf against the ray   
532          for (int i = 0; i < 4; i++) {
533            if (liveMask[i] ) {
534              // no intersection so far !
535              SimpleRay::IntersectionRes[i].maxt =
536                tmax4[i] + Limits::Small;
537#if 0
538              // Using subroutine
539              // Test only rays that were not finished
540              if (TestFullLeaf(sray[i], currNode, i))
541#else
542              // avoiding one call
543              const ObjectContainer * const list = GetObjList(currNode);
544              int intersected = 0;
545              // iterate the whole list and find out the nearest intersection
546              ObjectContainer::const_iterator sc_end = list->end();
547              for (ObjectContainer::const_iterator sc = list->begin();
548                   sc != sc_end; sc++) {
549                // if the intersection realy lies in the node       
550                intersected |= ((*sc)->CastSimpleRay(sray[i], i));
551              } // for all objects
552              if (intersected)
553#endif         
554              {
555                rp.SetT(i, SimpleRay::IntersectionRes[i].maxt);
556                rp.SetObject(i, SimpleRay::IntersectionRes[i].intersectable);
557                // signed distance should be already set in TestFullLeaf
558                // the first object intersected was found
559                if (--maxIntersections == 0)
560                  return;
561                // inters32 &= ~(1 << i);
562                liveMask[i] = 0;
563              }
564            } // if this ray did not hit the triangle so far
565          } // for all 4 rays
566        } // full leaf
567
568        // pop farChild from the stack
569        // restore the current values
570        // update the minimum distance since we traverse to the next one
571        do {
572          if (indexStack == 0)
573            return;
574          indexStack--;
575          currNode = stack4[indexStack].nodep;
576          k = GetNodeType(currNode);
577#ifdef _NOT_STORE_MINT
578          // this is an attempt !
579          tmin_4 = tmax_4;
580#else
581          // This surrely works
582          tmin_4 = stack4[indexStack].tmin_4;
583#endif   
584          tmax_4 = stack4[indexStack].tmax_4;
585          activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);
586        }
587        while (_mm_movemask_ps(activeMask_4) == 0);
588      }
589      else {
590        // cout << "Link node was accessed" << endl;
591        assert(k == CKTBAxes::EE_Link);
592        currNode = GetLinkNode(currNode);
593        k = GetNodeType(currNode);
594      }
595    } // for(;;)
596    return;
597  }}}
598
599  // Trace ray by ray
600  SimpleRay ray;
601  for (int i = 0; i < 4; i++) {
602    ray.mOrigin = rp.GetLoc(i);
603    ray.mDirection = rp.GetDir(i);
604    FindNearestI(ray, localbox);
605    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
606    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
607    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
608  } // for
609}
610
611#endif // __SSE__
612#endif // _USE_HAVRAN_SSE 
613
614#endif //  TRV00F
615
616} // namespace
617
Note: See TracBrowser for help on using the repository browser.