source: GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.cpp @ 2709

Revision 2709, 6.5 KB checked in by mattausch, 16 years ago (diff)

sheduling dynamic object only when necessary

  • Property svn:executable set to *
Line 
1#include <iostream>
2#include "AxisAlignedBox3.h"
3#include "SepPlanesBox3.h"
4
5#include <cassert>
6using namespace std;
7
8namespace GtpVisibilityPreprocessor {
9
10int
11Side(const Plane3 &pl, const AxisAlignedBox3 &box)
12{
13  // Better implementation than below, takes the
14  // problem as computing the extrema of the function
15  // Written by V.H. in November 2001.
16  float sumMin = pl.mD;
17  float sumMax = pl.mD;
18  const Vector3 &min = box.Min();
19  const Vector3 &max = box.Max();
20
21  // maximize and minimize the value for the function
22  // normal * vertex + d
23 
24  // for x-axis
25  if (pl.mNormal.x >= 0.0) {
26    sumMax += pl.mNormal.x * max.x;
27    sumMin += pl.mNormal.x * min.x;
28  }
29  else {
30    sumMin += pl.mNormal.x * max.x;
31    sumMax += pl.mNormal.x * min.x;
32  }
33 
34  // for y-axis
35  if (pl.mNormal.y >= 0.0) {
36    sumMax += pl.mNormal.y * max.y;
37    sumMin += pl.mNormal.y * min.y;
38  }
39  else {
40    sumMin += pl.mNormal.y * max.y;
41    sumMax += pl.mNormal.y * min.y;
42  }
43 
44  // for z-axis
45  if (pl.mNormal.z >= 0.0) {
46    sumMax += pl.mNormal.z * max.z;
47    sumMin += pl.mNormal.z * min.z;
48  }
49  else {
50    sumMin += pl.mNormal.z * max.z;
51    sumMax += pl.mNormal.z * min.z;
52  }
53 
54  if (sumMax >= 0.0) {
55    if (sumMin >= 0.0)
56      return 1; // box only in positive halfspace
57    return 0; // box is intersected by the plane
58  }
59
60  // sumMax < 0.0
61  assert(sumMin < 0.0);
62 
63  return -1; // box only in the negative halfspace
64}
65
66 
67  // constructor, no planes
68CSeparatingAxisTester::CSeparatingAxisTester()
69{
70  cntPlanes = 0;
71}
72
73void
74CSeparatingAxisTester::InsertPlane(const Plane3 &pl)
75{
76  assert(cntPlanes < 16);
77  planes[cntPlanes].mNormal = pl.mNormal;
78  planes[cntPlanes].mD = pl.mD;
79  cntPlanes++;
80}
81
82void
83CSeparatingAxisTester::OnePhase(const AxisAlignedBox3 &origBox,
84                                const AxisAlignedBox3 &shadBox,
85                                const Vector3 &pointBACKSIDE)
86{
87  Vector3 centerOrig = origBox.Center();
88  Vector3 centerShad = shadBox.Center();
89  const float eps = 1e-3f;
90  int cnt = 0;
91 
92  // We check first for all edges of the 'origBox' and one
93  // vertex of the 'shadBox' existence of the plane.
94  for (int i = 0; i < 12; i++) {
95    Vector3 a,b;
96    // You get one edge from the orig box
97    origBox.GetEdge(i, &a, &b);
98    // Move the vertices a bit outside the box
99    a += eps * (a-centerOrig);
100    b += eps * (b-centerOrig);
101
102    // Now you take all the vertices from the 'shadBox',
103    // which contains a new position of the moved object
104    for (int j = 0; j < 8; j++) {
105      Vector3 c;
106      shadBox.GetVertex(j, c);
107      c += eps * (c-centerShad);
108      Plane3 pl(a, b, c);
109
110      cnt++;
111      // if (cnt == 17) { cout << "Problem " << endl; }
112     
113      int centerFlag = pl.Side(pointBACKSIDE, 1e-6f);
114      if (centerFlag == Plane3:: INTERSECTS)
115        continue; // plane crosses the center of the box!
116     
117      if (centerFlag == Plane3::FRONT_SIDE) {
118        // we have to change the plane orientation
119        pl.mNormal = -pl.mNormal;
120        pl.mD = -pl.mD;
121        centerFlag = Plane3::BACK_SIDE;
122        assert(pl.Side(pointBACKSIDE, 1e-6) == Plane3::BACK_SIDE);
123      }
124
125      // Check if the shad box is on one side of the plane
126      if ((Side(pl, origBox) == Plane3::FRONT_SIDE) &&
127          (Side(pl, shadBox) == Plane3::BACK_SIDE)) {
128        //cout << "Inserting plane normal=" << pl.mNormal
129        //     << " mD=" << pl.mD << endl;
130        InsertPlane(pl);
131      }
132    } // for j
133  } // for i
134}
135
136// brute force separating planes construction algorithm
137void
138CSeparatingAxisTester::Init(const AxisAlignedBox3 &origBox,
139                                                        const AxisAlignedBox3 &shadBox)
140{
141  // test all edges of the axis aligned box
142  Vector3 a,b;
143  const float eps = 1e-3f;
144  Vector3 centerShad = shadBox.Center();
145
146  cntPlanes = 0;
147
148  // First, we check for all edges of the 'origBox' and one
149  // vertex of the 'shadBox' existence of the plane.
150  OnePhase(origBox, shadBox, centerShad);
151
152  // Second, we check for all edges of the 'shadBox' and one
153  // vertex of the 'origBox' existence of the plane.
154  OnePhase(shadBox, origBox, centerShad);
155 
156  // Finally, we add the separating plane, which touches the
157  // 'shadBox', lies between 'origBox' and 'shadBox',
158  // 'origBox' lies in the FRONT_SIDE of this plane, and
159  // 'shadBox' lies in the BACK_SIDE of this plane.
160 
161  Vector3 centerOrig = origBox.Center();
162  Vector3 normal = Normalize(centerOrig - centerShad);
163  // Now we check all the vertices of the shadBox and find the
164  // one closest to the box
165  bool f = false;
166  for (int i = 0; i < 8; i++) {
167    Vector3 c;
168    shadBox.GetVertex(i, c);
169    c += eps * (c-centerShad);
170    Plane3 pl(normal, c);
171    if (Side(pl, shadBox) == -1) {
172      assert(pl.Side(centerShad, 1e-6) == Plane3::BACK_SIDE);
173      //assert(pl.Side(centerOrig, 1e-6) == Plane3::FRONT_SIDE);
174      InsertPlane(pl);
175      f = true;
176      break;
177    }
178  } // for all vertices
179
180  if (!f) {
181    cout << "Problem finding last separating plane" << endl;
182    abort();
183  }
184 
185  return;
186}
187 
188// This function returns true if a ray starting
189// in the 'origBox' and intersecting 'shadBox'
190// can intersect the box as input of this function
191bool
192CSeparatingAxisTester::TestIsInsideShaft(const AxisAlignedBox3 &testBox)
193{
194  for (int i = 0; i < cntPlanes; i++) {
195    if (Side(planes[i], testBox) == Plane3::FRONT_SIDE)
196      // there is such a plane which separates 'origBox' and 'shadBox'
197      // that no ray can intersect all three boxes, starting in 'origBox'
198      return false;
199  }
200
201  // there is a ray intersecting 'origBox', 'shadBox', and 'testBox'
202  // at the same time
203  return true;
204}
205 
206// Testing code
207void
208TestSepAxis()
209{
210  CSeparatingAxisTester st;
211#if 0
212  Vector3 vo1(0, 0, 0);
213  Vector3 vo2(1, 1, 1);
214
215  Vector3 vs1(10, -1, -1);
216  Vector3 vs2(11, 1, 1);
217#else
218  // JB test
219  Vector3 vo1(1279.08, 211.942, -76.4611);
220  Vector3 vo2(1395.34, 215.833, 37.5);
221  Vector3 vs1(-2446.14, 1381.31, -2621.98);
222  Vector3 vs2(-2426.14, 1391.57, -2608.9);
223#endif
224 
225  st.Init(AxisAlignedBox3(vo1, vo2),
226          AxisAlignedBox3(vs1, vs2));
227
228  // Box that should return true
229  Vector3 vt1(10, -1, 1);
230  Vector3 vt2(11, -1, 1);
231  int res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
232  cout << "Res1 = " << res << endl;
233
234  // Box that should return true
235  vt1.SetValue(11, 1, 1);
236  vt2.SetValue(12, 2, 2);
237  res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
238  cout << "Res2 = " << res << endl;
239 
240  // Box that should return false
241  vt1.SetValue(-1, -1, -1);
242  vt2.SetValue(1, 1, 1);
243  res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
244  cout << "Res3 = " << res << endl;
245
246  // Box that should also return false
247  vt1.SetValue(12, 12, 12);
248  vt2.SetValue(13, 13, 13);
249  res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
250  cout << "Res4 = " << res << endl;
251}
252
253}
254
Note: See TracBrowser for help on using the repository browser.