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

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