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

Revision 2629, 19.4 KB checked in by bittner, 16 years ago (diff)

commit after merge with vlastimil

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