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

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

commit after merge with vlastimil

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