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

Revision 2035, 7.0 KB checked in by bittner, 18 years ago (diff)

merge

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
7
8namespace GtpVisibilityPreprocessor {
9
10
11#define DEBUG_RAYCAST 0
12
[1942]13#define EXACT_BOX_CLIPPING 0
[1520]14
15RayCaster::RayCaster(const Preprocessor &preprocessor):
16mPreprocessor(preprocessor)
17{
18}
19
20
[1521]21RayCaster::~RayCaster()
22{
23}
24
25
[1545]26VssRay *RayCaster::CastRay(const SimpleRay &simpleRay,
[1990]27                                                   const AxisAlignedBox3 &box,
[1996]28                                                   const bool castDoubleRay)
[1521]29{
[1932]30        VssRayContainer rays;
[1996]31        CastRay(simpleRay, rays, box, castDoubleRay, true);
[1932]32   
33        if (!rays.empty())
34                return rays.back();
35        else
36                return NULL;
[1521]37}
38
[1990]39
[1942]40bool
41RayCaster::ClipToViewSpaceBox(const Vector3 &origin,
42                                                          const Vector3 &termination,
43                                                          Vector3 &clippedOrigin,
44                                                          Vector3 &clippedTermination)
45{
[1952]46 
[1942]47  Ray ray(origin, termination - origin, Ray::LINE_SEGMENT);     
48  ray.Precompute();
49 
50  float tmin, tmax;
51  if ((!mPreprocessor.mViewCellsManager->
52           GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax)) ||
53          tmin>=tmax
54          )
55        return false;
[1521]56
[1942]57  if (tmin >= 1.0f || tmax <=0.0f)
58        return false;
59 
60  if (tmin > 0.0f)
61        clippedOrigin = ray.Extrap(tmin);
62  else
63        clippedOrigin = origin;
64 
65  if (tmax < 1.0f)
66        clippedTermination = ray.Extrap(tmax);
67  else
68        clippedTermination = termination;
69 
70  return true;
71}
72
[1528]73/** Checks if ray is valid, (e.g., not in empty view space or outside the view space)
74*/
[1867]75bool
76RayCaster::ValidateRay(const Vector3 &origin,
77                                           const Vector3 &direction,
78                                           const AxisAlignedBox3 &box,
79                                           Intersection &hit)
[1528]80{
[1932]81        if (!hit.mObject) 
82        {
83                // compute intersection with the scene bounding box
[1584]84#if EXACT_BOX_CLIPPING
[1932]85                static Ray ray;
86                mPreprocessor.SetupRay(ray, origin, direction);
87
88                float tmin, tmax;
89                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
90                {
91                        hit.mPoint = ray.Extrap(tmax);
92                }
93                else
94                {
95                        // cout<<" invalid hp "<<tmin<<" "<<tmax<<endl;
96                        // cout<<" box "<<box<<endl;
97                        // cout<<" origin "<<origin<<endl;
98                        // cout<<" direction "<<direction<<endl;
99                        // cout<< "inv dir"<<ray.GetInvDir()<<endl;
100                        return false;
101                }
[1584]102#else
[1932]103                hit.mPoint = origin + direction * Magnitude(box.Diagonal());
[1584]104#endif
105        }
[1932]106        else
107        {
[2035]108          if (mPreprocessor.mDetectEmptyViewSpace)  {
109                if (DotProd(hit.mNormal, direction) >= -Limits::Small)  {       
110                  hit.mObject = NULL;
111                  return false;
[1932]112                }
[2035]113          }
[1932]114        }
[2035]115       
[1932]116        return true;
[1528]117}
118
[1974]119void
120RayCaster::SortRays(SimpleRayContainer &rays)
121{
[1984]122  AxisAlignedBox3 box =
123        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
124       
125  float b[12]={
126        box.Min().x,
127        box.Min().y,
128        box.Min().z,
129        -1,
130        -1,
131        -1,
132        box.Max().x,
133        box.Max().y,
134        box.Max().z,
135        1,
136        1,
137        1
138  };
139
140  _SortRays(rays,
141                        0,
[1990]142                        (int)rays.size()-1,
[1984]143                        0,
144                        b
145                        );
[1974]146}
147                                       
148void
149RayCaster::_SortRays(SimpleRayContainer &rays,
150                                         const int l,
151                                         const int r,
[1984]152                                         const int depth,
153                                         float box[12])
[1974]154{
155  // pick-up a pivot
[1984]156  int axis;
157 
158  float maxDiff = -1.0f;
159  // get the largest axis
160  int offset = 0;
[1990]161  int i;
[1984]162
[2008]163  const int batchsize = 8192;
164
165  //  if (r - l < 32*batchsize)
[2002]166  //    offset = 3;
[2008]167       
168  //  if (depth%5==0)
169  //    offset = 3;
[1984]170 
[2002]171  for (i=offset; i < offset + 3; i++) {
172        float diff = box[i + 6] - box[i];
[1984]173        if (diff > maxDiff) {
174          maxDiff = diff;
175          axis = i;
176        }
177  }
178
[2008]179  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
[1984]180 
[1990]181  i=l;
182  int j=r;
183
[1984]184  float x = (box[axis] + box[axis+6])*0.5f;
185  //  float x = rays[(l+r)/2].GetParam(axis);
[1974]186  do {
[2008]187        while(i<j && rays[i].GetParam(axis) < x)
[1974]188          i++;
[2008]189        while(i<j && x < rays[j].GetParam(axis))
[1974]190          j--;
191       
192        if (i <= j) {
193          swap(rays[i], rays[j]);
194          i++;
195          j--;
196        }
197  } while (i<=j);
[2008]198
[1974]199 
[2008]200  if (l + batchsize < j ) {
[1984]201        // set new max
202        float save = box[axis+6];
203        box[axis+6] = x;
204        _SortRays(rays, l, j, depth+1, box);
205        box[axis+6] = save;
[2008]206  } else {
207        //      for (int k=0; k < 6; k++)
208        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
[1984]209  }
[1974]210 
[2008]211  if (i + batchsize < r) {
[1984]212        // set new min
213        box[axis] = x;
214    _SortRays(rays, i, r, depth+1, box);
[2008]215  } else {
216        //      for (int k=0; k < 6; k++)
217        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
[1984]218  }
[2008]219       
[1974]220}
221 
222                                       
[1528]223
[1867]224int
225RayCaster::ProcessRay(const SimpleRay &simpleRay,
226                                          Intersection &hitA,
227                                          Intersection &hitB,
228                                          VssRayContainer &vssRays,
229                                          const AxisAlignedBox3 &box,
230                                          const bool castDoubleRay,
[1996]231                                          const bool pruneInvalidRays)
[1520]232{
[1984]233  int hits = 0;
[1528]234
[2014]235
[1520]236#if DEBUG_RAYCAST
[2013]237  static int id=0;
238  Debug<<"PRA "<<id++<<endl<<flush;
[1520]239#endif
[1528]240       
[1932]241        if (pruneInvalidRays)
242        {
[1952]243          if (!hitA.mObject && !hitB.mObject) {
244                return 0;
245          }
[1520]246        }
[1966]247
[1584]248       
[1952]249        // regardless of the pruneInvalidRays setting reject rays whic degenerate to a point
[1966]250        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
[2035]251          return 0;
[1966]252        }
253       
254       
[1952]255        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
[1932]256        const bool validB = //castDoubleRay &&
[1952]257          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
[1867]258       
[1952]259       
[1757]260#if DEBUG_RAYCAST
261        Debug<<"PR1"<<flush;
262#endif
[1584]263       
[1867]264        // reset both contributions
[1952]265        if (!validA || !validB) {
266          if (pruneInvalidRays)
267                return 0;
[1867]268         
[1952]269          // reset both contributions of this ray
270          hitA.mObject = NULL;
271          hitB.mObject = NULL;
272        }
273       
[1867]274        // 8.11. 2007 JB
275        // degenerate rays checked by geometrical constraint...
276        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
[1942]277
[1584]278       
[1757]279#if DEBUG_RAYCAST
280        Debug<<"PR2"<<flush;
281#endif
[1942]282        const bool validSample = true;
283        if (validSample) {
284          Vector3 clipA, clipB;
285          if (!ClipToViewSpaceBox(hitA.mPoint,
286                                                          hitB.mPoint,
287                                                          clipA,
288                                                          clipB))
289                return 0;
[1952]290
[1942]291          if (!pruneInvalidRays || hitA.mObject) {
[2014]292#if DEBUG_RAYCAST
293                Debug<<"PR2a"<<flush;
294#endif
295               
[2012]296                VssRay *vssRay = mVssRayPool.Alloc();
[2014]297
298#if DEBUG_RAYCAST
299                Debug<<"PR2b"<<flush;
300#endif
[2012]301                *vssRay = VssRay(
302                                                 !castDoubleRay ? simpleRay.mOrigin : clipB,
303                                                 hitA.mPoint,
304                                                 hitB.mObject,
305                                                 hitA.mObject,
306                                                 mPreprocessor.mPass,
307                                                 simpleRay.mPdf
308                                                 );
[2014]309#if DEBUG_RAYCAST
310                Debug<<"PR2c"<<flush;
311#endif
[2021]312               
[1867]313                if (validA)
[2021]314                  vssRay->mFlags |= VssRay::Valid;
[1932]315
[2021]316               
[1883]317                vssRay->mDistribution = simpleRay.mDistribution;
[1989]318                vssRay->mGeneratorId = simpleRay.mGeneratorId;
319
[1867]320                vssRays.push_back(vssRay);
321                ++ hits;
322                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
[1932]323        }
324
[1867]325#if DEBUG_RAYCAST
[1932]326        Debug<<"PR3"<<flush;
[1867]327#endif
328
[1942]329          if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
330                {
[2012]331                  VssRay *vssRay = mVssRayPool.Alloc();
[2013]332                               
[2012]333                  *vssRay = VssRay(
334                                                   clipA,
335                                                   hitB.mPoint,
336                                                   hitA.mObject,
337                                                   hitB.mObject,
338                                                   mPreprocessor.mPass,
339                                                   simpleRay.mPdf
340                                                   );
[1942]341                  if (validB)
[1771]342                        vssRay->mFlags |= VssRay::Valid;
[1932]343
[2021]344                 
[1932]345                vssRay->mDistribution = simpleRay.mDistribution;
[1989]346                vssRay->mGeneratorId = simpleRay.mGeneratorId;
[1932]347                vssRays.push_back(vssRay);
348                ++ hits;
349                //cout << "vssray 2: " << *vssRay << endl;
[1942]350                }
351#if DEBUG_RAYCAST
352          Debug<<"PR4"<<flush;
353#endif
[1520]354        }
[1867]355       
[1520]356        return hits;
357}
358
[1583]359}
Note: See TracBrowser for help on using the repository browser.