colmathaabtri.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWMath *
  23. * *
  24. * $Archive:: /Commando/Code/wwmath/colmathaabtri.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 5/08/01 9:52a $*
  29. * *
  30. * $Revision:: 17 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * aabtri_separation_test -- test the projected extents for separation *
  35. * aabtri_check_axis -- project the aab and tri onto an arbitrary axis *
  36. * aabtri_check_cross_axis -- projects aab and tri onto a "cross" axis *
  37. * aabtri_check_basis_axis -- projects the aab and tri onto a basis axis *
  38. * aabtri_check_normal_axis -- project the box and tri onto the tri-normal *
  39. * eval_side -- returns -1,0,+1 depending on the sign of val and side *
  40. * aabtri_compute_contact_normal -- computes the normal of the collision *
  41. * CollisionMath::Collide -- collide an aabox into a triangle *
  42. * aabtri_intersect_cross_axis -- intersection check for a "cross-product" axis *
  43. * aabtri_intersect_basis_axis -- intersection check for a basis axis *
  44. * aabtri_intersect_normal_axis -- intersection check for the triangle normal *
  45. * CollisionMath::Intersection_Test -- Intersection check for an AABox and a triangle *
  46. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  47. #include "colmath.h"
  48. #include "aabox.h"
  49. #include "tri.h"
  50. #include "wwdebug.h"
  51. /*
  52. ** Separating Axes have to be rejected if their length is smaller than some epsilon.
  53. ** Otherwise, erroneous results can be reported.
  54. */
  55. #define AXISLEN_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON // squared length of a separating axis must be larger than this
  56. /*
  57. ** Axes used in Box-Tri intersection tests
  58. ** The axes of the box are A0,A1,A2. N is the normal of the triangle,
  59. ** E0,E1,E2 are direction vectors for the edges of the triangle.
  60. ** (the box axes are labeled A0,A1,A2 as a holdover from the obbox-obbox
  61. ** collision code which this was derived from where there are two boxes
  62. ** A and B)
  63. */
  64. enum
  65. {
  66. INTERSECTION = 0,
  67. AXIS_N, // normal of the triangle
  68. AXIS_A0, // first basis vector of the box
  69. AXIS_A1, // second basis vector of the box
  70. AXIS_A2, // third basis vector of the box
  71. AXIS_A0E0, // box0 x edge0...
  72. AXIS_A1E0,
  73. AXIS_A2E0,
  74. AXIS_A0E1,
  75. AXIS_A1E1,
  76. AXIS_A2E1,
  77. AXIS_A0E2,
  78. AXIS_A1E2,
  79. AXIS_A2E2
  80. };
  81. /******************************************************************************************
  82. AABox->Triangle collision
  83. This code is basically a special-case optimization of the OBBox->Triangle collision
  84. detection code. There are many dot and cross products that can be simplified due
  85. to the fact that we know the axes of the boxes are always the same and are aligned
  86. with the world coordinate axes.
  87. Each axis test will use the following logic:
  88. Project D onto the axis being used, it is the separation distance. If the
  89. projection of the extent of the box + the projection of the extent of the
  90. tri is greater than D*axis then the two intersect
  91. March 13, 2000 - Modified these routines to all use a static instance of
  92. the BTCollisionStruct. The compiler was generating lots of extra code for the
  93. constructor of this object and testing determined that re-using the same static
  94. struct was slightly faster anyway.
  95. NOTE: this makes the code not Thread-Safe!!!!
  96. ******************************************************************************************/
  97. /*
  98. ** BoxTriColStruct
  99. ** Scratchpad variables for the AABox-Triangle collision detection functions. One instance
  100. ** of this structure will be used for all of the local variables and its pointer will be
  101. ** handed of to various inline functions for the axis tests.
  102. ** Note that much of the code needs the un-normalized triangle normal. For this reason,
  103. ** I have to compute N rather than copying it from the triangle. (commenting this to
  104. ** avoid re-generating a difficult to find bug that I had)
  105. */
  106. struct BTCollisionStruct
  107. {
  108. BTCollisionStruct(void) {}
  109. void Init(const AABoxClass &box,const Vector3 &move,const TriClass &tri,const Vector3 &trimove)
  110. {
  111. StartBad = true; // true until an axis clears it
  112. MaxFrac = -0.01f; // maximum move allowed so far
  113. AxisId = INTERSECTION; // axis that allowed the longest move
  114. Point = 0; // index of triangle point that was closest to the box
  115. Side = 0; // side of the interval
  116. Box = &box;
  117. Tri = &tri;
  118. BoxMove = &move;
  119. TriMove = &trimove;
  120. Vector3::Subtract(*tri.V[0],box.Center,&D); // vector from center of box to vertex 0
  121. Vector3::Subtract(move,trimove,&Move); // move vector relative to stationary triangle
  122. Vector3::Subtract(*tri.V[1],*tri.V[0],&E[0]);
  123. Vector3::Subtract(*tri.V[2],*tri.V[0],&E[1]);
  124. Vector3::Subtract(E[1],E[0],&E[2]);
  125. Vector3::Cross_Product(E[0],E[1],&N);
  126. }
  127. bool StartBad; // Inital configuration is intersecting?
  128. float MaxFrac; // Longest move allowed so far
  129. int AxisId; // Last separating axis
  130. int Side; // which side of the interval
  131. int Point; // Index of the "closest" triangle point (or one of them)
  132. int TestAxisId; // Axis 'id' we're working on
  133. int TestSide; // Was the axis we're working on flipped
  134. int TestPoint; // Index of the closest vertex
  135. Vector3 TestAxis; // Axis we're working on
  136. Vector3 D; // Vector from the center of the box to v0
  137. Vector3 Move; // Move vector relative to stationary triangle
  138. float AE[3][3]; // Dot products of the Basis vectors and edges
  139. float AN[3]; // Dot products of the Basis vectors and the normal
  140. Vector3 AxE[3][3]; // Cross products of the Basis vectors and edges
  141. Vector3 E[3]; // edge vectors for the triangle
  142. Vector3 N; // normal (NOT normalized!!!)
  143. Vector3 FinalD; // Vector from center of box to v0 at end of move
  144. const AABoxClass * Box;
  145. const TriClass * Tri;
  146. const Vector3 * BoxMove;
  147. const Vector3 * TriMove;
  148. private:
  149. // not implemented
  150. BTCollisionStruct(const BTCollisionStruct &);
  151. BTCollisionStruct & operator = (const BTCollisionStruct &);
  152. };
  153. static BTCollisionStruct CollisionContext;
  154. /***********************************************************************************************
  155. * aabtri_separation_test -- test the projected extents for separation *
  156. * *
  157. * Once the extents are projected onto the axis, this function contains *
  158. * the logic that determines the allowed fraction. *
  159. * *
  160. * INPUT: *
  161. * *
  162. * OUTPUT: *
  163. * *
  164. * WARNINGS: *
  165. * *
  166. * HISTORY: *
  167. * 4/8/99 GTH : Created. *
  168. * 7/12/99 GTH : Converted original OBBox code to AABox *
  169. *=============================================================================================*/
  170. static inline bool aabtri_separation_test
  171. (
  172. float lp,float leb0,float leb1
  173. )
  174. {
  175. /*
  176. ** - If (I'm no more than 'EPSILON' embedded in the wall)
  177. ** - not startbad
  178. ** - If (I'm moving towards)
  179. ** - fraction = How far I can move before embedding (can be negative if started embedded)
  180. ** - If (I can take entire move)
  181. ** - accept entire move
  182. ** - Else If (I can move more than I could have before; *negative always fails!)
  183. ** - update fraction
  184. ** - Else
  185. ** - Accept entire move since I'm not moving towards
  186. */
  187. float eps = 0.0f;
  188. if (lp - leb0 <= 0.0f) {
  189. eps = COLLISION_EPSILON * CollisionContext.TestAxis.Length(); // trying to only compute epsilon if I have to
  190. }
  191. if (lp - leb0 > -eps) {
  192. CollisionContext.StartBad = false;
  193. if (leb1 - leb0 > 0.0f) {
  194. float frac = (lp-leb0)/(leb1-leb0);
  195. if (frac >= 1.0f) {
  196. /* moving toward but not hitting triangle */
  197. CollisionContext.AxisId = CollisionContext.TestAxisId;
  198. CollisionContext.MaxFrac = 1.0f;
  199. return true;
  200. } else {
  201. /* moving toward, hitting triangle */
  202. if (frac > CollisionContext.MaxFrac) {
  203. CollisionContext.MaxFrac = frac;
  204. CollisionContext.AxisId = CollisionContext.TestAxisId;
  205. CollisionContext.Side = CollisionContext.TestSide;
  206. CollisionContext.Point = CollisionContext.TestPoint;
  207. }
  208. }
  209. } else {
  210. /* moving away or not moving */
  211. CollisionContext.AxisId = CollisionContext.TestAxisId;
  212. CollisionContext.MaxFrac = 1.0f;
  213. return true;
  214. }
  215. }
  216. return false;
  217. }
  218. /***********************************************************************************************
  219. * aabtri_check_axis -- project the aab and tri onto an arbitrary axis *
  220. * *
  221. * projects the box and the triangle onto the given axis and calls *
  222. * obbtri_separation_test. return true if separation was detected *
  223. * *
  224. * INPUT: *
  225. * *
  226. * OUTPUT: *
  227. * *
  228. * WARNINGS: *
  229. * *
  230. * HISTORY: *
  231. * 4/8/99 GTH : Created. *
  232. * 7/12/99 GTH : converted to AABox *
  233. *=============================================================================================*/
  234. static inline bool aabtri_check_axis(void)
  235. {
  236. float dist; // separation along the axis
  237. float axismove; // size of the move along the axis.
  238. float leb0; // initial coordinate of the leading edge of the box
  239. float leb1; // final coordinate of the leading edge of the box
  240. float lp; // leading edge of the polygon.
  241. float tmp; // temporary
  242. dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
  243. axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
  244. // I want the axis centered at the box, pointing towards the triangle
  245. if (dist < 0) {
  246. dist = -dist;
  247. axismove = -axismove;
  248. CollisionContext.TestAxis = -CollisionContext.TestAxis;
  249. CollisionContext.TestSide = -1.0f;
  250. } else {
  251. CollisionContext.TestSide = 1.0f;
  252. }
  253. // compute coordinates of the leading edge of the box at t0 and t1
  254. leb0 = CollisionContext.Box->Extent.X * WWMath::Fabs(CollisionContext.TestAxis.X) +
  255. CollisionContext.Box->Extent.Y * WWMath::Fabs(CollisionContext.TestAxis.Y) +
  256. CollisionContext.Box->Extent.Z * WWMath::Fabs(CollisionContext.TestAxis.Z);
  257. leb1 = leb0 + axismove;
  258. // compute coordinate of "leading edge of the triangle" relative to the box center.
  259. lp = 0;
  260. tmp = Vector3::Dot_Product(CollisionContext.E[0],CollisionContext.TestAxis); if (tmp < lp) lp = tmp;
  261. tmp = Vector3::Dot_Product(CollisionContext.E[1],CollisionContext.TestAxis); if (tmp < lp) lp = tmp;
  262. lp = dist + lp;
  263. return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
  264. }
  265. /***********************************************************************************************
  266. * aabtri_check_cross_axis -- projects aab and tri onto a "cross" axis *
  267. * *
  268. * Assumes that the axis given is one generated from a cross product of one of the edge and *
  269. * basis vectors. In this case, the box extent can be optimized and only two triangle verts *
  270. * need to be checked. *
  271. * *
  272. * INPUT: *
  273. * *
  274. * OUTPUT: *
  275. * *
  276. * WARNINGS: *
  277. * *
  278. * HISTORY: *
  279. * 4/8/99 GTH : Created. *
  280. *=============================================================================================*/
  281. static inline bool aabtri_check_cross_axis
  282. (
  283. float dp,
  284. int dpi,
  285. float leb0
  286. )
  287. {
  288. float p0; // distance from box center to vertex 0
  289. float axismove; // size of the move along the axis.
  290. float leb1; // final coordinate of the leading edge of the box
  291. float lp; // leading edge of the polygon.
  292. p0 = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
  293. axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
  294. // I want the axis centered at the box, pointing towards the triangle
  295. if (p0 < 0) {
  296. p0 = -p0;
  297. axismove = -axismove;
  298. dp = -dp;
  299. CollisionContext.TestAxis = -CollisionContext.TestAxis;
  300. CollisionContext.TestSide = -1.0f;
  301. } else {
  302. CollisionContext.TestSide = 1.0f;
  303. }
  304. // compute coordinates of the leading edge of the box at t1
  305. leb1 = leb0 + axismove;
  306. // compute coordinate of "leading edge of the triangle" relative to the box center.
  307. lp = 0; CollisionContext.TestPoint = 0;
  308. if (dp < 0) { lp = dp; CollisionContext.TestPoint = dpi; }
  309. lp = p0 + lp;
  310. return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
  311. }
  312. /***********************************************************************************************
  313. * aabtri_check_basis_axis -- projects the aab and tri onto a basis axis *
  314. * *
  315. * Projects the box and triangle onto an axis that is assumed to be a basis *
  316. * vector from the box. In this case, we can skip a dot-product and use the *
  317. * corresponding extent of the box (which is passed in as leb0). *
  318. * *
  319. * INPUT: *
  320. * *
  321. * OUTPUT: *
  322. * *
  323. * WARNINGS: *
  324. * *
  325. * HISTORY: *
  326. * 4/8/99 GTH : Created. *
  327. *=============================================================================================*/
  328. static inline bool aabtri_check_basis_axis
  329. (
  330. float leb0,
  331. float dp1,
  332. float dp2
  333. )
  334. {
  335. float dist; // separation along the axis
  336. float axismove; // size of the move along the axis.
  337. float leb1; // final coordinate of the leading edge of the box
  338. float lp; // leading edge of the polygon.
  339. dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
  340. axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
  341. // we want the axis centered at the box, pointing towards the triangle
  342. if (dist < 0) {
  343. dist = -dist;
  344. axismove = -axismove;
  345. dp1 = -dp1;
  346. dp2 = -dp2;
  347. CollisionContext.TestAxis = -CollisionContext.TestAxis;
  348. CollisionContext.TestSide = -1.0f;
  349. } else {
  350. CollisionContext.TestSide = 1.0f;
  351. }
  352. // this is the "optimization", leb0 = one of the extents
  353. leb1 = leb0 + axismove;
  354. // compute coordinate of "leading edge of the polygon" relative to the box center.
  355. lp = 0; CollisionContext.TestPoint = 0;
  356. if (dp1 < lp) { lp = dp1; CollisionContext.TestPoint = 1; }
  357. if (dp2 < lp) { lp = dp2; CollisionContext.TestPoint = 2; }
  358. lp = dist + lp;
  359. return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
  360. }
  361. /***********************************************************************************************
  362. * aabtri_check_normal_axis -- project the box and tri onto the tri-normal *
  363. * *
  364. * Projects the box and triangle onto an axis that is assumed to be the normal *
  365. * vector from the triangle. In this case, the triangle extents are zero. *
  366. * *
  367. * INPUT: *
  368. * *
  369. * OUTPUT: *
  370. * *
  371. * WARNINGS: *
  372. * *
  373. * HISTORY: *
  374. * 4/8/99 GTH : Created. *
  375. *=============================================================================================*/
  376. static inline bool aabtri_check_normal_axis(void)
  377. {
  378. float dist; // separation along the axis
  379. float axismove; // size of the move along the axis.
  380. float leb0; // initial coordinate of the leading edge of the box
  381. float leb1; // final coordinate of the leading edge of the box
  382. float lp; // leading edge of the polygon.
  383. dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
  384. axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
  385. // we want the axis centered at the box, pointing towards the triangle
  386. if (dist < 0) {
  387. dist = -dist;
  388. axismove = -axismove;
  389. CollisionContext.TestAxis = -CollisionContext.TestAxis;
  390. CollisionContext.TestSide = -1.0f;
  391. } else {
  392. CollisionContext.TestSide = 1.0f;
  393. }
  394. leb0 = CollisionContext.Box->Extent.X * WWMath::Fabs(CollisionContext.AN[0]) +
  395. CollisionContext.Box->Extent.Y * WWMath::Fabs(CollisionContext.AN[1]) +
  396. CollisionContext.Box->Extent.Z * WWMath::Fabs(CollisionContext.AN[2]);
  397. leb1 = leb0 + axismove;
  398. CollisionContext.TestPoint = 0;
  399. lp = dist; // this is the "optimization", don't have to find lp
  400. return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
  401. }
  402. /***********************************************************************************************
  403. * eval_side -- returns -1,0,+1 depending on the sign of val and side *
  404. * *
  405. * INPUT: *
  406. * *
  407. * OUTPUT: *
  408. * *
  409. * WARNINGS: *
  410. * *
  411. * HISTORY: *
  412. * 4/8/99 GTH : Created. *
  413. *=============================================================================================*/
  414. static inline float eval_side(float val,int side)
  415. {
  416. if (val > 0.0f) {
  417. return side;
  418. } else if (val < 0.0f) {
  419. return -side;
  420. } else {
  421. return 0.0f;
  422. }
  423. }
  424. /***********************************************************************************************
  425. * aabtri_compute_contact_normal -- computes the normal of the collision *
  426. * *
  427. * INPUT: *
  428. * *
  429. * OUTPUT: *
  430. * *
  431. * WARNINGS: *
  432. * *
  433. * HISTORY: *
  434. * 4/8/99 GTH : Created. *
  435. *=============================================================================================*/
  436. static inline void aabtri_compute_contact_normal
  437. (
  438. Vector3 & set_norm
  439. )
  440. {
  441. #if 1
  442. switch(CollisionContext.AxisId)
  443. {
  444. case INTERSECTION:
  445. set_norm = *CollisionContext.Tri->N;
  446. break;
  447. case AXIS_N:
  448. set_norm = -CollisionContext.Side * *CollisionContext.Tri->N;
  449. set_norm.Normalize();
  450. break;
  451. case AXIS_A0:
  452. set_norm = -CollisionContext.Side * Vector3(1.0f,0.0f,0.0f);
  453. break;
  454. case AXIS_A1:
  455. set_norm = -CollisionContext.Side * Vector3(0.0f,1.0f,0.0f);
  456. break;
  457. case AXIS_A2:
  458. set_norm = -CollisionContext.Side * Vector3(0.0f,0.0f,1.0f);
  459. break;
  460. case AXIS_A0E0:
  461. set_norm = -CollisionContext.Side * CollisionContext.AxE[0][0];
  462. set_norm.Normalize();
  463. break;
  464. case AXIS_A1E0:
  465. set_norm = -CollisionContext.Side * CollisionContext.AxE[1][0];
  466. set_norm.Normalize();
  467. break;
  468. case AXIS_A2E0:
  469. set_norm = -CollisionContext.Side * CollisionContext.AxE[2][0];
  470. set_norm.Normalize();
  471. break;
  472. case AXIS_A0E1:
  473. set_norm = -CollisionContext.Side * CollisionContext.AxE[0][1];
  474. set_norm.Normalize();
  475. break;
  476. case AXIS_A1E1:
  477. set_norm = -CollisionContext.Side * CollisionContext.AxE[1][1];
  478. set_norm.Normalize();
  479. break;
  480. case AXIS_A2E1:
  481. set_norm = -CollisionContext.Side * CollisionContext.AxE[2][1];
  482. set_norm.Normalize();
  483. break;
  484. case AXIS_A0E2:
  485. set_norm = -CollisionContext.Side * CollisionContext.AxE[0][2];
  486. set_norm.Normalize();
  487. break;
  488. case AXIS_A1E2:
  489. set_norm = -CollisionContext.Side * CollisionContext.AxE[1][2];
  490. set_norm.Normalize();
  491. break;
  492. case AXIS_A2E2:
  493. set_norm = -CollisionContext.Side * CollisionContext.AxE[2][2];
  494. set_norm.Normalize();
  495. break;
  496. }
  497. WWASSERT(set_norm.Length2() > 0.0f);
  498. #else
  499. set_norm = *CollisionContext.Tri.N;
  500. if (Vector3::Dot_Product(set_norm,CollisionContext.Move) > 0.0f) {
  501. set_norm = -(set_norm);
  502. }
  503. #endif
  504. }
  505. inline void VERIFY_CROSS(const Vector3 & a, const Vector3 & b,const Vector3 & cross)
  506. {
  507. #ifdef WWDEBUG
  508. Vector3 tmp_cross;
  509. Vector3::Cross_Product(a,b,&tmp_cross);
  510. Vector3 diff = cross - tmp_cross;
  511. WWASSERT(WWMath::Fabs(diff.Length()) < 0.0001f);
  512. #endif
  513. }
  514. /***********************************************************************************************
  515. * CollisionMath::Collide -- collide an aabox into a triangle *
  516. * *
  517. * INPUT: *
  518. * *
  519. * OUTPUT: *
  520. * *
  521. * WARNINGS: *
  522. * *
  523. * HISTORY: *
  524. * 4/8/99 GTH : Created. *
  525. *=============================================================================================*/
  526. bool CollisionMath::Collide
  527. (
  528. const AABoxClass & box,
  529. const Vector3 & move,
  530. const TriClass & tri,
  531. CastResultStruct * result
  532. )
  533. {
  534. TRACK_COLLISION_AABOX_TRI;
  535. float dp,leb0;
  536. CollisionContext.Init(box,move,tri,Vector3(0,0,0));
  537. /*
  538. ** AXIS_N
  539. */
  540. CollisionContext.TestAxis = CollisionContext.N;
  541. CollisionContext.TestAxisId = AXIS_N;
  542. CollisionContext.AN[0] = CollisionContext.N.X;
  543. CollisionContext.AN[1] = CollisionContext.N.Y;
  544. CollisionContext.AN[2] = CollisionContext.N.Z;
  545. if (aabtri_check_normal_axis()) goto exit;
  546. /*
  547. ** AXIS_A0
  548. */
  549. CollisionContext.TestAxis.Set(1,0,0);
  550. CollisionContext.TestAxisId = AXIS_A0;
  551. CollisionContext.AE[0][0] = CollisionContext.E[0].X;
  552. CollisionContext.AE[0][1] = CollisionContext.E[1].X;
  553. if (aabtri_check_basis_axis(box.Extent.X,CollisionContext.AE[0][0],CollisionContext.AE[0][1])) goto exit;
  554. /*
  555. ** AXIS_A1
  556. */
  557. CollisionContext.TestAxis.Set(0,1,0);
  558. CollisionContext.TestAxisId = AXIS_A1;
  559. CollisionContext.AE[1][0] = CollisionContext.E[0].Y;
  560. CollisionContext.AE[1][1] = CollisionContext.E[1].Y;
  561. if (aabtri_check_basis_axis(box.Extent.Y,CollisionContext.AE[1][0],CollisionContext.AE[1][1])) goto exit;
  562. /*
  563. ** AXIS_A2
  564. */
  565. CollisionContext.TestAxis.Set(0,0,1);
  566. CollisionContext.TestAxisId = AXIS_A2;
  567. CollisionContext.AE[2][0] = CollisionContext.E[0].Z;
  568. CollisionContext.AE[2][1] = CollisionContext.E[1].Z;
  569. if (aabtri_check_basis_axis(box.Extent.Z,CollisionContext.AE[2][0],CollisionContext.AE[2][1])) goto exit;
  570. /*
  571. ** AXIS_A0xE0
  572. */
  573. CollisionContext.AxE[0][0].Set(0,-CollisionContext.E[0].Z,CollisionContext.E[0].Y);
  574. VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[0],CollisionContext.AxE[0][0]);
  575. CollisionContext.TestAxis = CollisionContext.AxE[0][0];
  576. CollisionContext.TestAxisId = AXIS_A0E0;
  577. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  578. dp = CollisionContext.AN[0];
  579. leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][0]);
  580. if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
  581. }
  582. /*
  583. ** AXIS_A0xE1
  584. */
  585. CollisionContext.AxE[0][1].Set(0,-CollisionContext.E[1].Z,CollisionContext.E[1].Y);
  586. VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[1],CollisionContext.AxE[0][1]);
  587. CollisionContext.TestAxis = CollisionContext.AxE[0][1];
  588. CollisionContext.TestAxisId = AXIS_A0E1;
  589. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  590. dp = -CollisionContext.AN[0];
  591. leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][1]);
  592. if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
  593. }
  594. /*
  595. ** AXIS_A0xE2
  596. */
  597. CollisionContext.AE[0][2] = CollisionContext.E[2].X;
  598. CollisionContext.AE[1][2] = CollisionContext.E[2].Y;
  599. CollisionContext.AE[2][2] = CollisionContext.E[2].Z;
  600. CollisionContext.AxE[0][2].Set(0,-CollisionContext.E[2].Z,CollisionContext.E[2].Y);
  601. VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[2],CollisionContext.AxE[0][2]);
  602. CollisionContext.TestAxis = CollisionContext.AxE[0][2];
  603. CollisionContext.TestAxisId = AXIS_A0E2;
  604. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  605. dp = -CollisionContext.AN[0];
  606. leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][2]);
  607. if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
  608. }
  609. /*
  610. ** AXIS_A1xE0
  611. */
  612. CollisionContext.AxE[1][0].Set(CollisionContext.E[0].Z,0,-CollisionContext.E[0].X);
  613. VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[0],CollisionContext.AxE[1][0]);
  614. CollisionContext.TestAxis = CollisionContext.AxE[1][0];
  615. CollisionContext.TestAxisId = AXIS_A1E0;
  616. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  617. dp = CollisionContext.AN[1];
  618. leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][0]);
  619. if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
  620. }
  621. /*
  622. ** AXIS_A1xE1
  623. */
  624. CollisionContext.AxE[1][1].Set(CollisionContext.E[1].Z,0,-CollisionContext.E[1].X);
  625. VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[1],CollisionContext.AxE[1][1]);
  626. CollisionContext.TestAxis = CollisionContext.AxE[1][1];
  627. CollisionContext.TestAxisId = AXIS_A1E1;
  628. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  629. dp = -CollisionContext.AN[1];
  630. leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][1]);
  631. if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
  632. }
  633. /*
  634. ** AXIS_A1xE2
  635. */
  636. CollisionContext.AxE[1][2].Set(CollisionContext.E[2].Z,0,-CollisionContext.E[2].X);
  637. VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[2],CollisionContext.AxE[1][2]);
  638. CollisionContext.TestAxis = CollisionContext.AxE[1][2];
  639. CollisionContext.TestAxisId = AXIS_A1E2;
  640. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  641. dp = -CollisionContext.AN[1];
  642. leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][2]);
  643. if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
  644. }
  645. /*
  646. ** AXIS_A2xE0
  647. */
  648. CollisionContext.AxE[2][0].Set(-CollisionContext.E[0].Y,CollisionContext.E[0].X,0);
  649. VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[0],CollisionContext.AxE[2][0]);
  650. CollisionContext.TestAxis = CollisionContext.AxE[2][0];
  651. CollisionContext.TestAxisId = AXIS_A2E0;
  652. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  653. dp = CollisionContext.AN[2];
  654. leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][0]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][0]);
  655. if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
  656. }
  657. /*
  658. ** AXIS_A2xE1
  659. */
  660. CollisionContext.AxE[2][1].Set(-CollisionContext.E[1].Y,CollisionContext.E[1].X,0);
  661. VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[1],CollisionContext.AxE[2][1]);
  662. CollisionContext.TestAxis = CollisionContext.AxE[2][1];
  663. CollisionContext.TestAxisId = AXIS_A2E1;
  664. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  665. dp = -CollisionContext.AN[2];
  666. leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][1]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][1]);
  667. if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
  668. }
  669. /*
  670. ** AXIS_A2xE2
  671. */
  672. CollisionContext.AxE[2][2].Set(-CollisionContext.E[2].Y,CollisionContext.E[2].X,0);
  673. VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[2],CollisionContext.AxE[2][2]);
  674. CollisionContext.TestAxis = CollisionContext.AxE[2][2];
  675. CollisionContext.TestAxisId = AXIS_A2E2;
  676. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  677. dp = -CollisionContext.AN[2];
  678. leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][2]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][2]);
  679. if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
  680. }
  681. /*
  682. ** Last ditch effort, check an axis based on the move vector
  683. */
  684. if (!CollisionContext.StartBad) {
  685. CollisionContext.TestPoint = CollisionContext.Point;
  686. CollisionContext.TestAxisId = CollisionContext.AxisId;
  687. CollisionContext.TestAxis.Set(0,-CollisionContext.Move.Z,CollisionContext.Move.Y); // A0 X Move
  688. VERIFY_CROSS(Vector3(1,0,0),CollisionContext.Move,CollisionContext.TestAxis);
  689. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  690. if (aabtri_check_axis()) goto exit;
  691. }
  692. CollisionContext.TestAxis.Set(CollisionContext.Move.Z,0,-CollisionContext.Move.X); // A1 X Move
  693. VERIFY_CROSS(Vector3(0,1,0),CollisionContext.Move,CollisionContext.TestAxis);
  694. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  695. if (aabtri_check_axis()) goto exit;
  696. }
  697. CollisionContext.TestAxis.Set(-CollisionContext.Move.Y,CollisionContext.Move.X,0); // A2 X Move
  698. VERIFY_CROSS(Vector3(0,0,1),CollisionContext.Move,CollisionContext.TestAxis);
  699. if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
  700. if (aabtri_check_axis()) goto exit;
  701. }
  702. }
  703. exit:
  704. /*
  705. ** If MaxFrac is less than zero, clamp it to zero. Negative fractions can
  706. ** leak through this routine due to the epsilon in the separation test.
  707. */
  708. if (CollisionContext.MaxFrac < 0.0f) {
  709. CollisionContext.MaxFrac = 0.0f;
  710. }
  711. /*
  712. ** If the triangle and box are intersecting before the move, return that
  713. ** result.
  714. */
  715. if (CollisionContext.StartBad) {
  716. result->StartBad = true;
  717. result->Fraction = 0.0f;
  718. result->Normal = *tri.N;
  719. TRACK_COLLISION_AABOX_TRI_HIT;
  720. return true;
  721. }
  722. /*
  723. ** If the fraction allowed is basically equal to the fraction allowed by
  724. ** another polygon, try to pick the polygon which is least "edge-on" to the
  725. ** move.
  726. */
  727. if ((CollisionContext.MaxFrac <= result->Fraction) && (CollisionContext.MaxFrac < 1.0f)) {
  728. /*
  729. ** Reflect the normal if it is pointing the same way as our move
  730. ** (probably hitting the back side of a polygon)
  731. */
  732. Vector3 tmp_norm(0.0f,0.0f,0.0f);
  733. aabtri_compute_contact_normal(tmp_norm);
  734. // if (Vector3::Dot_Product(tmp_norm,move) > 0.0f) {
  735. // tmp_norm = -tmp_norm;
  736. // }
  737. /*
  738. ** If this polygon cuts off more of the move -OR- this polygon cuts
  739. ** of the same amount but has a "better" normal, then use this normal
  740. */
  741. if ( (WWMath::Fabs(CollisionContext.MaxFrac - result->Fraction) > WWMATH_EPSILON) ||
  742. (Vector3::Dot_Product(tmp_norm,move) < Vector3::Dot_Product(result->Normal,move)))
  743. {
  744. result->Normal = tmp_norm;
  745. #pragma message("fatal assert disabled for demo")
  746. //WWASSERT(WWMath::Fabs(result->Normal.Length() - 1.0f) < WWMATH_EPSILON);
  747. }
  748. result->Fraction = CollisionContext.MaxFrac;
  749. TRACK_COLLISION_AABOX_TRI_HIT;
  750. return true;
  751. }
  752. return false;
  753. }
  754. /*
  755. ** AABTIntersectStruct
  756. ** Scratchpad variables for the AABox-Triangle intersection functions. One instance
  757. ** of this structure will be used for all of the local variables and its pointer will be
  758. ** handed of to various inline functions for the axis tests.
  759. ** Note that much of the code needs the un-normalized triangle normal. For this reason,
  760. ** I have to compute N rather than copying it from the triangle. (commenting this to
  761. ** avoid re-generating a difficult to find bug that I had)
  762. */
  763. struct AABTIntersectStruct
  764. {
  765. AABTIntersectStruct(void) :
  766. Box(NULL),
  767. Tri(NULL)
  768. {
  769. }
  770. void Init(const AABoxClass &box,const TriClass &tri)
  771. {
  772. Box = &box;
  773. Tri = &tri;
  774. Vector3::Subtract(*tri.V[0],box.Center,&D); // vector from center of box to vertex 0
  775. Vector3::Subtract(*tri.V[1],*tri.V[0],&E[0]);
  776. Vector3::Subtract(*tri.V[2],*tri.V[0],&E[1]);
  777. Vector3::Subtract(E[1],E[0],&E[2]);
  778. Vector3::Cross_Product(E[0],E[1],&N);
  779. }
  780. Vector3 D; // Vector from the center of the box to v0
  781. float AE[3][3]; // Dot products of the Basis vectors and edges
  782. float AN[3]; // Dot products of the Basis vectors and the normal
  783. Vector3 AxE[3][3]; // Cross produts of the Basis vectors and edges
  784. Vector3 E[3]; // edge vectors for the triangle
  785. Vector3 N; // normal (NOT normalized!!!)
  786. const AABoxClass * Box;
  787. const TriClass * Tri;
  788. private:
  789. // not implemented
  790. AABTIntersectStruct(const AABTIntersectStruct &);
  791. AABTIntersectStruct & operator = (const AABTIntersectStruct &);
  792. };
  793. static AABTIntersectStruct IntersectContext;
  794. /***********************************************************************************************
  795. * aabtri_intersect_cross_axis -- intersection check for a "cross-product" axis *
  796. * *
  797. * axis being checked is a cross product between a triangle edge and a box basis vector *
  798. * *
  799. * INPUT: *
  800. * *
  801. * OUTPUT: *
  802. * *
  803. * WARNINGS: *
  804. * *
  805. * HISTORY: *
  806. * 5/4/99 GTH : Created. *
  807. *=============================================================================================*/
  808. static inline bool aabtri_intersect_cross_axis
  809. (
  810. Vector3 & axis,
  811. float dp,
  812. float leb0
  813. )
  814. {
  815. float p0; // distance from box center to vertex 0
  816. float lp; // leading edge of the polygon.
  817. p0 = Vector3::Dot_Product(IntersectContext.D,axis);
  818. // I want the axis centered at the box, pointing towards the triangle
  819. if (p0 < 0) {
  820. p0 = -p0;
  821. axis = -axis;
  822. dp = -dp;
  823. }
  824. // compute coordinate of "leading edge of the triangle" relative to the box center.
  825. lp = 0;
  826. if (dp < 0) { lp = dp; }
  827. lp = p0 + lp;
  828. return (lp - leb0 > -WWMATH_EPSILON);
  829. }
  830. /***********************************************************************************************
  831. * aabtri_intersect_basis_axis -- intersection check for a basis axis *
  832. * *
  833. * axis being checked is one of the basis vectors for the box *
  834. * *
  835. * INPUT: *
  836. * *
  837. * OUTPUT: *
  838. * *
  839. * WARNINGS: *
  840. * *
  841. * HISTORY: *
  842. * 5/4/99 GTH : Created. *
  843. *=============================================================================================*/
  844. static inline bool aabtri_intersect_basis_axis
  845. (
  846. Vector3 & axis,
  847. float leb0,
  848. float dp1,
  849. float dp2
  850. )
  851. {
  852. float dist; // separation along the axis
  853. float lp; // leading edge of the polygon.
  854. dist = Vector3::Dot_Product(IntersectContext.D,axis);
  855. // we want the axis centered at the box, pointing towards the triangle
  856. if (dist < 0) {
  857. dist = -dist;
  858. axis = -axis;
  859. dp1 = -dp1;
  860. dp2 = -dp2;
  861. }
  862. // compute coordinate of "leading edge of the polygon" relative to the box center.
  863. lp = 0;
  864. if (dp1 < lp) { lp = dp1; }
  865. if (dp2 < lp) { lp = dp2; }
  866. lp = dist + lp;
  867. return (lp - leb0 > -WWMATH_EPSILON);
  868. }
  869. /***********************************************************************************************
  870. * aabtri_intersect_normal_axis -- intersection check for the triangle normal *
  871. * *
  872. * axis being checked is the triangle's normal *
  873. * *
  874. * INPUT: *
  875. * *
  876. * OUTPUT: *
  877. * *
  878. * WARNINGS: *
  879. * *
  880. * HISTORY: *
  881. * 5/4/99 GTH : Created. *
  882. *=============================================================================================*/
  883. static inline bool aabtri_intersect_normal_axis
  884. (
  885. Vector3 & axis
  886. )
  887. {
  888. float dist; // separation along the axis
  889. float leb0; // initial coordinate of the leading edge of the box
  890. float lp; // leading edge of the polygon.
  891. dist = Vector3::Dot_Product(IntersectContext.D,axis);
  892. // we want the axis centered at the box, pointing towards the triangle
  893. if (dist < 0) {
  894. dist = -dist;
  895. axis = -axis;
  896. }
  897. leb0 = IntersectContext.Box->Extent.X * WWMath::Fabs(IntersectContext.AN[0]) +
  898. IntersectContext.Box->Extent.Y * WWMath::Fabs(IntersectContext.AN[1]) +
  899. IntersectContext.Box->Extent.Z * WWMath::Fabs(IntersectContext.AN[2]);
  900. lp = dist; // this is the "optimization", don't have to find lp
  901. return (lp - leb0 > -WWMATH_EPSILON);
  902. }
  903. /***********************************************************************************************
  904. * CollisionMath::Intersection_Test -- Intersection check for an AABox and a triangle *
  905. * *
  906. * INPUT: *
  907. * *
  908. * OUTPUT: *
  909. * *
  910. * WARNINGS: *
  911. * *
  912. * HISTORY: *
  913. * 1/20/00 gth : copied from OBBox version and removed some Dot-products *
  914. *=============================================================================================*/
  915. bool CollisionMath::Intersection_Test(const AABoxClass & box,const TriClass & tri)
  916. {
  917. Vector3 axis;
  918. float dp,leb0;
  919. IntersectContext.Init(box,tri);
  920. /*
  921. ** AXIS_N
  922. */
  923. axis = IntersectContext.N;
  924. IntersectContext.AN[0] = IntersectContext.N.X;
  925. IntersectContext.AN[1] = IntersectContext.N.Y;
  926. IntersectContext.AN[2] = IntersectContext.N.Z;
  927. if (aabtri_intersect_normal_axis(axis)) return false;
  928. /*
  929. ** AXIS_A0
  930. */
  931. axis.Set(1,0,0);
  932. IntersectContext.AE[0][0] = IntersectContext.E[0].X;
  933. IntersectContext.AE[0][1] = IntersectContext.E[1].Y;
  934. if (aabtri_intersect_basis_axis(axis,box.Extent.X,IntersectContext.AE[0][0],IntersectContext.AE[0][1])) return false;
  935. /*
  936. ** AXIS_A1
  937. */
  938. axis.Set(0,1,0);
  939. IntersectContext.AE[1][0] = IntersectContext.E[0].Y;
  940. IntersectContext.AE[1][1] = IntersectContext.E[1].Y;
  941. if (aabtri_intersect_basis_axis(axis,box.Extent.Y,IntersectContext.AE[1][0],IntersectContext.AE[1][1])) return false;
  942. /*
  943. ** AXIS_A2
  944. */
  945. axis.Set(0,0,1);
  946. IntersectContext.AE[2][0] = IntersectContext.E[0].Z;
  947. IntersectContext.AE[2][1] = IntersectContext.E[1].Z;
  948. if (aabtri_intersect_basis_axis(axis,box.Extent.Z,IntersectContext.AE[2][0],IntersectContext.AE[2][1])) return false;
  949. /*
  950. ** AXIS_A0xE0
  951. */
  952. Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[0],&IntersectContext.AxE[0][0]);
  953. axis = IntersectContext.AxE[0][0];
  954. if (axis.Length2() > AXISLEN_EPSILON2) {
  955. dp = IntersectContext.AN[0];
  956. leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][0]);
  957. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  958. }
  959. /*
  960. ** AXIS_A0xE1
  961. */
  962. Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[1],&IntersectContext.AxE[0][1]);
  963. axis = IntersectContext.AxE[0][1];
  964. if (axis.Length2() > AXISLEN_EPSILON2) {
  965. dp = -IntersectContext.AN[0];
  966. leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][1]);
  967. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  968. }
  969. /*
  970. ** AXIS_A0xE2
  971. */
  972. Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[2],&IntersectContext.AxE[0][2]);
  973. axis = IntersectContext.AxE[0][2];
  974. IntersectContext.AE[1][2] = IntersectContext.E[2].Y;
  975. IntersectContext.AE[2][2] = IntersectContext.E[2].Z;
  976. if (axis.Length2() > AXISLEN_EPSILON2) {
  977. dp = -IntersectContext.AN[0];
  978. leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][2]);
  979. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  980. }
  981. /*
  982. ** AXIS_A1xE0
  983. */
  984. Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[0],&IntersectContext.AxE[1][0]);
  985. axis = IntersectContext.AxE[1][0];
  986. if (axis.Length2() > AXISLEN_EPSILON2) {
  987. dp = IntersectContext.AN[1];
  988. leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][0]);
  989. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  990. }
  991. /*
  992. ** AXIS_A1xE1
  993. */
  994. Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[1],&IntersectContext.AxE[1][1]);
  995. axis = IntersectContext.AxE[1][1];
  996. if (axis.Length2() > AXISLEN_EPSILON2) {
  997. dp = -IntersectContext.AN[1];
  998. leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][1]);
  999. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  1000. }
  1001. /*
  1002. ** AXIS_A1xE2
  1003. */
  1004. Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[2],&IntersectContext.AxE[1][2]);
  1005. axis = IntersectContext.AxE[1][2];
  1006. IntersectContext.AE[0][2] = IntersectContext.E[2].X;
  1007. if (axis.Length2() > AXISLEN_EPSILON2) {
  1008. dp = -IntersectContext.AN[1];
  1009. leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][2]);
  1010. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  1011. }
  1012. /*
  1013. ** AXIS_A2xE0
  1014. */
  1015. Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[0],&IntersectContext.AxE[2][0]);
  1016. axis = IntersectContext.AxE[2][0];
  1017. if (axis.Length2() > AXISLEN_EPSILON2) {
  1018. dp = IntersectContext.AN[2];
  1019. leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][0]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][0]);
  1020. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  1021. }
  1022. /*
  1023. ** AXIS_A2xE1
  1024. */
  1025. Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[1],&IntersectContext.AxE[2][1]);
  1026. axis = IntersectContext.AxE[2][1];
  1027. if (axis.Length2() > AXISLEN_EPSILON2) {
  1028. dp = -IntersectContext.AN[2];
  1029. leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][1]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][1]);
  1030. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  1031. }
  1032. /*
  1033. ** AXIS_A2xE2
  1034. */
  1035. Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[2],&IntersectContext.AxE[2][2]);
  1036. axis = IntersectContext.AxE[2][2];
  1037. if (axis.Length2() > AXISLEN_EPSILON2) {
  1038. dp = -IntersectContext.AN[2];
  1039. leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][2]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][2]);
  1040. if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
  1041. }
  1042. return true;
  1043. }