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

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