Box.cpp 22 KB

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