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

Revision 1990, 6.6 KB checked in by mattausch, 17 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
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,
28                                                   const bool keepOrigin)
[1521]29{
[1932]30        // note: make no sense otherwise
31        const bool castDoubleRay = false;
[1990]32       
[1932]33        VssRayContainer rays;
[1990]34        CastRay(simpleRay, rays, box, castDoubleRay, true, keepOrigin);
[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
[1942]60  if (tmin >= 1.0f || tmax <=0.0f)
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
[1528]76/** Checks if ray is valid, (e.g., not in empty view space or outside the view space)
77*/
[1867]78bool
79RayCaster::ValidateRay(const Vector3 &origin,
80                                           const Vector3 &direction,
81                                           const AxisAlignedBox3 &box,
82                                           Intersection &hit)
[1528]83{
[1932]84        if (!hit.mObject) 
85        {
86                // compute intersection with the scene bounding box
[1584]87#if EXACT_BOX_CLIPPING
[1932]88                static Ray ray;
89                mPreprocessor.SetupRay(ray, origin, direction);
90
91                float tmin, tmax;
92                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
93                {
94                        hit.mPoint = ray.Extrap(tmax);
95                }
96                else
97                {
98                        // cout<<" invalid hp "<<tmin<<" "<<tmax<<endl;
99                        // cout<<" box "<<box<<endl;
100                        // cout<<" origin "<<origin<<endl;
101                        // cout<<" direction "<<direction<<endl;
102                        // cout<< "inv dir"<<ray.GetInvDir()<<endl;
103                        return false;
104                }
[1584]105#else
[1932]106                hit.mPoint = origin + direction * Magnitude(box.Diagonal());
[1584]107#endif
108        }
[1932]109        else
110        {
111                if (mPreprocessor.mDetectEmptyViewSpace)
112                {
113                        if (DotProd(hit.mNormal, direction) >= -Limits::Small)
114                        {       
115                                hit.mObject = NULL;
116                                return false;
117                        }
118                }
119        }
120
121        return true;
[1528]122}
123
[1974]124void
125RayCaster::SortRays(SimpleRayContainer &rays)
126{
[1984]127  AxisAlignedBox3 box =
128        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
129       
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
145  _SortRays(rays,
146                        0,
[1990]147                        (int)rays.size()-1,
[1984]148                        0,
149                        b
150                        );
[1974]151}
152                                       
153void
154RayCaster::_SortRays(SimpleRayContainer &rays,
155                                         const int l,
156                                         const int r,
[1984]157                                         const int depth,
158                                         float box[12])
[1974]159{
160  // pick-up a pivot
[1984]161  int axis;
162 
163  float maxDiff = -1.0f;
164  // get the largest axis
165  int offset = 0;
[1990]166  int i;
[1984]167
168  if (depth%5==0)
169        offset = 3;
170 
[1990]171  for (i=offset; i < offset+3; i++) {
[1984]172        float diff = box[i+6] - box[i];
173        if (diff > maxDiff) {
174          maxDiff = diff;
175          axis = i;
176        }
177  }
178
179  //  cout<<depth<<" "<<axis<<endl;
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 {
[1984]187        while(rays[i].GetParam(axis) < x && i<=j)
[1974]188          i++;
[1984]189        while(x < rays[j].GetParam(axis) && i<=j)
[1974]190          j--;
191       
192        if (i <= j) {
193          swap(rays[i], rays[j]);
194          i++;
195          j--;
196        }
197  } while (i<=j);
198 
[1984]199  if (l + 64 < j ) {
200        // set new max
201        float save = box[axis+6];
202        box[axis+6] = x;
203        _SortRays(rays, l, j, depth+1, box);
204        box[axis+6] = save;
205  }
[1974]206 
[1984]207  if (i + 64 < r) {
208        // set new min
209        box[axis] = x;
210    _SortRays(rays, i, r, depth+1, box);
211  }
[1974]212}
213 
214                                       
[1528]215
[1867]216int
217RayCaster::ProcessRay(const SimpleRay &simpleRay,
218                                          Intersection &hitA,
219                                          Intersection &hitB,
220                                          VssRayContainer &vssRays,
221                                          const AxisAlignedBox3 &box,
222                                          const bool castDoubleRay,
[1990]223                                          const bool pruneInvalidRays,
224                                          const bool keepOrigin)
[1520]225{
[1984]226  int hits = 0;
[1528]227
[1520]228#if DEBUG_RAYCAST
[1952]229        static int id=0;
230        Debug<<"PRA "<<id++<<endl<<flush;
[1520]231#endif
[1528]232       
[1932]233        if (pruneInvalidRays)
234        {
[1952]235          if (!hitA.mObject && !hitB.mObject) {
236                return 0;
237          }
[1520]238        }
[1966]239
[1584]240       
[1952]241        // regardless of the pruneInvalidRays setting reject rays whic degenerate to a point
[1966]242        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
[1990]243                return 0;
[1966]244        }
245       
246       
[1952]247        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
[1932]248        const bool validB = //castDoubleRay &&
[1952]249          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
[1867]250       
[1952]251       
[1757]252#if DEBUG_RAYCAST
253        Debug<<"PR1"<<flush;
254#endif
[1584]255       
[1867]256        // reset both contributions
[1952]257        if (!validA || !validB) {
258          if (pruneInvalidRays)
259                return 0;
[1867]260         
[1952]261          // reset both contributions of this ray
262          hitA.mObject = NULL;
263          hitB.mObject = NULL;
264        }
265       
[1867]266        // 8.11. 2007 JB
267        // degenerate rays checked by geometrical constraint...
268        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
[1942]269
[1584]270       
[1757]271#if DEBUG_RAYCAST
272        Debug<<"PR2"<<flush;
273#endif
[1942]274        const bool validSample = true;
275        if (validSample) {
276          Vector3 clipA, clipB;
277          if (!ClipToViewSpaceBox(hitA.mPoint,
278                                                          hitB.mPoint,
279                                                          clipA,
280                                                          clipB))
281                return 0;
[1952]282
[1942]283          if (!pruneInvalidRays || hitA.mObject) {
284                VssRay *vssRay = new VssRay(
[1990]285                                                                        keepOrigin ? simpleRay.mOrigin : clipB,
[1867]286                                                                        hitA.mPoint,
287                                                                        hitB.mObject,
288                                                                        hitA.mObject,
289                                                                        mPreprocessor.mPass,
[1989]290                                                                        simpleRay.mPdf
291                                                                        );
[1932]292
[1867]293                if (validA)
[1932]294                        vssRay->mFlags |= VssRay::Valid;
295
[1883]296                vssRay->mDistribution = simpleRay.mDistribution;
[1989]297                vssRay->mGeneratorId = simpleRay.mGeneratorId;
298
[1867]299                vssRays.push_back(vssRay);
300                ++ hits;
301                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
[1932]302        }
303
[1867]304#if DEBUG_RAYCAST
[1932]305        Debug<<"PR3"<<flush;
[1867]306#endif
307
[1942]308          if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
309                {
310                  VssRay *vssRay = new VssRay(
[1990]311                                                                          keepOrigin ? simpleRay.mOrigin : clipA,
[1942]312                                                                          hitB.mPoint,
313                                                                          hitA.mObject,
314                                                                          hitB.mObject,
315                                                                          mPreprocessor.mPass,
316                                                                          simpleRay.mPdf
317                                                                          );
318                  if (validB)
[1771]319                        vssRay->mFlags |= VssRay::Valid;
[1932]320
321                vssRay->mDistribution = simpleRay.mDistribution;
[1989]322                vssRay->mGeneratorId = simpleRay.mGeneratorId;
[1932]323                vssRays.push_back(vssRay);
324                ++ hits;
325                //cout << "vssray 2: " << *vssRay << endl;
[1942]326                }
327#if DEBUG_RAYCAST
328          Debug<<"PR4"<<flush;
329#endif
[1520]330        }
[1867]331       
[1520]332        return hits;
333}
334
[1583]335}
Note: See TracBrowser for help on using the repository browser.