obbox.cpp 31 KB

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