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

Revision 2575, 8.5 KB checked in by bittner, 17 years ago (diff)

big merge: preparation for havran ray caster, check if everything works

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
74        (e.g., not in empty view space or outside the view space)
75*/
76bool
77RayCaster::ValidateRay(const Vector3 &origin,
78                                           const Vector3 &direction,
79                                           const AxisAlignedBox3 &box,
80                                           Intersection &hit)
81{
82        if (!hit.mObject) 
83        {
84                // compute intersection with the scene bounding box
85#if EXACT_BOX_CLIPPING
86                static Ray ray;
87                mPreprocessor.SetupRay(ray, origin, direction);
88
89                float tmin, tmax;
90                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
91                {
92                        hit.mPoint = ray.Extrap(tmax);
93                }
94                else
95                {
96                        // cout<<" invalid hp "<<tmin<<" "<<tmax<<endl;
97                        // cout<<" box "<<box<<endl;
98                        // cout<<" origin "<<origin<<endl;
99                        // cout<<" direction "<<direction<<endl;
100                        // cout<< "inv dir"<<ray.GetInvDir()<<endl;
101                        return false;
102                }
103#else
104                hit.mPoint = origin + direction * Magnitude(box.Diagonal());
105#endif
106        }
107        else
108        {
109          if (mPreprocessor.mDetectEmptyViewSpace)  {
110                if (DotProd(hit.mNormal, direction) >= -Limits::Small)  {       
111                  hit.mObject = NULL;
112                  return false;
113                }
114          }
115        }
116       
117        return true;
118}
119
120void
121RayCaster::SortRays(SimpleRayContainer &rays)
122{
123  AxisAlignedBox3 box =
124        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
125 
126  float b[12]={
127        box.Min().x,
128        box.Min().y,
129        box.Min().z,
130        -1,
131        -1,
132        -1,
133        box.Max().x,
134        box.Max().y,
135        box.Max().z,
136        1,
137        1,
138        1
139  };
140
141#if 0
142  static vector<SimpleRay *> pointerArray;
143
144  if (pointerArray.size()!=rays.size()) {
145        // realloc the pointerarray
146        pointerArray.resize(rays.size());
147  }
148
149  // init pointer array
150  SimpleRay *p = &pointerArray[0];
151  for (i=0; i < rays.size(); i++, p++)
152        pointerArray[i] = p;
153#endif
154 
155  _SortRays(rays,
156                        0,
157                        (int)rays.size()-1,
158                        0,
159                        b
160                        );
161}
162                                       
163void
164RayCaster::_SortRays(SimpleRayContainer &rays,
165                                         const int l,
166                                         const int r,
167                                         const int depth,
168                                         float box[12])
169{
170  // pick-up a pivot
171  int axis;
172 
173  float maxDiff = -1.0f;
174  // get the largest axis
175  int offset = 0;
176  int i;
177
178  //const int batchsize = 16384;
179  const int batchsize = 8192;
180  //const int batchsize = 128;
181
182  //if (r - l < 16*batchsize)
183  //    offset = 3;
184       
185  //  if (depth%2==0)
186  //    offset = 3;
187 
188  for (i=offset; i < offset + 3; i++) {
189        float diff = box[i + 6] - box[i];
190        if (diff > maxDiff) {
191          maxDiff = diff;
192          axis = i;
193        }
194  }
195
196  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
197 
198  i=l;
199  int j=r;
200
201  float x = (box[axis] + box[axis+6])*0.5f;
202  //  float x = rays[(l+r)/2].GetParam(axis);
203  do {
204        while(i<j && rays[i].GetParam(axis) < x)
205          i++;
206        while(i<j && x < rays[j].GetParam(axis))
207          j--;
208       
209        if (i <= j) {
210          swap(rays[i], rays[j]);
211          i++;
212          j--;
213        }
214  } while (i<=j);
215
216 
217  if (l + batchsize < j ) {
218        // set new max
219        float save = box[axis+6];
220        box[axis+6] = x;
221        _SortRays(rays, l, j, depth+1, box);
222        box[axis+6] = save;
223  } else {
224        //      for (int k=0; k < 6; k++)
225        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
226  }
227 
228  if (i + batchsize < r) {
229        // set new min
230        box[axis] = x;
231    _SortRays(rays, i, r, depth+1, box);
232  } else {
233        //      for (int k=0; k < 6; k++)
234        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
235  }
236       
237}
238 
239                                       
240VssRay *RayCaster::RequestRay(const Vector3 &origin,
241                                                          const Vector3 &termination,
242                                                          Intersectable *originObject,
243                                                          Intersectable *terminationObject,
244                                                          const int pass,
245                                                          const float pdf)
246{
247 #if DEBUG_RAYCAST
248        Debug<<"PR2a"<<flush;
249#endif
250       
251        // old method: always allocate
252        if (0) return new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
253
254        VssRay *vssRay = mVssRayPool.Alloc();
255
256#if DEBUG_RAYCAST
257        Debug<<"PR2b"<<flush;
258#endif
259       
260        *vssRay = VssRay(origin, termination, originObject, terminationObject, pass, pdf);
261
262#if DEBUG_RAYCAST
263        Debug<<"PR2c"<<flush;
264#endif
265
266        return vssRay;
267}
268
269
270int
271RayCaster::ProcessRay(const SimpleRay &simpleRay,
272                      Intersection &hitA,
273                      Intersection &hitB,
274                      VssRayContainer &vssRays,
275                      const AxisAlignedBox3 &box,
276                      const bool castDoubleRay,
277                      const bool pruneInvalidRays)
278{
279  int hits = 0;
280
281
282#if DEBUG_RAYCAST
283  static int id=0;
284  Debug<<"PRA "<<id++<<endl<<flush;
285#endif
286       
287        if (pruneInvalidRays)
288        {
289          if (!hitA.mObject && !hitB.mObject) {
290                return 0;
291          }
292        }
293       
294        // regardless of the pruneInvalidRays setting reject
295        // rays whic degenerate to a point
296        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
297          return 0;
298        }
299       
300        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
301        const bool validB = //castDoubleRay &&
302          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
303       
304       
305#if DEBUG_RAYCAST
306        Debug<<"PR1"<<flush;
307#endif
308       
309        // reset both contributions
310        if (!validA || !validB) {
311          if (0 || pruneInvalidRays)
312                return 0;
313         
314          // reset both contributions of this ray
315          hitA.mObject = NULL;
316          hitB.mObject = NULL;
317        }
318       
319        // 8.11. 2007 JB
320        // degenerate rays checked by geometrical constraint...
321        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
322
323       
324#if DEBUG_RAYCAST
325        Debug<<"PR2"<<flush;
326#endif
327
328        // VH - I do not know what this is for, commented out temporarily
329        // !!!!!!!!!!!!!! !!!!!!!!!!!! !!!!!!!!!!
330#if 1
331        const bool validSample = true;
332        if (validSample) {
333          Vector3 clipA, clipB;
334          if (!ClipToViewSpaceBox(hitA.mPoint,
335                                                          hitB.mPoint,
336                                                          clipA,
337                                                          clipB))
338                return 0;
339
340          if (!pruneInvalidRays || hitA.mObject) {
341
342                  VssRay *vssRay =
343                          RequestRay(!castDoubleRay ? simpleRay.mOrigin : clipB,
344                                                 hitA.mPoint,
345                                                 hitB.mObject,
346                                                 hitA.mObject,
347                                                 mPreprocessor.mPass,
348                                                 1.0f //simpleRay.mPdf
349                                                 );
350
351                if (validA)
352                  vssRay->mFlags |= VssRay::Valid;
353               
354                vssRay->mDistribution = simpleRay.mDistribution;
355                vssRay->mGeneratorId = simpleRay.mGeneratorId;
356
357                vssRays.push_back(vssRay);
358                ++ hits;
359                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
360        }
361
362#if DEBUG_RAYCAST
363        Debug<<"PR3"<<flush;
364#endif
365
366        if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
367        {
368                VssRay *vssRay = RequestRay(
369                                            clipA,
370                                            hitB.mPoint,
371                                            hitA.mObject,
372                                            hitB.mObject,
373                                            mPreprocessor.mPass,
374                                            1.0f //simpleRay.mPdf
375                                            );
376
377                if (validB)
378                        vssRay->mFlags |= VssRay::Valid;
379
380                vssRay->mDistribution = simpleRay.mDistribution;
381                vssRay->mGeneratorId = simpleRay.mGeneratorId;
382                vssRays.push_back(vssRay);
383                ++ hits;
384                //cout << "vssray 2: " << *vssRay << endl;
385        }
386#if DEBUG_RAYCAST
387          Debug<<"PR4"<<flush;
388#endif
389        } // validSample
390#else
391        // Just pass if intersected or not
392        hits = (hitA.mObject != 0) ? 1 : 0;
393        intersect = hitA;
394#endif 
395       
396        return hits;
397}
398
399
400void
401RayCaster::CastRays(
402                    SimpleRayContainer &rays,
403                    VssRayContainer &vssRays,
404                    const AxisAlignedBox3 &sbox,
405                    const bool castDoubleRay,
406                    const bool pruneInvalidRays )
407{
408  SimpleRayContainer::const_iterator rit, rit_end = rays.end();
409 
410  for (rit = rays.begin(); rit != rit_end; ++ rit) {
411   
412    CastRay(
413            *rit,                               
414            vssRays,
415            sbox,
416            castDoubleRay,
417            pruneInvalidRays);
418        }
419}
420 
421
422}
Note: See TracBrowser for help on using the repository browser.