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

Revision 2076, 7.3 KB checked in by bittner, 17 years ago (diff)

merge

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  _SortRays(rays,
142                        0,
143                        (int)rays.size()-1,
144                        0,
145                        b
146                        );
147}
148                                       
149void
150RayCaster::_SortRays(SimpleRayContainer &rays,
151                                         const int l,
152                                         const int r,
153                                         const int depth,
154                                         float box[12])
155{
156  // pick-up a pivot
157  int axis;
158 
159  float maxDiff = -1.0f;
160  // get the largest axis
161  int offset = 0;
162  int i;
163
164  const int batchsize = 8192;
165
166  //  if (r - l < 32*batchsize)
167  //    offset = 3;
168       
169  //  if (depth%5==0)
170  //    offset = 3;
171 
172  for (i=offset; i < offset + 3; i++) {
173        float diff = box[i + 6] - box[i];
174        if (diff > maxDiff) {
175          maxDiff = diff;
176          axis = i;
177        }
178  }
179
180  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
181 
182  i=l;
183  int j=r;
184
185  float x = (box[axis] + box[axis+6])*0.5f;
186  //  float x = rays[(l+r)/2].GetParam(axis);
187  do {
188        while(i<j && rays[i].GetParam(axis) < x)
189          i++;
190        while(i<j && x < rays[j].GetParam(axis))
191          j--;
192       
193        if (i <= j) {
194          swap(rays[i], rays[j]);
195          i++;
196          j--;
197        }
198  } while (i<=j);
199
200 
201  if (l + batchsize < j ) {
202        // set new max
203        float save = box[axis+6];
204        box[axis+6] = x;
205        _SortRays(rays, l, j, depth+1, box);
206        box[axis+6] = save;
207  } else {
208        //      for (int k=0; k < 6; k++)
209        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
210  }
211 
212  if (i + batchsize < r) {
213        // set new min
214        box[axis] = x;
215    _SortRays(rays, i, r, depth+1, box);
216  } else {
217        //      for (int k=0; k < 6; k++)
218        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
219  }
220       
221}
222 
223                                       
224
225int
226RayCaster::ProcessRay(const SimpleRay &simpleRay,
227                                          Intersection &hitA,
228                                          Intersection &hitB,
229                                          VssRayContainer &vssRays,
230                                          const AxisAlignedBox3 &box,
231                                          const bool castDoubleRay,
232                                          const bool pruneInvalidRays)
233{
234  int hits = 0;
235
236
237#if DEBUG_RAYCAST
238  static int id=0;
239  Debug<<"PRA "<<id++<<endl<<flush;
240#endif
241       
242        if (pruneInvalidRays)
243        {
244          if (!hitA.mObject && !hitB.mObject) {
245                return 0;
246          }
247        }
248       
249        // regardless of the pruneInvalidRays setting reject
250        // rays whic degenerate to a point
251        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
252          return 0;
253        }
254       
255        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
256        const bool validB = //castDoubleRay &&
257          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
258       
259       
260#if DEBUG_RAYCAST
261        Debug<<"PR1"<<flush;
262#endif
263       
264        // reset both contributions
265        if (!validA || !validB) {
266          if (0 || pruneInvalidRays)
267                return 0;
268         
269          // reset both contributions of this ray
270          hitA.mObject = NULL;
271          hitB.mObject = NULL;
272        }
273       
274        // 8.11. 2007 JB
275        // degenerate rays checked by geometrical constraint...
276        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
277
278       
279#if DEBUG_RAYCAST
280        Debug<<"PR2"<<flush;
281#endif
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;
290
291          if (!pruneInvalidRays || hitA.mObject) {
292#if DEBUG_RAYCAST
293                Debug<<"PR2a"<<flush;
294#endif
295               
296                VssRay *vssRay = mVssRayPool.Alloc();
297
298#if DEBUG_RAYCAST
299                Debug<<"PR2b"<<flush;
300#endif
301                *vssRay = VssRay(
302                                                 !castDoubleRay ? simpleRay.mOrigin : clipB,
303                                                 hitA.mPoint,
304                                                 hitB.mObject,
305                                                 hitA.mObject,
306                                                 mPreprocessor.mPass,
307                                                 simpleRay.mPdf
308                                                 );
309#if DEBUG_RAYCAST
310                Debug<<"PR2c"<<flush;
311#endif
312               
313                if (validA)
314                  vssRay->mFlags |= VssRay::Valid;
315               
316                vssRay->mDistribution = simpleRay.mDistribution;
317                vssRay->mGeneratorId = simpleRay.mGeneratorId;
318
319                vssRays.push_back(vssRay);
320                ++ hits;
321                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
322        }
323
324#if DEBUG_RAYCAST
325        Debug<<"PR3"<<flush;
326#endif
327
328        if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
329        {
330                VssRay *vssRay = mVssRayPool.Alloc();
331
332                *vssRay = VssRay(
333                        clipA,
334                        hitB.mPoint,
335                        hitA.mObject,
336                        hitB.mObject,
337                        mPreprocessor.mPass,
338                        simpleRay.mPdf
339                        );
340
341                if (validB)
342                        vssRay->mFlags |= VssRay::Valid;
343
344                vssRay->mDistribution = simpleRay.mDistribution;
345                vssRay->mGeneratorId = simpleRay.mGeneratorId;
346                vssRays.push_back(vssRay);
347                ++ hits;
348                //cout << "vssray 2: " << *vssRay << endl;
349        }
350#if DEBUG_RAYCAST
351          Debug<<"PR4"<<flush;
352#endif
353        }
354       
355        return hits;
356}
357
358
359void
360RayCaster::CastRays(
361                                        SimpleRayContainer &rays,
362                                        VssRayContainer &vssRays,
363                                        const AxisAlignedBox3 &sbox,
364                                        const bool castDoubleRay,
365                                        const bool pruneInvalidRays )
366{
367  SimpleRayContainer::const_iterator rit, rit_end = rays.end();
368 
369  for (rit = rays.begin(); rit != rit_end; ++ rit) {
370        CastRay(
371                        *rit,                           
372                        vssRays,
373                        sbox,
374                        castDoubleRay,
375                        pruneInvalidRays);
376  }
377 
378}
379
380}
Note: See TracBrowser for help on using the repository browser.