1 | #include <cassert>
|
---|
2 | #include <iostream>
|
---|
3 | #include "AxisAlignedBox3.h"
|
---|
4 | #include "Plane3.h"
|
---|
5 |
|
---|
6 |
|
---|
7 | using namespace std;
|
---|
8 |
|
---|
9 |
|
---|
10 | namespace CHCDemoEngine
|
---|
11 | {
|
---|
12 |
|
---|
13 | // Overload << operator for C++-style output
|
---|
14 | ostream& operator<< (ostream &s, const AxisAlignedBox3 &A)
|
---|
15 | {
|
---|
16 | return s << '[' << A.mMin.x << ", " << A.mMin.y << ", " << A.mMin.z << "]["
|
---|
17 | << A.mMax.x << ", " << A.mMax.y << ", " << A.mMax.z << ']';
|
---|
18 | }
|
---|
19 |
|
---|
20 |
|
---|
21 | // Overload >> operator for C++-style input
|
---|
22 | istream& operator>> (istream &s, AxisAlignedBox3 &A)
|
---|
23 | {
|
---|
24 | char a;
|
---|
25 | // read "[min.x, min.y, min.z][mMax.x, mMax.y, mMax.z]"
|
---|
26 | return s >> a >> A.mMin.x >> a >> A.mMin.y >> a >> A.mMin.z >> a >> a
|
---|
27 | >> A.mMax.x >> a >> A.mMax.y >> a >> A.mMax.z >> a;
|
---|
28 | }
|
---|
29 |
|
---|
30 |
|
---|
31 | AxisAlignedBox3::AxisAlignedBox3()
|
---|
32 | { }
|
---|
33 |
|
---|
34 |
|
---|
35 | AxisAlignedBox3::AxisAlignedBox3(const Vector3 &nMin, const Vector3 &nMax)
|
---|
36 | : mMin(nMin), mMax(nMax)
|
---|
37 | {}
|
---|
38 |
|
---|
39 |
|
---|
40 |
|
---|
41 | bool AxisAlignedBox3::Unbounded() const
|
---|
42 | {
|
---|
43 | return (mMin == Vector3(-MAXFLOAT)) ||
|
---|
44 | (mMax == Vector3(-MAXFLOAT));
|
---|
45 | }
|
---|
46 |
|
---|
47 |
|
---|
48 | void AxisAlignedBox3::Include(const Vector3 &newpt)
|
---|
49 | {
|
---|
50 | Minimize(mMin, newpt);
|
---|
51 | Maximize(mMax, newpt);
|
---|
52 | }
|
---|
53 |
|
---|
54 |
|
---|
55 | void AxisAlignedBox3::Include(const AxisAlignedBox3 &bbox)
|
---|
56 | {
|
---|
57 | Minimize(mMin, bbox.mMin);
|
---|
58 | Maximize(mMax, bbox.mMax);
|
---|
59 | }
|
---|
60 |
|
---|
61 |
|
---|
62 | bool AxisAlignedBox3::IsCorrect()
|
---|
63 | {
|
---|
64 | if ( (mMin.x > mMax.x) ||
|
---|
65 | (mMin.y > mMax.y) ||
|
---|
66 | (mMin.z > mMax.z) )
|
---|
67 | return false; // box is not formed
|
---|
68 | return true;
|
---|
69 | }
|
---|
70 |
|
---|
71 |
|
---|
72 | void AxisAlignedBox3::GetEdge(const int edge, Vector3 *a, Vector3 *b) const
|
---|
73 | {
|
---|
74 | switch(edge) {
|
---|
75 | case 0:
|
---|
76 | a->SetValue(mMin.x, mMin.y, mMin.z);
|
---|
77 | b->SetValue(mMin.x, mMin.y, mMax.z);
|
---|
78 | break;
|
---|
79 | case 1:
|
---|
80 | a->SetValue(mMin.x, mMin.y, mMin.z);
|
---|
81 | b->SetValue(mMin.x, mMax.y, mMin.z);
|
---|
82 | break;
|
---|
83 | case 2:
|
---|
84 | a->SetValue(mMin.x, mMin.y, mMin.z);
|
---|
85 | b->SetValue(mMax.x, mMin.y, mMin.z);
|
---|
86 | break;
|
---|
87 | case 3:
|
---|
88 | a->SetValue(mMax.x, mMax.y, mMax.z);
|
---|
89 | b->SetValue(mMax.x, mMax.y, mMin.z);
|
---|
90 | break;
|
---|
91 | case 4:
|
---|
92 | a->SetValue(mMax.x, mMax.y, mMax.z);
|
---|
93 | b->SetValue(mMax.x, mMin.y, mMax.z);
|
---|
94 | break;
|
---|
95 | case 5:
|
---|
96 | a->SetValue(mMax.x, mMax.y, mMax.z);
|
---|
97 | b->SetValue(mMin.x, mMax.y, mMax.z);
|
---|
98 | break;
|
---|
99 |
|
---|
100 | case 6:
|
---|
101 | a->SetValue(mMin.x, mMin.y, mMax.z);
|
---|
102 | b->SetValue(mMin.x, mMax.y, mMax.z);
|
---|
103 | break;
|
---|
104 | case 7:
|
---|
105 | a->SetValue(mMin.x, mMin.y, mMax.z);
|
---|
106 | b->SetValue(mMax.x, mMin.y, mMax.z);
|
---|
107 | break;
|
---|
108 | case 8:
|
---|
109 | a->SetValue(mMin.x, mMax.y, mMin.z);
|
---|
110 | b->SetValue(mMin.x, mMax.y, mMax.z);
|
---|
111 | break;
|
---|
112 | case 9:
|
---|
113 | a->SetValue(mMin.x, mMax.y, mMin.z);
|
---|
114 | b->SetValue(mMax.x, mMax.y, mMin.z);
|
---|
115 | break;
|
---|
116 | case 10:
|
---|
117 | a->SetValue(mMax.x, mMin.y, mMin.z);
|
---|
118 | b->SetValue(mMax.x, mMax.y, mMin.z);
|
---|
119 | break;
|
---|
120 | case 11:
|
---|
121 | a->SetValue(mMax.x, mMin.y, mMin.z);
|
---|
122 | b->SetValue(mMax.x, mMin.y, mMax.z);
|
---|
123 | break;
|
---|
124 | }
|
---|
125 | }
|
---|
126 |
|
---|
127 | // returns the vertex indices in the range <0..7>, v = 4.x + 2.y + z, where
|
---|
128 | // x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
|
---|
129 | void
|
---|
130 | AxisAlignedBox3::GetEdge(const int edge, int &aIdx, int &bIdx) const
|
---|
131 | {
|
---|
132 | switch(edge) {
|
---|
133 | case 0: aIdx = 0; bIdx = 1; break;
|
---|
134 | case 1: aIdx = 0; bIdx = 2; break;
|
---|
135 | case 2: aIdx = 0; bIdx = 4; break;
|
---|
136 | case 3: aIdx = 7; bIdx = 6; break;
|
---|
137 | case 4: aIdx = 7; bIdx = 5; break;
|
---|
138 | case 5: aIdx = 7; bIdx = 3; break;
|
---|
139 | case 6: aIdx = 1; bIdx = 3; break;
|
---|
140 | case 7: aIdx = 1; bIdx = 5; break;
|
---|
141 | case 8: aIdx = 2; bIdx = 3; break;
|
---|
142 | case 9: aIdx = 2; bIdx = 6; break;
|
---|
143 | case 10: aIdx = 4; bIdx = 6; break;
|
---|
144 | case 11: aIdx = 4; bIdx = 5; break;
|
---|
145 | }
|
---|
146 | }
|
---|
147 |
|
---|
148 | void
|
---|
149 | AxisAlignedBox3::Include(const int &axis, const float &newBound)
|
---|
150 | {
|
---|
151 | switch (axis) {
|
---|
152 | case 0: { // x-axis
|
---|
153 | if (mMin.x > newBound)
|
---|
154 | mMin.x = newBound;
|
---|
155 | if (mMax.x < newBound)
|
---|
156 | mMax.x = newBound;
|
---|
157 | break;
|
---|
158 | }
|
---|
159 | case 1: { // y-axis
|
---|
160 | if (mMin.y > newBound)
|
---|
161 | mMin.y = newBound;
|
---|
162 | if (mMax.y < newBound)
|
---|
163 | mMax.y = newBound;
|
---|
164 | break;
|
---|
165 | }
|
---|
166 | case 2: { // z-axis
|
---|
167 | if (mMin.z > newBound)
|
---|
168 | mMin.z = newBound;
|
---|
169 | if (mMax.z < newBound)
|
---|
170 | mMax.z = newBound;
|
---|
171 | break;
|
---|
172 | }
|
---|
173 | }
|
---|
174 | }
|
---|
175 |
|
---|
176 |
|
---|
177 | void AxisAlignedBox3::Describe(ostream &app, int ind) const
|
---|
178 | {
|
---|
179 | indent(app, ind);
|
---|
180 | app << "AxisAlignedBox3: min at(" << mMin << "), max at(" << mMax << ")\n";
|
---|
181 | }
|
---|
182 |
|
---|
183 | int
|
---|
184 | AxisAlignedBox3::IsInside(const Vector3 &v) const
|
---|
185 | {
|
---|
186 | return ! ((v.x < mMin.x) ||
|
---|
187 | (v.x > mMax.x) ||
|
---|
188 | (v.y < mMin.y) ||
|
---|
189 | (v.y > mMax.y) ||
|
---|
190 | (v.z < mMin.z) ||
|
---|
191 | (v.z > mMax.z));
|
---|
192 | }
|
---|
193 |
|
---|
194 |
|
---|
195 | bool AxisAlignedBox3::Includes(const AxisAlignedBox3 &b) const
|
---|
196 | {
|
---|
197 | return (b.mMin.x >= mMin.x &&
|
---|
198 | b.mMin.y >= mMin.y &&
|
---|
199 | b.mMin.z >= mMin.z &&
|
---|
200 | b.mMax.x <= mMax.x &&
|
---|
201 | b.mMax.y <= mMax.y &&
|
---|
202 | b.mMax.z <= mMax.z);
|
---|
203 | }
|
---|
204 |
|
---|
205 |
|
---|
206 | // compute the coordinates of one vertex of the box
|
---|
207 | Vector3 AxisAlignedBox3::GetVertex(int xAxis, int yAxis, int zAxis) const
|
---|
208 | {
|
---|
209 | Vector3 p;
|
---|
210 | if (xAxis)
|
---|
211 | p.x = mMax.x;
|
---|
212 | else
|
---|
213 | p.x = mMin.x;
|
---|
214 |
|
---|
215 | if (yAxis)
|
---|
216 | p.y = mMax.y;
|
---|
217 | else
|
---|
218 | p.y = mMin.y;
|
---|
219 |
|
---|
220 | if (zAxis)
|
---|
221 | p.z = mMax.z;
|
---|
222 | else
|
---|
223 | p.z = mMin.z;
|
---|
224 | return p;
|
---|
225 | }
|
---|
226 |
|
---|
227 |
|
---|
228 | // compute the vertex for number N = <0..7>, N = 4.x + 2.y + z, where
|
---|
229 | // x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
|
---|
230 | void AxisAlignedBox3::GetVertex(const int N, Vector3 &vertex) const
|
---|
231 | {
|
---|
232 | switch (N)
|
---|
233 | {
|
---|
234 | case 0: vertex = mMin; break;
|
---|
235 | case 1: vertex.SetValue(mMin.x, mMin.y, mMax.z); break;
|
---|
236 | case 2: vertex.SetValue(mMin.x, mMax.y, mMin.z); break;
|
---|
237 | case 3: vertex.SetValue(mMin.x, mMax.y, mMax.z); break;
|
---|
238 | case 4: vertex.SetValue(mMax.x, mMin.y, mMin.z); break;
|
---|
239 | case 5: vertex.SetValue(mMax.x, mMin.y, mMax.z); break;
|
---|
240 | case 6: vertex.SetValue(mMax.x, mMax.y, mMin.z); break;
|
---|
241 | case 7: vertex = mMax; break;
|
---|
242 | default:
|
---|
243 | {
|
---|
244 | cerr << "ERROR in AxisAlignedBox3::GetVertex N=" << N << "\n";
|
---|
245 | }
|
---|
246 | }
|
---|
247 | }
|
---|
248 |
|
---|
249 |
|
---|
250 | float AxisAlignedBox3::SurfaceArea() const
|
---|
251 | {
|
---|
252 | Vector3 ext = mMax - mMin;
|
---|
253 |
|
---|
254 | return 2.0f * (ext.x * ext.y +
|
---|
255 | ext.x * ext.z +
|
---|
256 | ext.y * ext.z);
|
---|
257 | }
|
---|
258 |
|
---|
259 |
|
---|
260 | float AxisAlignedBox3::GetVolume() const
|
---|
261 | {
|
---|
262 | return (mMax.x - mMin.x) * (mMax.y - mMin.y) * (mMax.z - mMin.z);
|
---|
263 | }
|
---|
264 |
|
---|
265 |
|
---|
266 | const int AxisAlignedBox3::bvertices[27][9] =
|
---|
267 | { // region number.. position
|
---|
268 | {5,1,3,2,6,4,-1,-1,-1}, // 0 .. x=0 y=0 z=0
|
---|
269 | {4,5,1,3,2,0,-1,-1,-1}, // 1 .. x=0 y=0 z=1
|
---|
270 | {4,5,7,3,2,0,-1,-1,-1}, // 2 .. x=0 y=0 z=2
|
---|
271 |
|
---|
272 | {0,1,3,2,6,4,-1,-1,-1}, // 3 .. x=0 y=1 z=0
|
---|
273 | {0,1,3,2,-1,-1,-1,-1,-1}, // 4 .. x=0 y=1 z=1
|
---|
274 | {1,5,7,3,2,0,-1,-1,-1}, // 5 .. x=0 y=1 z=2
|
---|
275 |
|
---|
276 | {0,1,3,7,6,4,-1,-1,-1}, // 6 .. x=0 y=2 z=0
|
---|
277 | {0,1,3,7,6,2,-1,-1,-1}, // 7 .. x=0 y=2 z=1
|
---|
278 | {1,5,7,6,2,0,-1,-1,-1}, // 8 .. x=0 y=2 z=2
|
---|
279 |
|
---|
280 | // the regions number <9,17>
|
---|
281 | {5,1,0,2,6,4,-1,-1,-1}, // 9 .. x=1 y=0 z=0
|
---|
282 | {5,1,0,4,-1,-1,-1,-1,-1}, // 10 .. x=1 y=0 z=1
|
---|
283 | {7,3,1,0,4,5,-1,-1,-1}, // 11 .. x=1 y=0 z=2
|
---|
284 |
|
---|
285 | {4,0,2,6,-1,-1,-1,-1,-1}, // 12 .. x=1 y=1 z=0
|
---|
286 | {0,2,3,1,5,4,6,7,-1}, // 13 .. x=1 y=1 z=1 .. inside the box
|
---|
287 | {1,5,7,3,-1,-1,-1,-1,-1}, // 14 .. x=1 y=1 z=2
|
---|
288 |
|
---|
289 | {4,0,2,3,7,6,-1,-1,-1}, // 15 .. x=1 y=2 z=0
|
---|
290 | {6,2,3,7,-1,-1,-1,-1,-1}, // 16 .. x=1 y=2 z=1
|
---|
291 | {1,5,7,6,2,3,-1,-1,-1}, // 17 .. x=1 y=2 z=2
|
---|
292 |
|
---|
293 | // the regions number <18,26>
|
---|
294 | {1,0,2,6,7,5,-1,-1,-1}, // 18 .. x=2 y=0 z=0
|
---|
295 | {1,0,4,6,7,5,-1,-1,-1}, // 19 .. x=2 y=0 z=1
|
---|
296 | {0,4,6,7,3,1,-1,-1,-1}, // 20 .. x=2 y=0 z=2
|
---|
297 |
|
---|
298 | {4,0,2,6,7,5,-1,-1,-1}, // 21 .. x=2 y=1 z=0
|
---|
299 | {5,4,6,7,-1,-1,-1,-1,-1}, // 22 .. x=2 y=1 z=1
|
---|
300 | {5,4,6,7,3,1,-1,-1,-1}, // 23 .. x=2 y=1 z=2
|
---|
301 |
|
---|
302 | {4,0,2,3,7,5,-1,-1,-1}, // 24 .. x=2 y=2 z=0
|
---|
303 | {5,4,6,2,3,7,-1,-1,-1}, // 25 .. x=2 y=2 z=1
|
---|
304 | {5,4,6,2,3,1,-1,-1,-1}, // 26 .. x=2 y=2 z=2
|
---|
305 | };
|
---|
306 |
|
---|
307 | // the visibility of boundary faces from a given region
|
---|
308 | // one to three triples: (axis, min_vertex, max_vertex), axis==-1(terminator)
|
---|
309 | const int AxisAlignedBox3::bfaces[27][10] =
|
---|
310 | { // region number .. position
|
---|
311 | {0,0,3,1,0,5,2,0,6,-1}, // 0 .. x=0 y=0 z=0
|
---|
312 | {0,0,3,1,0,5,-1,-1,-1,-1}, // 1 .. x=0 y=0 z=1
|
---|
313 | {0,0,3,1,0,5,2,1,7,-1}, // 2 .. x=0 y=0 z=2
|
---|
314 |
|
---|
315 | {0,0,3,2,0,6,-1,-1,-1,-1}, // 3 .. x=0 y=1 z=0
|
---|
316 | {0,0,3,-1,-1,-1,-1,-1,-1,-1},// 4 .. x=0 y=1 z=1
|
---|
317 | {0,0,3,2,1,7,-1,-1,-1,-1}, // 5 .. x=0 y=1 z=2
|
---|
318 |
|
---|
319 | {0,0,3,1,2,7,2,0,6,-1}, // 6 .. x=0 y=2 z=0
|
---|
320 | {0,0,3,1,2,7,-1,-1,-1,-1}, // 7 .. x=0 y=2 z=1
|
---|
321 | {0,0,3,1,2,7,2,1,7,-1}, // 8 .. x=0 y=2 z=2
|
---|
322 |
|
---|
323 | // the regions number <9,17>
|
---|
324 | {1,0,5,2,0,6,-1,-1,-1,-1}, // 9 .. x=1 y=0 z=0
|
---|
325 | {1,0,5,-1,-1,-1,-1,-1,-1,-1},// 10 .. x=1 y=0 z=1
|
---|
326 | {1,0,5,2,1,7,-1,-1,-1,-1}, // 11 .. x=1 y=0 z=2
|
---|
327 |
|
---|
328 | {2,0,6,-1,-1,-1,-1,-1,-1,-1},// 12 .. x=1 y=1 z=0
|
---|
329 | {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},// 13 .. x=1 y=1 z=1 .. inside the box
|
---|
330 | {2,1,7,-1,-1,-1,-1,-1,-1,-1},// 14 .. x=1 y=1 z=2
|
---|
331 |
|
---|
332 | {1,2,7,2,0,6,-1,-1,-1,-1}, // 15 .. x=1 y=2 z=0
|
---|
333 | {1,2,7,-1,-1,-1,-1,-1,-1,-1},// 16 .. x=1 y=2 z=1
|
---|
334 | {1,2,7,2,1,7,-1,-1,-1,-1}, // 17 .. x=1 y=2 z=2
|
---|
335 |
|
---|
336 | // the region number <18,26>
|
---|
337 | {0,4,7,1,0,5,2,0,6,-1}, // 18 .. x=2 y=0 z=0
|
---|
338 | {0,4,7,1,0,5,-1,-1,-1,-1}, // 19 .. x=2 y=0 z=1
|
---|
339 | {0,4,7,1,0,5,2,1,7,-1}, // 20 .. x=2 y=0 z=2
|
---|
340 |
|
---|
341 | {0,4,7,2,0,6,-1,-1,-1,-1}, // 21 .. x=2 y=1 z=0
|
---|
342 | {0,4,7,-1,-1,-1,-1,-1,-1,-1},// 22 .. x=2 y=1 z=1
|
---|
343 | {0,4,7,2,1,7,-1,-1,-1,-1}, // 23 .. x=2 y=1 z=2
|
---|
344 |
|
---|
345 | {0,4,7,1,2,7,2,0,6,-1}, // 24 .. x=2 y=2 z=0
|
---|
346 | {0,4,7,1,2,7,-1,-1,-1,-1}, // 25 .. x=2 y=2 z=1
|
---|
347 | {0,4,7,1,2,7,2,1,7,-1}, // 26 .. x=2 y=2 z=2
|
---|
348 | };
|
---|
349 |
|
---|
350 | // the correct corners indexing from entry face to exit face
|
---|
351 | // first index determines entry face, second index exit face, and
|
---|
352 | // the two numbers (indx, inc) determines: ind = the index on the exit
|
---|
353 | // face, when starting from the vertex 0 on entry face, 'inc' is
|
---|
354 | // the increment when we go on entry face in order 0,1,2,3 to create
|
---|
355 | // convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
|
---|
356 | const int AxisAlignedBox3::pairFaceRects[6][6][2] = {
|
---|
357 | { // entry face = 0
|
---|
358 | {-1,0}, // exit face 0 .. no meaning
|
---|
359 | {0,-1}, // 1
|
---|
360 | {0,-1}, // 2
|
---|
361 | {0,1}, // 3 .. opposite face
|
---|
362 | {3,1}, // 4
|
---|
363 | {1,1} // 5
|
---|
364 | },
|
---|
365 | { // entry face = 1
|
---|
366 | {0,-1}, // exit face 0
|
---|
367 | {-1,0}, // 1 .. no meaning
|
---|
368 | {0,-1}, // 2
|
---|
369 | {1,1}, // 3
|
---|
370 | {0,1}, // 4 .. opposite face
|
---|
371 | {3,1} // 5
|
---|
372 | },
|
---|
373 | { // entry face = 2
|
---|
374 | {0,-1}, // 0
|
---|
375 | {0,-1}, // 1
|
---|
376 | {-1,0}, // 2 .. no meaning
|
---|
377 | {3,1}, // 3
|
---|
378 | {1,1}, // 4
|
---|
379 | {0,1} // 5 .. opposite face
|
---|
380 | },
|
---|
381 | { // entry face = 3
|
---|
382 | {0,1}, // 0 .. opposite face
|
---|
383 | {3,-1}, // 1
|
---|
384 | {1,1}, // 2
|
---|
385 | {-1,0}, // 3 .. no meaning
|
---|
386 | {0,-1}, // 4
|
---|
387 | {0,-1} // 5
|
---|
388 | },
|
---|
389 | { // entry face = 4
|
---|
390 | {1,1}, // 0
|
---|
391 | {0,1}, // 1 .. opposite face
|
---|
392 | {3,1}, // 2
|
---|
393 | {0,-1}, // 3
|
---|
394 | {-1,0}, // 4 .. no meaning
|
---|
395 | {0,-1} // 5
|
---|
396 | },
|
---|
397 | { // entry face = 5
|
---|
398 | {3,-1}, // 0
|
---|
399 | {1,1}, // 1
|
---|
400 | {0,1}, // 2 .. opposite face
|
---|
401 | {0,-1}, // 3
|
---|
402 | {0,-1}, // 4
|
---|
403 | {-1,0} // 5 .. no meaning
|
---|
404 | }
|
---|
405 | };
|
---|
406 |
|
---|
407 |
|
---|
408 | // ------------------------------------------------------------
|
---|
409 | // The vertices that form CLOSEST points with respect to the region
|
---|
410 | // for all the regions possible, number of regions is 3^3 = 27,
|
---|
411 | // since two parallel sides of bbox forms three disjoint spaces.
|
---|
412 | // The vertices are given in anti-clockwise order, stopped by value 15,
|
---|
413 | // at most 8 points, at least 1 point.
|
---|
414 | // The table includes the closest 1/2/4/8 points, followed possibly
|
---|
415 | // by the set of coordinates that should be used for testing for
|
---|
416 | // the proximity queries. The coordinates to be tested are described by
|
---|
417 | // the pair (a,b), when a=0, we want to test min vector of the box,
|
---|
418 | // when a=1, we want to test max vector of the box
|
---|
419 | // b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
|
---|
420 | // The sequence is ended by 15, number -1 is used as the separator
|
---|
421 | // between the vertices and coordinates.
|
---|
422 | const int
|
---|
423 | AxisAlignedBox3::cvertices[27][9] =
|
---|
424 | { // region number.. position
|
---|
425 | {0,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D one vertex
|
---|
426 | {0,1,-1,0,0,0,1,15,15}, // 1 .. x=0 y=0 z=1 D two vertices foll. by 2
|
---|
427 | {1,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D one vertex
|
---|
428 |
|
---|
429 | {0,2,-1,0,0,0,2,15,15}, // 3 .. x=0 y=1 z=0 D
|
---|
430 | {0,1,3,2,-1,0,0,15,15}, // 4 .. x=0 y=1 z=1 D
|
---|
431 | {1,3,-1,0,0,1,2,15,15}, // 5 .. x=0 y=1 z=2 D
|
---|
432 |
|
---|
433 | {2,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
|
---|
434 | {2,3,-1,0,0,1,1,15,15}, // 7 .. x=0 y=2 z=1 D
|
---|
435 | {3,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
|
---|
436 |
|
---|
437 | // the regions number <9,17>
|
---|
438 | {0,4,-1,0,1,0,2,15,15}, // 9 .. x=1 y=0 z=0 D
|
---|
439 | {5,1,0,4,-1,0,1,15,15}, // 10 .. x=1 y=0 z=1 D
|
---|
440 | {1,5,-1,0,1,1,2,15,15}, // 11 .. x=1 y=0 z=2 D
|
---|
441 |
|
---|
442 | {4,0,2,6,-1,0,2,15,15}, // 12 .. x=1 y=1 z=0 D
|
---|
443 | {0,2,3,1,5,4,6,7,15}, // 13 .. x=1 y=1 z=1 .. inside the box
|
---|
444 | {1,5,7,3,-1,1,2,15,15}, // 14 .. x=1 y=1 z=2 D
|
---|
445 |
|
---|
446 | {6,2,-1,0,2,1,1,15,15}, // 15 .. x=1 y=2 z=0 D
|
---|
447 | {6,2,3,7,-1,1,1,15,15}, // 16 .. x=1 y=2 z=1 D
|
---|
448 | {3,7,-1,1,1,1,2,15,15}, // 17 .. x=1 y=2 z=2 D
|
---|
449 |
|
---|
450 | // the regions number <18,26>
|
---|
451 | {4,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
|
---|
452 | {4,5,-1,0,1,1,0,15,15}, // 19 .. x=2 y=0 z=1 D
|
---|
453 | {5,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
|
---|
454 |
|
---|
455 | {4,6,-1,0,2,1,0,15,15}, // 21 .. x=2 y=1 z=0 D
|
---|
456 | {5,4,6,7,-1,1,0,15,15}, // 22 .. x=2 y=1 z=1 D
|
---|
457 | {7,5,-1,1,0,1,2,15,15}, // 23 .. x=2 y=1 z=2 D
|
---|
458 |
|
---|
459 | {6,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
|
---|
460 | {6,7,-1,1,0,1,1,15,15}, // 25 .. x=2 y=2 z=1 D
|
---|
461 | {7,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
|
---|
462 | };
|
---|
463 |
|
---|
464 | // Table for Sphere-AABB intersection based on the region knowledge
|
---|
465 | // Similar array to previous cvertices, but we omit the surfaces
|
---|
466 | // which are not necessary for testing. First are vertices,
|
---|
467 | // they are finished with -1. Second, there are indexes in
|
---|
468 | // the pair (a,b), when a=0, we want to test min vector of the box,
|
---|
469 | // when a=1, we want to test max vector of the box
|
---|
470 | // b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
|
---|
471 | //
|
---|
472 | // So either we check the vertices or only the distance in specified
|
---|
473 | // dimensions. There are at all four possible cases:
|
---|
474 | //
|
---|
475 | // 1) we check one vertex - then sequence start with non-negative index
|
---|
476 | // and is finished with 15
|
---|
477 | // 2) we check two coordinates of min/max vector describe by the pair
|
---|
478 | // (a,b) .. a=min/max(0/1) b=x/y/z (0/1/2), sequence starts with 8
|
---|
479 | // and finishes with 15
|
---|
480 | // 3) we check only one coordinate of min/max, as for 2), sequence start
|
---|
481 | // with 9 and ends with 15
|
---|
482 | // 4) Position 13 - sphere is inside the box, intersection always exist
|
---|
483 | // the sequence start with 15 .. no further testing is necessary
|
---|
484 | // in this case
|
---|
485 | const int
|
---|
486 | AxisAlignedBox3::csvertices[27][6] =
|
---|
487 | { // region number.. position
|
---|
488 | {0,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D vertex only
|
---|
489 | {8,0,0,0,1,15}, // 1 .. x=0 y=0 z=1 D two coords.
|
---|
490 | {1,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D vertex only
|
---|
491 |
|
---|
492 | {8,0,0,0,2,15}, // 3 .. x=0 y=1 z=0 D two coords
|
---|
493 | {9,0,0,15,15,15}, // 4 .. x=0 y=1 z=1 D one coord
|
---|
494 | {8,0,0,1,2,15}, // 5 .. x=0 y=1 z=2 D two coords.
|
---|
495 |
|
---|
496 | {2,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D one vertex
|
---|
497 | {8,0,0,1,1,15}, // 7 .. x=0 y=2 z=1 D two coords
|
---|
498 | {3,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D one vertex
|
---|
499 |
|
---|
500 | // the regions number <9,17>
|
---|
501 | {8,0,1,0,2,15}, // 9 .. x=1 y=0 z=0 D two coords
|
---|
502 | {9,0,1,15,15,15}, // 10 .. x=1 y=0 z=1 D one coord
|
---|
503 | {8,0,1,1,2,15}, // 11 .. x=1 y=0 z=2 D two coords
|
---|
504 |
|
---|
505 | {9,0,2,15,15,15}, // 12 .. x=1 y=1 z=0 D one coord
|
---|
506 | {15,15,15,15,15,15}, // 13 .. x=1 y=1 z=1 inside the box, special case/value
|
---|
507 | {9,1,2,15,15,15}, // 14 .. x=1 y=1 z=2 D one corrd
|
---|
508 |
|
---|
509 | {8,0,2,1,1,15}, // 15 .. x=1 y=2 z=0 D two coords
|
---|
510 | {9,1,1,15,15}, // 16 .. x=1 y=2 z=1 D one coord
|
---|
511 | {8,1,1,1,2,15}, // 17 .. x=1 y=2 z=2 D two coords
|
---|
512 |
|
---|
513 | // the regions number <18,26>
|
---|
514 | {4,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D one vertex
|
---|
515 | {8,0,1,1,0,15}, // 19 .. x=2 y=0 z=1 D two coords
|
---|
516 | {5,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D one vertex
|
---|
517 |
|
---|
518 | {8,0,2,1,0,15}, // 21 .. x=2 y=1 z=0 D two coords
|
---|
519 | {9,1,0,15,15,15}, // 22 .. x=2 y=1 z=1 D one coord
|
---|
520 | {8,1,0,1,2,15}, // 23 .. x=2 y=1 z=2 D two coords
|
---|
521 |
|
---|
522 | {6,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D one vertex
|
---|
523 | {8,1,0,1,1,15}, // 25 .. x=2 y=2 z=1 D two coords
|
---|
524 | {7,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D one vertex
|
---|
525 | };
|
---|
526 |
|
---|
527 |
|
---|
528 | // The vertices that form all FARTHEST points with respect to the region
|
---|
529 | // for all the regions possible, number of regions is 3^3 = 27,
|
---|
530 | // since two parallel sides of bbox forms three disjoint spaces.
|
---|
531 | // The vertices are given in anti-clockwise order, stopped by value 15,
|
---|
532 | // at most 8 points, at least 1 point.
|
---|
533 | // For testing, if the AABB is whole in the sphere, it is enough
|
---|
534 | // to test only vertices, either 1,2,4, or 8.
|
---|
535 | const int
|
---|
536 | AxisAlignedBox3::fvertices[27][9] =
|
---|
537 | { // region number.. position
|
---|
538 | {7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D
|
---|
539 | {6,7,15,15,15,15,15,15,15}, // 1 .. x=0 y=0 z=1 D
|
---|
540 | {6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D
|
---|
541 |
|
---|
542 | {5,7,15,15,15,15,15,15,15}, // 3 .. x=0 y=1 z=0 D
|
---|
543 | {4,5,7,6,15,15,15,15,15}, // 4 .. x=0 y=1 z=1 D
|
---|
544 | {4,6,15,15,15,15,15,15,15}, // 5 .. x=0 y=1 z=2 D
|
---|
545 |
|
---|
546 | {5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
|
---|
547 | {4,5,15,15,15,15,15,15,15}, // 7 .. x=0 y=2 z=1 D
|
---|
548 | {4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
|
---|
549 |
|
---|
550 | // the regions number <9,17>
|
---|
551 | {3,7,15,15,15,15,15,15,15}, // 9 .. x=1 y=0 z=0 D
|
---|
552 | {7,3,2,6,15,15,15,15,15}, // 10 .. x=1 y=0 z=1 D
|
---|
553 | {2,6,15,15,15,15,15,15,15}, // 11 .. x=1 y=0 z=2 D
|
---|
554 |
|
---|
555 | {5,1,3,7,15,15,15,15,15}, // 12 .. x=1 y=1 z=0 D
|
---|
556 | {0,7,1,6,3,4,5,2,15}, // 13 .. x=1 y=1 z=1 .. inside the box
|
---|
557 | {0,4,6,2,15,15,15,15,15}, // 14 .. x=1 y=1 z=2 D
|
---|
558 |
|
---|
559 | {5,1,15,15,15,15,15,15,15}, // 15 .. x=1 y=2 z=0 D
|
---|
560 | {4,0,1,5,15,15,15,15,15}, // 16 .. x=1 y=2 z=1 D
|
---|
561 | {4,0,15,15,15,15,15,15,15}, // 17 .. x=1 y=2 z=2 D
|
---|
562 |
|
---|
563 | // the regions number <18,26>
|
---|
564 | {3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
|
---|
565 | {2,3,15,15,15,15,15,15,15}, // 19 .. x=2 y=0 z=1 D
|
---|
566 | {2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
|
---|
567 |
|
---|
568 | {1,3,15,15,15,15,15,15,15}, // 21 .. x=2 y=1 z=0 D
|
---|
569 | {1,0,2,3,15,15,15,15,15}, // 22 .. x=2 y=1 z=1 D
|
---|
570 | {2,0,15,15,15,15,15,15,15}, // 23 .. x=2 y=1 z=2 D
|
---|
571 |
|
---|
572 | {1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
|
---|
573 | {0,1,15,15,15,15,15,15,15}, // 25 .. x=2 y=2 z=1 D
|
---|
574 | {0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
|
---|
575 | };
|
---|
576 |
|
---|
577 | // Similar table as above, farthest points, but only the ones
|
---|
578 | // necessary for testing the intersection problem. If we do
|
---|
579 | // not consider the case 13, center of the sphere is inside the
|
---|
580 | // box, then we can always test at most 2 box vertices to say whether
|
---|
581 | // the whole box is inside the sphere.
|
---|
582 | // The number of vertices is minimized using some assumptions
|
---|
583 | // about the ortogonality of vertices and sphere properties.
|
---|
584 | const int
|
---|
585 | AxisAlignedBox3::fsvertices[27][9] =
|
---|
586 | { // region number.. position
|
---|
587 | {7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D 1 vertex
|
---|
588 | {6,7,15,15,15,15,15,15,15}, // 1 .. x=0 y=0 z=1 D 2 vertices
|
---|
589 | {6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D 1 vertex
|
---|
590 |
|
---|
591 | {5,7,15,15,15,15,15,15,15}, // 3 .. x=0 y=1 z=0 D 2 vertices
|
---|
592 | {4,7,15,5,6,15,15,15,15}, // 4 .. x=0 y=1 z=1 D 4/2 vertices
|
---|
593 | {4,6,15,15,15,15,15,15,15}, // 5 .. x=0 y=1 z=2 D 2 vertices
|
---|
594 |
|
---|
595 | {5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D 1 vertex
|
---|
596 | {4,5,15,15,15,15,15,15,15}, // 7 .. x=0 y=2 z=1 D 2 vertices
|
---|
597 | {4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D 1 vertex
|
---|
598 |
|
---|
599 | // the regions number <9,17>
|
---|
600 | {3,7,15,15,15,15,15,15,15}, // 9 .. x=1 y=0 z=0 D 2 vertices
|
---|
601 | {7,2,15,3,6,15,15,15,15}, // 10 .. x=1 y=0 z=1 D 4/2 vertices
|
---|
602 | {2,6,15,15,15,15,15,15,15}, // 11 .. x=1 y=0 z=2 D 2 vertices
|
---|
603 |
|
---|
604 | {5,3,15,1,7,15,15,15,15}, // 12 .. x=1 y=1 z=0 D 4/2 vertices
|
---|
605 | {0,7,1,6,3,4,5,2,15}, // 13 .. x=1 y=1 z=1 .. inside the box
|
---|
606 | {0,6,15,4,2,15,15,15,15}, // 14 .. x=1 y=1 z=2 D 4/2 vertices
|
---|
607 |
|
---|
608 | {5,1,15,15,15,15,15,15,15}, // 15 .. x=1 y=2 z=0 D 2 vertices
|
---|
609 | {4,1,15,0,5,15,15,15,15}, // 16 .. x=1 y=2 z=1 D 4/2 vertices
|
---|
610 | {4,0,15,15,15,15,15,15,15}, // 17 .. x=1 y=2 z=2 D 2 vertices
|
---|
611 |
|
---|
612 | // the regions number <18,26>
|
---|
613 | {3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D 1 vertex
|
---|
614 | {2,3,15,15,15,15,15,15,15}, // 19 .. x=2 y=0 z=1 D 2 vertices
|
---|
615 | {2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D 1 vertex
|
---|
616 |
|
---|
617 | {1,3,15,15,15,15,15,15,15}, // 21 .. x=2 y=1 z=0 D 2 vertices
|
---|
618 | {1,2,15,0,3,15,15,15,15}, // 22 .. x=2 y=1 z=1 D 4/2 vertices
|
---|
619 | {2,0,15,15,15,15,15,15,15}, // 23 .. x=2 y=1 z=2 D 2 vertices
|
---|
620 |
|
---|
621 | {1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D 1 vertex
|
---|
622 | {0,1,15,15,15,15,15,15,15}, // 25 .. x=2 y=2 z=1 D 2 vertices
|
---|
623 | {0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D 1 vertex
|
---|
624 | };
|
---|
625 |
|
---|
626 |
|
---|
627 | // The fast computation of arctangent .. the maximal error is less
|
---|
628 | // than 4.1 degrees, according to Graphics GEMSII, 1991, pages 389--391
|
---|
629 | // Ron Capelli: "Fast approximation to the arctangent"
|
---|
630 | float atan22(const float& y)
|
---|
631 | {
|
---|
632 | const float x = 1.0;
|
---|
633 | const float c = (float)(M_PI * 0.25);
|
---|
634 |
|
---|
635 | if (y < 0.0) {
|
---|
636 | if (y < -1.0)
|
---|
637 | return c * (-2.0f + x / y); // for angle in <-PI/2, -PI/4)
|
---|
638 | else
|
---|
639 | return c * (y / x); // for angle in <-PI/4 , 0>
|
---|
640 | }
|
---|
641 | else {
|
---|
642 | if (y > 1.0)
|
---|
643 | return c * (2.0f - x / y); // for angle in <PI/4, PI/2>
|
---|
644 | else
|
---|
645 | return c * (y / x); // for angle in <0, PI/2>
|
---|
646 | }
|
---|
647 | }
|
---|
648 |
|
---|
649 |
|
---|
650 | // This definition allows to be a point when answering true
|
---|
651 | bool
|
---|
652 | AxisAlignedBox3::IsCorrectAndNotPoint() const
|
---|
653 | {
|
---|
654 | if ( (mMin.x > mMax.x) ||
|
---|
655 | (mMin.y > mMax.y) ||
|
---|
656 | (mMin.z > mMax.z) )
|
---|
657 | return false; // box is not formed
|
---|
658 |
|
---|
659 | if ( (mMin.x == mMax.x) &&
|
---|
660 | (mMin.y == mMax.y) &&
|
---|
661 | (mMin.z == mMax.z) )
|
---|
662 | return false; // degenerates to a point
|
---|
663 |
|
---|
664 | return true;
|
---|
665 | }
|
---|
666 |
|
---|
667 | // This definition allows to be a point when answering true
|
---|
668 | bool AxisAlignedBox3::IsPoint() const
|
---|
669 | {
|
---|
670 | if ( (mMin.x == mMax.x) &&
|
---|
671 | (mMin.y == mMax.y) &&
|
---|
672 | (mMin.z == mMax.z) )
|
---|
673 | return true; // degenerates to a point
|
---|
674 |
|
---|
675 | return false;
|
---|
676 | }
|
---|
677 |
|
---|
678 | // This definition requires shape of non-zero volume
|
---|
679 | bool AxisAlignedBox3::IsSingularOrIncorrect() const
|
---|
680 | {
|
---|
681 | if ( (mMin.x >= mMax.x) ||
|
---|
682 | (mMin.y >= mMax.y) ||
|
---|
683 | (mMin.z >= mMax.z) )
|
---|
684 | return true; // box is not formed
|
---|
685 |
|
---|
686 | return false; // has non-zero volume
|
---|
687 | }
|
---|
688 |
|
---|
689 |
|
---|
690 | void AxisAlignedBox3::GetSqrDistances(const Vector3 &point,
|
---|
691 | float &minDistance,
|
---|
692 | float &maxDistance) const
|
---|
693 | {
|
---|
694 | // some overlap is possible, check the distance of vertices
|
---|
695 | float sumMin = 0;
|
---|
696 | float sumMax = 0;
|
---|
697 |
|
---|
698 | // Try to minimize the function of a distance
|
---|
699 | // from the sphere center
|
---|
700 |
|
---|
701 | const float *minp = &(mMin.x);
|
---|
702 | const float *maxp = &(mMax.x);
|
---|
703 | const float *pcenter = &(point.x);
|
---|
704 |
|
---|
705 | // for x-axis
|
---|
706 | for (int i = 0; i < 3; i++, minp++, maxp++, pcenter++) {
|
---|
707 | float minsqr = sqr(*minp - *pcenter);
|
---|
708 | float maxsqr = sqr(*maxp - *pcenter);
|
---|
709 | if (*pcenter < *minp)
|
---|
710 | sumMin += minsqr;
|
---|
711 | else
|
---|
712 | if (*pcenter > *maxp)
|
---|
713 | sumMin += maxsqr;
|
---|
714 | sumMax += (minsqr > maxsqr) ? minsqr : maxsqr;
|
---|
715 | }
|
---|
716 |
|
---|
717 | minDistance = sumMin;
|
---|
718 | maxDistance = sumMax;
|
---|
719 | }
|
---|
720 |
|
---|
721 |
|
---|
722 | void AxisAlignedBox3::Scale(const float scale)
|
---|
723 | {
|
---|
724 | Vector3 newSize = Size()*(scale*0.5f);
|
---|
725 | Vector3 center = Center();
|
---|
726 | mMin = center - newSize;
|
---|
727 | mMax = center + newSize;
|
---|
728 | }
|
---|
729 |
|
---|
730 |
|
---|
731 | void AxisAlignedBox3::Scale(const Vector3 &scale)
|
---|
732 | {
|
---|
733 | Vector3 newSize = Size()*(scale*0.5f);
|
---|
734 | Vector3 center = Center();
|
---|
735 | mMin = center - newSize;
|
---|
736 | mMax = center + newSize;
|
---|
737 | }
|
---|
738 |
|
---|
739 |
|
---|
740 | void AxisAlignedBox3::Translate(const Vector3 &shift)
|
---|
741 | {
|
---|
742 | mMin += shift;
|
---|
743 | mMax += shift;
|
---|
744 | }
|
---|
745 |
|
---|
746 |
|
---|
747 | void AxisAlignedBox3::Initialize()
|
---|
748 | {
|
---|
749 | mMin = Vector3(MAXFLOAT);
|
---|
750 | mMax = Vector3(-MAXFLOAT);
|
---|
751 | }
|
---|
752 |
|
---|
753 |
|
---|
754 | Vector3 AxisAlignedBox3::Center() const
|
---|
755 | {
|
---|
756 | return 0.5 * (mMin + mMax);
|
---|
757 | }
|
---|
758 |
|
---|
759 |
|
---|
760 | Vector3 AxisAlignedBox3::Diagonal() const
|
---|
761 | {
|
---|
762 | return (mMax - mMin);
|
---|
763 | }
|
---|
764 |
|
---|
765 |
|
---|
766 | float AxisAlignedBox3::Center(const int axis) const
|
---|
767 | {
|
---|
768 | return 0.5f * (mMin[axis] + mMax[axis]);
|
---|
769 | }
|
---|
770 |
|
---|
771 |
|
---|
772 | float AxisAlignedBox3::Min(const int axis) const
|
---|
773 | {
|
---|
774 | return mMin[axis];
|
---|
775 | }
|
---|
776 |
|
---|
777 |
|
---|
778 | float AxisAlignedBox3::Max(const int axis) const
|
---|
779 | {
|
---|
780 | return mMax[axis];
|
---|
781 | }
|
---|
782 |
|
---|
783 |
|
---|
784 | float AxisAlignedBox3::Size(const int axis) const
|
---|
785 | {
|
---|
786 | return Max(axis) - Min(axis);
|
---|
787 | }
|
---|
788 |
|
---|
789 | // Read-only const access tomMin and max vectors using references
|
---|
790 | const Vector3& AxisAlignedBox3::Min() const
|
---|
791 | {
|
---|
792 | return mMin;
|
---|
793 | }
|
---|
794 |
|
---|
795 |
|
---|
796 | const Vector3& AxisAlignedBox3::Max() const
|
---|
797 | {
|
---|
798 | return mMax;
|
---|
799 | }
|
---|
800 |
|
---|
801 |
|
---|
802 | void AxisAlignedBox3::Enlarge (const Vector3 &v)
|
---|
803 | {
|
---|
804 | mMax += v;
|
---|
805 | mMin -= v;
|
---|
806 | }
|
---|
807 |
|
---|
808 |
|
---|
809 | void AxisAlignedBox3::EnlargeToMinSize()
|
---|
810 | {
|
---|
811 | const float epsMin = 1e-7f;
|
---|
812 | const float epsAdd = 1e-6f;
|
---|
813 | const float epsMul = 1.000005f;
|
---|
814 | float dir = mMax.x - mMin.x;
|
---|
815 |
|
---|
816 | assert(dir >= 0.f);
|
---|
817 |
|
---|
818 | if (dir < epsMin)
|
---|
819 | {
|
---|
820 | if (mMax.x > 0)
|
---|
821 | {
|
---|
822 | mMax.x *= epsMul;
|
---|
823 | mMax.x += epsAdd;
|
---|
824 | }
|
---|
825 | else
|
---|
826 | {
|
---|
827 | mMin.x *= epsMul;
|
---|
828 | mMin.x -= epsAdd;
|
---|
829 | }
|
---|
830 |
|
---|
831 | assert(mMin.x < mMax.x);
|
---|
832 | }
|
---|
833 |
|
---|
834 | dir = mMax.y - mMin.y;
|
---|
835 | assert(dir >= 0.f);
|
---|
836 |
|
---|
837 | if (dir < epsMin)
|
---|
838 | {
|
---|
839 | if (mMax.y > 0)
|
---|
840 | {
|
---|
841 | mMax.y *= epsMul;
|
---|
842 | mMax.y += epsAdd;
|
---|
843 | }
|
---|
844 | else
|
---|
845 | {
|
---|
846 | mMin.y *= epsMul;
|
---|
847 | mMin.y -= epsAdd;
|
---|
848 | }
|
---|
849 | assert(mMin.y < mMax.y);
|
---|
850 | }
|
---|
851 |
|
---|
852 | dir = mMax.z - mMin.z;
|
---|
853 | assert(dir >= 0.f);
|
---|
854 |
|
---|
855 | if (dir < epsMin)
|
---|
856 | {
|
---|
857 | if (mMax.z > 0)
|
---|
858 | {
|
---|
859 | mMax.z *= epsMul;
|
---|
860 | mMax.z += epsAdd;
|
---|
861 | }
|
---|
862 | else
|
---|
863 | {
|
---|
864 | mMin.z *= epsMul;
|
---|
865 | mMin.z -= epsAdd;
|
---|
866 | }
|
---|
867 |
|
---|
868 | assert(mMin.z < mMax.z);
|
---|
869 | }
|
---|
870 | }
|
---|
871 |
|
---|
872 |
|
---|
873 | void AxisAlignedBox3::SetMin(const Vector3 &v)
|
---|
874 | {
|
---|
875 | mMin = v;
|
---|
876 | }
|
---|
877 |
|
---|
878 |
|
---|
879 | void AxisAlignedBox3::SetMax(const Vector3 &v)
|
---|
880 | {
|
---|
881 | mMax = v;
|
---|
882 | }
|
---|
883 |
|
---|
884 |
|
---|
885 | void AxisAlignedBox3::SetMin(int axis, const float value)
|
---|
886 | {
|
---|
887 | mMin[axis] = value;
|
---|
888 | }
|
---|
889 |
|
---|
890 |
|
---|
891 | void AxisAlignedBox3::SetMax(int axis, const float value)
|
---|
892 | {
|
---|
893 | mMax[axis] = value;
|
---|
894 | }
|
---|
895 |
|
---|
896 |
|
---|
897 | // Decrease box by given splitting plane
|
---|
898 | void AxisAlignedBox3::Reduce(int axis, int right, float value)
|
---|
899 | {
|
---|
900 | if ((value >=mMin[axis]) && (value <= mMax[axis]))
|
---|
901 | {
|
---|
902 | if (right)
|
---|
903 | mMin[axis] = value;
|
---|
904 | else
|
---|
905 | mMax[axis] = value;
|
---|
906 | }
|
---|
907 | }
|
---|
908 |
|
---|
909 |
|
---|
910 | Vector3 AxisAlignedBox3::Size() const
|
---|
911 | {
|
---|
912 | return mMax - mMin;
|
---|
913 | }
|
---|
914 |
|
---|
915 |
|
---|
916 | Vector3 AxisAlignedBox3::GetRandomPoint() const
|
---|
917 | {
|
---|
918 | Vector3 size = Size();
|
---|
919 |
|
---|
920 | return mMin + Vector3(RandomValue(0.0f, 1.0f),
|
---|
921 | RandomValue(0.0f, 1.0f),
|
---|
922 | RandomValue(0.0f, 1.0f)) * Size();
|
---|
923 | }
|
---|
924 |
|
---|
925 |
|
---|
926 | bool AxisAlignedBox3::Intersects(const Vector3 &lStart,
|
---|
927 | const Vector3 &lEnd) const
|
---|
928 | {
|
---|
929 | float st, et, fst = 0, fet = 1;
|
---|
930 | float const *bmin = &mMin.x;
|
---|
931 | float const *bmax = &mMax.x;
|
---|
932 | float const *si = &lStart.x;
|
---|
933 | float const *ei = &lEnd.x;
|
---|
934 |
|
---|
935 | for (int i = 0; i < 3; ++ i)
|
---|
936 | {
|
---|
937 | if (*si < *ei)
|
---|
938 | {
|
---|
939 | if (*si > *bmax || *ei < *bmin)
|
---|
940 | return false;
|
---|
941 |
|
---|
942 | const float di = *ei - *si;
|
---|
943 |
|
---|
944 | st = (*si < *bmin)? (*bmin - *si) / di : 0;
|
---|
945 | et = (*ei > *bmax)? (*bmax - *si) / di : 1;
|
---|
946 | }
|
---|
947 | else
|
---|
948 | {
|
---|
949 | if (*ei > *bmax || *si < *bmin)
|
---|
950 | return false;
|
---|
951 |
|
---|
952 | const float di = *ei - *si;
|
---|
953 |
|
---|
954 | st = (*si > *bmax)? (*bmax - *si) / di : 0;
|
---|
955 | et = (*ei < *bmin)? (*bmin - *si) / di : 1;
|
---|
956 | }
|
---|
957 |
|
---|
958 | if (st > fst) fst = st;
|
---|
959 | if (et < fet) fet = et;
|
---|
960 | if (fet < fst)
|
---|
961 | return false;
|
---|
962 |
|
---|
963 | ++ bmin; ++ bmax;
|
---|
964 | ++ si; ++ ei;
|
---|
965 | }
|
---|
966 |
|
---|
967 | //*time = fst;
|
---|
968 | return true;
|
---|
969 | }
|
---|
970 |
|
---|
971 |
|
---|
972 | Vector3 AxisAlignedBox3::GetVertex(const int N) const
|
---|
973 | {
|
---|
974 | Vector3 v;
|
---|
975 | GetVertex(N, v);
|
---|
976 |
|
---|
977 | return v;
|
---|
978 | }
|
---|
979 |
|
---|
980 |
|
---|
981 | float AxisAlignedBox3::GetExtent(int face) const
|
---|
982 | {
|
---|
983 | if (face < 3)
|
---|
984 | return mMin[face];
|
---|
985 | else
|
---|
986 | return mMax[face - 3];
|
---|
987 | }
|
---|
988 |
|
---|
989 |
|
---|
990 | int AxisAlignedBox3::GetIndexNearestVertex(const Vector3 &vecPlaneNormal)
|
---|
991 | {
|
---|
992 | int x, y, z;
|
---|
993 |
|
---|
994 | x = (vecPlaneNormal.x > 0.0f) ? 0 : 1;
|
---|
995 | y = (vecPlaneNormal.y > 0.0f) ? 0 : 1;
|
---|
996 | z = (vecPlaneNormal.z > 0.0f) ? 0 : 1;
|
---|
997 |
|
---|
998 | return 4 * x + 2 * y + z;
|
---|
999 | }
|
---|
1000 |
|
---|
1001 |
|
---|
1002 | int AxisAlignedBox3::GetIndexFarthestVertex(const Vector3 &vecPlaneNormal)
|
---|
1003 | {
|
---|
1004 | int x, y, z;
|
---|
1005 |
|
---|
1006 | x = (vecPlaneNormal.x <= 0.0f) ? 0 : 1;
|
---|
1007 | y = (vecPlaneNormal.y <= 0.0f) ? 0 : 1;
|
---|
1008 | z = (vecPlaneNormal.z <= 0.0f) ? 0 : 1;
|
---|
1009 |
|
---|
1010 | return 4 * x + 2 * y + z;
|
---|
1011 | }
|
---|
1012 |
|
---|
1013 |
|
---|
1014 | float AxisAlignedBox3::GetDistance(int index, const Plane3 &plane) const
|
---|
1015 | {
|
---|
1016 | return plane.Distance(GetVertex(index));
|
---|
1017 | }
|
---|
1018 |
|
---|
1019 |
|
---|
1020 | float AxisAlignedBox3::GetMinVisibleDistance(const Plane3 &near) const
|
---|
1021 | {
|
---|
1022 | return near.mNormal.x * ((near.mNormal.x > 0.0f) ? mMin.x : mMax.x) +
|
---|
1023 | near.mNormal.y * ((near.mNormal.y > 0.0f) ? mMin.y : mMax.y) +
|
---|
1024 | near.mNormal.z * ((near.mNormal.z > 0.0f) ? mMin.z : mMax.z) +
|
---|
1025 | near.mD;
|
---|
1026 | }
|
---|
1027 |
|
---|
1028 | }
|
---|
1029 |
|
---|