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

Revision 2014, 7.0 KB checked in by bittner, 17 years ago (diff)

timer start

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