source: trunk/VUT/GtpVisibilityPreprocessor/src/MutualVisibility.cpp @ 223

Revision 223, 9.6 KB checked in by bittner, 19 years ago (diff)
Line 
1#include <assert.h>
2#include <stack>
3using namespace std;
4#include "KdTree.h"
5#include "AxisAlignedBox3.h"
6#include "Ray.h"
7#include "MutualVisibility.h"
8#include "Exporter.h"
9#include "Mesh.h"
10#include "Triangle3.h"
11
12void
13RayShaft::Init(
14               const Rectangle3 &source,
15               const Rectangle3 &target)
16{
17  mDepth = 0;
18  mSource = source;
19  mTarget = target;
20}
21
22
23Vector3
24RayShaft::GetIntersectionPoint(const int rayIndex,
25                               const int depth) const
26{
27  Vector3 origin, direction;
28  GetRay(rayIndex, origin, direction);
29  return origin + direction*mSamples[rayIndex].mIntersections[depth].mT;
30}
31
32void
33RayShaft::GetRay(const int rayIndex,
34                 Vector3 &origin,
35                 Vector3 &direction) const
36{
37 
38  assert(rayIndex < 4);
39 
40  origin = mSource.mVertices[rayIndex];
41  direction = mTarget.mVertices[rayIndex] - origin;
42}
43
44void
45MutualVisibilitySampler::PerformSplit(
46                                      const RayShaft &sample,
47                                      const bool splitSource,
48                                      const int axis,
49                                      RayShaft &sample1,
50                                      RayShaft &sample2
51                                      )
52{
53 
54
55  // split the triangles
56
57  if (splitSource) {
58    sample1.mTarget = sample.mTarget;
59    sample2.mTarget = sample.mTarget;
60    sample.mSource.Split(
61                         axis,
62                         sample1.mSource,
63                         sample2.mSource);
64  } else {
65   
66    sample1.mSource = sample.mSource;
67    sample2.mSource = sample.mSource;
68   
69    sample.mTarget.Split(
70                         axis,
71                         sample1.mTarget,
72                         sample2.mTarget);
73  }
74 
75  // split the intersections
76  switch (axis) {
77  case 0:
78    sample1.mSamples[0].mIntersections = sample.mSamples[0].mIntersections;
79    sample1.mSamples[3].mIntersections = sample.mSamples[3].mIntersections;
80   
81    sample2.mSamples[1].mIntersections = sample.mSamples[1].mIntersections;
82    sample2.mSamples[2].mIntersections = sample.mSamples[2].mIntersections;
83    break;
84
85  case 1:
86    sample1.mSamples[0].mIntersections = sample.mSamples[0].mIntersections;
87    sample1.mSamples[1].mIntersections = sample.mSamples[1].mIntersections;
88
89    sample2.mSamples[2].mIntersections = sample.mSamples[2].mIntersections;
90    sample2.mSamples[3].mIntersections = sample.mSamples[3].mIntersections;
91    break;
92  }
93
94  // the intersections for the new shaft rays will be established
95  // later
96  sample1.mDepth = sample2.mDepth = sample.mDepth+1;
97}
98
99float
100MutualVisibilitySampler::GetSpatialAngle(const RayShaft &sample,
101                                         const Vector3 &point
102                                         )
103{
104  const int sampleIndices[][2]={
105    (0,1,2),
106    (0,2,3)
107  };
108 
109  float sum = 0.0f;
110  int i;
111 
112  for (i=0; i < 2; i++) {
113    Triangle3 triangle(sample.GetIntersectionPoint(sampleIndices[i][0], 0),
114                       sample.GetIntersectionPoint(sampleIndices[i][1], 0),
115                       sample.GetIntersectionPoint(sampleIndices[i][2], 0));
116    sum += triangle.GetSpatialAngle(point);
117  }
118
119  return sum;
120}
121
122
123void
124MutualVisibilitySampler::ComputeError(RayShaft &sample)
125{
126  // evaluate minimal error which can be achieved by more precise evaluation
127  // if this is above the threshold do not proceed further
128
129  float maxAngle = GetSpatialAngle(sample,
130                                   sample.mSource.GetCenter());
131 
132  for (int i=0; i < 3; i++) {
133    float angle = GetSpatialAngle(sample,
134                                  sample.mSource.mVertices[i]);
135    if (angle > maxAngle)
136      maxAngle = angle;
137  }
138 
139  sample.mError = maxAngle;
140}
141
142
143void
144MutualVisibilitySampler::ConstructInitialSamples(
145                                                 const AxisAlignedBox3 &source,
146                                                 const AxisAlignedBox3 &target,
147                                                 vector<RayShaft *> &samples
148                                                 )
149{
150  Vector3 sourceCenter = source.Center();
151  Vector3 targetCenter = target.Center();
152  Vector3 normal = Normalize(sourceCenter - targetCenter );
153 
154  Plane3 sourcePlane(normal, source.GetVertex(0));
155  int i;
156  for (i=1; i < 8; i++) {
157    Vector3 v = source.GetVertex(i);
158    if (sourcePlane.Distance(v) > 0)
159      sourcePlane = Plane3(normal, v);
160  }
161 
162  Plane3 targetPlane(normal, target.GetVertex(0));
163  for (i=1; i < 8; i++) {
164    Vector3 v = target.GetVertex(i);
165    if (targetPlane.Distance(v) < 0)
166      targetPlane = Plane3(normal, v);
167  }
168
169 
170  Vector3 xBasis = CrossProd(Vector3(0,1,0), normal);
171
172  if (Magnitude(xBasis) > 1e-6)
173    xBasis.Normalize();
174  else {
175    xBasis = CrossProd(Vector3(0,0,1), normal);
176  }
177
178  Vector3 yBasis = Normalize( CrossProd(normal, xBasis) );
179  // cast rays between the centers of the boxes
180  Vector3 targetRCenter = targetPlane.FindIntersection(sourceCenter,
181                                                       targetCenter);
182 
183  Vector3 sourceRCenter = sourcePlane.FindIntersection(sourceCenter,
184                                                       targetCenter);
185 
186
187  Rectangle3 sourceRect;
188  Rectangle3 targetRect;
189
190 
191  float scale = Magnitude(source.Size())*0.7f;
192  sourceRect.mVertices[0] = sourceRCenter - scale*xBasis - scale*yBasis;
193  sourceRect.mVertices[1] = sourceRCenter + scale*xBasis - scale*yBasis;
194  sourceRect.mVertices[2] = sourceRCenter + scale*xBasis + scale*yBasis;
195  sourceRect.mVertices[3] = sourceRCenter - scale*xBasis + scale*yBasis;
196
197  scale = Magnitude(target.Size())*0.7f;
198  targetRect.mVertices[0] = targetRCenter - scale*xBasis - scale*yBasis;
199  targetRect.mVertices[1] = targetRCenter + scale*xBasis - scale*yBasis;
200  targetRect.mVertices[2] = targetRCenter + scale*xBasis + scale*yBasis;
201  targetRect.mVertices[3] = targetRCenter - scale*xBasis + scale*yBasis;
202
203  AddInitialSamples(sourceRect, targetRect, samples);
204
205  //    Plane3 bottomPlane(xBasis, source.Center());
206  //    Plane3 sidePlane(yBasis, source.Center());
207 
208  //    // cast rays between corresponding vertices of the boxes
209  //    for (i=0; i < 8; i++) {
210  //      Vector3 v;
211  //      bool coplanar;
212  //      v = sourcePlane.FindIntersection(source.GetVertex(i),
213  //                                 target.GetVertex(i),
214  //                                 NULL,
215  //                                 &coplanar);
216  //      if (!coplanar) {
217  //        // evaluate source and
218 
219  //      }
220  //    }
221 
222  //  AddInitialSamples(sourceRectangle, targetRectangle, samples);
223}
224
225void
226MutualVisibilitySampler::AddInitialSamples(
227                                           const Rectangle3 &sourceRect,
228                                           const Rectangle3 &targetRect,
229                                           vector<RayShaft *> &samples
230                                           )
231{
232
233  RayShaft *sample = new RayShaft(sourceRect,
234                                  targetRect);
235  samples.push_back(sample);
236}
237
238
239void
240MutualVisibilitySampler::ExportSamples(vector<RayShaft *> &samples)
241{
242  static int id = 0;
243  char filename[64];
244  if (id > 20)
245    return;
246                           
247  for (int i=0; i < samples.size(); i++) {
248    sprintf(filename, "samples%04d-%02d.x3d", id++, i);
249    Exporter *exporter = Exporter::GetExporter(filename);
250
251    exporter->SetWireframe();
252    exporter->ExportBox(mSource);
253    exporter->ExportBox(mTarget);
254
255    exporter->SetFilled();
256
257
258    RayShaft *sample = samples[i];
259    Mesh *mesh = new Mesh;
260    mesh->AddRectangle(sample->mSource);
261    mesh->AddRectangle(sample->mTarget);
262    vector<Ray> rays;
263    for (int j=0; j < 4; j++) {
264      Vector3 origin, direction;
265      sample->GetRay(j, origin, direction);
266      Ray ray(origin, direction, Ray::LINE_SEGMENT);
267      rays.push_back(ray);
268    }
269   
270    Material m = RandomMaterial();
271    exporter->SetForcedMaterial(m);
272    MeshInstance mi(mesh);
273    exporter->ExportIntersectable(&mi);
274    exporter->ExportRays(rays, -1.0f, m.mDiffuseColor);
275    delete exporter;
276  }
277}
278
279int
280MutualVisibilitySampler::CastRays(RayShaft &shaft)
281{
282  Ray ray;
283  int i;
284
285  for (i=0; i < 4; i++) {
286    Vector3 origin, direction;
287    shaft.GetRay(i, origin, direction);
288    // determine intersections with the boxes
289    ray.Init(origin, direction, Ray::LINE_SEGMENT);
290    float stmin, stmax, ttmin, ttmax;
291    if ( mSource.GetMinMaxT(ray, &stmin, &stmax) && mTarget.GetMinMaxT(ray, &ttmin, &ttmax) ) {
292      shaft.mSamples[i].mMinT = stmax;
293      shaft.mSamples[i].mMaxT = ttmin;
294      origin = ray.Extrap(stmax);
295      direction = ray.Extrap(ttmin) - origin;
296      // reinit the ray
297      ray.Init(origin, direction, Ray::LINE_SEGMENT);
298      if (!mKdTree->CastRay(ray))
299        return VISIBLE;
300    } else {
301      shaft.mSamples[i].mMaxT = -1.0;
302    }
303  }
304  return INVISIBLE;
305}
306
307int
308MutualVisibilitySampler::ComputeVisibility()
309{
310
311  vector<RayShaft *> shafts;
312  ConstructInitialSamples(mSource, mTarget, shafts);
313  ExportSamples(shafts);
314
315  stack<RayShaft *> shaftStack;
316 
317 
318 
319  Ray ray;
320  // now process the shafts as long as we have something to do
321  while (!shaftStack.empty()) {
322    RayShaft *shaft = shaftStack.top();
323    shaftStack.pop();
324   
325//      // cast a new ray
326//      int triangleSplitEdge = SetupExtremalRay(sample, source, ray);
327   
328    if (CastRays(*shaft) == VISIBLE)
329      return VISIBLE;
330   
331    //      // generate 2 new samples
332    //      RayShaft newSamples[2];
333    //      sample.Split(triangleSplitEdge, ray, newSamples[0], newSamples[1]);
334    //      for (i=0; i < 2; i++) {
335    //        newSamples[i].ComputeError();
336    //        if (newSamples[i].mError > solidAngleThreshold) {
337    //          sampleStack.push(newSamples[i]);
338    //        }
339    //      }
340    //    }
341  }
342
343  for (int i=0; i < shafts.size(); i++)
344    delete shafts[i];
345  return INVISIBLE;
346}
347
348MutualVisibilitySampler::MutualVisibilitySampler(KdTree *kdTree,
349                                                 AxisAlignedBox3 &source,
350                                                 AxisAlignedBox3 &target,
351                                                 const float solidAngleThreshold)
352{
353  mKdTree = kdTree;
354  mSource = source;
355  mTarget = target;
356  mSolidAngleThreshold = solidAngleThreshold;
357}
358 
359
360int
361ComputeBoxVisibility(KdTree *kdTree,
362                     AxisAlignedBox3 &source,
363                     AxisAlignedBox3 &target,
364                     const float solidAngleThreshold)
365{
366  MutualVisibilitySampler sampler(kdTree, source, target, solidAngleThreshold);
367
368 
369  int visibility = sampler.ComputeVisibility();
370
371  return visibility;
372 
373}
374 
Note: See TracBrowser for help on using the repository browser.