source: GTP/trunk/Lib/Vis/Preprocessing/src/HavranDynRayCaster.cpp @ 2655

Revision 2655, 26.4 KB checked in by mattausch, 16 years ago (diff)
Line 
1
2// Written by Vlastimil Havran, December 2007
3
4// This macro allows to use the ray shooting written by
5// Vlastimil Havran, 2007-2008
6
7
8#include "VssRay.h"
9#include "KdTree.h"
10#include "Preprocessor.h"
11#include "IntersectableWrapper.h"
12
13#ifdef USE_HAVRAN_RAYCASTER
14#include "ktbconf.h"
15#include "timer.h"
16#include "ktball.h"
17#include "ktb.h"
18#ifdef _USE_HAVRAN_SSE
19
20#include "raypack.h"
21#endif // _USE_HAVRAN_SSE
22#endif // _USE_HAVRAN_RAYCASTER
23
24#include "HavranRayCaster.h"
25
26#define DEBUG_RAYCAST 0
27
28namespace GtpVisibilityPreprocessor {
29
30#ifdef _USE_HAVRAN_SSE
31// static rays
32GALIGN16 RayPacket2x2
33HavranDynRayCaster::raypack_t;
34#endif // _USE_HAVRAN_SSE
35 
36HavranDynRayCaster::HavranDynRayCaster(const Preprocessor &preprocessor):
37  HavranRayCaster(preprocessor), mDynKtbtree(0),
38  dynobjects(0), dynamicFlag(false)
39{
40#ifdef USE_HAVRAN_RAYCASTER
41#ifdef _USE_HAVRAN_SSE
42  if ( ((int)(&raypack_t)) & 0xf != 0) {
43    cerr << "The ray pack data type not aligned on 16 Bytes boundary" << endl;
44    cerr << "Address is " << (void*)(&raypack_t) << endl;
45    cerr << "Reorganize your data structure to make it aligned" << endl;
46    abort();
47  }
48#endif
49#endif
50}
51 
52
53HavranDynRayCaster::~HavranDynRayCaster()
54{
55#ifdef USE_HAVRAN_RAYCASTER
56  DeleteDynamicObjects();
57#endif // USE_HAVRAN_RAYCASTER
58}
59
60void
61HavranDynRayCaster::DeleteDynamicObjects()
62{
63#ifdef USE_HAVRAN_RAYCASTER
64  delete mDynKtbtree; mDynKtbtree = 0;
65  delete dynobjects; dynobjects = 0;
66  dynamicFlag = false;
67#endif // USE_HAVRAN_RAYCASTER
68}
69
70void
71HavranDynRayCaster::AddDynamicObjecs(const ObjectContainer &objects, const Matrix4x4 &m)
72{
73#ifdef USE_HAVRAN_RAYCASTER
74  if (dynobjects)
75    DeleteDynamicObjects();
76
77  dynamicFlag = false;
78
79  if (objects.size()) {
80    dynamicFlag = true;
81    dynobjects = new ObjectContainer(objects);
82    assert(dynobjects);
83    // kd-tree built over the objects
84    mDynKtbtree = new CKTB;
85    mDynKtbtree->BuildUp(*dynobjects);
86
87    // The matrix to transform the objects
88    UpdateDynamicObjects(m);
89  }
90#endif // USE_HAVRAN_RAYCASTER 
91}
92
93void
94HavranDynRayCaster::UpdateDynamicObjects(const Matrix4x4 &m)
95{
96#ifdef USE_HAVRAN_RAYCASTER
97  matTr = m;
98  matTr_inv = Invert(matTr);
99#endif // USE_HAVRAN_RAYCASTER
100}
101
102// Using packet of 4 rays supposing that these are coherent
103// We give a box to which each ray is clipped to before the
104// ray shooting is computed !
105void HavranDynRayCaster::CastRaysPacket4(const Vector3 &minBox,
106                                         const Vector3 &maxBox,
107                                         const Vector3 origin4[],
108                                         const Vector3 direction4[],
109                                         int     result4[],
110                                         float   dist4[])
111{
112#ifdef USE_HAVRAN_RAYCASTER
113#ifdef _USE_HAVRAN_SSE 
114  for (int i = 0; i < 4; i++) {
115    result4[i] = -1;
116    result4_t[4] = -1;
117    raypack.SetLoc(i, origin4[i]);
118    raypack.SetDir(i, direction4[i]);
119  }
120 
121  // The same operations for packets of rays, if implemented by
122  // a particular ASDS, otherwise it is emulated by decomposition
123  // of a packet to individual rays and traced individually.
124  mKtbtree->FindNearestI(raypack, minBox, maxBox);
125 
126  for (int i = 0; i < 4; i++) {
127    // if ray intersects an object, we set the pointer to
128    // this object
129    Intersectable* intersectable = raypack.GetObject(i);
130    if (intersectable) {
131      result4[i] = intersectable->mId;
132      dist4[i] = raypack.GetT(i);
133    }
134  }
135
136  if (dynamicFlag) {
137    // The ray pack to be transformed
138    raypack_t = raypack;
139    raypack_t.ApplyTransform(matTr_inv);
140   
141    mDynKtbtree->FindNearestI(raypack_t, minBox, maxBox);
142   
143    for (int i = 0; i < 4; i++) {
144      // if ray intersects an object, we set the pointer to
145      // this object
146      Intersectable* intersectable = raypack_t.GetObject(i);
147      if (intersectable) {
148        float t = raypack_t.GetT(i);
149        if ( ( (result4[i] != -1) && (t < dist4[i]) ) ||
150             (result4[i] == -1) ) {
151          // update, dynamic object is closer
152          dist4[i] = t;
153          result4[i] = intersectable->mId;
154        }
155      }
156    } // for i
157  } // dynamic flag
158   
159  return;
160#else // _USE_HAVRAN_SSE
161  // Compute the result ray by ray
162  SimpleRay sray;
163  for (int i = 0; i < 4; i++) {
164    result4[i] = -1; // no intersection
165    sray.mOrigin = origin4[i];
166    sray.mDirection = direction4[i];
167    mKtbtree->FindNearestI(sray, minBox, maxBox);
168    if (SimpleRay::IntersectionRes[0].intersectable) {
169      // This is object ID - is this the triangle index ???
170      result4[i] = SimpleRay::IntersectionRes[0].intersectable->mId;
171      dist4[i] = SimpleRay::IntersectionRes[0].tdist;
172    }
173
174    if (dynamicFlag) {
175      // Now apply transform
176      ApplyTransform(sray);
177      mDynKtbtree->FindNearestI(sray, minBox, maxBox);
178      Intersectable *objdyn = SimpleRay::IntersectionRes[0].intersectable;
179      if (objdyn) {
180        float t = SimpleRay::IntersectionRes[0].tdist;
181        if ( ((result4[i] != -1) && (t < dist4[i])) ||
182             (result4[i] == -1) ) {
183          // = update, dynamic object is closer
184          dist4[i] = t;
185          result4[i] = objdyn->mId;
186        }
187      }
188    } // dynamic flag
189  } // for i;
190 
191#endif // _USE_HAVRAN_SSE 
192#endif // USE_HAVRAN_RAYCASTER
193}
194
195
196int HavranDynRayCaster::CastRay(const SimpleRay &simpleRay,
197                                VssRayContainer &vssRays,
198                                const AxisAlignedBox3 &box,
199                                const bool castDoubleRay,
200                                const bool pruneInvalidRays)
201{
202#ifdef USE_HAVRAN_RAYCASTER
203
204  // rays forwards - TESTED 21/1/2008 VH (only for forward rays)
205
206  int hits = 0;
207  Intersection hitA(simpleRay.mOrigin), hitB(simpleRay.mOrigin);
208   
209  // ray.mFlags &= ~Ray::CULL_BACKFACES;
210  bool result;
211  hitA.mObject = 0;
212  if ((result = mKtbtree->FindNearestI(simpleRay)))  {
213    hitA.mObject = SimpleRay::IntersectionRes[0].intersectable;
214    tdist[0] = SimpleRay::IntersectionRes[0].tdist;
215    hitA.mPoint = simpleRay.Extrap(tdist[0]);
216    hitA.mNormal = SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
217    //hitA.mNormal = (dynamic_cast< TriangleIntersectable *>
218    //              (hitA.mObject))->GetNormal(0);
219  }
220
221  if (dynamicFlag) {
222    bool result2 = false;
223    // For a dynamic object
224    sray_t = simpleRay;
225    // Now apply transform
226    ApplyTransform(sray_t);
227    if (mDynKtbtree->FindNearestI(sray_t)) {
228      float t = SimpleRay::IntersectionRes[0].tdist;
229      if  ( ((hitA.mObject) && (t < tdist[0])) ||
230          (!hitA.mObject) ) {
231        result = result2 = true; // dynamic object hit
232        // There is an intersection closer than the previous one
233        hitA.mObject = SimpleRay::IntersectionRes[0].intersectable;
234        tdist[0] = SimpleRay::IntersectionRes[0].tdist;
235        hitA.mPoint = simpleRay.Extrap(tdist[0]);
236        hitA.mNormal = hitA.mObject->GetNormal(0);
237        // We have to transform the normal
238        hitA.mNormal = TransformNormal(matTr_inv, hitA.mNormal);     
239      }
240    }
241    if (result && (!result2)) {
242      // We put back the result from hitA.mObject for ray tracing
243      SimpleRay::IntersectionRes[0].intersectable = hitA.mObject;
244      SimpleRay::IntersectionRes[0].tdist = tdist[0];
245    }
246  }
247 
248  bool resultB = false;
249  if (castDoubleRay) {
250    bool result2 = false;
251    // casting rays backward
252    Vector3 *v = (Vector3*)(&simpleRay.mDirection);
253    *v = -(*v);
254    // ray.mFlags &= ~Ray::CULL_BACKFACES;
255    if (mKtbtree->FindNearestI(simpleRay))  {
256      resultB = true;
257      hitB.mObject = SimpleRay::IntersectionRes[0].intersectable;
258      assert(hitB.mObject);
259      float tdist = SimpleRay::IntersectionRes[0].tdist;
260      hitB.mPoint = simpleRay.Extrap(tdist);
261      hitB.mNormal = hitB.mObject->GetNormal(0);
262    }
263   
264    if (dynamicFlag) {
265      // For a dynamic object
266      sray_t = simpleRay;
267      // Now apply transform
268      ApplyTransform(sray_t);
269      bool result2;
270      if ( mDynKtbtree->FindNearestI(sray_t)) {
271        assert(SimpleRay::IntersectionRes[0].intersectable);
272        float t = SimpleRay::IntersectionRes[0].tdist;
273        if ( ((hitB.mObject) && (t < tdist[0])) ||
274             (!hitB.mObject) ) {
275          // There is an intersection closer than the previous one
276          resultB = result2 = true; // dynamic object hit
277          hitB.mObject = SimpleRay::IntersectionRes[0].intersectable;
278          tdist[0] = SimpleRay::IntersectionRes[0].tdist;
279          hitB.mPoint = simpleRay.Extrap(tdist[0]);
280          hitB.mNormal = hitB.mObject->GetNormal(0);
281          // We have to transform the normal
282          hitB.mNormal = TransformNormal(matTr_inv, hitB.mNormal);     
283        }
284      }
285      if ((resultB) && (!result2)) {
286          // For visualization
287          SimpleRay::IntersectionRes[0].intersectable = hitB.mObject;
288          SimpleRay::IntersectionRes[0].tdist = tdist[0];
289        }     
290    } // dynamicFlag
291   
292    // restore the direction to the original
293    *v = -simpleRay.mDirection;
294  } // castDoubleRay
295
296#ifdef _PROCESS_RAY 
297  // This code is also in IntelRayCaster.cpp
298  return ProcessRay(
299                    simpleRay,
300                    hitA,
301                    hitB,
302                    vssRays,
303                    box,
304                    castDoubleRay,
305                    pruneInvalidRays
306                    );
307#else // _PROCESS_RAY
308  if (castDoubleRay)
309    return resultB;
310  return result;
311#endif // _PROCESS_RAY 
312
313#else
314  return 0;
315#endif // USE_HAVRAN_RAYCASTER   
316}
317
318void HavranDynRayCaster::CastRays16(SimpleRayContainer &rays,
319                                 VssRayContainer &vssRays,
320                                 const AxisAlignedBox3 &sbox,
321                                 const bool castDoubleRay,
322                                 const bool pruneInvalidRays)
323{
324  CastRays16(rays, 0, vssRays, sbox, castDoubleRay, pruneInvalidRays);
325}
326
327
328void HavranDynRayCaster::CastRays16(SimpleRayContainer &rays,
329                                 int offset,
330                                 VssRayContainer &vssRays,
331                                 const AxisAlignedBox3 &sbox,
332                                 const bool castDoubleRays,
333                                 const bool pruneInvalidRays)
334{
335#ifdef USE_HAVRAN_RAYCASTER
336 
337#if DEBUG_RAYCAST
338  Debug << "C16 " << flush;
339#endif
340
341  // Use special algorithm for 16 rays at once
342  if (castDoubleRays) {
343    // Here we decompose shooting into two phases
344
345    // First we delete the results from casting dynamic objects
346    if (dynamicFlag) {
347      for (int i = 0; i < 32; i++)
348        objI[i] = 0;
349    }
350   
351    // Here we shoot first backward rays and forward ones
352    SimpleRayContainer::iterator sit = rays.begin() + offset;
353    SimpleRayContainer::const_iterator sit_end = rays.begin() + offset + 16;
354    for ( ; sit != sit_end; ++ sit)
355    {
356      (*sit).mDirection = - (*sit).mDirection;
357    }
358    // backward rays to be shot - saving with offset 16
359
360#ifdef _USE_HAVRAN_SSE 
361    mKtbtree->SetOffset(0);
362    mKtbtree->FindNearestI_16oneDir(rays, offset, 16);
363#else
364    mKtbtree->SetOffset(16);
365    mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
366#endif // _USE_HAVRAN_SSE
367
368    if (dynamicFlag) {
369      for (int i = 0; i < 16; i++) {
370        // store the origin and direction of the ray
371        orig[i] = rays[offset+i].mOrigin;
372        dirs[i] = rays[offset+i].mDirection;
373
374        objI[i+16] = SimpleRay::IntersectionRes[i+16].intersectable;
375        if (objI[i+16])
376          normal[i+16] = objI[i+16]->GetNormal(0);
377        tdist[i+16] = SimpleRay::IntersectionRes[i+16].tdist;
378        ApplyTransform(rays[offset+i]);
379      } // for
380      // Now shoot the ray with dynamic object
381#ifdef _USE_HAVRAN_SSE 
382      mDynKtbtree->SetOffset(0);
383      mDynKtbtree->FindNearestI_16oneDir(rays, offset, 16);
384#else
385      mDynKtbtree->SetOffset(16);
386      mDynKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
387#endif // _USE_HAVRAN_SSE
388      for (int i = 0; i < 16; i++) {
389        Intersectable *intersectable =
390          SimpleRay::IntersectionRes[i+16].intersectable;
391        if (intersectable) {
392          float t = SimpleRay::IntersectionRes[i+16].tdist;
393          if  ( ((objI[i+16]) && (t < tdist[i+16])) ||
394                (!objI[i+16]) ) {
395            // There is an intersection closer than the previous one
396            objI[i+16] = intersectable;
397            tdist[i+16] = SimpleRay::IntersectionRes[i+16].tdist;
398            normal[i+16] = intersectable->GetNormal(0);
399            // We have to transform the normal
400            normal[i+16] = TransformNormal(matTr_inv, normal[i+16]);     
401          } // if update
402        } // if intersected dynamic object
403        else {
404          // we copy back the static object - only for visualization
405          SimpleRay::IntersectionRes[i+16].intersectable = objI[i+16];
406          SimpleRay::IntersectionRes[i+16].tdist = tdist[i+16];   
407        }
408      } // for
409    } // dynamic flag
410   
411    // set the ray direction to original direction
412    if (dynamicFlag) {
413      sit = rays.begin() + offset;
414      int i = 0;
415      for ( ; sit != sit_end; ++sit, ++i)
416      {
417        rays[offset+i].mOrigin = orig[i];
418        rays[offset+i].mDirection = -dirs[i];
419      }
420    }
421    else {
422      // no dynamic objects
423      sit = rays.begin() + offset;
424      for ( ; sit != sit_end; ++ sit)
425      {
426        (*sit).mDirection = - (*sit).mDirection;
427      }
428    }
429    // forward rays to be shot
430#ifdef _USE_HAVRAN_SSE
431    mKtbtree->SetOffset(0);
432    mKtbtree->FindNearestI_16oneDir(rays, offset, 0);
433#else
434    mKtbtree->SetOffset(0);
435    mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
436#endif // _USE_HAVRAN_SSE
437
438    if (dynamicFlag) {
439      for (int i = 0; i < 16; i++) {
440        objI[i] = SimpleRay::IntersectionRes[i].intersectable;
441        if (objI[i])
442          normal[i] = objI[i]->GetNormal(0);
443        tdist[i] = SimpleRay::IntersectionRes[i].tdist;
444        ApplyTransform(rays[offset+i]);
445      } // for
446      // Now shoot the ray with dynamic object
447#ifdef _USE_HAVRAN_SSE 
448      mDynKtbtree->SetOffset(0);
449      mDynKtbtree->FindNearestI_16oneDir(rays, offset, 0);
450#else
451      mDynKtbtree->SetOffset(0);
452      mDynKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
453#endif // _USE_HAVRAN_SSE
454      for (int i = 0; i < 16; i++) {
455        Intersectable *intersectable
456          = SimpleRay::IntersectionRes[i].intersectable;
457        if (intersectable) {
458          float t = SimpleRay::IntersectionRes[i].tdist;
459          if  ( ((objI[i]) && (t < tdist[i])) ||
460                (!objI[i]) ) {
461            // There is an intersection closer than the previous one
462            objI[i] = intersectable;
463            tdist[i] = SimpleRay::IntersectionRes[i].tdist;
464            normal[i] = objI[i]->GetNormal(0);
465            // We have to transform the normal
466            normal[i] = TransformNormal(matTr_inv, normal[i]);
467          } // update
468        } // intersection
469        // we have to recover the ray
470        rays[offset+i].mOrigin = orig[i];
471        rays[offset+i].mDirection = -dirs[i];   
472      } // for i
473    } // dynamic flag
474  } // cast double rays
475  else {
476    // ONLY forward rays - TESTED 21/1/2007 VH
477
478    // First we delete the results from casting dynamic objects
479    if (dynamicFlag) {
480      for (int i = 0; i < 16; i++) {
481        objI[i] = 0;
482        orig[i] = rays[offset+i].mOrigin;
483        dirs[i] = rays[offset+i].mDirection;   
484      }
485    }
486
487    // Shoot all 16 rays  at the same time using a special algorithm
488    mKtbtree->SetOffset(0);
489#ifdef _USE_HAVRAN_SSE 
490    mKtbtree->FindNearestI_16oneDir(rays, offset, 0);   
491#else
492    mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);   
493#endif // _USE_HAVRAN_SSE
494
495    // Here we must add dynamic objects
496    if (dynamicFlag) {
497      for (int i = 0; i < 16; i++) {
498        objI[i] = SimpleRay::IntersectionRes[i].intersectable;
499        if (objI[i])
500          normal[i] = objI[i]->GetNormal(0);
501        tdist[i] = SimpleRay::IntersectionRes[i].tdist;
502        ApplyTransform(rays[offset+i]);
503      } // for
504      // Now shoot the ray with dynamic object
505#ifdef _USE_HAVRAN_SSE 
506      mDynKtbtree->SetOffset(0);
507      mDynKtbtree->FindNearestI_16oneDir(rays, offset, 0);
508#else
509      mDynKtbtree->SetOffset(0);
510      mDynKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
511#endif // _USE_HAVRAN_SSE
512      for (int i = 0; i < 16; i++) {
513        Intersectable *intersectable
514          = SimpleRay::IntersectionRes[i].intersectable;
515        if (intersectable) {
516          float t = SimpleRay::IntersectionRes[i].tdist;
517          if  ( ((objI[i]) && (t < tdist[i])) ||
518                (!objI[i]) ) {     
519            // There is an intersection closer than the previous one
520            objI[i] = intersectable;
521            tdist[i] = SimpleRay::IntersectionRes[i].tdist;
522            normal[i] = objI[i]->GetNormal(0);
523            // We have to transform the normal
524            normal[i] = TransformNormal(matTr_inv, normal[i]);
525          } // update
526        } // intersection
527        // we have to recover the rays back
528        rays[offset+i].mOrigin = orig[i];
529        rays[offset+i].mDirection = dirs[i];   
530      } // for i
531    } // dynamic flag
532  }
533 
534  if (dynamicFlag) {
535    for (int i=0, k=offset; i < 16; i++, k++)
536    {
537      Intersection hitA(rays[k].mOrigin), hitB(rays[k].mOrigin);
538
539#if DEBUG_RAYCAST
540      Debug<<"FH\n"<<flush;
541#endif
542
543      Intersectable *intersectable = objI[i];
544      // For visualization needs only - forward rays
545      SimpleRay::IntersectionRes[i].intersectable = objI[i];
546      SimpleRay::IntersectionRes[i].tdist = tdist[i];
547      if (intersectable)
548      {
549        hitA.mObject = intersectable;
550        // Get the normal of that face
551        hitA.mNormal = normal[i];
552       
553        //-rays[index+i].mDirection; // $$ temporary
554        hitA.mPoint = rays[k].Extrap(tdist[i]);
555      }
556   
557#if DEBUG_RAYCAST
558      Debug<<"BH\n"<<flush;
559#endif
560
561      if (castDoubleRays)
562      {
563        Intersectable *intersectable = objI[i+16];
564
565        if (intersectable)
566        {
567          hitB.mObject = intersectable;
568          hitB.mNormal = normal[i+16];
569          hitB.mPoint = rays[k].Extrap(-tdist[i+16]);
570        }
571      }
572   
573#if DEBUG_RAYCAST
574      Debug<<"PR\n"<<flush;
575#endif
576
577#ifdef _PROCESS_RAY 
578      ProcessRay(rays[k],
579                 hitA,
580                 hitB,
581                 vssRays,
582                 sbox,
583                 castDoubleRays,
584                 pruneInvalidRays
585                 );
586#endif
587    } // for
588  }
589  else {
590    // no dynamic objects
591    for (int i=0, k=offset; i < 16; i++, k++)
592    {
593      Intersection hitA(rays[k].mOrigin), hitB(rays[k].mOrigin);
594
595#if DEBUG_RAYCAST
596      Debug<<"FH\n"<<flush;
597#endif
598
599      Intersectable *intersectable
600        = SimpleRay::IntersectionRes[i].intersectable;
601
602      if (intersectable)
603      {
604        hitA.mObject = intersectable;
605        // Get the normal of that face
606        hitA.mNormal = intersectable->GetNormal(0);
607       
608        //-rays[index+i].mDirection; // $$ temporary
609        float tdist = SimpleRay::IntersectionRes[i].tdist;
610        hitA.mPoint = rays[k].Extrap(tdist);
611      }
612     
613#if DEBUG_RAYCAST
614      Debug<<"BH\n"<<flush;
615#endif
616
617      if (castDoubleRays)
618      {
619        Intersectable *intersectable =
620          SimpleRay::IntersectionRes[i+16].intersectable;
621       
622        if (intersectable)
623        {
624          hitB.mObject = intersectable;
625          hitB.mNormal = intersectable->GetNormal(0);;
626          float tdist = SimpleRay::IntersectionRes[16+i].tdist;
627          hitB.mPoint = rays[k].Extrap(-tdist);
628        }
629      }
630   
631#if DEBUG_RAYCAST
632      Debug<<"PR\n"<<flush;
633#endif
634
635#ifdef _PROCESS_RAY 
636      ProcessRay(rays[k],
637                 hitA,
638                 hitB,
639                 vssRays,
640                 sbox,
641                 castDoubleRays,
642                 pruneInvalidRays
643                 );
644#endif
645    } // for
646  } // dynamic objects
647
648 
649#if DEBUG_RAYCAST
650  Debug<<"C16F\n"<<flush;
651#endif
652
653#endif // USE_HAVRAN_RAYCASTER
654}
655
656
657
658void
659HavranDynRayCaster::CastSimpleForwardRays(
660                                          SimpleRayContainer &rays,
661                                          const AxisAlignedBox3 &sbox
662                                         )
663{
664#ifdef USE_HAVRAN_RAYCASTER
665
666  int hit_triangles[16];
667  float dist[16];
668  Vector3 normals[16];
669  Vector3 min = sbox.Min();
670  Vector3 max = sbox.Max();
671 
672  int packets = rays.size() / 16;
673 
674  int i, j, k = 0;
675  Vector3 dir;
676 
677  // By groups of rays
678  for (i=0; i < packets; i++) {
679    int offset = i * 16;
680    mKtbtree->FindNearestI_16oneDir(rays, offset, 0);
681
682    if (dynamicFlag) {
683      for (int i = 0; i < 16; i++) {
684        orig[i] = rays[i].mOrigin;
685        dirs[i] = rays[i].mDirection;
686       
687        tdist[i] = SimpleRay::IntersectionRes[i].tdist;
688        objI[i] = SimpleRay::IntersectionRes[i].intersectable;
689        // for dynamic objects
690        ApplyTransform(rays[i]);
691      } // for
692
693      // shoot the rays against dynamic objects
694      mDynKtbtree->FindNearestI_16oneDir(rays, offset, 0);
695      // and combine the results
696      for (int i = 0; i < 16; i++) {
697        float t = SimpleRay::IntersectionRes[i].tdist;
698        if (SimpleRay::IntersectionRes[i].intersectable) {
699          if  ( ((objI[i]) && (t < tdist[i])) ||
700                (!objI[i]) ) {
701            // There is an intersection closer than the previous one
702            objI[i] = SimpleRay::IntersectionRes[i].intersectable;
703            tdist[i] = SimpleRay::IntersectionRes[i].tdist;
704          } // update
705        } // intersection
706        else {
707          // Only for visualization
708          SimpleRay::IntersectionRes[i].intersectable = objI[i];
709          SimpleRay::IntersectionRes[i].tdist = tdist[i];
710        }
711        // recover ray origin and direction
712        rays[i].mOrigin = orig[i];
713        rays[i].mDirection = dirs[i];   
714      } // for
715
716    } // dynamic objects
717   
718    // ??? What to do with the results ? These are
719    // not used at the moment also in IntelRayCaster.cpp
720  } // for
721
722
723  i = 0;
724  int k2 = k;
725  for (; k < rays.size(); k++, i++) {
726    double normal[3];
727    // Intersect with the static scene
728    bool result = mKtbtree->FindNearestI(rays[k]);
729    tdist[i] = SimpleRay::IntersectionRes[0].tdist;
730    objI[i] = SimpleRay::IntersectionRes[0].intersectable;
731   
732    if (dynamicFlag) {
733      orig[i] = rays[k].mOrigin;
734      dirs[i] = rays[k].mDirection;
735
736      // Intersect with the dynamic object
737      ApplyTransform(rays[k]);
738      bool result2 = false;
739      if (mDynKtbtree->FindNearestI(rays[k])) {
740        float t = SimpleRay::IntersectionRes[0].tdist;
741        if  ( ((objI[i]) && (t < tdist[i])) ||
742              (!objI[i]) ) {
743          // There is an intersection closer than the previous one
744          result2 = true;
745          objI[i] = SimpleRay::IntersectionRes[0].intersectable;
746          tdist[i] = t;
747        }
748      }
749     
750      // recover ray origin and direction
751      rays[k].mOrigin = orig[i];
752      rays[k].mDirection = dirs[i];     
753    } // dynamic objects
754   
755    // ??? What to do with the results ? These are
756    // not used at the moment also in IntelRayCaster.cpp
757  }
758  // The result will be in the array
759  i = 0;
760  for (; k2 < rays.size(); k2++, i++) {
761    SimpleRay::IntersectionRes[i].intersectable = objI[i];
762    SimpleRay::IntersectionRes[i].tdist = tdist[i];
763  }
764#endif // USE_HAVRAN_RAYCASTER
765
766  return;
767}
768
769void HavranDynRayCaster::CastRays(
770                               SimpleRayContainer &rays,
771                               VssRayContainer &vssRays,
772                               const AxisAlignedBox3 &sbox,
773                               const bool castDoubleRay,
774                               const bool pruneInvalidRays )
775{
776  int buckets = rays.size()/16;
777  int offset = 0;
778
779#if 0
780  int time = GetTime();
781  CastSimpleForwardRays(rays, sbox);
782  cout<<1e-3*2*rays.size()/TimeDiff(time, GetTime())<<" Mrays/sec"<<endl;
783#endif
784
785  // Cast only by 16 rays at once
786  for (int i=0; i < buckets; i++, offset+=16) {
787    CastRays16(rays, offset, vssRays, sbox,
788               castDoubleRay, pruneInvalidRays);
789
790    if ((int)rays.size() > 100000 && i % (100000/16) == 0)
791      cout<<"\r"<<offset<<"/"<<(int)rays.size()<<"\r";
792  }
793
794  // Cast the rest of the rays
795  for (; offset < (int)rays.size(); offset++)
796    CastRay(rays[offset], vssRays, sbox, castDoubleRay, pruneInvalidRays);
797
798  return;
799}
800
801#ifdef _USE_HAVRAN_SSE
802// BUG1 41579  196948 1064111
803// BUG2 254    1672   10869
804 
805// Just for testing concept
806void
807HavranDynRayCaster::CastRaysPacket2x2(RayPacket2x2 &raysPack,
808                                                                          bool castDoubleRay,
809                                                                          const bool pruneInvalidRays)
810{
811#ifdef USE_HAVRAN_RAYCASTER
812
813  if (castDoubleRay) {
814    // cast forward rays
815    mKtbtree->FindNearestI(raysPack);
816
817    if (dynamicFlag) {
818      // The ray pack to be transformed
819      raypack_t = raysPack;
820      raypack.ApplyTransform(matTr_inv);
821   
822      mDynKtbtree->FindNearestI(raypack_t);
823   
824      for (int i = 0; i < 4; i++) {
825        // if ray intersects an object, we set the pointer to
826        // this object
827        Intersectable* intersectable = raypack_t.GetObject(i);
828        if (intersectable) {
829          Intersectable *o = raysPack.GetObject(i);
830          if ( ((o) && (raypack_t.GetT(i) < tdist[i])) ||
831               (!o) ) {
832            // update, dynamic object is closer
833            raysPack.SetT(i, raypack_t.GetT(i));
834            raysPack.SetObject(i, raypack_t.GetObject(i));
835          } // if update is required
836        } // if intersectable
837      } // for i
838    } // dynamic object   
839
840    // Double (=opposite) direction
841    for (int i = 0; i < 4; i++)
842      raysPack.SetDir(i, -raysPack.GetDir(i));
843    // cast backward rays
844    mKtbtree->FindNearestI(raysPack);
845
846    if (dynamicFlag) {
847
848      // The ray pack to be transformed
849      raypack_t = raysPack;
850      raypack_t.ApplyTransform(matTr_inv);
851   
852      mDynKtbtree->FindNearestI(raypack_t);
853   
854      for (int i = 0; i < 4; i++) {
855        // if ray intersects an object, we set the pointer to
856        // this object
857        Intersectable* intersectable = raypack_t.GetObject(i);
858        if (intersectable) {
859          Intersectable *o = raysPack.GetObject(i);
860          if ( ((o) && (raypack_t.GetT(i) < tdist[i])) ||
861               (!o) ) {
862            // update, dynamic object is closer
863            raysPack.SetT(i, raypack_t.GetT(i));
864            raysPack.SetObject(i, raypack_t.GetObject(i));
865          } // if update is required
866        } // if intersectable
867      } // for i
868    } // dynamic object   
869   
870    // reverse the rays back
871    for (int i = 0; i < 4; i++)
872      raysPack.SetDir(i, -raysPack.GetDir(i));
873  }
874  else {
875    // ONLY forward rays - TESTED 21/1/2007 VH
876
877    mKtbtree->FindNearestI(raysPack);
878
879    if (dynamicFlag) {
880      // The ray pack to be transformed
881      raypack_t = raysPack;
882      raypack_t.ApplyTransform(matTr_inv);
883   
884      mDynKtbtree->FindNearestI(raypack_t);
885   
886      for (int i = 0; i < 4; i++) {
887        // if ray intersects an object, we set the pointer to
888        // this object
889        Intersectable* intersectable = raypack_t.GetObject(i);
890        if (intersectable) {
891          Intersectable *o = raysPack.GetObject(i);
892          if ( ((o) && (raypack_t.GetT(i) < tdist[i])) ||
893               (!o) ) {
894            // update, dynamic object is closer
895            raysPack.SetT(i, raypack_t.GetT(i));
896            raysPack.SetObject(i, raypack_t.GetObject(i));
897          } // if update is required
898        } // if intersectable
899      } // for i
900    } // dynamic object   
901   
902#if 0
903    // Only verification of correctness by casting single rays
904    static int cntBugs = 0;
905    SimpleRay ray;
906    int cntErrors = 0, cntDistErrors = 0;
907    bool newBug = false;
908    for (int i = 0; i < 4; i++) {
909      ray.mOrigin = raysPack.GetLoc(i);
910      ray.mDirection = raysPack.GetDir(i);
911      mKtbtree->FindNearestI(ray);
912      if (raysPack.GetObject(i) != SimpleRay::IntersectionRes[0].intersectable) {
913        float dist = (raysPack.GetT(i) - SimpleRay::IntersectionRes[0].tdist);
914        if (fabs(dist) > 0.001f) {
915          cntErrors++; newBug = true;
916          cntBugs++;
917          cout << " BUG1 d= " << dist;
918        }
919      }
920      else {
921        float dist = 0.f;
922        if (raysPack.GetObject(i) && SimpleRay::IntersectionRes[0].intersectable)
923          if (fabs((dist=(fabs (raysPack.GetT(i) - SimpleRay::IntersectionRes[0].tdist)))) > 1.f) {
924            cntDistErrors++; newBug = true; cntBugs++;
925            cout << " BUG2 distdf= " << dist ;     
926          }
927      }
928    } // for
929    if (newBug) cout << " CB= " << cntBugs << "\n";
930#endif
931  }
932
933  return;
934
935#endif // USE_HAVRAN_RAYCASTER
936
937}
938#endif // _USE_HAVRAN_SSE
939
940 
941} // the namespace
942
Note: See TracBrowser for help on using the repository browser.