HitTest.cpp 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953
  1. /*
  2. ** Copyright (C) 1996, 1997 Microsoft Corporation. All Rights Reserved.
  3. **
  4. ** File: HitTest.cpp
  5. **
  6. ** Author:
  7. **
  8. ** Description:
  9. **
  10. ** History:
  11. */
  12. #include "pch.h"
  13. void HitTest::SetBB(Time start,
  14. Time stop,
  15. float dt)
  16. {
  17. assert (stop >= start);
  18. assert (m_timeStop >= m_timeStart);
  19. if (m_staticF)
  20. {
  21. m_tStart = 0.0f;
  22. m_tStop = dt;
  23. m_lastTest = NULL;
  24. }
  25. else
  26. {
  27. if (m_timeStart == m_timeStop)
  28. {
  29. //hittest always exists (or, at least, started before
  30. //start and ends after stop)
  31. m_tStart = 0.0f;
  32. m_tStop = dt;
  33. m_stopPosition = GetPosition() + m_velocity * m_tStop;
  34. }
  35. else if (stop < m_timeStart)
  36. {
  37. //The object shouldn't exist yet ... flag it as dead
  38. m_deadF = true;
  39. m_stopPosition = GetPosition();
  40. }
  41. else if (m_timeStop > start)
  42. {
  43. if (start < m_timeStart)
  44. {
  45. //The object does not come into existance until after start.
  46. m_tStart = m_timeStart - start;
  47. //Back the object up so that it is in the correct position at time 0.
  48. SetPosition(GetPosition() - m_velocity * m_tStart);
  49. m_deadF = false; //just in case it was disabled by the above test
  50. }
  51. else
  52. {
  53. m_tStart = 0.0f;
  54. assert (!m_deadF);
  55. }
  56. m_tStop = ((m_timeStop < stop) ? m_timeStop : stop) - start;
  57. m_stopPosition = GetPosition() + m_velocity * m_tStop;
  58. }
  59. else
  60. {
  61. //The will die before the time interval of interest starts
  62. m_deadF = true;
  63. m_stopPosition = GetPosition();
  64. }
  65. assert (m_stopPosition.LengthSquared() >= 0.0f);
  66. assert (m_stopPosition.LengthSquared() < 1.0e12f);
  67. UpdateBB();
  68. }
  69. }
  70. void HitTest::UpdateBB(void)
  71. {
  72. if (!m_staticF)
  73. {
  74. Vector startPosition = m_tStart == 0.0f
  75. ? GetPosition()
  76. : GetPosition() + m_velocity * m_tStart; //offset for delayed start
  77. //let's assume were using the xy & z axes.
  78. assert (c_nAxes == 3);
  79. for (int i = 0; (i < c_nAxes); i++)
  80. {
  81. float v1 = startPosition[i];
  82. float v2 = m_stopPosition[i];
  83. if (v1 <= v2)
  84. {
  85. m_boundingBox.axes[i].values[0] = v1 - m_radius;
  86. m_boundingBox.axes[i].values[1] = v2 + m_radius;
  87. }
  88. else
  89. {
  90. m_boundingBox.axes[i].values[0] = v2 - m_radius;
  91. m_boundingBox.axes[i].values[1] = v1 + m_radius;
  92. }
  93. m_endpoints[i][0].value = m_boundingBox.axes[i].values[0];
  94. m_endpoints[i][1].value = m_boundingBox.axes[i].values[1];
  95. }
  96. }
  97. m_lastTest = NULL;
  98. }
  99. const double epsilon = 1.0f / 128.0f;
  100. void HitTest::Collide(HitTest* pHitTest,
  101. CollisionQueue* pQueue)
  102. {
  103. assert (pQueue);
  104. const BoundingBox& hitTestBB = pHitTest->m_boundingBox;
  105. if ((m_boundingBox.axes[0].values[1] > hitTestBB.axes[0].values[0]) &&
  106. (m_boundingBox.axes[0].values[0] < hitTestBB.axes[0].values[1]) &&
  107. (m_boundingBox.axes[1].values[1] > hitTestBB.axes[1].values[0]) &&
  108. (m_boundingBox.axes[1].values[0] < hitTestBB.axes[1].values[1]) &&
  109. (m_boundingBox.axes[2].values[1] > hitTestBB.axes[2].values[0]) &&
  110. (m_boundingBox.axes[2].values[0] < hitTestBB.axes[2].values[1]))
  111. {
  112. //Calculate the time when pHitTest and this first collide (if ever)
  113. Vector dP = GetPosition() - pHitTest->GetPosition();
  114. float r = pHitTest->m_radius + m_radius;
  115. double c = (double)(dP * dP) - (double)(r * r);
  116. Vector dV = pHitTest->m_velocity - m_velocity; //negative to eliminate an extraneous - below
  117. //Distance(t) = |dP - dV * t|
  118. //Distance(t)^2 = (dP - dV * t) * (dP - dV * t)
  119. // = (dP * dP - 2 * dP * dV * t + dV * dV * t^2)
  120. //Solve for Distance(t)^2 == radius^2 : a*t^2 - b * t + c = 0 => t = (b +- sqrt(b^2 - 4ac)) / 2a
  121. //
  122. bool fCollision = false;
  123. float tCollision;
  124. float tMax;
  125. double halfB = (dP * dV); //b/2
  126. if (halfB > 0.0) //objects need to be closing at least a little to generate a collision
  127. {
  128. double a = dV * dV;
  129. if (a > 0.0) //Shouldn't be a problem but ... float do have their limits of resolution
  130. {
  131. double b2ac = halfB*halfB - a * c;
  132. if (b2ac >= 0.0)
  133. {
  134. //real roots ... at some point (past or future), they'll be close enough to collide
  135. //pick the minimum time: when they would first collide
  136. double s = sqrt(b2ac);
  137. tCollision = (c <= 0.0) ? 0.0f //Bounding spheres already intersect
  138. : (float)((halfB - s) / a);
  139. tMax = (float)((halfB + s) / a);
  140. if (tMax > m_tStop)
  141. tMax = m_tStop;
  142. fCollision = true;
  143. }
  144. }
  145. }
  146. else if (c < 0.0)
  147. {
  148. //The object bounding sphere's overlap ... we have a possible collision even if the
  149. //objects are not moving (or are moving apart)
  150. tCollision = m_tStart;
  151. tMax = FLT_MAX;
  152. if (halfB != 0.0)
  153. {
  154. //The objects are moving apart ... when will their bounding spheres no longer overlap.
  155. double a = dV * dV;
  156. if (a > 0.0) //Shouldn't be a problem but ... float do have their limits of resolution
  157. {
  158. tMax = (float)((halfB + (float)sqrt(halfB*halfB - a * c)) / a);
  159. }
  160. }
  161. if (tMax > m_tStop)
  162. tMax = m_tStop;
  163. fCollision = true;
  164. }
  165. //Is it in the window of time we are interested in?
  166. //The range of legal times is always updated in updateBB() and
  167. //projectiles will always have the most restrictive range (and
  168. //in a projectile vs. non-projectile, the projectile is always this).
  169. //
  170. //Allow collisions that occur slightly beyond m_tStop to guarantee that
  171. //all collisions get processed at least once (this could lead to collisions
  172. //happening twice but the less of a problem than missing a collision)
  173. if (fCollision && (tCollision >= m_tStart) && (tCollision <= m_tStop + (float)epsilon))
  174. {
  175. HitTestShape htsThis = m_shape;
  176. HitTestShape htsPHT = pHitTest->m_shape;
  177. if (((m_shape <= c_htsSphere) && (pHitTest->m_shape <= c_htsSphere)) ||
  178. HullCollide(&tCollision, tMax + (float)epsilon, this, &htsThis, pHitTest, &htsPHT, dP, dV))
  179. {
  180. pQueue->addCollision(tCollision, this, htsThis, pHitTest, htsPHT);
  181. }
  182. }
  183. }
  184. }
  185. class BoundingPoint : public HitTest
  186. {
  187. public:
  188. BoundingPoint(IObject* d, bool staticF)
  189. :
  190. HitTest(d, 0.0f, staticF, c_htsPoint)
  191. {
  192. }
  193. };
  194. class BoundingSphere : public HitTest
  195. {
  196. public:
  197. BoundingSphere(IObject* d, bool staticF)
  198. :
  199. HitTest(d, 0.0f, staticF, c_htsSphere)
  200. {
  201. }
  202. };
  203. class ConvexVertex
  204. {
  205. public:
  206. const Vector& GetPosition(void) const
  207. {
  208. return m_position;
  209. }
  210. void SetPosition(const Vector& p)
  211. {
  212. m_position = p;
  213. }
  214. const ConvexVertex** GetAdjacencies(void) const
  215. {
  216. return m_adjacencies;
  217. }
  218. private:
  219. Vector m_position;
  220. const ConvexVertex** m_adjacencies;
  221. friend class HitTest;
  222. friend class BoundingHull;
  223. friend class SingleHull;
  224. };
  225. class BoundingCone : public HitTest
  226. {
  227. public:
  228. BoundingCone(IObject* d, bool staticF)
  229. :
  230. HitTest(d, 0.0f, staticF, c_htsCone)
  231. {
  232. }
  233. Vector GetExtreme(const Vector& direction)
  234. {
  235. //On the cone portion of the cone
  236. if (direction.z >= (sqrt2 / 2.0f))
  237. {
  238. return Vector(0.0f, 0.0f, GetRadius()); //Near the tip
  239. }
  240. else
  241. {
  242. //Near the edge ... return the corresponding point on the edge.
  243. float l = (float)sqrt(direction.x * direction.x + direction.y * direction.y);
  244. if (l < 0.01f)
  245. return Vector(0.0f, 0.0f, 0.0f);
  246. else
  247. {
  248. float xy = GetRadius() / l;
  249. return Vector(direction.x * xy, direction.y * xy, 0.0f);
  250. }
  251. }
  252. }
  253. };
  254. #undef new
  255. class SingleHull
  256. {
  257. public:
  258. SingleHull(int nVertices, const Vector& center)
  259. :
  260. m_nVertices(nVertices),
  261. m_center(center)
  262. {
  263. }
  264. void* operator new(size_t size, int nVertices, int nAdjacencies)
  265. {
  266. return (void*)(::new char [size +
  267. sizeof(ConvexVertex) * nVertices +
  268. sizeof(ConvexVertex*) * (nAdjacencies + nVertices)]);
  269. }
  270. const ConvexVertex* GetExtremeVertex(const Vector& direction) const
  271. {
  272. return m_pcvExtremes[((direction.x < 0.0) ? 0 : 1) +
  273. ((direction.y < 0.0) ? 0 : 2) +
  274. ((direction.z < 0.0) ? 0 : 4)];
  275. }
  276. void CalculateExtremeVertices(void)
  277. {
  278. static const float octants[][3] = {
  279. {-1.0f, -1.0f, -1.0f},
  280. { 1.0f, -1.0f, -1.0f},
  281. {-1.0f, 1.0f, -1.0f},
  282. { 1.0f, 1.0f, -1.0f},
  283. {-1.0f, -1.0f, 1.0f},
  284. { 1.0f, -1.0f, 1.0f},
  285. {-1.0f, 1.0f, 1.0f},
  286. { 1.0f, 1.0f, 1.0f}
  287. };
  288. //Pre-find the extreme vertices in each octant
  289. for (int octant = 0; (octant < 8); octant++)
  290. {
  291. const Vector& direction = *((Vector*)(octants[octant]));
  292. const ConvexVertex* pcv = vertex0();
  293. double dotMax = direction * pcv->m_position;
  294. while (true)
  295. {
  296. const ConvexVertex* pcvNext = NULL;
  297. const ConvexVertex** ppcvAdjacent = pcv->m_adjacencies;
  298. do
  299. {
  300. double dot = direction * (*ppcvAdjacent)->m_position;
  301. if (dot > dotMax)
  302. {
  303. dotMax = dot;
  304. pcvNext = (*ppcvAdjacent);
  305. }
  306. }
  307. while (*(++ppcvAdjacent) != NULL);
  308. if (pcvNext)
  309. pcv = pcvNext;
  310. else
  311. {
  312. m_pcvExtremes[octant] = pcv;
  313. break;
  314. }
  315. }
  316. }
  317. }
  318. const Vector& GetCenter(void) const
  319. {
  320. return m_center;
  321. }
  322. private:
  323. const ConvexVertex* vertex0(void) const
  324. {
  325. return ((const ConvexVertex*)(((char*)this) + sizeof(*this)));
  326. }
  327. const ConvexVertex** adjacency0(void) const
  328. {
  329. return ((const ConvexVertex**)(vertex0() + m_nVertices));
  330. }
  331. int m_nVertices;
  332. const ConvexVertex* m_pcvExtremes[8];
  333. Vector m_center;
  334. friend class BoundingHull;
  335. friend class HitTest;
  336. };
  337. class MultiHull : public MultiHullBase
  338. {
  339. public:
  340. MultiHull(int nHulls,
  341. float originalRadius,
  342. const Vector& ellipseEquation,
  343. float ellipseRadiusMultiplier)
  344. :
  345. MultiHullBase(ellipseEquation, originalRadius),
  346. m_nHulls(nHulls),
  347. //m_ellipseEquation(ellipseEquation),
  348. m_ellipseRadiusMultiplier(ellipseRadiusMultiplier)
  349. {
  350. }
  351. ~MultiHull(void)
  352. {
  353. for (int i = 0; (i < m_nHulls); i++)
  354. delete GetSingleHull(i);
  355. }
  356. void* operator new(size_t size, int nHulls)
  357. {
  358. return (void*)(::new char [size +
  359. sizeof(SingleHull*) * nHulls]);
  360. }
  361. int GetNhulls(void) const
  362. {
  363. return m_nHulls;
  364. }
  365. SingleHull* GetSingleHull(int hullID) const
  366. {
  367. assert (hullID >= 0);
  368. assert (hullID < m_nHulls);
  369. return hull0()[hullID];
  370. }
  371. private:
  372. SingleHull** hull0(void) const
  373. {
  374. return ((SingleHull**)(((char*)this) + sizeof(*this)));
  375. }
  376. int m_nHulls;
  377. float m_ellipseRadiusMultiplier; //>= m_originalRadius
  378. //Vector m_ellipseEquation; //(x/ee.x)^2 + (y/ee.y)^2 + (z/ee.z)^2 <= 1
  379. friend class BoundingHull;
  380. friend class HitTest;
  381. };
  382. class BoundingHull : public HitTest
  383. {
  384. public:
  385. BoundingHull(IObject* d,
  386. bool staticF,
  387. const MultiHull* pMultiHull)
  388. :
  389. HitTest(d, pMultiHull->m_originalRadius, staticF, pMultiHull->GetNhulls()),
  390. m_pMultiHull(pMultiHull)
  391. {
  392. const ConvexVertex** pcvRecent = recentVertex0();
  393. for (int i = pMultiHull->GetNhulls() - 1; (i >= 0); i--)
  394. pcvRecent[i] = pMultiHull->GetSingleHull(i)->vertex0();
  395. }
  396. void* operator new(size_t size, const MultiHull* pMultiHull)
  397. {
  398. return (void*)(::new char [size +
  399. sizeof(ConvexVertex*) * pMultiHull->GetNhulls()]);
  400. }
  401. virtual void UpdateStaticBB(void)
  402. {
  403. HitTest::UpdateStaticBB(m_desiredRadius * m_pMultiHull->m_ellipseRadiusMultiplier);
  404. }
  405. Vector GetCenter(HitTestShape hts) const
  406. {
  407. assert (hts >= c_htsConvexHullMin);
  408. return m_pMultiHull->GetSingleHull(hts)->GetCenter() * m_scale;
  409. }
  410. Vector GetEllipseExtreme(const Vector& direction)
  411. {
  412. //Get the extreme point of an ellipse in direction
  413. //The ellipse equation is: (x/a)^2 + (y/b)^2 + (z/c)^2 <= 1
  414. //
  415. //The normal to the ellipse at (x,y,z) is (x/a^2, y/b^2, z/c^2)
  416. //and the normal must be parallel to the direction. Therefore:
  417. // direction = Dxyz = k * (x/a^2, y/b^2, z/c^2)
  418. // x = a^2 Dx/k, y = b^2 Dy/k, z = c^2 Dz / k
  419. // and a^2 Dx^2 + b^2 Dy^2 + c^2 Dz^2 = k^2
  420. double a2 = m_ellipseEquation.x * m_ellipseEquation.x;
  421. double b2 = m_ellipseEquation.y * m_ellipseEquation.y;
  422. double c2 = m_ellipseEquation.z * m_ellipseEquation.z;
  423. double rk = 1.0 / sqrt(a2 * direction.x * direction.x +
  424. b2 * direction.y * direction.y +
  425. c2 * direction.z * direction.z);
  426. Vector extreme((float)(direction.x * a2 * rk),
  427. (float)(direction.y * b2 * rk),
  428. (float)(direction.z * c2 * rk));
  429. return extreme;
  430. }
  431. #pragma optimize ("p", on)
  432. Vector GetHullExtreme(int hullID, const Vector& direction)
  433. {
  434. assert (hullID >= 0);
  435. assert (hullID < m_pMultiHull->GetNhulls());
  436. assert (direction.LengthSquared() >= 0.98f);
  437. assert (direction.LengthSquared() <= 1.02f);
  438. assert (m_pMultiHull);
  439. const ConvexVertex** ppcvRecent = &(recentVertex0()[hullID]);
  440. assert (ppcvRecent);
  441. const ConvexVertex* pcv = *ppcvRecent;
  442. assert (pcv);
  443. float dotMax = direction * pcv->m_position;
  444. if (dotMax < 0.0)
  445. {
  446. pcv = m_pMultiHull->GetSingleHull(hullID)->GetExtremeVertex(direction);
  447. dotMax = direction * pcv->m_position;
  448. }
  449. int n = 0;
  450. while (true)
  451. {
  452. //Hack to verify that FPU round-off error will not cause an infinite loop in retail
  453. n++;
  454. ZRetailAssert (n < 300);
  455. const ConvexVertex* pcvNext = NULL;
  456. const ConvexVertex** ppcvAdjacent = pcv->m_adjacencies;
  457. do
  458. {
  459. float dot = direction * (*ppcvAdjacent)->m_position;
  460. #ifdef _M_IX86 // should only be a problem on x86 CPUs
  461. __asm lea eax, [dot];
  462. #endif
  463. if (dot > dotMax)
  464. {
  465. dotMax = dot;
  466. pcvNext = (*ppcvAdjacent);
  467. }
  468. }
  469. while (*(++ppcvAdjacent) != NULL);
  470. if (pcvNext)
  471. pcv = pcvNext;
  472. else
  473. {
  474. *ppcvRecent = pcv;
  475. return pcv->m_position * m_scale;
  476. }
  477. }
  478. }
  479. #pragma optimize ("", on)
  480. virtual void SetShape(HitTestShape shape)
  481. {
  482. //Never upgrade to anything more complex than our true shape
  483. HitTestShape s = (shape <= m_shapeTrue) ? shape : m_shapeTrue;
  484. if (s != m_shape)
  485. {
  486. m_shape = s;
  487. if (m_shape == c_htsEllipse)
  488. m_radius = m_desiredRadius * m_pMultiHull->m_ellipseRadiusMultiplier;
  489. else
  490. m_radius = m_desiredRadius;
  491. }
  492. }
  493. virtual void SetRadius(float r)
  494. {
  495. m_desiredRadius = r;
  496. m_scale = r / m_pMultiHull->m_originalRadius;
  497. m_ellipseEquation = m_scale * m_pMultiHull->GetEllipseEquation();
  498. //Add a fudge factor to the bounding sphere for an ellipse
  499. //which is generally larger than the bounding sphere for either
  500. //a sphere or a convex hull.
  501. if (m_shape == c_htsEllipse)
  502. m_radius = r * m_pMultiHull->m_ellipseRadiusMultiplier;
  503. else
  504. m_radius = r;
  505. }
  506. virtual float GetScale(void) const
  507. {
  508. return m_scale;
  509. }
  510. virtual const Vector* GetEllipseEquation(void) const
  511. {
  512. return &m_ellipseEquation;
  513. }
  514. const Vector GetFrameOffset(const char* pszFrameName) const
  515. {
  516. return m_pMultiHull->GetFrameOffset(pszFrameName) * m_scale;
  517. }
  518. const Vector& GetFrameForward(const char* pszFrameName) const
  519. {
  520. return m_pMultiHull->GetFrameOffset(pszFrameName);
  521. }
  522. const FrameDataUTL* GetFrame(const char* pszFrameName) const
  523. {
  524. return m_pMultiHull->GetFrame(pszFrameName);
  525. }
  526. private:
  527. const ConvexVertex** recentVertex0(void) const
  528. {
  529. return ((const ConvexVertex**)(((char*)this) + sizeof(*this)));
  530. }
  531. float m_desiredRadius;
  532. float m_scale;
  533. Vector m_ellipseEquation;
  534. const MultiHull* m_pMultiHull;
  535. };
  536. class CachedMultiHull
  537. {
  538. public:
  539. ~CachedMultiHull(void)
  540. {
  541. delete m_pMultiHull;
  542. }
  543. char m_name[c_cbName];
  544. MultiHull* m_pMultiHull;
  545. friend bool operator!=(const CachedMultiHull& r1, const CachedMultiHull& r2)
  546. {
  547. return false;
  548. }
  549. };
  550. typedef Slist_utl<CachedMultiHull> CachedList;
  551. typedef Slink_utl<CachedMultiHull> CachedLink;
  552. CachedList cachedMultiHulls;
  553. MultiHullBase* HitTest::Load(const char* pszFileName)
  554. {
  555. if ((!pszFileName) || (pszFileName[0] == '\0'))
  556. return NULL;
  557. MultiHull* pMultiHull = NULL;
  558. #ifndef DREAMCAST
  559. //Does the name exist in the cache?
  560. //It could exist but be a non-existant hull
  561. bool bFound = false;
  562. {
  563. for (CachedLink* pcl = cachedMultiHulls.first();
  564. (pcl != NULL);
  565. pcl = pcl->next())
  566. {
  567. const CachedMultiHull& cmh = pcl->data();
  568. if (_stricmp(pszFileName, cmh.m_name) == 0)
  569. {
  570. pMultiHull = cmh.m_pMultiHull;
  571. bFound = true;
  572. break;
  573. }
  574. }
  575. }
  576. if (!bFound)
  577. {
  578. assert (pMultiHull == NULL);
  579. //First time we've seen this file ... read it in.
  580. char artwork[MAX_PATH];
  581. HRESULT hr = UTL::getFile(pszFileName, ".cvh", artwork,
  582. true, true);
  583. if (hr == S_OK) //Don't bother to try and read a file that doesn't contain a valid convex hull
  584. {
  585. FILE* fileIn = fopen(artwork, "r");
  586. if (fileIn)
  587. {
  588. const int c_maxLine = 512;
  589. char line[c_maxLine];
  590. float radius;
  591. Vector ee; //ellipse equation
  592. float erm;
  593. if (fgets(line, c_maxLine, fileIn) &&
  594. (sscanf(line, "%f %f %f %f %f",
  595. &radius, &ee.x, &ee.y, &ee.z, &erm) == 5))
  596. {
  597. int nHulls;
  598. if (fgets(line, c_maxLine, fileIn) &&
  599. (sscanf(line, "%d",
  600. &nHulls) == 1))
  601. {
  602. assert (nHulls > 0);
  603. assert (nHulls < c_htsConvexHullMax);
  604. pMultiHull = new(nHulls) MultiHull(nHulls, radius, ee, erm);
  605. SingleHull** ppsh = pMultiHull->hull0();
  606. for (int hullID = nHulls - 1; (hullID >= 0); hullID--)
  607. {
  608. int nVertices;
  609. int nAdjacencies;
  610. Vector center;
  611. if (fgets(line, c_maxLine, fileIn) &&
  612. (sscanf(line, "%d %d %f %f %f",
  613. &nVertices, &nAdjacencies,
  614. &(center.x), &(center.y), &(center.z)) == 5))
  615. {
  616. assert (nVertices > 0);
  617. assert (nAdjacencies > 0);
  618. //Same LHS nonsense as for vertices.
  619. center.x = -center.x;
  620. SingleHull* psh = new(nVertices, nAdjacencies) SingleHull(nVertices, center);
  621. *(ppsh++) = psh;
  622. //Hack alert: force a cast away from constness so that we can modify the vertex
  623. //as we read it in.
  624. ConvexVertex* pcv = (ConvexVertex*)(psh->vertex0());
  625. const ConvexVertex** ppcvAdjacent = psh->adjacency0();
  626. //Read in the vertices and their adjacency information.
  627. do
  628. {
  629. Vector xyz;
  630. int n;
  631. if (fgets(line, c_maxLine, fileIn) &&
  632. (sscanf(line, "%f %f %f %d", &xyz.x, &xyz.y, &xyz.z, &n) == 4))
  633. {
  634. assert (n > 0);
  635. //NYI hack, hack, hack ... objects are yaw'd 180 degrees so apply the same
  636. //transformation the vertices in the convex hull
  637. xyz.x = -xyz.x;
  638. //Initialize the vertex
  639. pcv->SetPosition(xyz);
  640. pcv->m_adjacencies = ppcvAdjacent;
  641. //Read in the adjacent vertex information
  642. do
  643. {
  644. int id;
  645. if (fscanf(fileIn, "%d ", &id) == 1)
  646. {
  647. nAdjacencies--;
  648. assert (nAdjacencies >= 0);
  649. *(ppcvAdjacent++) = psh->vertex0() + id;
  650. }
  651. else
  652. assert (false);
  653. }
  654. while (--n);
  655. *(ppcvAdjacent++) = NULL;
  656. }
  657. else
  658. assert (false);
  659. pcv++;
  660. }
  661. while (--nVertices);
  662. assert (nAdjacencies == 0);
  663. psh->CalculateExtremeVertices();
  664. }
  665. }
  666. }
  667. }
  668. while (fgets(line, c_maxLine, fileIn))
  669. {
  670. FrameLink* pfl = new FrameLink;
  671. FrameDataUTL* pfd = &(pfl->data());
  672. assert (strlen(line) > 0);
  673. assert (strlen(line) < c_cbFrameName);
  674. line[strlen(line) - 1] = '\0'; //Trim off the \n
  675. strcpy(pfd->szName, line);
  676. ZVerify(fgets(line, c_maxLine, fileIn));
  677. sscanf(line, "%f %f %f",
  678. &(pfd->position.x),
  679. &(pfd->position.y),
  680. &(pfd->position.z));
  681. ZVerify(fgets(line, c_maxLine, fileIn));
  682. sscanf(line, "%f %f %f",
  683. &(pfd->forward.x),
  684. &(pfd->forward.y),
  685. &(pfd->forward.z));
  686. //Hack ... objects are flipped when they are read in so do it for the frames as well.
  687. pfd->position.x = -pfd->position.x;
  688. //Forward directions are completely reversed (and need X flipped ... so flip y & z)
  689. pfd->forward.y = -pfd->forward.y;
  690. pfd->forward.z = -pfd->forward.z;
  691. pMultiHull->m_frames.last(pfl);
  692. }
  693. fclose(fileIn);
  694. }
  695. }
  696. //Create a cache entry for this convex hull file (whether or not we were
  697. //actually able to load the .cvh file)
  698. {
  699. CachedLink* pcl = new CachedLink;
  700. CachedMultiHull& cmh = pcl->data();
  701. assert (strlen(pszFileName) < c_cbName);
  702. strcpy(cmh.m_name, pszFileName);
  703. cmh.m_pMultiHull = pMultiHull;
  704. //Put it at the front of the list (since we might read another one in real soon).
  705. cachedMultiHulls.first(pcl);
  706. }
  707. }
  708. #endif
  709. return pMultiHull;
  710. }
  711. HitTest* HitTest::Create(const char* pszFileName,
  712. IObject* data,
  713. bool staticF,
  714. HitTestShape htsDefault)
  715. {
  716. HitTest* pHitTest = NULL;
  717. #ifndef DREAMCAST
  718. if (pszFileName)
  719. {
  720. //An unsafe upcast ... but we know better.
  721. MultiHull* pMultiHull = (MultiHull*)Load(pszFileName);
  722. if (pMultiHull)
  723. {
  724. pHitTest = new (pMultiHull) BoundingHull(data, staticF, pMultiHull);
  725. }
  726. }
  727. #endif //dreamcast
  728. if (!pHitTest)
  729. {
  730. switch (htsDefault)
  731. {
  732. case c_htsSphere:
  733. pHitTest = (HitTest*)(new BoundingSphere(data, staticF));
  734. break;
  735. case c_htsPoint:
  736. pHitTest = (HitTest*)(new BoundingPoint(data, staticF));
  737. break;
  738. case c_htsCone:
  739. pHitTest = (HitTest*)(new BoundingCone(data, staticF));
  740. break;
  741. default:
  742. assert (false);
  743. }
  744. }
  745. return pHitTest;
  746. }
  747. Vector HitTest::GetMinExtreme(HitTestShape hts,
  748. const Vector& position,
  749. const Orientation& orientation,
  750. const Vector& direction)
  751. {
  752. switch (hts)
  753. {
  754. case c_htsPoint:
  755. return position;
  756. case c_htsEllipse:
  757. return position + ((BoundingHull*)this)->GetEllipseExtreme(orientation.TimesInverse(-direction)) * orientation;
  758. case c_htsCone:
  759. return position + ((BoundingCone*)this)->GetExtreme(orientation.TimesInverse(-direction)) * orientation;
  760. case c_htsSphere:
  761. return position - direction * m_radius;
  762. default:
  763. return position + ((BoundingHull*)this)->GetHullExtreme(hts, orientation.TimesInverse(-direction)) * orientation;
  764. }
  765. }
  766. Vector HitTest::GetMaxExtreme(HitTestShape hts,
  767. const Vector& direction)
  768. {
  769. switch (hts)
  770. {
  771. case c_htsPoint:
  772. return Vector::GetZero();
  773. case c_htsEllipse:
  774. return ((BoundingHull*)this)->GetEllipseExtreme(direction);
  775. case c_htsCone:
  776. return ((BoundingCone*)this)->GetExtreme(direction);
  777. case c_htsSphere:
  778. return direction * m_radius;
  779. default:
  780. return ((BoundingHull*)this)->GetHullExtreme(hts, direction);
  781. }
  782. }
  783. static bool DoGilbert(HitTest* phtObjectA,
  784. HitTestShape htsA,
  785. const Vector& positionStart,
  786. const Vector& positionStop,
  787. const Vector& dV,
  788. const Orientation& orientationHullA,
  789. HitTest* phtObjectB,
  790. HitTestShape htsB,
  791. Vector simplex[4]);
  792. bool HitTest::HullCollide(float* tStart,
  793. float tMax,
  794. HitTest* phtHullA,
  795. HitTestShape* phtsA,
  796. HitTest* phtHullB,
  797. HitTestShape* phtsB,
  798. const Vector& dP,
  799. const Vector& dV)
  800. {
  801. assert (tStart);
  802. assert (phtHullA);
  803. assert (phtHullB);
  804. //In general, phtHullB is more complex than phtHullA ... so optimize things to minimize the manipulations of phtHullB
  805. //In particular, re-orient everything so that we are in B's local coordinate space (dP & dV are aready wrt B).
  806. const Orientation& oB = phtHullB->GetOrientation();
  807. //A common special case is a c_htsPoint vs. c_htsEllipse, so test that explicitly
  808. if ((phtHullA->m_shape == c_htsPoint) && (phtHullB->m_shape == c_htsEllipse))
  809. {
  810. Vector p = oB.TimesInverse(dP - *tStart * dV);
  811. //Point vs. ellipse ... distort the coordinate system based on the ellipse equation of phtHullB (which we can do since we
  812. //are in phtHullB's local coordinate system).
  813. const Vector& ee = *(phtHullB->GetEllipseEquation());
  814. //Now ... when does a point starting at p and moving -v intersect a sphere with radius 1.0 around the origin
  815. //P(t) = p - v * t; P(t)^2 = 1 = p*p - 2v*p*t + v*v*t^2
  816. //
  817. //v*v*t^2 - 2v*p*t + p*p-1 = 0
  818. //(v*v/2) t^2 - v*p t + ((p*p-1)/2) = 0
  819. //
  820. //(a/2) t^2 - b t + (c/2) = 0
  821. // t = (b +- sqrt(b*b-4(a/2)(c/2))) / (2 * (a/2)) = (b +- sqrt(b*b-ac)) / a
  822. p.x /= ee.x;
  823. p.y /= ee.y;
  824. p.z /= ee.z;
  825. double c = p * p - 1.0;
  826. if (c <= 0.0)
  827. {
  828. //Special case ... point is on or inside the ellipse at the start of the interval
  829. *phtsA = phtHullA->m_shape;
  830. *phtsB = phtHullB->m_shape;
  831. return true;
  832. }
  833. //c > 0
  834. Vector v = oB.TimesInverse(dV);
  835. v.x /= ee.x;
  836. v.y /= ee.y;
  837. v.z /= ee.z;
  838. double b = v * p;
  839. if (b > 0.0)
  840. {
  841. //The point is moving closer to the ellipse ... continue
  842. double a = v * v; //>= 0
  843. double bac = b*b - a * c; //a*c >= 0.0 so bac <= b*b
  844. if (bac >= 0.0)
  845. {
  846. //Starting from *tStart so ... calculate time time of collision appropriately
  847. float t = *tStart + float((b - sqrt(bac)) / a);
  848. if (t <= tMax)
  849. {
  850. *tStart = t;
  851. *phtsA = phtHullA->m_shape;
  852. *phtsB = phtHullB->m_shape;
  853. return true;
  854. }
  855. }
  856. }
  857. return false;
  858. }
  859. else
  860. {
  861. Vector p = oB.TimesInverse(dP);
  862. Vector v = oB.TimesInverse(dV);
  863. const Orientation& oA = phtHullA->GetOrientation();
  864. Orientation o = oA.TimesInverse(oB); // == oA * oB^-1
  865. const double c_maxDelta = 0.25;
  866. double speed = dV.Length();
  867. //Hack alert ... only phtHullB should be subject to the on the fly adjustment
  868. //of the hit test shape ... so fiddle with their shape.
  869. HitTestShape htsA = phtHullA->m_shape;
  870. HitTestShape htsB = ((phtHullB->m_pvUseTrueShapeSelf == NULL) ||
  871. (phtHullB->m_pvUseTrueShapeSelf != phtHullA->m_pvUseTrueShapeOther)) ? phtHullB->m_shape : phtHullB->m_shapeTrue;
  872. HitTestShape htsAcurrent = (htsA < 0) ? htsA : 0;
  873. float tOriginalStart = *tStart;
  874. bool bCollision = false;
  875. do
  876. {
  877. HitTestShape htsBcurrent = (htsB < 0) ? htsB : 0;
  878. do
  879. {
  880. if (HitTest::IntervalCollide(tOriginalStart, tMax, (speed == 0.0) ? FLT_MAX : (float)(c_maxDelta / speed),
  881. phtHullA, htsAcurrent,
  882. phtHullB, htsBcurrent,
  883. p, v, o,
  884. tStart))
  885. {
  886. bCollision = true;
  887. *phtsA = htsAcurrent;
  888. *phtsB = htsBcurrent;
  889. tMax = *tStart; //No point in worrying about collisions that happen after colliding with another part
  890. }
  891. }
  892. while (++htsBcurrent < htsB);
  893. }
  894. while (++htsAcurrent < htsA);
  895. return bCollision;
  896. }
  897. }
  898. bool HitTest::IntervalCollide(float tStart,
  899. float tStop,
  900. float maxDeltaT,
  901. HitTest* phtHullA,
  902. HitTestShape htsA,
  903. HitTest* phtHullB,
  904. HitTestShape htsB,
  905. const Vector& dP,
  906. const Vector& dV,
  907. const Orientation& orientationA,
  908. float* tCollision)
  909. {
  910. float tMiddle = (tStart + tStop) / 2.0f;
  911. //Do the two convex hulls intersect anywhere along the interval between *tCollision and tMax?
  912. Vector direction = dP - tMiddle * dV;
  913. if (htsA >= c_htsConvexHullMin)
  914. direction += phtHullA->GetCenter(htsA) * orientationA;
  915. if (htsB >= c_htsConvexHullMin)
  916. direction -= phtHullB->GetCenter(htsB);
  917. if ((direction.x == 0.0f) && (direction.y == 0.0f) && (direction.z == 0.0f))
  918. return true;
  919. direction.SetNormalize();
  920. Vector positionStart = (dP - tStart * dV);
  921. Vector positionStop = (dP - tStop * dV);
  922. //Try 4 times, saving each result to see if we
  923. //can find a plane that clearly puts the sphere
  924. //outside the hull
  925. const int c_maxAttempts = 4;
  926. Vector extremesHullB[c_maxAttempts];
  927. Vector extremesHullA[c_maxAttempts];
  928. int attempt = 0;
  929. while (true)
  930. {
  931. //For hull A, the extreme is found by takeing the extreme in the given direction and then
  932. //offsetting it by the position at start or the end of the interval (which ever is appropriate:
  933. //there are two sets of negation cancelling out here).
  934. extremesHullA[attempt] = phtHullA->GetMinExtreme(htsA, (direction * dV) >= 0.0f ? positionStop : positionStart,
  935. orientationA, direction);
  936. extremesHullB[attempt] = phtHullB->GetMaxExtreme(htsB, direction);
  937. Vector delta = extremesHullA[attempt] - extremesHullB[attempt];
  938. double distance = (delta * direction);
  939. if (distance > 0.0)
  940. {
  941. //There is no collision anywyare along the interval ... bye
  942. return false;
  943. }
  944. else if (attempt++ >= c_maxAttempts - 1)
  945. break;
  946. //Didn't find a good separating plane ... munge direction in the hopes of finding a better one
  947. //reflect direction around the vector from the extreme to the sphere
  948. //Get the vector from direction to its projection onto -delta
  949. direction -= delta * (2.0f * (direction * delta) / delta.LengthSquared());
  950. assert (direction.Length() >= 0.98f);
  951. assert (direction.Length() <= 1.02f);
  952. }
  953. //We made 4 attempts to find a separating plane and failed.
  954. //Invoke Gilbert's algorithm.
  955. Vector simplex[4];
  956. {
  957. int i = 0;
  958. do
  959. simplex[i] = extremesHullA[i] - extremesHullB[i];
  960. while (i++ < 3);
  961. }
  962. if (!DoGilbert(phtHullA, htsA, positionStart, positionStop, dV, orientationA,
  963. phtHullB, htsB, simplex))
  964. {
  965. //No collision ... also bye
  966. return false;
  967. }
  968. //We have a collision somewhere along the interval ...
  969. if (tStop - tStart <= maxDeltaT)
  970. {
  971. //The interval is small enough that we really do not care any more.
  972. *tCollision = tMiddle;
  973. return true;
  974. }
  975. else //split the interval in two and try again
  976. return IntervalCollide(tStart, tMiddle, maxDeltaT, phtHullA, htsA, phtHullB, htsB, dP, dV, orientationA, tCollision) ||
  977. IntervalCollide(tMiddle, tStop, maxDeltaT, phtHullA, htsA, phtHullB, htsB, dP, dV, orientationA, tCollision);
  978. }
  979. static int closest_vertex(int v0,
  980. const Vector p[],
  981. //double lambda[],
  982. int index[],
  983. Vector* cp)
  984. {
  985. //lambda[0] = 1;
  986. index[0] = v0;
  987. *cp = p[v0];
  988. return 1;
  989. }
  990. static int closest_edge(double e0,
  991. double e1,
  992. int ie0,
  993. int ie1,
  994. const Vector p[],
  995. int index[],
  996. Vector* cp)
  997. {
  998. double esum_inv = 1.0f/(e0+e1);
  999. float lambda[2];
  1000. lambda[0] = (float)(e0*esum_inv);
  1001. lambda[1] = (float)(e1*esum_inv);
  1002. index[0] = ie0;
  1003. index[1] = ie1;
  1004. *cp = lambda[0] * p[ie0] + lambda[1] * p[ie1];
  1005. return 2;
  1006. }
  1007. static int closest_face(double f0,
  1008. double f1,
  1009. double f2,
  1010. int if0,
  1011. int if1,
  1012. int if2,
  1013. const Vector p[],
  1014. //double lambda[],
  1015. int index[],
  1016. Vector* cp)
  1017. {
  1018. double fsum_inv = 1.0 / (f0+f1+f2);
  1019. float lambda[3];
  1020. lambda[0] = (float)(f0*fsum_inv);
  1021. lambda[1] = (float)(f1*fsum_inv);
  1022. lambda[2] = (float)(f2*fsum_inv);
  1023. index[0] = if0;
  1024. index[1] = if1;
  1025. index[2] = if2;
  1026. *cp = lambda[0] * p[if0] +
  1027. lambda[1] * p[if1] +
  1028. lambda[2] * p[if2];
  1029. return 3;
  1030. }
  1031. /*
  1032. Johnson algorithm for tetrahedron
  1033. Johnson's algorithm for finding the closest point to the origin on a simplex (3d).
  1034. Inputs:
  1035. p -- array of n 3d points forming the simplex
  1036. n -- number of points, must be 1, 2, 3, or 4.
  1037. Outputs:
  1038. cp -- closest point to origin on simplex
  1039. index -- indices of simplex points forming feature closest to origin {in increasing order]
  1040. lambda -- coefficients of above indexed points forming cp
  1041. Each coefficient is nonnegative and their sum is 1.
  1042. Returns: number of simplex points forming closest feature:
  1043. 1 = vertex
  1044. 2 = edge
  1045. 3 = face
  1046. 4 = tetrahedron (inside simplex interior)
  1047. The return value is always <= n and >= 1.
  1048. */
  1049. static int Johnson2(const Vector p[2],
  1050. Vector* cp,
  1051. int index[])
  1052. {
  1053. Vector d = p[1] - p[0];
  1054. double l0 = p[0] * d;
  1055. if (l0 >= 0)
  1056. {
  1057. *cp = p[0];
  1058. index[0] = 0;
  1059. return 1;
  1060. }
  1061. double l1 = p[1] * d; //Note ... sense is reversed wrt l0
  1062. if (l1 <= 0)
  1063. {
  1064. *cp = p[1];
  1065. index[0] = 1;
  1066. return 1;
  1067. }
  1068. index[0] = 0;
  1069. index[1] = 1;
  1070. *cp = p[0] + (float)(l0 / (l0 - l1)) * d;
  1071. return 2;
  1072. }
  1073. /*
  1074. #define DOT(a,b) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] )
  1075. static
  1076. int jsny3(double *p,double cp[3], int index[])
  1077. {
  1078. double d[3][3]; // array of dot products d[i][j] = <p[i],p[j]>
  1079. double d2[3][2]; // array of D_k{i,j} encoded as [l][0 if k=i, 1 if k=j] i < j, k in {i,j}
  1080. // where l=0 -> {0,1}, l=1 -> {1,2}, l=2 -> {0,2}
  1081. double d3[3]; // array of D_l{i,j,k} encoded as [l], i < j < k, l in {i,j,k}
  1082. register double *pi,*pj;
  1083. register int i,j;
  1084. //double min;
  1085. //int n_min;
  1086. // compute dot products
  1087. pi = p;
  1088. for (i = 0; i < 3; i++) {
  1089. pj = pi;
  1090. for (j = i; j < 3; j++) {
  1091. d[i][j] = d[j][i] = DOT(pi,pj);
  1092. pj += 3;
  1093. }
  1094. pi += 3;
  1095. }
  1096. // compute D2
  1097. d2[0][0] = d[1][1] - d[1][0];
  1098. d2[0][1] = d[0][0] - d[0][1];
  1099. d2[1][0] = d[2][2] - d[2][1];
  1100. d2[1][1] = d[1][1] - d[1][2];
  1101. d2[2][0] = d[2][2] - d[2][0];
  1102. d2[2][1] = d[0][0] - d[0][2];
  1103. // compute D3
  1104. d3[0] = d2[1][0]*(d[1][1]-d[1][0]) + d2[1][1]*(d[2][1]-d[2][0]);
  1105. d3[1] = d2[2][0]*(d[0][0]-d[0][1]) + d2[2][1]*(d[2][0]-d[2][1]);
  1106. d3[2] = d2[0][0]*(d[0][0]-d[0][2]) + d2[0][1]*(d[1][0]-d[1][2]);
  1107. debugf("jsny3\n");
  1108. {
  1109. debugf("p[]\n");
  1110. for (int i = 0; (i < 3); i++)
  1111. debugf("%f %f %f\n", p[i*3+0], p[i*3+1], p[i*3+2]);
  1112. debugf("d[][]\n");
  1113. for (int j = 0; (j < 3); j++)
  1114. debugf("%f %f %f\n", d[j][0], d[j][1], d[j][2]);
  1115. debugf("d2[][]\n");
  1116. for (int k = 0; (k < 3); k++)
  1117. debugf("%f %f\n", d2[k][0], d2[k][1]);
  1118. debugf("d3\n");
  1119. debugf("%f %f %f\n", d3[0], d3[1], d3[2]);
  1120. }
  1121. return 0;
  1122. }
  1123. */
  1124. static int Johnson3(const Vector p[3],
  1125. Vector* cp,
  1126. int index[])
  1127. {
  1128. //Mappings between all possible subsets of the vertices and a
  1129. //unique subset ID.
  1130. // subset1[i] ({Pi})
  1131. // subset2[i][j] ({Pi, Pj}) i != j
  1132. // subset3 ({P0, P1, P2})
  1133. static const int subset1[3] = { 0, 1, 2};
  1134. static const int subset2[3][3] = {{-1, 3, 4},
  1135. { 3, -1, 5},
  1136. { 4, 5, -1}};
  1137. static const int subset3 = 6;
  1138. double dp[3][3];
  1139. {
  1140. for (int i = 0; (i < 3); i++)
  1141. for (int j = i; (j < 3); j++)
  1142. dp[i][j] = dp[j][i] = (double)(p[i].x) * (double)(p[j].x) +
  1143. (double)(p[i].y) * (double)(p[j].y) +
  1144. (double)(p[i].z) * (double)(p[j].z);
  1145. }
  1146. double delta[3][subset3 + 1];
  1147. //Generic form: delta[i][{Pi}] = 1.0
  1148. // but don't bother
  1149. {
  1150. //Generic form: delta[i][{Pj} | {Pi}] = Pj * (Pj - Pi) [i != j]
  1151. // = dp[j][j] - dp[j][i]
  1152. #define SetDelta(i,j) delta[i][subset2[j][i]] = dp[j][j] - dp[j][i]
  1153. SetDelta(1, 0);
  1154. SetDelta(2, 0);
  1155. SetDelta(0, 1);
  1156. SetDelta(2, 1);
  1157. SetDelta(0, 2);
  1158. SetDelta(1, 2);
  1159. #undef SetDelta
  1160. }
  1161. {
  1162. //Generic form: delta[i][{Pj, Pk} | {Pi}] = delta[j][{Pj, Pk}] * (Pj * (Pj - Pi)) + [i != j, k; j < k]
  1163. // delta[k][{Pj, Pk}] * (Pk * (Pj - Pi))
  1164. // = delta[j][{Pj, Pk}] * (dp[j][j] - dp[j][i]) +
  1165. // delta[k][{Pj, Pk}] * (dp[k][j] - dp[k][i])
  1166. // i != j, k; j < k; x != i, j, k
  1167. #define SetDelta(i, j, k) delta[i][subset3] = (delta[j][subset2[j][k]] * (dp[j][j] - dp[j][i])) + \
  1168. (delta[k][subset2[j][k]] * (dp[k][j] - dp[k][i]))
  1169. SetDelta(2, 0, 1);
  1170. SetDelta(1, 0, 2);
  1171. SetDelta(0, 1, 2);
  1172. #undef SetDelta
  1173. }
  1174. //Now that we've done all this ... see if we have a solution
  1175. //We have a valid solution if:
  1176. // delta[i][S] > 0 (for all i in S)
  1177. // delta[j][S | {Pj}] <= 0 (for all j not in S)
  1178. /*
  1179. {
  1180. debugf("p[]\n");
  1181. for (int i = 0; (i < 3); i++)
  1182. debugf("%f %f %f\n", p[i].x, p[i].y, p[i].z);
  1183. debugf("dp[][]\n");
  1184. for (int j = 0; (j < 3); j++)
  1185. debugf("%f %f %f\n", dp[j][0], dp[j][1], dp[j][2]);
  1186. debugf("delta[][]\n");
  1187. debugf("%f %f\n", delta[0][subset2[0][1]], delta[1][subset2[0][1]]);
  1188. debugf("%f %f\n", delta[1][subset2[1][2]], delta[2][subset2[1][2]]);
  1189. debugf("%f %f\n", delta[2][subset2[0][2]], delta[2][subset2[0][2]]);
  1190. debugf("d3\n");
  1191. debugf("%f %f %f\n", delta[0][subset3], delta[1][subset3], delta[2][subset3]);
  1192. }
  1193. */
  1194. //Inside for the triangle. The last clause of the test is degenerate
  1195. //since there is no Pj not in S
  1196. if ((delta[0][subset3] > 0.0) &&
  1197. (delta[1][subset3] > 0.0) &&
  1198. (delta[2][subset3] > 0.0))
  1199. {
  1200. //Yes
  1201. return closest_face(delta[0][subset3], delta[1][subset3], delta[2][subset3],
  1202. 0, 1, 2, p, index, cp);
  1203. }
  1204. {
  1205. //Test for each vertex. The first clause of the test is degerate
  1206. //since delta[i][S[i]] = 1
  1207. //Test for vertex i
  1208. #define TestDelta(i, j, k) if ((delta[i][subset2[j][i]] <= 0.0) && \
  1209. (delta[i][subset2[k][i]] <= 0.0)) \
  1210. return closest_vertex(i, p, index, cp);
  1211. TestDelta(0, 1, 2);
  1212. TestDelta(1, 0, 2);
  1213. TestDelta(2, 0, 1);
  1214. #undef TestDelta
  1215. }
  1216. {
  1217. //Test for each edge i, j
  1218. // delta[i][subset2[i][j]] > 0
  1219. // delta[j][subset2[i][j]] > 0
  1220. //
  1221. // delta[k][subset3[l]] < 0
  1222. // delta[l][subset3[k]] < 0
  1223. #define TestDelta(i, j, k) if ((delta[i][subset2[i][j]] > 0.0) && \
  1224. (delta[j][subset2[i][j]] > 0.0) && \
  1225. (delta[k][subset3] <= 0.0)) \
  1226. return closest_edge(delta[i][subset2[i][j]], \
  1227. delta[j][subset2[i][j]], \
  1228. i, j, p, index, cp)
  1229. TestDelta(0, 1, 2);
  1230. TestDelta(0, 2, 1);
  1231. TestDelta(1, 2, 0);
  1232. #undef TestDelta
  1233. }
  1234. {
  1235. //Test for each face i, j, k
  1236. // delta[i][subset3[l]] > 0
  1237. // delta[j][subset3[l]] > 0
  1238. // delta[k][subset3[l]] > 0
  1239. //
  1240. // delta[l][subset4] <= 0.0f
  1241. #define TestDelta(i, j, k) if ((delta[i][subset3] > 0.0) && \
  1242. (delta[j][subset3] > 0.0) && \
  1243. (delta[k][subset3] > 0.0)) \
  1244. return closest_face(delta[i][subset3], \
  1245. delta[j][subset3], \
  1246. delta[k][subset3], \
  1247. i, j, k, p, index, cp)
  1248. TestDelta(0, 1, 2);
  1249. #undef TestDelta
  1250. }
  1251. //If we haven't found a solution so far (round off or some such) ...
  1252. int nMin;
  1253. double dMin2 = HUGE_VAL;
  1254. {
  1255. //Try the vertices
  1256. int v;
  1257. for (int i = 0; (i < 3); i++)
  1258. {
  1259. if (dp[i][i] < dMin2)
  1260. {
  1261. dMin2 = dp[i][i];
  1262. v = i;
  1263. }
  1264. }
  1265. nMin = closest_vertex(v, p, index, cp);
  1266. }
  1267. {
  1268. //Try the edges
  1269. for (int i = 0; (i < 2); i++)
  1270. {
  1271. for (int j = i + 1; (j < 3); j++)
  1272. {
  1273. if ((delta[i][subset2[i][j]] > 0.0) &&
  1274. (delta[j][subset2[i][j]] > 0.0))
  1275. {
  1276. double d = (delta[i][subset2[i][j]] * dp[i][i] +
  1277. delta[j][subset2[i][j]] * dp[j][i]) /
  1278. (delta[i][subset2[i][j]] + delta[j][subset2[i][j]]);
  1279. if (d < dMin2)
  1280. {
  1281. dMin2 = d;
  1282. nMin = closest_edge(delta[i][subset2[i][j]],
  1283. delta[j][subset2[i][j]],
  1284. i, j, p, index, cp);
  1285. }
  1286. }
  1287. }
  1288. }
  1289. }
  1290. {
  1291. if ((delta[0][subset3] > 0.0) &&
  1292. (delta[1][subset3] > 0.0) &&
  1293. (delta[2][subset3] > 0.0))
  1294. {
  1295. double d = (delta[0][subset3] * dp[0][0] +
  1296. delta[1][subset3] * dp[1][0] +
  1297. delta[2][subset3] * dp[2][0]) /
  1298. (delta[0][subset3] +
  1299. delta[1][subset3] +
  1300. delta[2][subset3]);
  1301. if (d < dMin2)
  1302. {
  1303. dMin2 = d;
  1304. nMin = closest_face(delta[0][subset3],
  1305. delta[1][subset3],
  1306. delta[2][subset3],
  1307. 0, 1, 2, p, index, cp);
  1308. }
  1309. }
  1310. }
  1311. return nMin;
  1312. }
  1313. static int Johnson4(const Vector p[4],
  1314. Vector* cp,
  1315. int index[])
  1316. {
  1317. //Mappings between all possible subsets of the vertices and a
  1318. //unique subset ID.
  1319. // subset1[i] ({Pi})
  1320. // subset2[i][j] ({Pi, Pj}), i != j
  1321. // subset3[i] ({Pj, Pk, Pl}), i != j; i != k; i != l
  1322. // subset4 ({P0, P1, P2, P3})
  1323. static const int subset1[4] = { 0, 1, 2, 3};
  1324. static const int subset2[4][4] = {{-1, 4, 5, 6},
  1325. { 4, -1, 7, 8},
  1326. { 5, 7, -1, 9},
  1327. { 6, 8, 9, -1}};
  1328. static const int subset3[4] = {10, 11, 12, 13};
  1329. static const int subset4 = 14;
  1330. double dp[4][4];
  1331. {
  1332. for (int i = 0; (i < 4); i++)
  1333. for (int j = i; (j < 4); j++)
  1334. dp[i][j] = dp[j][i] = (double)(p[i].x) * (double)(p[j].x) +
  1335. (double)(p[i].y) * (double)(p[j].y) +
  1336. (double)(p[i].z) * (double)(p[j].z);
  1337. }
  1338. double delta[4][subset4 + 1];
  1339. //Generic form: delta[i][{Pi}] = 1.0
  1340. // but don't bother
  1341. {
  1342. //Generic form: delta[i][{Pj} | {Pi}] = Pj * (Pj - Pi) [i != j]
  1343. // = dp[j][j] - dp[j][i]
  1344. #define SetDelta(i,j) delta[i][subset2[j][i]] = dp[j][j] - dp[j][i]
  1345. SetDelta(1, 0);
  1346. SetDelta(2, 0);
  1347. SetDelta(3, 0);
  1348. SetDelta(0, 1);
  1349. SetDelta(2, 1);
  1350. SetDelta(3, 1);
  1351. SetDelta(0, 2);
  1352. SetDelta(1, 2);
  1353. SetDelta(3, 2);
  1354. SetDelta(0, 3);
  1355. SetDelta(1, 3);
  1356. SetDelta(2, 3);
  1357. #undef SetDelta
  1358. }
  1359. {
  1360. //Generic form: delta[i][{Pj, Pk} | {Pi}] = delta[j][{Pj, Pk}] * (Pj * (Pj - Pi)) + [i != j, k; j < k]
  1361. // delta[k][{Pj, Pk}] * (Pk * (Pj - Pi))
  1362. //
  1363. // = delta[j][{Pj, Pk}] * (dp[j][j] - dp[j][i]) +
  1364. // delta[k][{Pj, Pk}] * (dp[k][j] - dp[k][i])
  1365. // i != j, k; j < k; x != i, j, k
  1366. #define SetDelta(i, j, k, x) delta[i][subset3[x]] = (delta[j][subset2[j][k]] * (dp[j][j] - dp[j][i])) + \
  1367. (delta[k][subset2[j][k]] * (dp[k][j] - dp[k][i]))
  1368. SetDelta(2, 0, 1, 3);
  1369. SetDelta(3, 0, 1, 2);
  1370. SetDelta(1, 0, 2, 3);
  1371. SetDelta(3, 0, 2, 1);
  1372. SetDelta(1, 0, 3, 2);
  1373. SetDelta(2, 0, 3, 1);
  1374. SetDelta(0, 1, 2, 3);
  1375. SetDelta(3, 1, 2, 0);
  1376. SetDelta(0, 1, 3, 2);
  1377. SetDelta(2, 1, 3, 0);
  1378. SetDelta(0, 2, 3, 1);
  1379. SetDelta(1, 2, 3, 0);
  1380. #undef SetDelta
  1381. }
  1382. {
  1383. //Generic form: delta[i][{Pj, Pk, Pl} | {Pi}] = delta[j][{Pj, Pk, Pl}] * (Pj * (Pj - Pi)) + [i != j, k, l; j < k, l, k != l]
  1384. // delta[k][{Pj, Pk, Pl}] * (Pk * (Pj - Pi)) +
  1385. // delta[l][{Pj, Pk, Pl}] * (Pl * (Pj - Pi))
  1386. // = delta[j][{Pj, Pk, Pl}] * (dp[j][j] - dp[j][i]) +
  1387. // = delta[j][{Pj, Pk, Pl}] * (dp[k][j] - dp[k][i]) +
  1388. // = delta[j][{Pj, Pk, Pl}] * (dp[k][j] - dp[l][i])
  1389. // i != j, k, l; j < k, l, k != l
  1390. #define SetDelta(i, j, k, l) delta[i][subset4] = delta[j][subset3[i]] * (dp[j][j] - dp[j][i]) + \
  1391. delta[k][subset3[i]] * (dp[k][j] - dp[k][i]) + \
  1392. delta[l][subset3[i]] * (dp[l][j] - dp[l][i])
  1393. SetDelta(0, 1, 2, 3);
  1394. SetDelta(1, 0, 2, 3);
  1395. SetDelta(2, 0, 1, 3);
  1396. SetDelta(3, 0, 1, 2);
  1397. #undef SetDelta
  1398. }
  1399. //Now that we've done all this ... see if we have a solution
  1400. //We have a valid solution if:
  1401. // delta[i][S] > 0 (for all i in S)
  1402. // delta[j][S | {Pj}] <= 0 (for all j not in S)
  1403. //Inside for the tetrahedron. The last clause of the test is degenerate
  1404. //since there is no Pj not in S
  1405. if ((delta[0][subset4] > 0.0) &&
  1406. (delta[1][subset4] > 0.0) &&
  1407. (delta[2][subset4] > 0.0) &&
  1408. (delta[3][subset4] > 0.0))
  1409. {
  1410. //Yes
  1411. *cp = Vector::GetZero();
  1412. return 4;
  1413. }
  1414. {
  1415. //Test for each vertex. The first clause of the test is degerate
  1416. //since delta[i][S[i]] = 1
  1417. //Test for vertex i
  1418. #define TestDelta(i, j, k, l) if ((delta[i][subset2[j][i]] <= 0.0) && \
  1419. (delta[i][subset2[k][i]] <= 0.0) && \
  1420. (delta[i][subset2[l][i]] <= 0.0)) \
  1421. return closest_vertex(i, p, index, cp);
  1422. TestDelta(0, 1, 2, 3);
  1423. TestDelta(1, 0, 2, 3);
  1424. TestDelta(2, 0, 1, 3);
  1425. TestDelta(3, 0, 1, 2);
  1426. #undef TestDelta
  1427. }
  1428. {
  1429. //Test for each edge i, j
  1430. // delta[i][subset2[i][j]] > 0
  1431. // delta[j][subset2[i][j]] > 0
  1432. //
  1433. // delta[k][subset3[l]] < 0
  1434. // delta[l][subset3[k]] < 0
  1435. #define TestDelta(i, j, k, l) if ((delta[i][subset2[i][j]] > 0.0) && \
  1436. (delta[j][subset2[i][j]] > 0.0) && \
  1437. (delta[k][subset3[l]] <= 0.0) && \
  1438. (delta[l][subset3[k]] <= 0.0)) \
  1439. return closest_edge(delta[i][subset2[i][j]], \
  1440. delta[j][subset2[i][j]], \
  1441. i, j, p, index, cp)
  1442. TestDelta(0, 1, 2, 3);
  1443. TestDelta(0, 2, 1, 3);
  1444. TestDelta(0, 3, 1, 2);
  1445. TestDelta(1, 2, 0, 3);
  1446. TestDelta(1, 3, 0, 2);
  1447. TestDelta(2, 3, 0, 1);
  1448. #undef TestDelta
  1449. }
  1450. {
  1451. //Test for each face i, j, k
  1452. // delta[i][subset3[l]] > 0
  1453. // delta[j][subset3[l]] > 0
  1454. // delta[k][subset3[l]] > 0
  1455. //
  1456. // delta[l][subset4] <= 0.0f
  1457. #define TestDelta(i, j, k, l) if ((delta[i][subset3[l]] > 0.0) && \
  1458. (delta[j][subset3[l]] > 0.0) && \
  1459. (delta[k][subset3[l]] > 0.0) && \
  1460. (delta[l][subset4] <= 0.0)) \
  1461. return closest_face(delta[i][subset3[l]], \
  1462. delta[j][subset3[l]], \
  1463. delta[k][subset3[l]], \
  1464. i, j, k, p, index, cp)
  1465. TestDelta(0, 1, 2, 3);
  1466. TestDelta(0, 1, 3, 2);
  1467. TestDelta(0, 2, 3, 1);
  1468. TestDelta(1, 2, 3, 0);
  1469. #undef TestDelta
  1470. }
  1471. //If we haven't found a solution so far (round off or some such) ...
  1472. int nMin;
  1473. double dMin2 = HUGE_VAL;
  1474. {
  1475. //Try the vertices
  1476. int v;
  1477. for (int i = 0; (i < 4); i++)
  1478. {
  1479. if (dp[i][i] < dMin2)
  1480. {
  1481. dMin2 = dp[i][i];
  1482. v = i;
  1483. }
  1484. }
  1485. nMin = closest_vertex(v, p, index, cp);
  1486. }
  1487. {
  1488. //Try the edges
  1489. for (int i = 0; (i < 3); i++)
  1490. {
  1491. for (int j = i + 1; (j < 4); j++)
  1492. {
  1493. if ((delta[i][subset2[i][j]] > 0.0) &&
  1494. (delta[j][subset2[i][j]] > 0.0))
  1495. {
  1496. double d = (delta[i][subset2[i][j]] * dp[i][i] +
  1497. delta[j][subset2[i][j]] * dp[j][i]) /
  1498. (delta[i][subset2[i][j]] + delta[j][subset2[i][j]]);
  1499. if (d < dMin2)
  1500. {
  1501. dMin2 = d;
  1502. nMin = closest_edge(delta[i][subset2[i][j]],
  1503. delta[j][subset2[i][j]],
  1504. i, j, p, index, cp);
  1505. }
  1506. }
  1507. }
  1508. }
  1509. }
  1510. {
  1511. {
  1512. //Try the faces
  1513. const int ids[4][4] = {{0, 1, 2, 3}, {0, 1, 3, 2},
  1514. {0, 2, 3, 1}, {1, 2, 3, 0}};
  1515. for (int f = 0; (f < 4); f++)
  1516. {
  1517. int i = ids[f][0];
  1518. int j = ids[f][1];
  1519. int k = ids[f][2];
  1520. int l = ids[f][3];
  1521. if ((delta[i][subset3[l]] > 0.0) &&
  1522. (delta[j][subset3[l]] > 0.0) &&
  1523. (delta[k][subset3[l]] > 0.0))
  1524. {
  1525. double d = (delta[i][subset3[l]] * dp[i][i] +
  1526. delta[j][subset3[l]] * dp[j][i] +
  1527. delta[k][subset3[l]] * dp[k][i]) /
  1528. (delta[i][subset3[l]] +
  1529. delta[j][subset3[l]] +
  1530. delta[k][subset3[l]]);
  1531. if (d < dMin2)
  1532. {
  1533. dMin2 = d;
  1534. nMin = closest_face(delta[i][subset3[l]],
  1535. delta[j][subset3[l]],
  1536. delta[k][subset3[l]],
  1537. i, j, k, p, index, cp);
  1538. }
  1539. }
  1540. }
  1541. }
  1542. }
  1543. return nMin;
  1544. }
  1545. int Johnson(int n,
  1546. const Vector p[],
  1547. Vector* cp,
  1548. int index[])
  1549. {
  1550. switch (n)
  1551. {
  1552. case 1:
  1553. {
  1554. *cp = p[0];
  1555. index[0] = 0;
  1556. return 1;
  1557. }
  1558. case 2:
  1559. {
  1560. return Johnson2(p, cp, index);
  1561. }
  1562. case 3:
  1563. {
  1564. return Johnson3(p, cp, index);
  1565. }
  1566. default:
  1567. {
  1568. return Johnson4(p, cp, index);
  1569. }
  1570. }
  1571. }
  1572. static bool DoGilbert(HitTest* phtHullA,
  1573. HitTestShape htsA,
  1574. const Vector& positionStart,
  1575. const Vector& positionStop,
  1576. const Vector& dV,
  1577. const Orientation& orientationHullA,
  1578. HitTest* phtHullB,
  1579. HitTestShape htsB,
  1580. Vector simplex[4])
  1581. {
  1582. int nVertices = 3; //Always start with four (but the three is incremented before it is used).
  1583. static const int c_maxHistory = 100;
  1584. static Vector vertexHistory[c_maxHistory];
  1585. vertexHistory[0] = simplex[0];
  1586. vertexHistory[1] = simplex[1];
  1587. vertexHistory[2] = simplex[2];
  1588. vertexHistory[3] = simplex[3];
  1589. int vertexID = 3;
  1590. Vector cp;
  1591. Vector delta;
  1592. while (true)
  1593. {
  1594. int indices[3];
  1595. int nMin = Johnson(++nVertices, simplex, &cp, indices);
  1596. if (nMin == 4)
  1597. {
  1598. return true;
  1599. }
  1600. //Find a new extreme point
  1601. {
  1602. double l2 = cp.LengthSquared();
  1603. if (l2 < epsilon * epsilon)
  1604. return true;
  1605. cp /= (float)sqrt(l2);
  1606. }
  1607. Vector v0 = phtHullA->GetMinExtreme(htsA, (cp * dV >= 0.0f) ? positionStop : positionStart, orientationHullA, cp) -
  1608. phtHullB->GetMaxExtreme(htsB, cp);
  1609. if ((v0 * cp) > 0.0)
  1610. {
  1611. //Found a separating plane
  1612. return false;
  1613. }
  1614. //Have we been here before?
  1615. {
  1616. for (int i = vertexID; (i >= 0); i--)
  1617. {
  1618. if ((vertexHistory[i] - v0).LengthSquared() < epsilon * epsilon)
  1619. {
  1620. //A duplicate point ... so the simplex will not contain the origin.
  1621. return false;
  1622. }
  1623. }
  1624. assert (vertexID < c_maxHistory - 1);
  1625. vertexHistory[++vertexID] = v0;
  1626. }
  1627. //Otherwise ... eliminate all the points from the simplex
  1628. //that are not in the index array (assume the index array
  1629. //is sorted).
  1630. {
  1631. int i = 0;
  1632. do
  1633. {
  1634. if (indices[i] != i)
  1635. {
  1636. assert (indices[i] > i);
  1637. simplex[i] = simplex[indices[i]];
  1638. }
  1639. }
  1640. while (++i < nMin);
  1641. nVertices = i;
  1642. }
  1643. //Replace the last vertex in the simplex array with new vertex
  1644. simplex[nVertices] = v0;
  1645. }
  1646. return false;
  1647. }