source: GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp @ 2743

Revision 2743, 11.4 KB checked in by mattausch, 16 years ago (diff)
RevLine 
[1520]1#include "RayCaster.h"
2#include "VssRay.h"
3#include "Ray.h"
4#include "Preprocessor.h"
[1942]5#include "ViewCellsManager.h"
[1520]6
[2629]7#include <cassert>
[1520]8
9namespace GtpVisibilityPreprocessor {
10
11
[2635]12#define DEBUG_PROCESS_RAY 0
13
[1520]14#define DEBUG_RAYCAST 0
15
[1942]16#define EXACT_BOX_CLIPPING 0
[1520]17
18RayCaster::RayCaster(const Preprocessor &preprocessor):
[2583]19  mVssRayPool(), mPreprocessor(preprocessor)
[1520]20{
21}
22
23
[1521]24RayCaster::~RayCaster()
25{
26}
27
28
[1545]29VssRay *RayCaster::CastRay(const SimpleRay &simpleRay,
[1990]30                                                   const AxisAlignedBox3 &box,
[1996]31                                                   const bool castDoubleRay)
[1521]32{
[1932]33        VssRayContainer rays;
[2743]34        //CastRay(simpleRay, rays, box, castDoubleRay, true);
35        CastRay(simpleRay, rays, box, castDoubleRay, false);
[1932]36   
37        if (!rays.empty())
38                return rays.back();
39        else
40                return NULL;
[1521]41}
42
[1990]43
[1942]44bool
45RayCaster::ClipToViewSpaceBox(const Vector3 &origin,
46                                                          const Vector3 &termination,
47                                                          Vector3 &clippedOrigin,
48                                                          Vector3 &clippedTermination)
49{
[1952]50 
[1942]51  Ray ray(origin, termination - origin, Ray::LINE_SEGMENT);     
52  ray.Precompute();
53 
54  float tmin, tmax;
55  if ((!mPreprocessor.mViewCellsManager->
56           GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax)) ||
57          tmin>=tmax
58          )
59        return false;
[1521]60
[2070]61  if (tmin >= 1.0f || tmax <= 0.0f)
[1942]62        return false;
63 
64  if (tmin > 0.0f)
65        clippedOrigin = ray.Extrap(tmin);
66  else
67        clippedOrigin = origin;
68 
69  if (tmax < 1.0f)
70        clippedTermination = ray.Extrap(tmax);
71  else
72        clippedTermination = termination;
73 
74  return true;
75}
76
[2070]77/** Checks if ray is valid
78        (e.g., not in empty view space or outside the view space)
[1528]79*/
[1867]80bool
81RayCaster::ValidateRay(const Vector3 &origin,
82                                           const Vector3 &direction,
83                                           const AxisAlignedBox3 &box,
84                                           Intersection &hit)
[1528]85{
[1932]86        if (!hit.mObject) 
87        {
88                // compute intersection with the scene bounding box
[1584]89#if EXACT_BOX_CLIPPING
[1932]90                static Ray ray;
91                mPreprocessor.SetupRay(ray, origin, direction);
92
93                float tmin, tmax;
94                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
95                {
96                        hit.mPoint = ray.Extrap(tmax);
97                }
98                else
99                {
100                        // cout<<" invalid hp "<<tmin<<" "<<tmax<<endl;
101                        // cout<<" box "<<box<<endl;
102                        // cout<<" origin "<<origin<<endl;
103                        // cout<<" direction "<<direction<<endl;
104                        // cout<< "inv dir"<<ray.GetInvDir()<<endl;
105                        return false;
106                }
[1584]107#else
[1932]108                hit.mPoint = origin + direction * Magnitude(box.Diagonal());
[1584]109#endif
110        }
[1932]111        else
112        {
[2035]113          if (mPreprocessor.mDetectEmptyViewSpace)  {
114                if (DotProd(hit.mNormal, direction) >= -Limits::Small)  {       
115                  hit.mObject = NULL;
116                  return false;
[1932]117                }
[2035]118          }
[1932]119        }
[2035]120       
[1932]121        return true;
[1528]122}
123
[1974]124void
125RayCaster::SortRays(SimpleRayContainer &rays)
126{
[1984]127  AxisAlignedBox3 box =
128        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
[2105]129 
[1984]130  float b[12]={
131        box.Min().x,
132        box.Min().y,
133        box.Min().z,
134        -1,
135        -1,
136        -1,
137        box.Max().x,
138        box.Max().y,
139        box.Max().z,
140        1,
141        1,
142        1
143  };
144
[2105]145#if 0
146  static vector<SimpleRay *> pointerArray;
147
148  if (pointerArray.size()!=rays.size()) {
149        // realloc the pointerarray
150        pointerArray.resize(rays.size());
151  }
152
153  // init pointer array
154  SimpleRay *p = &pointerArray[0];
155  for (i=0; i < rays.size(); i++, p++)
156        pointerArray[i] = p;
157#endif
158 
[2718]159#if 1
[1984]160  _SortRays(rays,
161                        0,
[1990]162                        (int)rays.size()-1,
[1984]163                        0,
164                        b
165                        );
[2660]166#endif
[1974]167}
168                                       
169void
170RayCaster::_SortRays(SimpleRayContainer &rays,
171                                         const int l,
172                                         const int r,
[1984]173                                         const int depth,
[2660]174                                         float *box)
[1974]175{
176  // pick-up a pivot
[2660]177  int axis = 0;
[1984]178 
179  float maxDiff = -1.0f;
180  // get the largest axis
181  int offset = 0;
[1990]182  int i;
[1984]183
[2105]184  //const int batchsize = 16384;
[2008]185  const int batchsize = 8192;
[2105]186  //const int batchsize = 128;
[2008]187
[2105]188  //if (r - l < 16*batchsize)
189  //    offset = 3;
[2008]190       
[2105]191  //  if (depth%2==0)
[2008]192  //    offset = 3;
[1984]193 
[2002]194  for (i=offset; i < offset + 3; i++) {
195        float diff = box[i + 6] - box[i];
[1984]196        if (diff > maxDiff) {
197          maxDiff = diff;
198          axis = i;
199        }
200  }
201
[2008]202  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
[1984]203 
[1990]204  i=l;
205  int j=r;
206
[1984]207  float x = (box[axis] + box[axis+6])*0.5f;
208  //  float x = rays[(l+r)/2].GetParam(axis);
[1974]209  do {
[2008]210        while(i<j && rays[i].GetParam(axis) < x)
[1974]211          i++;
[2008]212        while(i<j && x < rays[j].GetParam(axis))
[1974]213          j--;
214       
215        if (i <= j) {
216          swap(rays[i], rays[j]);
217          i++;
218          j--;
219        }
220  } while (i<=j);
[2008]221
[1974]222 
[2008]223  if (l + batchsize < j ) {
[1984]224        // set new max
225        float save = box[axis+6];
226        box[axis+6] = x;
227        _SortRays(rays, l, j, depth+1, box);
228        box[axis+6] = save;
[2008]229  } else {
230        //      for (int k=0; k < 6; k++)
231        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
[1984]232  }
[1974]233 
[2008]234  if (i + batchsize < r) {
[1984]235        // set new min
236        box[axis] = x;
237    _SortRays(rays, i, r, depth+1, box);
[2008]238  } else {
239        //      for (int k=0; k < 6; k++)
240        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
[1984]241  }
[2008]242       
[1974]243}
244 
[2629]245
246void
247RayCaster::SortRays2(SimpleRayContainer &rays)
248{
249  AxisAlignedBox3 box =
250        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
251
252  const float sizeBox = Magnitude(box.Diagonal());
253  // This is some size of the
254  const float sizeDir = 0.2f * sizeBox;
255 
256  float b[12]={
257    box.Min().x,
258    box.Min().y,
259    box.Min().z,
260    -sizeDir,
261    -sizeDir,
262    -sizeDir,
263    box.Max().x,
264    box.Max().y,
265    box.Max().z,
266    sizeDir,
267    sizeDir,
268    sizeDir
269  };
270
271#if 0
272  static vector<SimpleRay *> pointerArray;
273
274  if (pointerArray.size()!=rays.size()) {
275        // realloc the pointerarray
276        pointerArray.resize(rays.size());
277  }
278
279  // init pointer array
280  SimpleRay *p = &pointerArray[0];
281  for (i=0; i < rays.size(); i++, p++)
282        pointerArray[i] = p;
283#endif
284 
285  _SortRays2(rays, 0, (int)rays.size()-1, 0, b);
286
287  return;
288}
[1974]289                                       
[2629]290void
291RayCaster::_SortRays2(SimpleRayContainer &rays,
292                      const int l,
293                      const int r,
294                      const int depth,
295                      float box[12])
296{
297  // pick-up a pivot
298  int axis;
299 
300  float maxDiff = -1.0f;
301  // get the largest axis
302  int offset = 0;
303  int i;
304
305  //const int batchsize = 16384;
306  //const int batchsize = 8192;
307  const int batchsize = 128;
308
309  //if (r - l < 16*batchsize)
310  //    offset = 3;
311       
312  //  if (depth%2==0)
313  //    offset = 3;
314 
315  for (i=offset; i < offset + 6; i++) {
316    float diff = box[i + 6] - box[i];
317    assert(diff >= 0.f);
318    if (diff > maxDiff) {
319      // Find the maximum
320      maxDiff = diff;
321      axis = i;
322    }
323  }
324
325  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
326 
327  i=l;
328  int j=r;
329
330  float x = (box[axis] + box[axis+6])*0.5f;
331  //  float x = rays[(l+r)/2].GetParam(axis);
332  do {
333        while(i<j && rays[i].GetParam(axis) < x)
334          i++;
335        while(i<j && x < rays[j].GetParam(axis))
336          j--;
337       
338        if (i <= j) {
339          swap(rays[i], rays[j]);
340          i++;
341          j--;
342        }
343  } while (i<=j);
344
345 
346  if (l + batchsize < j ) {
347        // set new max
348        float save = box[axis+6];
349        box[axis+6] = x;
350        _SortRays2(rays, l, j, depth+1, box);
351        box[axis+6] = save;
352  } else {
353        //      for (int k=0; k < 6; k++)
354        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
355  }
356 
357  if (i + batchsize < r) {
358    // set new min
359    box[axis] = x;
360    _SortRays2(rays, i, r, depth+1, box);
361  } else {
362        //      for (int k=0; k < 6; k++)
363        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
364  }
365       
366}
367 
368 
[2187]369VssRay *RayCaster::RequestRay(const Vector3 &origin,
370                                                          const Vector3 &termination,
371                                                          Intersectable *originObject,
372                                                          Intersectable *terminationObject,
373                                                          const int pass,
374                                                          const float pdf)
375{
[2742]376#ifdef USE_RAY_POOL
377
[2187]378 #if DEBUG_RAYCAST
379        Debug<<"PR2a"<<flush;
380#endif
381       
382        // old method: always allocate
[2198]383        if (0) return new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
[1528]384
[2187]385        VssRay *vssRay = mVssRayPool.Alloc();
386
387#if DEBUG_RAYCAST
388        Debug<<"PR2b"<<flush;
389#endif
390       
391        *vssRay = VssRay(origin, termination, originObject, terminationObject, pass, pdf);
392
393#if DEBUG_RAYCAST
394        Debug<<"PR2c"<<flush;
395#endif
396
[2742]397#else
398        VssRay *vssRay = new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
399#endif
[2187]400        return vssRay;
401}
402
403
[2742]404void RayCaster::SheduleRayForDeletion(VssRay *ray)
405{
406#ifndef USE_RAY_POOL
407        delete ray;
408#endif
409}
410
411
[1867]412int
413RayCaster::ProcessRay(const SimpleRay &simpleRay,
[2583]414                                          Intersection &hitA,
415                                          Intersection &hitB,
416                                          VssRayContainer &vssRays,
417                                          const AxisAlignedBox3 &box,
418                                          const bool castDoubleRay,
419                                          const bool pruneInvalidRays)
[1520]420{
[1984]421  int hits = 0;
[1528]422
[2014]423
[1520]424#if DEBUG_RAYCAST
[2013]425  static int id=0;
426  Debug<<"PRA "<<id++<<endl<<flush;
[1520]427#endif
[1528]428       
[1932]429        if (pruneInvalidRays)
430        {
[1952]431          if (!hitA.mObject && !hitB.mObject) {
[2635]432#if DEBUG_PROCESS_RAY
433                cout<<"I1 ";
434#endif
[1952]435                return 0;
436          }
[1520]437        }
[1584]438       
[2070]439        // regardless of the pruneInvalidRays setting reject
[2743]440        // rays which degenerate to a point
[1966]441        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
[2635]442#if DEBUG_PROCESS_RAY
443                cout<<"I2 ";
444#endif
[2035]445          return 0;
[1966]446        }
447       
[1952]448        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
[1932]449        const bool validB = //castDoubleRay &&
[1952]450          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
[1867]451       
[1952]452       
[1757]453#if DEBUG_RAYCAST
454        Debug<<"PR1"<<flush;
455#endif
[1584]456       
[1867]457        // reset both contributions
[1952]458        if (!validA || !validB) {
[2743]459          if (pruneInvalidRays)
[1952]460                return 0;
[2635]461
462#if DEBUG_PROCESS_RAY
463                cout<<"I2 ";
464#endif
465
[1952]466          // reset both contributions of this ray
467          hitA.mObject = NULL;
468          hitB.mObject = NULL;
469        }
470       
[1867]471        // 8.11. 2007 JB
472        // degenerate rays checked by geometrical constraint...
473        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
[1942]474
[1584]475       
[1757]476#if DEBUG_RAYCAST
477        Debug<<"PR2"<<flush;
478#endif
[2575]479
480        // VH - I do not know what this is for, commented out temporarily
481        // !!!!!!!!!!!!!! !!!!!!!!!!!! !!!!!!!!!!
482#if 1
[1942]483        const bool validSample = true;
484        if (validSample) {
485          Vector3 clipA, clipB;
486          if (!ClipToViewSpaceBox(hitA.mPoint,
487                                                          hitB.mPoint,
488                                                          clipA,
[2635]489                                                          clipB)) {
490#if DEBUG_PROCESS_RAY
491                cout<<"I3 ";
492#endif
493
[1942]494                return 0;
[2635]495          }
[1952]496
[1942]497          if (!pruneInvalidRays || hitA.mObject) {
[2014]498
[2187]499                  VssRay *vssRay =
500                          RequestRay(!castDoubleRay ? simpleRay.mOrigin : clipB,
[2012]501                                                 hitA.mPoint,
502                                                 hitB.mObject,
503                                                 hitA.mObject,
504                                                 mPreprocessor.mPass,
[2105]505                                                 1.0f //simpleRay.mPdf
[2012]506                                                 );
[2187]507
[1867]508                if (validA)
[2021]509                  vssRay->mFlags |= VssRay::Valid;
510               
[1883]511                vssRay->mDistribution = simpleRay.mDistribution;
[1989]512                vssRay->mGeneratorId = simpleRay.mGeneratorId;
513
[1867]514                vssRays.push_back(vssRay);
515                ++ hits;
516                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
[1932]517        }
518
[1867]519#if DEBUG_RAYCAST
[1932]520        Debug<<"PR3"<<flush;
[1867]521#endif
522
[2070]523        if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
524        {
[2187]525                VssRay *vssRay = RequestRay(
[2575]526                                            clipA,
527                                            hitB.mPoint,
528                                            hitA.mObject,
529                                            hitB.mObject,
530                                            mPreprocessor.mPass,
531                                            1.0f //simpleRay.mPdf
532                                            );
[2070]533
534                if (validB)
[1771]535                        vssRay->mFlags |= VssRay::Valid;
[1932]536
537                vssRay->mDistribution = simpleRay.mDistribution;
[1989]538                vssRay->mGeneratorId = simpleRay.mGeneratorId;
[1932]539                vssRays.push_back(vssRay);
540                ++ hits;
541                //cout << "vssray 2: " << *vssRay << endl;
[2070]542        }
[1942]543#if DEBUG_RAYCAST
544          Debug<<"PR4"<<flush;
545#endif
[2575]546        } // validSample
547#else
548        // Just pass if intersected or not
549        hits = (hitA.mObject != 0) ? 1 : 0;
550        intersect = hitA;
551#endif 
[1867]552       
[1520]553        return hits;
554}
555
[2076]556
557void
558RayCaster::CastRays(
[2575]559                    SimpleRayContainer &rays,
560                    VssRayContainer &vssRays,
561                    const AxisAlignedBox3 &sbox,
562                    const bool castDoubleRay,
563                    const bool pruneInvalidRays )
[2076]564{
[2575]565  SimpleRayContainer::const_iterator rit, rit_end = rays.end();
566 
567  for (rit = rays.begin(); rit != rit_end; ++ rit) {
568   
569    CastRay(
570            *rit,                               
571            vssRays,
572            sbox,
573            castDoubleRay,
574            pruneInvalidRays);
[2187]575        }
[1583]576}
[2575]577 
[2076]578
579}
Note: See TracBrowser for help on using the repository browser.