DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Box.cpp (22712B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition 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 BFG Edition 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 #pragma hdrstop
     30 #include "../precompiled.h"
     31 
     32 idBox box_zero( vec3_zero, vec3_zero, mat3_identity );
     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 = IEEE_FLT_SIGNBITNOTSET( f );
    798 	f = dir2 * axis[0];
    799 	planeBits |= IEEE_FLT_SIGNBITSET( f ) << 1;
    800 	f = dir1 * axis[1];
    801 	planeBits |= IEEE_FLT_SIGNBITNOTSET( f ) << 2;
    802 	f = dir2 * axis[1];
    803 	planeBits |= IEEE_FLT_SIGNBITSET( f ) << 3;
    804 	f = dir1 * axis[2];
    805 	planeBits |= IEEE_FLT_SIGNBITNOTSET( f ) << 4;
    806 	f = dir2 * axis[2];
    807 	planeBits |= IEEE_FLT_SIGNBITSET( 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 ( IEEE_FLT_ISNOTZERO( f ) ) {
    832 		planeBits = 1 << IEEE_FLT_SIGNBITSET( f );
    833 	}
    834 	f = projectionDir * axis[1];
    835 	if ( IEEE_FLT_ISNOTZERO( f ) ) {
    836 		planeBits |= 4 << IEEE_FLT_SIGNBITSET( f );
    837 	}
    838 	f = projectionDir * axis[2];
    839 	if ( IEEE_FLT_ISNOTZERO( f ) ) {
    840 		planeBits |= 16 << IEEE_FLT_SIGNBITSET( 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 }