doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Box.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../precompiled.h"
30 #pragma hdrstop
31 
33 
34 /*
35  4---{4}---5
36  + /| /|
37  Z {7} {8} {5} |
38  - / | / {9}
39  7--{6}----6 |
40  | | | |
41  {11} 0---|-{0}-1
42  | / | / -
43  | {3} {10} {1} Y
44  |/ |/ +
45  3---{2}---2
46 
47  - X +
48 
49  plane bits:
50  0 = min x
51  1 = max x
52  2 = min y
53  3 = max y
54  4 = min z
55  5 = max z
56 
57 */
58 
59 /*
60 static int boxVertPlanes[8] = {
61  ( (1<<0) | (1<<2) | (1<<4) ),
62  ( (1<<1) | (1<<2) | (1<<4) ),
63  ( (1<<1) | (1<<3) | (1<<4) ),
64  ( (1<<0) | (1<<3) | (1<<4) ),
65  ( (1<<0) | (1<<2) | (1<<5) ),
66  ( (1<<1) | (1<<2) | (1<<5) ),
67  ( (1<<1) | (1<<3) | (1<<5) ),
68  ( (1<<0) | (1<<3) | (1<<5) )
69 };
70 
71 static int boxVertEdges[8][3] = {
72  // bottom
73  { 3, 0, 8 },
74  { 0, 1, 9 },
75  { 1, 2, 10 },
76  { 2, 3, 11 },
77  // top
78  { 7, 4, 8 },
79  { 4, 5, 9 },
80  { 5, 6, 10 },
81  { 6, 7, 11 }
82 };
83 
84 static int boxEdgePlanes[12][2] = {
85  // bottom
86  { 4, 2 },
87  { 4, 1 },
88  { 4, 3 },
89  { 4, 0 },
90  // top
91  { 5, 2 },
92  { 5, 1 },
93  { 5, 3 },
94  { 5, 0 },
95  // sides
96  { 0, 2 },
97  { 2, 1 },
98  { 1, 3 },
99  { 3, 0 }
100 };
101 
102 static int boxEdgeVerts[12][2] = {
103  // bottom
104  { 0, 1 },
105  { 1, 2 },
106  { 2, 3 },
107  { 3, 0 },
108  // top
109  { 4, 5 },
110  { 5, 6 },
111  { 6, 7 },
112  { 7, 4 },
113  // sides
114  { 0, 4 },
115  { 1, 5 },
116  { 2, 6 },
117  { 3, 7 }
118 };
119 */
120 
121 static int boxPlaneBitsSilVerts[64][7] = {
122  { 0, 0, 0, 0, 0, 0, 0 }, // 000000 = 0
123  { 4, 7, 4, 0, 3, 0, 0 }, // 000001 = 1
124  { 4, 5, 6, 2, 1, 0, 0 }, // 000010 = 2
125  { 0, 0, 0, 0, 0, 0, 0 }, // 000011 = 3
126  { 4, 4, 5, 1, 0, 0, 0 }, // 000100 = 4
127  { 6, 3, 7, 4, 5, 1, 0 }, // 000101 = 5
128  { 6, 4, 5, 6, 2, 1, 0 }, // 000110 = 6
129  { 0, 0, 0, 0, 0, 0, 0 }, // 000111 = 7
130  { 4, 6, 7, 3, 2, 0, 0 }, // 001000 = 8
131  { 6, 6, 7, 4, 0, 3, 2 }, // 001001 = 9
132  { 6, 5, 6, 7, 3, 2, 1 }, // 001010 = 10
133  { 0, 0, 0, 0, 0, 0, 0 }, // 001011 = 11
134  { 0, 0, 0, 0, 0, 0, 0 }, // 001100 = 12
135  { 0, 0, 0, 0, 0, 0, 0 }, // 001101 = 13
136  { 0, 0, 0, 0, 0, 0, 0 }, // 001110 = 14
137  { 0, 0, 0, 0, 0, 0, 0 }, // 001111 = 15
138  { 4, 0, 1, 2, 3, 0, 0 }, // 010000 = 16
139  { 6, 0, 1, 2, 3, 7, 4 }, // 010001 = 17
140  { 6, 3, 2, 6, 5, 1, 0 }, // 010010 = 18
141  { 0, 0, 0, 0, 0, 0, 0 }, // 010011 = 19
142  { 6, 1, 2, 3, 0, 4, 5 }, // 010100 = 20
143  { 6, 1, 2, 3, 7, 4, 5 }, // 010101 = 21
144  { 6, 2, 3, 0, 4, 5, 6 }, // 010110 = 22
145  { 0, 0, 0, 0, 0, 0, 0 }, // 010111 = 23
146  { 6, 0, 1, 2, 6, 7, 3 }, // 011000 = 24
147  { 6, 0, 1, 2, 6, 7, 4 }, // 011001 = 25
148  { 6, 0, 1, 5, 6, 7, 3 }, // 011010 = 26
149  { 0, 0, 0, 0, 0, 0, 0 }, // 011011 = 27
150  { 0, 0, 0, 0, 0, 0, 0 }, // 011100 = 28
151  { 0, 0, 0, 0, 0, 0, 0 }, // 011101 = 29
152  { 0, 0, 0, 0, 0, 0, 0 }, // 011110 = 30
153  { 0, 0, 0, 0, 0, 0, 0 }, // 011111 = 31
154  { 4, 7, 6, 5, 4, 0, 0 }, // 100000 = 32
155  { 6, 7, 6, 5, 4, 0, 3 }, // 100001 = 33
156  { 6, 5, 4, 7, 6, 2, 1 }, // 100010 = 34
157  { 0, 0, 0, 0, 0, 0, 0 }, // 100011 = 35
158  { 6, 4, 7, 6, 5, 1, 0 }, // 100100 = 36
159  { 6, 3, 7, 6, 5, 1, 0 }, // 100101 = 37
160  { 6, 4, 7, 6, 2, 1, 0 }, // 100110 = 38
161  { 0, 0, 0, 0, 0, 0, 0 }, // 100111 = 39
162  { 6, 6, 5, 4, 7, 3, 2 }, // 101000 = 40
163  { 6, 6, 5, 4, 0, 3, 2 }, // 101001 = 41
164  { 6, 5, 4, 7, 3, 2, 1 }, // 101010 = 42
165  { 0, 0, 0, 0, 0, 0, 0 }, // 101011 = 43
166  { 0, 0, 0, 0, 0, 0, 0 }, // 101100 = 44
167  { 0, 0, 0, 0, 0, 0, 0 }, // 101101 = 45
168  { 0, 0, 0, 0, 0, 0, 0 }, // 101110 = 46
169  { 0, 0, 0, 0, 0, 0, 0 }, // 101111 = 47
170  { 0, 0, 0, 0, 0, 0, 0 }, // 110000 = 48
171  { 0, 0, 0, 0, 0, 0, 0 }, // 110001 = 49
172  { 0, 0, 0, 0, 0, 0, 0 }, // 110010 = 50
173  { 0, 0, 0, 0, 0, 0, 0 }, // 110011 = 51
174  { 0, 0, 0, 0, 0, 0, 0 }, // 110100 = 52
175  { 0, 0, 0, 0, 0, 0, 0 }, // 110101 = 53
176  { 0, 0, 0, 0, 0, 0, 0 }, // 110110 = 54
177  { 0, 0, 0, 0, 0, 0, 0 }, // 110111 = 55
178  { 0, 0, 0, 0, 0, 0, 0 }, // 111000 = 56
179  { 0, 0, 0, 0, 0, 0, 0 }, // 111001 = 57
180  { 0, 0, 0, 0, 0, 0, 0 }, // 111010 = 58
181  { 0, 0, 0, 0, 0, 0, 0 }, // 111011 = 59
182  { 0, 0, 0, 0, 0, 0, 0 }, // 111100 = 60
183  { 0, 0, 0, 0, 0, 0, 0 }, // 111101 = 61
184  { 0, 0, 0, 0, 0, 0, 0 }, // 111110 = 62
185  { 0, 0, 0, 0, 0, 0, 0 }, // 111111 = 63
186 };
187 
188 
189 /*
190 ============
191 idBox::AddPoint
192 ============
193 */
194 bool idBox::AddPoint( const idVec3 &v ) {
195  idMat3 axis2;
196  idBounds bounds1, bounds2;
197 
198  if ( extents[0] < 0.0f ) {
199  extents.Zero();
200  center = v;
201  axis.Identity();
202  return true;
203  }
204 
205  bounds1[0][0] = bounds1[1][0] = center * axis[0];
206  bounds1[0][1] = bounds1[1][1] = center * axis[1];
207  bounds1[0][2] = bounds1[1][2] = center * axis[2];
208  bounds1[0] -= extents;
209  bounds1[1] += extents;
210  if ( !bounds1.AddPoint( idVec3( v * axis[0], v * axis[1], v * axis[2] ) ) ) {
211  // point is contained in the box
212  return false;
213  }
214 
215  axis2[0] = v - center;
216  axis2[0].Normalize();
217  axis2[1] = axis[ Min3Index( axis2[0] * axis[0], axis2[0] * axis[1], axis2[0] * axis[2] ) ];
218  axis2[1] = axis2[1] - ( axis2[1] * axis2[0] ) * axis2[0];
219  axis2[1].Normalize();
220  axis2[2].Cross( axis2[0], axis2[1] );
221 
222  AxisProjection( axis2, bounds2 );
223  bounds2.AddPoint( idVec3( v * axis2[0], v * axis2[1], v * axis2[2] ) );
224 
225  // create new box based on the smallest bounds
226  if ( bounds1.GetVolume() < bounds2.GetVolume() ) {
227  center = ( bounds1[0] + bounds1[1] ) * 0.5f;
228  extents = bounds1[1] - center;
229  center *= axis;
230  }
231  else {
232  center = ( bounds2[0] + bounds2[1] ) * 0.5f;
233  extents = bounds2[1] - center;
234  center *= axis2;
235  axis = axis2;
236  }
237  return true;
238 }
239 
240 /*
241 ============
242 idBox::AddBox
243 ============
244 */
245 bool idBox::AddBox( const idBox &a ) {
246  int i, besti;
247  float v, bestv;
248  idVec3 dir;
249  idMat3 ax[4];
250  idBounds bounds[4], b;
251 
252  if ( a.extents[0] < 0.0f ) {
253  return false;
254  }
255 
256  if ( extents[0] < 0.0f ) {
257  center = a.center;
258  extents = a.extents;
259  axis = a.axis;
260  return true;
261  }
262 
263  // test axis of this box
264  ax[0] = axis;
265  bounds[0][0][0] = bounds[0][1][0] = center * ax[0][0];
266  bounds[0][0][1] = bounds[0][1][1] = center * ax[0][1];
267  bounds[0][0][2] = bounds[0][1][2] = center * ax[0][2];
268  bounds[0][0] -= extents;
269  bounds[0][1] += extents;
270  a.AxisProjection( ax[0], b );
271  if ( !bounds[0].AddBounds( b ) ) {
272  // the other box is contained in this box
273  return false;
274  }
275 
276  // test axis of other box
277  ax[1] = a.axis;
278  bounds[1][0][0] = bounds[1][1][0] = a.center * ax[1][0];
279  bounds[1][0][1] = bounds[1][1][1] = a.center * ax[1][1];
280  bounds[1][0][2] = bounds[1][1][2] = a.center * ax[1][2];
281  bounds[1][0] -= a.extents;
282  bounds[1][1] += a.extents;
283  AxisProjection( ax[1], b );
284  if ( !bounds[1].AddBounds( b ) ) {
285  // this box is contained in the other box
286  center = a.center;
287  extents = a.extents;
288  axis = a.axis;
289  return true;
290  }
291 
292  // test axes aligned with the vector between the box centers and one of the box axis
293  dir = a.center - center;
294  dir.Normalize();
295  for ( i = 2; i < 4; i++ ) {
296  ax[i][0] = dir;
297  ax[i][1] = ax[i-2][ Min3Index( dir * ax[i-2][0], dir * ax[i-2][1], dir * ax[i-2][2] ) ];
298  ax[i][1] = ax[i][1] - ( ax[i][1] * dir ) * dir;
299  ax[i][1].Normalize();
300  ax[i][2].Cross( dir, ax[i][1] );
301 
302  AxisProjection( ax[i], bounds[i] );
303  a.AxisProjection( ax[i], b );
304  bounds[i].AddBounds( b );
305  }
306 
307  // get the bounds with the smallest volume
308  bestv = idMath::INFINITY;
309  besti = 0;
310  for ( i = 0; i < 4; i++ ) {
311  v = bounds[i].GetVolume();
312  if ( v < bestv ) {
313  bestv = v;
314  besti = i;
315  }
316  }
317 
318  // create a box from the smallest bounds axis pair
319  center = ( bounds[besti][0] + bounds[besti][1] ) * 0.5f;
320  extents = bounds[besti][1] - center;
321  center *= ax[besti];
322  axis = ax[besti];
323 
324  return false;
325 }
326 
327 /*
328 ================
329 idBox::PlaneDistance
330 ================
331 */
332 float idBox::PlaneDistance( const idPlane &plane ) const {
333  float d1, d2;
334 
335  d1 = plane.Distance( center );
336  d2 = idMath::Fabs( extents[0] * plane.Normal()[0] ) +
337  idMath::Fabs( extents[1] * plane.Normal()[1] ) +
338  idMath::Fabs( extents[2] * plane.Normal()[2] );
339 
340  if ( d1 - d2 > 0.0f ) {
341  return d1 - d2;
342  }
343  if ( d1 + d2 < 0.0f ) {
344  return d1 + d2;
345  }
346  return 0.0f;
347 }
348 
349 /*
350 ================
351 idBox::PlaneSide
352 ================
353 */
354 int idBox::PlaneSide( const idPlane &plane, const float epsilon ) const {
355  float d1, d2;
356 
357  d1 = plane.Distance( center );
358  d2 = idMath::Fabs( extents[0] * plane.Normal()[0] ) +
359  idMath::Fabs( extents[1] * plane.Normal()[1] ) +
360  idMath::Fabs( extents[2] * plane.Normal()[2] );
361 
362  if ( d1 - d2 > epsilon ) {
363  return PLANESIDE_FRONT;
364  }
365  if ( d1 + d2 < -epsilon ) {
366  return PLANESIDE_BACK;
367  }
368  return PLANESIDE_CROSS;
369 }
370 
371 /*
372 ============
373 idBox::IntersectsBox
374 ============
375 */
376 bool idBox::IntersectsBox( const idBox &a ) const {
377  idVec3 dir; // vector between centers
378  float c[3][3]; // matrix c = axis.Transpose() * a.axis
379  float ac[3][3]; // absolute values of c
380  float axisdir[3]; // axis[i] * dir
381  float d, e0, e1; // distance between centers and projected extents
382 
383  dir = a.center - center;
384 
385  // axis C0 + t * A0
386  c[0][0] = axis[0] * a.axis[0];
387  c[0][1] = axis[0] * a.axis[1];
388  c[0][2] = axis[0] * a.axis[2];
389  axisdir[0] = axis[0] * dir;
390  ac[0][0] = idMath::Fabs( c[0][0] );
391  ac[0][1] = idMath::Fabs( c[0][1] );
392  ac[0][2] = idMath::Fabs( c[0][2] );
393 
394  d = idMath::Fabs( axisdir[0] );
395  e0 = extents[0];
396  e1 = a.extents[0] * ac[0][0] + a.extents[1] * ac[0][1] + a.extents[2] * ac[0][2];
397  if ( d > e0 + e1 ) {
398  return false;
399  }
400 
401  // axis C0 + t * A1
402  c[1][0] = axis[1] * a.axis[0];
403  c[1][1] = axis[1] * a.axis[1];
404  c[1][2] = axis[1] * a.axis[2];
405  axisdir[1] = axis[1] * dir;
406  ac[1][0] = idMath::Fabs( c[1][0] );
407  ac[1][1] = idMath::Fabs( c[1][1] );
408  ac[1][2] = idMath::Fabs( c[1][2] );
409 
410  d = idMath::Fabs( axisdir[1] );
411  e0 = extents[1];
412  e1 = a.extents[0] * ac[1][0] + a.extents[1] * ac[1][1] + a.extents[2] * ac[1][2];
413  if ( d > e0 + e1 ) {
414  return false;
415  }
416 
417  // axis C0 + t * A2
418  c[2][0] = axis[2] * a.axis[0];
419  c[2][1] = axis[2] * a.axis[1];
420  c[2][2] = axis[2] * a.axis[2];
421  axisdir[2] = axis[2] * dir;
422  ac[2][0] = idMath::Fabs( c[2][0] );
423  ac[2][1] = idMath::Fabs( c[2][1] );
424  ac[2][2] = idMath::Fabs( c[2][2] );
425 
426  d = idMath::Fabs( axisdir[2] );
427  e0 = extents[2];
428  e1 = a.extents[0] * ac[2][0] + a.extents[1] * ac[2][1] + a.extents[2] * ac[2][2];
429  if ( d > e0 + e1 ) {
430  return false;
431  }
432 
433  // axis C0 + t * B0
434  d = idMath::Fabs( a.axis[0] * dir );
435  e0 = extents[0] * ac[0][0] + extents[1] * ac[1][0] + extents[2] * ac[2][0];
436  e1 = a.extents[0];
437  if ( d > e0 + e1 ) {
438  return false;
439  }
440 
441  // axis C0 + t * B1
442  d = idMath::Fabs( a.axis[1] * dir );
443  e0 = extents[0] * ac[0][1] + extents[1] * ac[1][1] + extents[2] * ac[2][1];
444  e1 = a.extents[1];
445  if ( d > e0 + e1 ) {
446  return false;
447  }
448 
449  // axis C0 + t * B2
450  d = idMath::Fabs( a.axis[2] * dir );
451  e0 = extents[0] * ac[0][2] + extents[1] * ac[1][2] + extents[2] * ac[2][2];
452  e1 = a.extents[2];
453  if ( d > e0 + e1 ) {
454  return false;
455  }
456 
457  // axis C0 + t * A0xB0
458  d = idMath::Fabs( axisdir[2] * c[1][0] - axisdir[1] * c[2][0] );
459  e0 = extents[1] * ac[2][0] + extents[2] * ac[1][0];
460  e1 = a.extents[1] * ac[0][2] + a.extents[2] * ac[0][1];
461  if ( d > e0 + e1 ) {
462  return false;
463  }
464 
465  // axis C0 + t * A0xB1
466  d = idMath::Fabs( axisdir[2] * c[1][1] - axisdir[1] * c[2][1] );
467  e0 = extents[1] * ac[2][1] + extents[2] * ac[1][1];
468  e1 = a.extents[0] * ac[0][2] + a.extents[2] * ac[0][0];
469  if ( d > e0 + e1 ) {
470  return false;
471  }
472 
473  // axis C0 + t * A0xB2
474  d = idMath::Fabs( axisdir[2] * c[1][2] - axisdir[1] * c[2][2] );
475  e0 = extents[1] * ac[2][2] + extents[2] * ac[1][2];
476  e1 = a.extents[0] * ac[0][1] + a.extents[1] * ac[0][0];
477  if ( d > e0 + e1 ) {
478  return false;
479  }
480 
481  // axis C0 + t * A1xB0
482  d = idMath::Fabs( axisdir[0] * c[2][0] - axisdir[2] * c[0][0] );
483  e0 = extents[0] * ac[2][0] + extents[2] * ac[0][0];
484  e1 = a.extents[1] * ac[1][2] + a.extents[2] * ac[1][1];
485  if ( d > e0 + e1 ) {
486  return false;
487  }
488 
489  // axis C0 + t * A1xB1
490  d = idMath::Fabs( axisdir[0] * c[2][1] - axisdir[2] * c[0][1] );
491  e0 = extents[0] * ac[2][1] + extents[2] * ac[0][1];
492  e1 = a.extents[0] * ac[1][2] + a.extents[2] * ac[1][0];
493  if ( d > e0 + e1 ) {
494  return false;
495  }
496 
497  // axis C0 + t * A1xB2
498  d = idMath::Fabs( axisdir[0] * c[2][2] - axisdir[2] * c[0][2] );
499  e0 = extents[0] * ac[2][2] + extents[2] * ac[0][2];
500  e1 = a.extents[0] * ac[1][1] + a.extents[1] * ac[1][0];
501  if ( d > e0 + e1 ) {
502  return false;
503  }
504 
505  // axis C0 + t * A2xB0
506  d = idMath::Fabs( axisdir[1] * c[0][0] - axisdir[0] * c[1][0] );
507  e0 = extents[0] * ac[1][0] + extents[1] * ac[0][0];
508  e1 = a.extents[1] * ac[2][2] + a.extents[2] * ac[2][1];
509  if ( d > e0 + e1 ) {
510  return false;
511  }
512 
513  // axis C0 + t * A2xB1
514  d = idMath::Fabs( axisdir[1] * c[0][1] - axisdir[0] * c[1][1] );
515  e0 = extents[0] * ac[1][1] + extents[1] * ac[0][1];
516  e1 = a.extents[0] * ac[2][2] + a.extents[2] * ac[2][0];
517  if ( d > e0 + e1 ) {
518  return false;
519  }
520 
521  // axis C0 + t * A2xB2
522  d = idMath::Fabs( axisdir[1] * c[0][2] - axisdir[0] * c[1][2] );
523  e0 = extents[0] * ac[1][2] + extents[1] * ac[0][2];
524  e1 = a.extents[0] * ac[2][1] + a.extents[1] * ac[2][0];
525  if ( d > e0 + e1 ) {
526  return false;
527  }
528  return true;
529 }
530 
531 /*
532 ============
533 idBox::LineIntersection
534 
535  Returns true if the line intersects the box between the start and end point.
536 ============
537 */
538 bool idBox::LineIntersection( const idVec3 &start, const idVec3 &end ) const {
539  float ld[3];
540  idVec3 lineDir = 0.5f * ( end - start );
541  idVec3 lineCenter = start + lineDir;
542  idVec3 dir = lineCenter - center;
543 
544  ld[0] = idMath::Fabs( lineDir * axis[0] );
545  if ( idMath::Fabs( dir * axis[0] ) > extents[0] + ld[0] ) {
546  return false;
547  }
548 
549  ld[1] = idMath::Fabs( lineDir * axis[1] );
550  if ( idMath::Fabs( dir * axis[1] ) > extents[1] + ld[1] ) {
551  return false;
552  }
553 
554  ld[2] = idMath::Fabs( lineDir * axis[2] );
555  if ( idMath::Fabs( dir * axis[2] ) > extents[2] + ld[2] ) {
556  return false;
557  }
558 
559  idVec3 cross = lineDir.Cross( dir );
560 
561  if ( idMath::Fabs( cross * axis[0] ) > extents[1] * ld[2] + extents[2] * ld[1] ) {
562  return false;
563  }
564 
565  if ( idMath::Fabs( cross * axis[1] ) > extents[0] * ld[2] + extents[2] * ld[0] ) {
566  return false;
567  }
568 
569  if ( idMath::Fabs( cross * axis[2] ) > extents[0] * ld[1] + extents[1] * ld[0] ) {
570  return false;
571  }
572 
573  return true;
574 }
575 
576 /*
577 ============
578 BoxPlaneClip
579 ============
580 */
581 static bool BoxPlaneClip( const float denom, const float numer, float &scale0, float &scale1 ) {
582  if ( denom > 0.0f ) {
583  if ( numer > denom * scale1 ) {
584  return false;
585  }
586  if ( numer > denom * scale0 ) {
587  scale0 = numer / denom;
588  }
589  return true;
590  }
591  else if ( denom < 0.0f ) {
592  if ( numer > denom * scale0 ) {
593  return false;
594  }
595  if ( numer > denom * scale1 ) {
596  scale1 = numer / denom;
597  }
598  return true;
599  }
600  else {
601  return ( numer <= 0.0f );
602  }
603 }
604 
605 /*
606 ============
607 idBox::RayIntersection
608 
609  Returns true if the ray intersects the box.
610  The ray can intersect the box in both directions from the start point.
611  If start is inside the box then scale1 < 0 and scale2 > 0.
612 ============
613 */
614 bool idBox::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const {
615  idVec3 localStart, localDir;
616 
617  localStart = ( start - center ) * axis.Transpose();
618  localDir = dir * axis.Transpose();
619 
620  scale1 = -idMath::INFINITY;
621  scale2 = idMath::INFINITY;
622  return BoxPlaneClip( localDir.x, -localStart.x - extents[0], scale1, scale2 ) &&
623  BoxPlaneClip( -localDir.x, localStart.x - extents[0], scale1, scale2 ) &&
624  BoxPlaneClip( localDir.y, -localStart.y - extents[1], scale1, scale2 ) &&
625  BoxPlaneClip( -localDir.y, localStart.y - extents[1], scale1, scale2 ) &&
626  BoxPlaneClip( localDir.z, -localStart.z - extents[2], scale1, scale2 ) &&
627  BoxPlaneClip( -localDir.z, localStart.z - extents[2], scale1, scale2 );
628 }
629 
630 /*
631 ============
632 idBox::FromPoints
633 
634  Tight box for a collection of points.
635 ============
636 */
637 void idBox::FromPoints( const idVec3 *points, const int numPoints ) {
638  int i;
639  float invNumPoints, sumXX, sumXY, sumXZ, sumYY, sumYZ, sumZZ;
640  idVec3 dir;
641  idBounds bounds;
642  idMatX eigenVectors;
643  idVecX eigenValues;
644 
645  // compute mean of points
646  center = points[0];
647  for ( i = 1; i < numPoints; i++ ) {
648  center += points[i];
649  }
650  invNumPoints = 1.0f / numPoints;
651  center *= invNumPoints;
652 
653  // compute covariances of points
654  sumXX = 0.0f; sumXY = 0.0f; sumXZ = 0.0f;
655  sumYY = 0.0f; sumYZ = 0.0f; sumZZ = 0.0f;
656  for ( i = 0; i < numPoints; i++ ) {
657  dir = points[i] - center;
658  sumXX += dir.x * dir.x;
659  sumXY += dir.x * dir.y;
660  sumXZ += dir.x * dir.z;
661  sumYY += dir.y * dir.y;
662  sumYZ += dir.y * dir.z;
663  sumZZ += dir.z * dir.z;
664  }
665  sumXX *= invNumPoints;
666  sumXY *= invNumPoints;
667  sumXZ *= invNumPoints;
668  sumYY *= invNumPoints;
669  sumYZ *= invNumPoints;
670  sumZZ *= invNumPoints;
671 
672  // compute eigenvectors for covariance matrix
673  eigenValues.SetData( 3, VECX_ALLOCA( 3 ) );
674  eigenVectors.SetData( 3, 3, MATX_ALLOCA( 3 * 3 ) );
675 
676  eigenVectors[0][0] = sumXX;
677  eigenVectors[0][1] = sumXY;
678  eigenVectors[0][2] = sumXZ;
679  eigenVectors[1][0] = sumXY;
680  eigenVectors[1][1] = sumYY;
681  eigenVectors[1][2] = sumYZ;
682  eigenVectors[2][0] = sumXZ;
683  eigenVectors[2][1] = sumYZ;
684  eigenVectors[2][2] = sumZZ;
685  eigenVectors.Eigen_SolveSymmetric( eigenValues );
686  eigenVectors.Eigen_SortIncreasing( eigenValues );
687 
688  axis[0][0] = eigenVectors[0][0];
689  axis[0][1] = eigenVectors[0][1];
690  axis[0][2] = eigenVectors[0][2];
691  axis[1][0] = eigenVectors[1][0];
692  axis[1][1] = eigenVectors[1][1];
693  axis[1][2] = eigenVectors[1][2];
694  axis[2][0] = eigenVectors[2][0];
695  axis[2][1] = eigenVectors[2][1];
696  axis[2][2] = eigenVectors[2][2];
697 
698  extents[0] = eigenValues[0];
699  extents[1] = eigenValues[0];
700  extents[2] = eigenValues[0];
701 
702  // refine by calculating the bounds of the points projected onto the axis and adjusting the center and extents
703  bounds.Clear();
704  for ( i = 0; i < numPoints; i++ ) {
705  bounds.AddPoint( idVec3( points[i] * axis[0], points[i] * axis[1], points[i] * axis[2] ) );
706  }
707  center = ( bounds[0] + bounds[1] ) * 0.5f;
708  extents = bounds[1] - center;
709  center *= axis;
710 }
711 
712 /*
713 ============
714 idBox::FromPointTranslation
715 
716  Most tight box for the translational movement of the given point.
717 ============
718 */
719 void idBox::FromPointTranslation( const idVec3 &point, const idVec3 &translation ) {
720  // FIXME: implement
721 }
722 
723 /*
724 ============
725 idBox::FromBoxTranslation
726 
727  Most tight box for the translational movement of the given box.
728 ============
729 */
730 void idBox::FromBoxTranslation( const idBox &box, const idVec3 &translation ) {
731  // FIXME: implement
732 }
733 
734 /*
735 ============
736 idBox::FromPointRotation
737 
738  Most tight bounds for the rotational movement of the given point.
739 ============
740 */
741 void idBox::FromPointRotation( const idVec3 &point, const idRotation &rotation ) {
742  // FIXME: implement
743 }
744 
745 /*
746 ============
747 idBox::FromBoxRotation
748 
749  Most tight box for the rotational movement of the given box.
750 ============
751 */
752 void idBox::FromBoxRotation( const idBox &box, const idRotation &rotation ) {
753  // FIXME: implement
754 }
755 
756 /*
757 ============
758 idBox::ToPoints
759 ============
760 */
761 void idBox::ToPoints( idVec3 points[8] ) const {
762  idMat3 ax;
763  idVec3 temp[4];
764 
765  ax[0] = extents[0] * axis[0];
766  ax[1] = extents[1] * axis[1];
767  ax[2] = extents[2] * axis[2];
768  temp[0] = center - ax[0];
769  temp[1] = center + ax[0];
770  temp[2] = ax[1] - ax[2];
771  temp[3] = ax[1] + ax[2];
772  points[0] = temp[0] - temp[3];
773  points[1] = temp[1] - temp[3];
774  points[2] = temp[1] + temp[2];
775  points[3] = temp[0] + temp[2];
776  points[4] = temp[0] - temp[2];
777  points[5] = temp[1] - temp[2];
778  points[6] = temp[1] + temp[3];
779  points[7] = temp[0] + temp[3];
780 }
781 
782 /*
783 ============
784 idBox::GetProjectionSilhouetteVerts
785 ============
786 */
787 int idBox::GetProjectionSilhouetteVerts( const idVec3 &projectionOrigin, idVec3 silVerts[6] ) const {
788  float f;
789  int i, planeBits, *index;
790  idVec3 points[8], dir1, dir2;
791 
792  ToPoints( points );
793 
794  dir1 = points[0] - projectionOrigin;
795  dir2 = points[6] - projectionOrigin;
796  f = dir1 * axis[0];
797  planeBits = FLOATSIGNBITNOTSET( f );
798  f = dir2 * axis[0];
799  planeBits |= FLOATSIGNBITSET( f ) << 1;
800  f = dir1 * axis[1];
801  planeBits |= FLOATSIGNBITNOTSET( f ) << 2;
802  f = dir2 * axis[1];
803  planeBits |= FLOATSIGNBITSET( f ) << 3;
804  f = dir1 * axis[2];
805  planeBits |= FLOATSIGNBITNOTSET( f ) << 4;
806  f = dir2 * axis[2];
807  planeBits |= FLOATSIGNBITSET( f ) << 5;
808 
809  index = boxPlaneBitsSilVerts[planeBits];
810  for ( i = 0; i < index[0]; i++ ) {
811  silVerts[i] = points[index[i+1]];
812  }
813 
814  return index[0];
815 }
816 
817 /*
818 ============
819 idBox::GetParallelProjectionSilhouetteVerts
820 ============
821 */
822 int idBox::GetParallelProjectionSilhouetteVerts( const idVec3 &projectionDir, idVec3 silVerts[6] ) const {
823  float f;
824  int i, planeBits, *index;
825  idVec3 points[8];
826 
827  ToPoints( points );
828 
829  planeBits = 0;
830  f = projectionDir * axis[0];
831  if ( FLOATNOTZERO( f ) ) {
832  planeBits = 1 << FLOATSIGNBITSET( f );
833  }
834  f = projectionDir * axis[1];
835  if ( FLOATNOTZERO( f ) ) {
836  planeBits |= 4 << FLOATSIGNBITSET( f );
837  }
838  f = projectionDir * axis[2];
839  if ( FLOATNOTZERO( f ) ) {
840  planeBits |= 16 << FLOATSIGNBITSET( f );
841  }
842 
843  index = boxPlaneBitsSilVerts[planeBits];
844  for ( i = 0; i < index[0]; i++ ) {
845  silVerts[i] = points[index[i+1]];
846  }
847 
848  return index[0];
849 }
bool AddPoint(const idVec3 &v)
Definition: Box.cpp:194
GLsizei const GLfloat * points
Definition: glext.h:3884
bool AddBounds(const idBounds &a)
Definition: Bounds.h:255
static const float INFINITY
Definition: Math.h:218
void FromPointRotation(const idVec3 &point, const idRotation &rotation)
Definition: Box.cpp:741
bool Eigen_SolveSymmetric(idVecX &eigenValues)
Definition: Matrix.cpp:6550
float Normalize(void)
Definition: Vector.h:646
void cross(float a[], float b[], float c[])
Definition: Model_lwo.cpp:3889
const idVec3 & Normal(void) const
Definition: Plane.h:239
idMat3 mat3_identity(idVec3(1, 0, 0), idVec3(0, 1, 0), idVec3(0, 0, 1))
#define FLOATNOTZERO(f)
Definition: Math.h:70
const GLdouble * v
Definition: glext.h:2936
bool AddBox(const idBox &a)
Definition: Box.cpp:245
idMat3 Transpose(void) const
Definition: Matrix.h:677
float Distance(const idVec3 &v) const
Definition: Plane.h:324
idVec3 extents
Definition: Box.h:111
float z
Definition: Vector.h:320
#define VECX_ALLOCA(n)
Definition: Vector.h:1432
Definition: Vector.h:316
void ToPoints(idVec3 points[8]) const
Definition: Box.cpp:761
void Clear(void)
Definition: Bounds.h:201
float GetVolume(void) const
Definition: Bounds.h:215
void Identity(void)
Definition: Matrix.h:591
float x
Definition: Vector.h:318
int i
Definition: process.py:33
void FromBoxTranslation(const idBox &box, const idVec3 &translation)
Definition: Box.cpp:730
void FromPointTranslation(const idVec3 &point, const idVec3 &translation)
Definition: Box.cpp:719
#define PLANESIDE_FRONT
Definition: Plane.h:53
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
#define FLOATSIGNBITSET(f)
Definition: Math.h:68
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
int GetParallelProjectionSilhouetteVerts(const idVec3 &projectionDir, idVec3 silVerts[6]) const
Definition: Box.cpp:822
#define vec3_zero
Definition: Vector.h:390
GLuint GLuint end
Definition: glext.h:2845
static float Fabs(float f)
Definition: Math.h:779
#define PLANESIDE_BACK
Definition: Plane.h:54
#define MATX_ALLOCA(n)
Definition: Matrix.h:1783
float y
Definition: Vector.h:319
Definition: Plane.h:71
idBox box_zero(vec3_zero, vec3_zero, mat3_identity)
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
GLubyte GLubyte b
Definition: glext.h:4662
ID_INLINE int Min3Index(T x, T y, T z)
Definition: Math.h:101
bool IntersectsBox(const idBox &a) const
Definition: Box.cpp:376
Definition: Matrix.h:333
void FromBoxRotation(const idBox &box, const idRotation &rotation)
Definition: Box.cpp:752
tuple f
Definition: idal.py:89
#define FLOATSIGNBITNOTSET(f)
Definition: Math.h:69
idVec3 center
Definition: Box.h:110
void SetData(int rows, int columns, float *data)
Definition: Matrix.h:2278
void SetData(int length, float *data)
Definition: Vector.h:1756
int GetProjectionSilhouetteVerts(const idVec3 &projectionOrigin, idVec3 silVerts[6]) const
Definition: Box.cpp:787
idMat3 axis
Definition: Box.h:112
#define PLANESIDE_CROSS
Definition: Plane.h:56
float PlaneDistance(const idPlane &plane) const
Definition: Box.cpp:332
void Eigen_SortIncreasing(idVecX &eigenValues)
Definition: Matrix.cpp:7088
bool LineIntersection(const idVec3 &start, const idVec3 &end) const
Definition: Box.cpp:538
bool RayIntersection(const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2) const
Definition: Box.cpp:614
void Zero(void)
Definition: Vector.h:415
Definition: Box.h:40
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Box.cpp:354
GLuint start
Definition: glext.h:2845
void FromPoints(const idVec3 *points, const int numPoints)
Definition: Box.cpp:637
void AxisProjection(const idVec3 &dir, float &min, float &max) const
Definition: Box.h:277