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

Revision 1989, 6.5 KB checked in by bittner, 17 years ago (diff)

mutation updates

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        // note: make no sense otherwise
31        const bool castDoubleRay = false;
32        VssRayContainer rays;
33        CastRay(simpleRay, rays, box, castDoubleRay);
34   
35        if (!rays.empty())
36                return rays.back();
37        else
38                return NULL;
39}
40
41bool
42RayCaster::ClipToViewSpaceBox(const Vector3 &origin,
43                                                          const Vector3 &termination,
44                                                          Vector3 &clippedOrigin,
45                                                          Vector3 &clippedTermination)
46{
47 
48  Ray ray(origin, termination - origin, Ray::LINE_SEGMENT);     
49  ray.Precompute();
50 
51  float tmin, tmax;
52  if ((!mPreprocessor.mViewCellsManager->
53           GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax)) ||
54          tmin>=tmax
55          )
56        return false;
57
58  if (tmin >= 1.0f || tmax <=0.0f)
59        return false;
60 
61  if (tmin > 0.0f)
62        clippedOrigin = ray.Extrap(tmin);
63  else
64        clippedOrigin = origin;
65 
66  if (tmax < 1.0f)
67        clippedTermination = ray.Extrap(tmax);
68  else
69        clippedTermination = termination;
70 
71  return true;
72}
73
74/** Checks if ray is valid, (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                {
111                        if (DotProd(hit.mNormal, direction) >= -Limits::Small)
112                        {       
113                                hit.mObject = NULL;
114                                return false;
115                        }
116                }
117        }
118
119        return true;
120}
121
122void
123RayCaster::SortRays(SimpleRayContainer &rays)
124{
125  AxisAlignedBox3 box =
126        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
127       
128  float b[12]={
129        box.Min().x,
130        box.Min().y,
131        box.Min().z,
132        -1,
133        -1,
134        -1,
135        box.Max().x,
136        box.Max().y,
137        box.Max().z,
138        1,
139        1,
140        1
141  };
142
143  _SortRays(rays,
144                        0,
145                        rays.size()-1,
146                        0,
147                        b
148                        );
149}
150                                       
151void
152RayCaster::_SortRays(SimpleRayContainer &rays,
153                                         const int l,
154                                         const int r,
155                                         const int depth,
156                                         float box[12])
157{
158  // pick-up a pivot
159  int axis;
160 
161  float maxDiff = -1.0f;
162  // get the largest axis
163  int offset = 0;
164
165  if (depth%5==0)
166        offset = 3;
167 
168  for (int i=offset; i < offset+3; i++) {
169        float diff = box[i+6] - box[i];
170        if (diff > maxDiff) {
171          maxDiff = diff;
172          axis = i;
173        }
174  }
175
176  //  cout<<depth<<" "<<axis<<endl;
177 
178  int i=l,j=r;
179  float x = (box[axis] + box[axis+6])*0.5f;
180  //  float x = rays[(l+r)/2].GetParam(axis);
181  do {
182        while(rays[i].GetParam(axis) < x && i<=j)
183          i++;
184        while(x < rays[j].GetParam(axis) && i<=j)
185          j--;
186       
187        if (i <= j) {
188          swap(rays[i], rays[j]);
189          i++;
190          j--;
191        }
192  } while (i<=j);
193 
194  if (l + 64 < j ) {
195        // set new max
196        float save = box[axis+6];
197        box[axis+6] = x;
198        _SortRays(rays, l, j, depth+1, box);
199        box[axis+6] = save;
200  }
201 
202  if (i + 64 < r) {
203        // set new min
204        box[axis] = x;
205    _SortRays(rays, i, r, depth+1, box);
206  }
207}
208 
209                                       
210
211int
212RayCaster::ProcessRay(const SimpleRay &simpleRay,
213                                          Intersection &hitA,
214                                          Intersection &hitB,
215                                          VssRayContainer &vssRays,
216                                          const AxisAlignedBox3 &box,
217                                          const bool castDoubleRay,
218                                          const bool pruneInvalidRays)
219{
220  int hits = 0;
221
222#if DEBUG_RAYCAST
223        static int id=0;
224        Debug<<"PRA "<<id++<<endl<<flush;
225#endif
226       
227        if (pruneInvalidRays)
228        {
229          if (!hitA.mObject && !hitB.mObject) {
230                return 0;
231          }
232        }
233
234       
235        // regardless of the pruneInvalidRays setting reject rays whic degenerate to a point
236        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
237          return 0;
238        }
239       
240       
241        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
242        const bool validB = //castDoubleRay &&
243          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
244       
245       
246#if DEBUG_RAYCAST
247        Debug<<"PR1"<<flush;
248#endif
249       
250        // reset both contributions
251        if (!validA || !validB) {
252          if (pruneInvalidRays)
253                return 0;
254         
255          // reset both contributions of this ray
256          hitA.mObject = NULL;
257          hitB.mObject = NULL;
258        }
259       
260        // 8.11. 2007 JB
261        // degenerate rays checked by geometrical constraint...
262        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
263
264       
265#if DEBUG_RAYCAST
266        Debug<<"PR2"<<flush;
267#endif
268        const bool validSample = true;
269        if (validSample) {
270          Vector3 clipA, clipB;
271          if (!ClipToViewSpaceBox(hitA.mPoint,
272                                                          hitB.mPoint,
273                                                          clipA,
274                                                          clipB))
275                return 0;
276
277          if (!pruneInvalidRays || hitA.mObject) {
278                VssRay *vssRay = new VssRay(
279                                                                        clipB,
280                                                                        hitA.mPoint,
281                                                                        hitB.mObject,
282                                                                        hitA.mObject,
283                                                                        mPreprocessor.mPass,
284                                                                        simpleRay.mPdf
285                                                                        );
286
287                if (validA)
288                        vssRay->mFlags |= VssRay::Valid;
289
290                vssRay->mDistribution = simpleRay.mDistribution;
291                vssRay->mGeneratorId = simpleRay.mGeneratorId;
292
293                vssRays.push_back(vssRay);
294                ++ hits;
295                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
296        }
297
298#if DEBUG_RAYCAST
299        Debug<<"PR3"<<flush;
300#endif
301
302          if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
303                {
304                  VssRay *vssRay = new VssRay(
305                                                                          clipA,
306                                                                          hitB.mPoint,
307                                                                          hitA.mObject,
308                                                                          hitB.mObject,
309                                                                          mPreprocessor.mPass,
310                                                                          simpleRay.mPdf
311                                                                          );
312                  if (validB)
313                        vssRay->mFlags |= VssRay::Valid;
314
315                vssRay->mDistribution = simpleRay.mDistribution;
316                vssRay->mGeneratorId = simpleRay.mGeneratorId;
317                vssRays.push_back(vssRay);
318                ++ hits;
319                //cout << "vssray 2: " << *vssRay << endl;
320                }
321#if DEBUG_RAYCAST
322          Debug<<"PR4"<<flush;
323#endif
324        }
325       
326        return hits;
327}
328
329}
Note: See TracBrowser for help on using the repository browser.