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

Revision 2608, 19.3 KB checked in by bittner, 16 years ago (diff)

HR updates

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,
416                                                        const Vector3 &boxmin,
417                                                        const Vector3 &boxmax)
418{
419  static AxisAlignedBox3 localbox;
420  localbox.SetMin(boxmin);
421  localbox.SetMax(boxmax);
422
423  int m1 = _mm_movemask_ps(rp.dx4);
424  if ((m1 == 0)||(m1 == 15)) {
425  m1 = _mm_movemask_ps(rp.dy4);
426  if ((m1 == 0)||(m1 == 15)) {
427  m1 = _mm_movemask_ps(rp.dz4);
428  if ((m1 == 0)||(m1 == 15)) {
429    rp.Init();
430   
431    // all the signs for 4 rays are the same, use
432    // ray packet traversal
433    // Compute min and max distances
434    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
435    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
436    GALIGN16 union { unsigned int activeMask[4]; __m128 activeMask_4; };
437    GALIGN16 union { unsigned int liveMask[4]; __m128 liveMask_4; };
438    liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;
439
440    GALIGN16 SimpleRay sray[4];
441    int maxIntersections = 4;
442    // unsigned int inters32 = 0xf;
443    for (int i = 0; i < 4; i++) {
444      SimpleRay::IntersectionRes[i].intersectable = 0;
445      rp.SetObject(i, 0);
446      localbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i),
447                              &(tmin4[i]), &(tmax4[i]));
448      if ( (tmin4[i] >= tmax4[i]) ||
449           (tmax4[i] < 0.f) ) {
450        liveMask[i] = 0; // finished
451        // inters32 &= ~(1 << i); // bit zero when ray is invalid
452        maxIntersections--;
453      }
454      if (tmin4[i] < 0.f)
455        tmin4[i] = 0.f;
456      sray[i].mOrigin = rp.GetLoc(i);
457      sray[i].mDirection = rp.GetDir(i);
458    } // for i
459    if (maxIntersections == 0)
460      return;
461
462    // This is the mask 128 bits witdth
463    //activeMask_4 =
464    //  _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),
465    //           _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));
466    activeMask_4 = liveMask_4;
467
468    SKTBNodeT * childNodes[2];
469    int RayDirs[4];
470    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
471    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
472    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
473    int indexStack = 0;
474    SKTBNodeT *currNode = root;
475    unsigned int k = GetNodeType(currNode);
476    for (;;) {
477      // traverse until we find a leaf
478      while (k < CKTBAxes::EE_Leaf) {
479        // the 3 operations below can be brought down to 3 simple float
480        // calculations by precomputing min/max of the inverse dir
481        // const __m128 node_split = ;
482        const __m128 t4 =
483          _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),
484                                rp.orig[k]), rp.idir[k]);
485        childNodes[0] = GetLeft(currNode);
486        childNodes[1] = GetRight(currNode);
487        int rayDir = RayDirs[k];
488        SKTBNodeT *far = childNodes[rayDir];
489        if (!_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),
490                                        activeMask_4))) {         
491          currNode = far;
492          k = GetNodeType(currNode);
493          continue;
494        }
495
496        currNode = childNodes[rayDir ^ 0x1]; // this is near node
497        k = GetNodeType(currNode);     
498        if (!_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),
499                                        activeMask_4)))
500          continue;
501
502        // pop far node to the stack
503        stack4[indexStack].nodep = far;
504        stack4[indexStack].tmax_4 = tmax_4;
505
506// Uncomenting this macro is unsafe!
507// Not convinced if for packet of 4 rays we can say that since when
508// one ray is different than the others, it could bring to wrong state
509// It is surely true for one ray when tmin < t < tmax, but for a packet
510// of rays this condition can be true only for a single ray
511//   tmin4 = max(t4, tmin4) = min(t4, tmax4)
512#undef _NOT_STORE_MINT 
513//#define _NOT_STORE_MINT
514
515#ifdef _NOT_STORE_MINT 
516#else
517        // store mint onto the stack
518        stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
519#endif 
520        // stack4[indexStack].mask = activeMask;
521        indexStack++;
522       
523        tmax_4 = _mm_min_ps(t4, tmax_4);
524        activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );
525      } // while this is an interior node
526
527      // either a leaf or a link
528      if (k == CKTBAxes::EE_Leaf) {
529        // test objects for intersection
530        if (!IsEmptyLeaf_(currNode)) {
531          // cout << "Full leaf" << endl;
532         
533          // test the objects in the full leaf against the ray   
534          for (int i = 0; i < 4; i++) {
535            if (liveMask[i] ) {
536              // no intersection so far !
537              SimpleRay::IntersectionRes[i].maxt =
538                tmax4[i] + Limits::Small;
539#if 0
540              // Using subroutine
541              // Test only rays that were not finished
542              if (TestFullLeaf(sray[i], currNode, i))
543#else
544              // avoiding one call
545              const ObjectContainer * const list = GetObjList(currNode);
546              int intersected = 0;
547              // iterate the whole list and find out the nearest intersection
548              ObjectContainer::const_iterator sc_end = list->end();
549              for (ObjectContainer::const_iterator sc = list->begin();
550                   sc != sc_end; sc++) {
551                // if the intersection realy lies in the node       
552                intersected |= ((*sc)->CastSimpleRay(sray[i], i));
553              } // for all objects
554              if (intersected)
555#endif         
556              {
557                rp.SetT(i, SimpleRay::IntersectionRes[i].maxt);
558                rp.SetObject(i, SimpleRay::IntersectionRes[i].intersectable);
559                // signed distance should be already set in TestFullLeaf
560                // the first object intersected was found
561                if (--maxIntersections == 0)
562                  return;
563                // inters32 &= ~(1 << i);
564                liveMask[i] = 0;
565              }
566            } // if this ray did not hit the triangle so far
567          } // for all 4 rays
568        } // full leaf
569
570        // pop farChild from the stack
571        // restore the current values
572        // update the minimum distance since we traverse to the next one
573        do {
574          if (indexStack == 0)
575            return;
576          indexStack--;
577          currNode = stack4[indexStack].nodep;
578          k = GetNodeType(currNode);
579#ifdef _NOT_STORE_MINT
580          // this is an attempt !
581          tmin_4 = tmax_4;
582#else
583          // This surrely works
584          tmin_4 = stack4[indexStack].tmin_4;
585#endif   
586          tmax_4 = stack4[indexStack].tmax_4;
587          activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);
588        }
589        while (_mm_movemask_ps(activeMask_4) == 0);
590      }
591      else {
592        // cout << "Link node was accessed" << endl;
593        assert(k == CKTBAxes::EE_Link);
594        currNode = GetLinkNode(currNode);
595        k = GetNodeType(currNode);
596      }
597    } // for(;;)
598    return;
599  }}}
600
601  // Trace ray by ray
602  SimpleRay ray;
603  for (int i = 0; i < 4; i++) {
604    ray.mOrigin = rp.GetLoc(i);
605    ray.mDirection = rp.GetDir(i);
606    FindNearestI(ray, localbox);
607    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
608    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
609    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
610  } // for
611}
612
613#endif // __SSE__
614#endif // _USE_HAVRAN_SSE 
615
616#endif //  TRV00F
617
618} // namespace
619
Note: See TracBrowser for help on using the repository browser.