obbox.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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/obbox.cpp $*
  25. * *
  26. * Org Author:: Greg_h *
  27. * *
  28. * Author : Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 24 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * OBBoxClass::OBBoxClass -- Constructor that computes the box for a set of point *
  38. * OBBoxClass::Init_From_Box_Points -- Create an OBBox from 8 corners of a box *
  39. * OBBoxClass::Init_Random -- initalize a random oriented box *
  40. * Oriented_Boxes_Intersect_On_Axis -- test if two boxes intersect on given axis *
  41. * Oriented_Boxes_Intersect -- test if two oriented boxes intersect *
  42. * Oriented_Boxes_Collide_On_Axis -- test if two boxes collide on the given axis *
  43. * Oriented_Boxes_Collide -- test if two oriented boxes collide *
  44. * Oriented_Box_Intersects_Tri_On_Axis -- tests if the box and tri intersect on the axis *
  45. * Oriented_Box_Intersects_Tri -- tests if the given box and tri intersect *
  46. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  47. #include "obbox.h"
  48. #include "matrix3.h"
  49. #include "vector3.h"
  50. #include "aabox.h"
  51. #include "tri.h"
  52. #include "plane.h"
  53. #include "quat.h"
  54. #include <assert.h>
  55. //#include <stdlib.h>
  56. /***********************************************************************************************
  57. * OBBoxClass::OBBoxClass -- Constructor that computes the box for a set of points *
  58. * *
  59. * INPUT: *
  60. * *
  61. * OUTPUT: *
  62. * *
  63. * WARNINGS: *
  64. * *
  65. * HISTORY: *
  66. * 2/4/98 GTH : Created. *
  67. *=============================================================================================*/
  68. OBBoxClass::OBBoxClass(const Vector3 * /*points*/, int /*n*/)
  69. {
  70. // TODO: IMPLEMENT THIS!!!
  71. assert(0);
  72. #if 0
  73. int i;
  74. // compute mean and covariances of points
  75. float xsum = 0.0f, ysum = 0.0f, zsum = 0.0f;;
  76. float xxsum = 0.0f, xysum = 0.0f, xzsum = 0.0f;
  77. float yysum = 0.0f, yzsum = 0.0f, zzsum = 0.0f;
  78. for (i = 0; i < n; i++)
  79. {
  80. xsum += points[i].X;
  81. ysum += points[i].Y;
  82. zsum += points[i].Z;
  83. xxsum += points[i].X * points[i].X;
  84. xysum += points[i].X * points[i].Y;
  85. xzsum += points[i].X * points[i].Z;
  86. yysum += points[i].Y * points[i].Y;
  87. yzsum += points[i].Y * points[i].Z;
  88. zzsum += points[i].Z * points[i].Z;
  89. }
  90. float xmean = xsum/n;
  91. float ymean = ysum/n;
  92. float zmean = zsum/n;
  93. float xxcov = xxsum/n - xmean*xmean;
  94. float xycov = xysum/n - xmean*ymean;
  95. float xzcov = xzsum/n - xmean*zmean;
  96. float yycov = yysum/n - ymean*ymean;
  97. float yzcov = yzsum/n - ymean*zmean;
  98. float zzcov = zzsum/n - zmean*zmean;
  99. // compute eigenvectors for covariance matrix,
  100. // these will be the axes.
  101. mgcEigen eig(3);
  102. eig.Matrix(0,0) = xxcov;
  103. eig.Matrix(0,1) = xycov;
  104. eig.Matrix(0,2) = xzcov;
  105. eig.Matrix(1,0) = xycov;
  106. eig.Matrix(1,1) = yycov;
  107. eig.Matrix(1,2) = yzcov;
  108. eig.Matrix(2,0) = xzcov;
  109. eig.Matrix(2,1) = yzcov;
  110. eig.Matrix(2,2) = zzcov;
  111. eig.EigenStuff3();
  112. Point3 U =
  113. {
  114. eig.Eigenvector(0,0),
  115. eig.Eigenvector(1,0),
  116. eig.Eigenvector(2,0)
  117. };
  118. Point3 V =
  119. {
  120. eig.Eigenvector(0,1),
  121. eig.Eigenvector(1,1),
  122. eig.Eigenvector(2,1)
  123. };
  124. Point3 W =
  125. {
  126. eig.Eigenvector(0,2),
  127. eig.Eigenvector(1,2),
  128. eig.Eigenvector(2,2)
  129. };
  130. // box center is the mean of the distribution
  131. box.center.x = xmean;
  132. box.center.y = ymean;
  133. box.center.z = zmean;
  134. // Box axes are the eigenvectors of the covariance matrix with
  135. // adjusted lengths to enclose the points. If U, V, and W are the
  136. // eigenvectors, C is the center of the box, and X is a point in
  137. // the input list, then X = C + a*U + b*V + c*W. The box extent is
  138. // determined by max|a|, max|b|, and max|c|. The box axes are then
  139. // defined to be (max|a|)*U and (max|b|)*V. Note that since U and V
  140. // are unit length and orthogonal, a = Dot(U,X-C), b = Dot(V,X-C),
  141. // and c = Dot(W,X-C).
  142. float amax = 0.0f, bmax = 0.0f, cmax = 0.0f;
  143. for (i = 0; i < n; i++)
  144. {
  145. float dx = pt[i].x - box.center.x;
  146. float dy = pt[i].y - box.center.y;
  147. float dz = pt[i].z - box.center.z;
  148. float absdot = float(WWMath::Fabs(U.x*dx+U.y*dy+U.z*dz));
  149. if ( absdot > amax )
  150. amax = absdot;
  151. absdot = float(WWMath::Fabs(V.x*dx+V.y*dy+V.z*dz));
  152. if ( absdot > bmax )
  153. bmax = absdot;
  154. absdot = float(WWMath::Fabs(W.x*dx+W.y*dy+W.z*dz));
  155. if ( absdot > cmax )
  156. cmax = absdot;
  157. }
  158. box.axis[0].x = amax*U.x;
  159. box.axis[0].y = amax*U.y;
  160. box.axis[0].z = amax*U.z;
  161. box.axis[1].x = bmax*V.x;
  162. box.axis[1].y = bmax*V.y;
  163. box.axis[1].z = bmax*V.z;
  164. box.axis[2].x = cmax*W.x;
  165. box.axis[2].y = cmax*W.y;
  166. box.axis[2].z = cmax*W.z;
  167. #endif
  168. }
  169. /***********************************************************************************************
  170. * OBBoxClass::Init_From_Box_Points -- Create an OBBox from 8 corners of a box *
  171. * *
  172. * INPUT: *
  173. * *
  174. * OUTPUT: *
  175. * *
  176. * WARNINGS: *
  177. * *
  178. * HISTORY: *
  179. * 2/24/98 GTH : Created. *
  180. *=============================================================================================*/
  181. void OBBoxClass::Init_From_Box_Points(Vector3 * points,int num)
  182. {
  183. int i,j;
  184. /*
  185. ** This function assumes that you pass in 8 points which are the
  186. ** corners of a rectangular solid. Bad things will happen if
  187. ** this assumption is not true!!!!
  188. */
  189. assert(num == 8);
  190. /*
  191. ** Just pick the first point as the preliminary center. Compute
  192. ** vectors from this point to each of the other points
  193. */
  194. Vector3 dp[8];
  195. for (i=1;i<num;i++) {
  196. dp[i] = points[i] - points[0];
  197. }
  198. /*
  199. ** Find the shortest two candidate axes. Then the
  200. ** third axis will be the cross product of these two.
  201. */
  202. for (i=1;i<num;i++) {
  203. for (j=i+1;j<num;j++) {
  204. if (dp[j].Length2() < dp[i].Length2()) {
  205. Swap(dp[j],dp[i]);
  206. }
  207. }
  208. }
  209. Vector3 axis0,axis1,axis2;
  210. #ifdef ALLOW_TEMPORARIES
  211. axis0 = Normalize(dp[1]);
  212. axis1 = Normalize(dp[2]);
  213. #else
  214. axis0 = dp[1]; axis0.Normalize();
  215. axis1 = dp[2]; axis1.Normalize();
  216. #endif
  217. Vector3::Cross_Product(axis0,axis1,&axis2);
  218. Basis = Matrix3x3(axis0,axis1,axis2);
  219. /*
  220. ** Center is the average of all of the points
  221. */
  222. Center.Set(0,0,0);
  223. for (i=0; i<num; i++) {
  224. Center += points[i];
  225. }
  226. Center.X /= num;
  227. Center.Y /= num;
  228. Center.Z /= num;
  229. /*
  230. ** Compute extents along the computed axes. This is done
  231. ** by projecting each point onto the three axes and keeping
  232. ** the largest projection on each.
  233. */
  234. Extent.Set(0,0,0);
  235. for (i=0; i<num; i++) {
  236. float dx = points[i].X - Center.X;
  237. float dy = points[i].Y - Center.Y;
  238. float dz = points[i].Z - Center.Z;
  239. float xprj = float(WWMath::Fabs(axis0.X * dx + axis0.Y * dy + axis0.Z * dz));
  240. if (xprj > Extent.X) Extent.X = xprj;
  241. float yprj = float(WWMath::Fabs(axis1.X * dx + axis1.Y * dy + axis1.Z * dz));
  242. if (yprj > Extent.Y) Extent.Y = yprj;
  243. float zprj = float(WWMath::Fabs(axis2.X * dx + axis2.Y * dy + axis2.Z * dz));
  244. if (zprj > Extent.Z) Extent.Z = zprj;
  245. }
  246. }
  247. /***********************************************************************************************
  248. * OBBoxClass::Init_Random -- initalize a random oriented box *
  249. * *
  250. * INPUT: *
  251. * *
  252. * OUTPUT: *
  253. * *
  254. * WARNINGS: *
  255. * *
  256. * HISTORY: *
  257. * 4/21/98 GTH : Created. *
  258. *=============================================================================================*/
  259. void OBBoxClass::Init_Random(float min_extent,float max_extent)
  260. {
  261. Center.Set(0,0,0);
  262. Extent.X = min_extent + WWMath::Random_Float() * (max_extent - min_extent);
  263. Extent.Y = min_extent + WWMath::Random_Float() * (max_extent - min_extent);
  264. Extent.Z = min_extent + WWMath::Random_Float() * (max_extent - min_extent);
  265. Quaternion orient;
  266. orient.X = WWMath::Random_Float();
  267. orient.Y = WWMath::Random_Float();
  268. orient.Z = WWMath::Random_Float();
  269. orient.W = WWMath::Random_Float();
  270. orient.Normalize();
  271. Basis = Build_Matrix3(orient);
  272. }
  273. /***********************************************************************************************
  274. * Oriented_Boxes_Intersect_On_Axis -- test if two boxes intersect on given axis *
  275. * *
  276. * INPUT: *
  277. * *
  278. * OUTPUT: *
  279. * *
  280. * WARNINGS: *
  281. * *
  282. * HISTORY: *
  283. * 4/7/99 GTH : Created. *
  284. *=============================================================================================*/
  285. bool Oriented_Boxes_Intersect_On_Axis
  286. (
  287. const OBBoxClass & box0,
  288. const OBBoxClass & box1,
  289. const Vector3 & axis
  290. )
  291. {
  292. float ra,rb,rsum;
  293. if (axis.Length2() < WWMATH_EPSILON) return true;
  294. ra = box0.Project_To_Axis(axis);
  295. rb = box1.Project_To_Axis(axis);
  296. rsum = WWMath::Fabs(ra) + WWMath::Fabs(rb);
  297. // project the center distance onto the line:
  298. Vector3 C = box1.Center - box0.Center;
  299. float cdist = Vector3::Dot_Product(axis,C);
  300. if ((cdist > rsum) || (cdist < -rsum)) {
  301. return false;
  302. }
  303. return true;
  304. }
  305. /***********************************************************************************************
  306. * Oriented_Boxes_Intersect -- test if two oriented boxes intersect *
  307. * *
  308. * INPUT: *
  309. * *
  310. * OUTPUT: *
  311. * *
  312. * WARNINGS: *
  313. * *
  314. * HISTORY: *
  315. * 4/7/99 GTH : Created. *
  316. *=============================================================================================*/
  317. bool Oriented_Boxes_Intersect
  318. (
  319. const OBBoxClass & box0,
  320. const OBBoxClass & box1
  321. )
  322. {
  323. Vector3 axis;
  324. Vector3 A[3],B[3];
  325. // vectors for the axis directions of the two boxes in world space
  326. A[0].Set(box0.Basis[0][0],box0.Basis[1][0],box0.Basis[2][0]);
  327. A[1].Set(box0.Basis[0][1],box0.Basis[1][1],box0.Basis[2][1]);
  328. A[2].Set(box0.Basis[0][2],box0.Basis[1][2],box0.Basis[2][2]);
  329. B[0].Set(box1.Basis[0][0],box1.Basis[1][0],box1.Basis[2][0]);
  330. B[1].Set(box1.Basis[0][1],box1.Basis[1][1],box1.Basis[2][1]);
  331. B[2].Set(box1.Basis[0][2],box1.Basis[1][2],box1.Basis[2][2]);
  332. /////////////////////////////////////////////////////////////////////////
  333. // Projecting the two boxes onto Box0's X axis. If their intervals
  334. // on this line do not intersect, the boxes are not intersecting.
  335. // Each of the tests in this function work in a similar way.
  336. /////////////////////////////////////////////////////////////////////////
  337. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,A[0])) return false;
  338. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,A[1])) return false;
  339. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,A[2])) return false;
  340. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,B[0])) return false;
  341. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,B[1])) return false;
  342. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,B[2])) return false;
  343. /////////////////////////////////////////////////////////////////////////
  344. // None of the aligned axes turned out to be separating axes. Now
  345. // we check all combinations of cross products of the two boxes axes.
  346. /////////////////////////////////////////////////////////////////////////
  347. Vector3::Cross_Product(A[0],B[0],&axis);
  348. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  349. Vector3::Cross_Product(A[0],B[1],&axis);
  350. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  351. Vector3::Cross_Product(A[0],B[2],&axis);
  352. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  353. Vector3::Cross_Product(A[1],B[0],&axis);
  354. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  355. Vector3::Cross_Product(A[1],B[1],&axis);
  356. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  357. Vector3::Cross_Product(A[1],B[2],&axis);
  358. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  359. Vector3::Cross_Product(A[2],B[0],&axis);
  360. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  361. Vector3::Cross_Product(A[2],B[1],&axis);
  362. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  363. Vector3::Cross_Product(A[2],B[2],&axis);
  364. if (!Oriented_Boxes_Intersect_On_Axis(box0,box1,axis)) return false;
  365. // None of the above tests separated the two boxes, so they are intersecting
  366. return true;
  367. }
  368. /***********************************************************************************************
  369. * Oriented_Boxes_Collide_On_Axis -- test if two boxes collide on the given axis *
  370. * *
  371. * INPUT: *
  372. * *
  373. * OUTPUT: *
  374. * *
  375. * WARNINGS: *
  376. * *
  377. * HISTORY: *
  378. * 4/7/99 GTH : Created. *
  379. *=============================================================================================*/
  380. bool Oriented_Boxes_Collide_On_Axis
  381. (
  382. const OBBoxClass & box0,
  383. const Vector3 & v0,
  384. const OBBoxClass & box1,
  385. const Vector3 & v1,
  386. const Vector3 & axis,
  387. float dt
  388. )
  389. {
  390. float ra,rb,rsum;
  391. if (axis.Length2() < WWMATH_EPSILON) return true;
  392. ra = box0.Project_To_Axis(axis);
  393. rb = box1.Project_To_Axis(axis);
  394. rsum = WWMath::Fabs(ra) + WWMath::Fabs(rb);
  395. // project the center distance onto the line:
  396. Vector3 C = box1.Center - box0.Center;
  397. Vector3 V = v1 - v0;
  398. float cdist = Vector3::Dot_Product(axis,C);
  399. float vdist = cdist + dt * Vector3::Dot_Product(axis,V);
  400. if ((cdist > rsum && vdist > rsum) || (cdist < -rsum && vdist < -rsum)) {
  401. return false;
  402. }
  403. return true;
  404. }
  405. /***********************************************************************************************
  406. * Oriented_Boxes_Collide -- test if two oriented boxes collide *
  407. * *
  408. * INPUT: *
  409. * *
  410. * OUTPUT: *
  411. * *
  412. * WARNINGS: *
  413. * *
  414. * HISTORY: *
  415. * 4/7/99 GTH : Created. *
  416. *=============================================================================================*/
  417. bool Oriented_Boxes_Collide
  418. (
  419. const OBBoxClass & box0,
  420. const Vector3 & v0,
  421. const OBBoxClass & box1,
  422. const Vector3 & v1,
  423. float dt
  424. )
  425. {
  426. bool intersect = true;
  427. // variables for holding the separating axis and the projected distances
  428. Vector3 SepAxis;
  429. // vectors for the axis directions of the two boxes in world space
  430. Vector3 A0(box0.Basis[0][0],box0.Basis[1][0],box0.Basis[2][0]);
  431. Vector3 A1(box0.Basis[0][1],box0.Basis[1][1],box0.Basis[2][1]);
  432. Vector3 A2(box0.Basis[0][2],box0.Basis[1][2],box0.Basis[2][2]);
  433. Vector3 B0(box1.Basis[0][0],box1.Basis[1][0],box1.Basis[2][0]);
  434. Vector3 B1(box1.Basis[0][1],box1.Basis[1][1],box1.Basis[2][1]);
  435. Vector3 B2(box1.Basis[0][2],box1.Basis[1][2],box1.Basis[2][2]);
  436. /////////////////////////////////////////////////////////////////////////
  437. // L = A0
  438. //
  439. // Projecting the two boxes onto Box0's X axis. If their intervals
  440. // on this line do not intersect, the boxes are not intersecting!
  441. // Each of the tests in this function work in a similar way.
  442. /////////////////////////////////////////////////////////////////////////
  443. SepAxis = A0;
  444. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  445. intersect = false;
  446. goto exit;
  447. }
  448. /////////////////////////////////////////////////////////////////////////
  449. // L = A1
  450. // Separating Axis is Box0's Y axis
  451. /////////////////////////////////////////////////////////////////////////
  452. SepAxis = A1;
  453. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  454. intersect = false;
  455. goto exit;
  456. }
  457. /////////////////////////////////////////////////////////////////////////
  458. // L = A2
  459. // Separating Axis is Box0's Z axis
  460. /////////////////////////////////////////////////////////////////////////
  461. SepAxis = A2;
  462. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  463. intersect = false;
  464. goto exit;
  465. }
  466. /////////////////////////////////////////////////////////////////////////
  467. // L = B0
  468. // Separating Axis is Box1's X axis
  469. /////////////////////////////////////////////////////////////////////////
  470. SepAxis = B0;
  471. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  472. intersect = false;
  473. goto exit;
  474. }
  475. /////////////////////////////////////////////////////////////////////////
  476. // L = B1
  477. // Separating Axis is Box1's Y axis
  478. /////////////////////////////////////////////////////////////////////////
  479. SepAxis = B1;
  480. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  481. intersect = false;
  482. goto exit;
  483. }
  484. /////////////////////////////////////////////////////////////////////////
  485. // L = B2
  486. // Separating Axis is Box1's Z axis
  487. /////////////////////////////////////////////////////////////////////////
  488. SepAxis = B2;
  489. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  490. intersect = false;
  491. goto exit;
  492. }
  493. /////////////////////////////////////////////////////////////////////////
  494. // None of the aligned axes turned out to be separating axes. Now
  495. // we check all combinations of cross products of the two boxes axes.
  496. /////////////////////////////////////////////////////////////////////////
  497. /////////////////////////////////////////////////////////////////////////
  498. // L = A0xB0
  499. /////////////////////////////////////////////////////////////////////////
  500. Vector3::Cross_Product(A0,B0,&SepAxis);
  501. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  502. intersect = false;
  503. goto exit;
  504. }
  505. /////////////////////////////////////////////////////////////////////////
  506. // L = A0xB1
  507. /////////////////////////////////////////////////////////////////////////
  508. Vector3::Cross_Product(A0,B1,&SepAxis);
  509. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  510. intersect = false;
  511. goto exit;
  512. }
  513. /////////////////////////////////////////////////////////////////////////
  514. // L = A0xB2
  515. /////////////////////////////////////////////////////////////////////////
  516. Vector3::Cross_Product(A0,B2,&SepAxis);
  517. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  518. intersect = false;
  519. goto exit;
  520. }
  521. /////////////////////////////////////////////////////////////////////////
  522. // L = A1xB0
  523. /////////////////////////////////////////////////////////////////////////
  524. Vector3::Cross_Product(A1,B0,&SepAxis);
  525. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  526. intersect = false;
  527. goto exit;
  528. }
  529. /////////////////////////////////////////////////////////////////////////
  530. // L = A1xB1
  531. /////////////////////////////////////////////////////////////////////////
  532. Vector3::Cross_Product(A1,B1,&SepAxis);
  533. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  534. intersect = false;
  535. goto exit;
  536. }
  537. /////////////////////////////////////////////////////////////////////////
  538. // L = A1xB2
  539. /////////////////////////////////////////////////////////////////////////
  540. Vector3::Cross_Product(A1,B2,&SepAxis);
  541. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  542. intersect = false;
  543. goto exit;
  544. }
  545. /////////////////////////////////////////////////////////////////////////
  546. // L = A2xB0
  547. /////////////////////////////////////////////////////////////////////////
  548. Vector3::Cross_Product(A2,B0,&SepAxis);
  549. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  550. intersect = false;
  551. goto exit;
  552. }
  553. /////////////////////////////////////////////////////////////////////////
  554. // L = A2xB1
  555. /////////////////////////////////////////////////////////////////////////
  556. Vector3::Cross_Product(A2,B1,&SepAxis);
  557. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  558. intersect = false;
  559. goto exit;
  560. }
  561. /////////////////////////////////////////////////////////////////////////
  562. // L = A2xB2
  563. /////////////////////////////////////////////////////////////////////////
  564. Vector3::Cross_Product(A2,B2,&SepAxis);
  565. if (!Oriented_Boxes_Collide_On_Axis(box0,v0,box1,v1,SepAxis,dt)) {
  566. intersect = false;
  567. goto exit;
  568. }
  569. exit:
  570. return intersect;
  571. }
  572. /***********************************************************************************************
  573. * Oriented_Box_Intersects_Tri_On_Axis -- tests if the box and tri intersect on the axis *
  574. * *
  575. * INPUT: *
  576. * *
  577. * OUTPUT: *
  578. * *
  579. * WARNINGS: *
  580. * *
  581. * HISTORY: *
  582. * 4/7/99 GTH : Created. *
  583. *=============================================================================================*/
  584. bool Oriented_Box_Intersects_Tri_On_Axis(const OBBoxClass & box,const TriClass & tri,Vector3 & axis)
  585. {
  586. float leb; // leading edge of box (farthest point from center)
  587. float lep; // leading edge of poly (closest point to center)
  588. float dist; // distance from box center to v0
  589. float tmp;
  590. if (axis.Length2() < WWMATH_EPSILON) return true;
  591. Vector3 D = *(tri.V[0]) - box.Center;
  592. Vector3 r1 = *(tri.V[1]) - *(tri.V[0]);
  593. Vector3 r2 = *(tri.V[2]) - *(tri.V[0]);
  594. // I want the axis to point from box.center to tri.v0
  595. dist = Vector3::Dot_Product(D,axis);
  596. if (dist < 0) {
  597. dist = -dist;
  598. axis = -axis;
  599. }
  600. // compute leading edge of the box
  601. leb = box.Project_To_Axis(axis);
  602. // compute the leading edge of the triangle
  603. lep = 0;
  604. tmp = Vector3::Dot_Product(r1,axis); if (tmp < lep) lep = tmp;
  605. tmp = Vector3::Dot_Product(r2,axis); if (tmp < lep) lep = tmp;
  606. lep += dist;
  607. if (lep >= leb) {
  608. return false;
  609. } else {
  610. return true;
  611. }
  612. }
  613. /***********************************************************************************************
  614. * Oriented_Box_Intersects_Tri -- tests if the given box and tri intersect *
  615. * *
  616. * INPUT: *
  617. * *
  618. * OUTPUT: *
  619. * *
  620. * WARNINGS: *
  621. * *
  622. * HISTORY: *
  623. * 4/7/99 GTH : Created. *
  624. *=============================================================================================*/
  625. bool Oriented_Box_Intersects_Tri(const OBBoxClass & box,const TriClass & tri)
  626. {
  627. Vector3 axis;
  628. // vectors for the axis directions of the two boxes in world space
  629. Vector3 A[3];
  630. Vector3 E[3];
  631. Vector3 normal = *tri.N;
  632. A[0].Set(box.Basis[0][0],box.Basis[1][0],box.Basis[2][0]);
  633. A[1].Set(box.Basis[0][1],box.Basis[1][1],box.Basis[2][1]);
  634. A[2].Set(box.Basis[0][2],box.Basis[1][2],box.Basis[2][2]);
  635. E[0] = *(tri.V[1]) - *(tri.V[0]);
  636. E[1] = *(tri.V[2]) - *(tri.V[1]);
  637. E[2] = *(tri.V[0]) - *(tri.V[2]);
  638. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,normal)) return false;
  639. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,A[0])) return false;
  640. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,A[1])) return false;
  641. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,A[2])) return false;
  642. Vector3::Cross_Product(A[0],E[0],&axis);
  643. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  644. Vector3::Cross_Product(A[0],E[1],&axis);
  645. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  646. Vector3::Cross_Product(A[0],E[2],&axis);
  647. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  648. Vector3::Cross_Product(A[1],E[0],&axis);
  649. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  650. Vector3::Cross_Product(A[1],E[1],&axis);
  651. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  652. Vector3::Cross_Product(A[1],E[2],&axis);
  653. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  654. Vector3::Cross_Product(A[2],E[0],&axis);
  655. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  656. Vector3::Cross_Product(A[2],E[1],&axis);
  657. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  658. Vector3::Cross_Product(A[2],E[2],&axis);
  659. if (!Oriented_Box_Intersects_Tri_On_Axis(box,tri,axis)) return false;
  660. return true;
  661. }