oldcol.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. #include "col.h"
  19. // The eight box vertices of the box at time zero are
  20. // center+extent[i]*basis[i]
  21. // center-extent[i]*basis[i]
  22. // for i = 0,1,2,3. The vertices after a time step of dt are
  23. // center+dt*velocity+extent[i]*basis[i]
  24. // center+dt*velocity-extent[i]*basis[i]
  25. // for i = 0,1,2,3.
  26. //---------------------------------------------------------------------------
  27. IntersectType BoxesIntersect (float dt, const Box& box0, const Box& box1)
  28. {
  29. // Comments indicate where additional speed is gained for orthonormal bases
  30. // for both boxes. If a box is known to be flat (a[i] = 0 for some i OR
  31. // b[j] = 0 for some j), then more terms can be eliminated.
  32. const Vector* A = box0.basis;
  33. const Vector* B = box1.basis;
  34. const float* a = box0.extent;
  35. const float* b = box1.extent;
  36. // memoized values for Dot(A[i],A[j]), Dot(A[i],B[j]), Dot(B[i],B[j])
  37. float AA[3][3], AB[3][3], BB[3][3];
  38. // calculate difference of centers
  39. Vector C, V;
  40. Sub(box1.center,box0.center,C);
  41. Sub(box1.velocity,box0.velocity,V);
  42. float ra, rb, rsum, u0, u1;
  43. // L = A0
  44. AA[0][0] = Dot(A[0],A[0]); // = 1 for orthonormal basis
  45. AA[0][1] = Dot(A[0],A[1]); // = 0 for orthonormal basis
  46. AA[0][2] = Dot(A[0],A[2]); // = 0 for orthonormal basis
  47. AB[0][0] = Dot(A[0],B[0]);
  48. AB[0][1] = Dot(A[0],B[1]);
  49. AB[0][2] = Dot(A[0],B[2]);
  50. ra = FABS(a[0]*AA[0][0])+FABS(a[1]*AA[0][1])+FABS(a[2]*AA[0][2]);
  51. // = FABS(a[0]) for orthonormal basis
  52. rb = FABS(b[0]*AB[0][0])+FABS(b[1]*AB[0][1])+FABS(b[2]*AB[0][2]);
  53. rsum = ra+rb;
  54. u0 = Dot(C,A[0]);
  55. u1 = u0+dt*Dot(V,A[0]);
  56. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  57. return itA0;
  58. // L = A1
  59. AA[1][1] = Dot(A[1],A[1]); // = 1 for orthonormal basis
  60. AA[1][2] = Dot(A[1],A[2]); // = 0 for orthonormal basis
  61. AB[1][0] = Dot(A[1],B[0]);
  62. AB[1][1] = Dot(A[1],B[1]);
  63. AB[1][2] = Dot(A[1],B[2]);
  64. ra = FABS(a[0]*AA[0][1])+FABS(a[1]*AA[1][1])+FABS(a[2]*AA[1][2]);
  65. // = FABS(a[1]) for orthonormal basis
  66. rb = FABS(b[0]*AB[1][0])+FABS(b[1]*AB[1][1])+FABS(b[2]*AB[1][2]);
  67. rsum = ra+rb;
  68. u0 = Dot(C,A[1]);
  69. u1 = u0+dt*Dot(V,A[1]);
  70. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  71. return itA1;
  72. // L = A2
  73. AA[2][2] = Dot(A[2],A[2]); // = 1 for orthonormal basis
  74. AB[2][0] = Dot(A[2],B[0]);
  75. AB[2][1] = Dot(A[2],B[1]);
  76. AB[2][2] = Dot(A[2],B[2]);
  77. ra = FABS(a[0]*AA[0][2])+FABS(a[1]*AA[1][2])+FABS(a[2]*AA[2][2]);
  78. // = FABS(a[2]) for orthonormal basis
  79. rb = FABS(b[0]*AB[2][0])+FABS(b[1]*AB[2][1])+FABS(b[2]*AB[2][2]);
  80. rsum = ra+rb;
  81. u0 = Dot(C,A[2]);
  82. u1 = u0+dt*Dot(V,A[2]);
  83. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  84. return itA2;
  85. // L = B0
  86. BB[0][0] = Dot(B[0],B[0]); // = 1 for orthonormal basis
  87. BB[0][1] = Dot(B[0],B[1]); // = 0 for orthonormal basis
  88. BB[0][2] = Dot(B[0],B[2]); // = 0 for orthonormal basis
  89. ra = FABS(a[0]*AB[0][0])+FABS(a[1]*AB[1][0])+FABS(a[2]*AB[2][0]);
  90. rb = FABS(b[0]*BB[0][0])+FABS(b[1]*BB[0][1])+FABS(b[2]*BB[0][2]);
  91. // = FABS(b[0]) for orthonormal basis
  92. rsum = ra+rb;
  93. u0 = Dot(C,B[0]);
  94. u1 = u0+dt*Dot(V,B[0]);
  95. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  96. return itB0;
  97. // L = B1
  98. BB[1][1] = Dot(B[1],B[1]); // = 1 for orthonormal basis
  99. BB[1][2] = Dot(B[1],B[2]); // = 0 for orthonormal basis
  100. ra = FABS(a[0]*AB[0][1])+FABS(a[1]*AB[1][1])+FABS(a[2]*AB[2][1]);
  101. rb = FABS(b[0]*BB[0][1])+FABS(b[1]*BB[1][1])+FABS(b[2]*BB[1][2]);
  102. // = FABS(b[1]) for orthonormal basis
  103. rsum = ra+rb;
  104. u0 = Dot(C,B[1]);
  105. u1 = u0+dt*Dot(V,B[1]);
  106. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  107. return itB1;
  108. // L = B2
  109. BB[2][2] = Dot(B[2],B[2]); // = 1 for orthonormal basis
  110. ra = FABS(a[0]*AB[0][2])+FABS(a[1]*AB[1][2])+FABS(a[2]*AB[2][2]);
  111. rb = FABS(b[0]*BB[0][2])+FABS(b[1]*BB[1][2])+FABS(b[2]*BB[2][2]);
  112. // = FABS(b[2]) for orthonormal basis
  113. rsum = ra+rb;
  114. u0 = Dot(C,B[2]);
  115. u1 = u0+dt*Dot(V,B[2]);
  116. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  117. return itB2;
  118. // check separating axes which are cross products of box edges
  119. float Ainv[3][3], coeff[3][3];
  120. Invert3x3(A,Ainv);
  121. // Ainv = Transpose(A) for orthonormal basis, no need to invert
  122. MultiplyMM(B,Ainv,coeff);
  123. // coeff[i][j] = AB[j][i] for orthonormal basis, no need to multiply
  124. // memoize minors of coefficient matrix
  125. float minor[3][3];
  126. // difference of centers in A-basis
  127. Vector d0, d1, product;
  128. MultiplyVM(C,Ainv,d0); // Ainv = Transpose(A) for orthonormal basis
  129. MultiplyVM(V,Ainv,d1); // Ainv = Transpose(A) for orthonormal basis
  130. ScalarMult(dt,d1,product);
  131. Add(d0,product,d1);
  132. // L = A0xB0
  133. minor[0][1] = coeff[0][1]*coeff[2][2]-coeff[2][1]*coeff[0][2];
  134. // = -coeff[1][0] for orthonormal bases
  135. minor[0][2] = coeff[0][1]*coeff[1][2]-coeff[1][1]*coeff[0][2];
  136. // = +coeff[2][0] for orthonormal bases
  137. ra = FABS(a[1]*coeff[0][2])+FABS(a[2]*coeff[0][1]);
  138. rb = FABS(b[1]*minor[0][2])+FABS(b[2]*minor[0][1]);
  139. // = FABS(b[1]*coeff[2][0])+FABS(b[2]*coeff[1][0]) for orthonormal bases
  140. rsum = ra+rb;
  141. u0 = d0[2]*coeff[1][0]-d0[1]*coeff[2][0];
  142. u1 = d1[2]*coeff[1][0]-d1[1]*coeff[2][0];
  143. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  144. return itA0B0;
  145. // L = A0xB1
  146. minor[0][0] = coeff[1][1]*coeff[2][2]-coeff[2][1]*coeff[1][2];
  147. // = +coeff[0][0] for orthonormal bases
  148. ra = FABS(a[1]*coeff[1][2])+FABS(a[2]*coeff[1][1]);
  149. rb = FABS(b[0]*minor[0][2])+FABS(b[2]*minor[0][0]);
  150. // = FABS(b[0]*coeff[2][0])+FABS(b[2]*coeff[0][0]) for orthonormal bases
  151. rsum = ra+rb;
  152. u0 = d0[2]*coeff[1][1]-d0[1]*coeff[1][2];
  153. u1 = d1[2]*coeff[1][1]-d1[1]*coeff[1][2];
  154. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  155. return itA0B1;
  156. // L = A0xB2
  157. ra = FABS(a[1]*coeff[2][2])+FABS(a[2]*coeff[2][1]);
  158. rb = FABS(b[0]*minor[0][1])+FABS(b[1]*minor[0][0]);
  159. // = FABS(b[0]*coeff[1][0])+FABS(b[1]*coeff[0][0]) for orthonormal bases
  160. rsum = ra+rb;
  161. u0 = d0[2]*coeff[2][1]-d0[1]*coeff[2][2];
  162. u1 = d1[2]*coeff[2][1]-d1[1]*coeff[2][2];
  163. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  164. return itA0B2;
  165. // L = A1xB0
  166. minor[1][1] = coeff[0][0]*coeff[2][2]-coeff[2][0]*coeff[0][2];
  167. // = +coeff[1][1] for orthonormal bases
  168. minor[1][2] = coeff[0][0]*coeff[1][2]-coeff[1][0]*coeff[0][2];
  169. // = -coeff[2][1] for orthonormal bases
  170. ra = FABS(a[0]*coeff[0][2])+FABS(a[2]*coeff[0][0]);
  171. rb = FABS(b[1]*minor[1][2])+FABS(b[2]*minor[1][1]);
  172. // = FABS(b[1]*coeff[2][1])+FABS(b[2]*coeff[1][1]) for orthonormal bases
  173. rsum = ra+rb;
  174. u0 = d0[0]*coeff[0][2]-d0[2]*coeff[0][0];
  175. u1 = d1[0]*coeff[0][2]-d1[2]*coeff[0][0];
  176. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  177. return itA1B0;
  178. // L = A1xB1
  179. minor[1][0] = coeff[1][0]*coeff[2][2]-coeff[2][0]*coeff[1][2];
  180. // = -coeff[0][1] for orthonormal bases
  181. ra = FABS(a[0]*coeff[1][2])+FABS(a[2]*coeff[1][0]);
  182. rb = FABS(b[0]*minor[1][2])+FABS(b[2]*minor[1][0]);
  183. // = FABS(b[0]*coeff[2][1])+FABS(b[2]*coeff[0][1]) for orthonormal bases
  184. rsum = ra+rb;
  185. u0 = d0[0]*coeff[1][2]-d0[2]*coeff[1][0];
  186. u1 = d1[0]*coeff[1][2]-d1[2]*coeff[1][0];
  187. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  188. return itA1B1;
  189. // L = A1xB2
  190. ra = FABS(a[0]*coeff[2][2])+FABS(a[2]*coeff[2][0]);
  191. rb = FABS(b[0]*minor[1][1])+FABS(b[1]*minor[1][0]);
  192. // = FABS(b[0]*coeff[1][1])+FABS(b[1]*coeff[0][1]) for orthonormal bases
  193. rsum = ra+rb;
  194. u0 = d0[0]*coeff[2][2]-d0[2]*coeff[2][0];
  195. u1 = d1[0]*coeff[2][2]-d1[2]*coeff[2][0];
  196. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  197. return itA1B2;
  198. // L = A2xB0
  199. minor[2][1] = coeff[0][0]*coeff[2][1]-coeff[2][0]*coeff[0][1];
  200. // = -coeff[2][1] for orthonormal bases
  201. minor[2][2] = coeff[0][0]*coeff[1][1]-coeff[1][0]*coeff[0][1];
  202. // = +coeff[2][2] for orthonormal bases
  203. ra = FABS(a[0]*coeff[0][1])+FABS(a[1]*coeff[0][0]);
  204. rb = FABS(b[1]*minor[2][2])+FABS(b[2]*minor[2][1]);
  205. // = FABS(b[1]*coeff[2][2])+FABS(b[2]*coeff[1][2]) for orthonormal bases
  206. rsum = ra+rb;
  207. u0 = d0[1]*coeff[0][0]-d0[0]*coeff[0][1];
  208. u1 = d1[1]*coeff[0][0]-d1[0]*coeff[0][1];
  209. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  210. return itA2B0;
  211. // L = A2xB1
  212. minor[2][0] = coeff[1][0]*coeff[2][1]-coeff[2][0]*coeff[1][1];
  213. // = +coeff[0][2] for orthonormal bases
  214. ra = FABS(a[0]*coeff[1][1])+FABS(a[1]*coeff[1][0]);
  215. rb = FABS(b[0]*minor[2][2])+FABS(b[2]*minor[2][0]);
  216. // = FABS(b[0]*coeff[2][2])+FABS(b[2]*coeff[0][2]) for orthonormal bases
  217. rsum = ra+rb;
  218. u0 = d0[1]*coeff[1][0]-d0[0]*coeff[1][1];
  219. u1 = d1[1]*coeff[1][0]-d1[0]*coeff[1][1];
  220. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  221. return itA2B1;
  222. // L = A2xB2
  223. ra = FABS(a[0]*coeff[2][1])+FABS(a[1]*coeff[2][0]);
  224. rb = FABS(b[0]*minor[2][1])+FABS(b[1]*minor[2][0]);
  225. // = FABS(b[0]*coeff[1][2])+FABS(b[1]*coeff[0][2]) for orthonormal bases
  226. rsum = ra+rb;
  227. u0 = d0[1]*coeff[2][0]-d0[0]*coeff[2][1];
  228. u1 = d1[1]*coeff[2][0]-d1[0]*coeff[2][1];
  229. if ((u0 > rsum && u1 > rsum) || (u0 < -rsum && u1 < -rsum) )
  230. return itA2B2;
  231. return itIntersects;
  232. }