convex.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "collision/convex.h"
  24. #include "platform/types.h"
  25. #include "core/dataChunker.h"
  26. #include "collision/collision.h"
  27. #include "scene/sceneObject.h"
  28. #include "collision/gjk.h"
  29. #include "collision/concretePolyList.h"
  30. #include "platform/profiler.h"
  31. //----------------------------------------------------------------------------
  32. //----------------------------------------------------------------------------
  33. static DataChunker sChunker;
  34. CollisionStateList CollisionStateList::sFreeList;
  35. CollisionWorkingList CollisionWorkingList::sFreeList;
  36. F32 sqrDistanceEdges(const Point3F& start0,
  37. const Point3F& end0,
  38. const Point3F& start1,
  39. const Point3F& end1,
  40. Point3F* is,
  41. Point3F* it);
  42. //----------------------------------------------------------------------------
  43. // Collision State
  44. //----------------------------------------------------------------------------
  45. CollisionState::CollisionState()
  46. {
  47. mLista = mListb = 0;
  48. }
  49. CollisionState::~CollisionState()
  50. {
  51. if (mLista)
  52. mLista->free();
  53. if (mListb)
  54. mListb->free();
  55. }
  56. void CollisionState::swap()
  57. {
  58. }
  59. void CollisionState::set(Convex* a,Convex* b,const MatrixF& a2w, const MatrixF& b2w)
  60. {
  61. }
  62. F32 CollisionState::distance(const MatrixF& a2w, const MatrixF& b2w, const F32 dontCareDist,
  63. const MatrixF* w2a, const MatrixF* _w2b)
  64. {
  65. return 0;
  66. }
  67. //----------------------------------------------------------------------------
  68. // Feature Collision
  69. //----------------------------------------------------------------------------
  70. void ConvexFeature::reset()
  71. {
  72. material = NULL;
  73. object = NULL;
  74. mVertexList.clear();
  75. mEdgeList.clear();
  76. mFaceList.clear();
  77. }
  78. bool ConvexFeature::collide(ConvexFeature& cf,CollisionList* cList, F32 tol)
  79. {
  80. // Our vertices vs. other faces
  81. const Point3F* vert = mVertexList.begin();
  82. const Point3F* vend = mVertexList.end();
  83. while (vert != vend) {
  84. cf.testVertex(*vert,cList,false, tol);
  85. vert++;
  86. }
  87. // Other vertices vs. our faces
  88. vert = cf.mVertexList.begin();
  89. vend = cf.mVertexList.end();
  90. while (vert != vend) {
  91. U32 storeCount = cList->getCount();
  92. testVertex(*vert,cList,true, tol);
  93. // Fix up last reference. material and object are copied from this rather
  94. // than the object we're colliding against.
  95. if (storeCount != cList->getCount())
  96. {
  97. Collision &col = (*cList)[cList->getCount() - 1];
  98. col.material = cf.material;
  99. col.object = cf.object;
  100. }
  101. vert++;
  102. }
  103. // Edge vs. Edge
  104. const Edge* edge = mEdgeList.begin();
  105. const Edge* eend = mEdgeList.end();
  106. while (edge != eend) {
  107. cf.testEdge(this,mVertexList[edge->vertex[0]],
  108. mVertexList[edge->vertex[1]],cList, tol);
  109. edge++;
  110. }
  111. return true;
  112. }
  113. inline bool isInside(const Point3F& p, const Point3F& a, const Point3F& b, const VectorF& n)
  114. {
  115. VectorF v;
  116. mCross(n,b - a,&v);
  117. return mDot(v,p - a) < 0.0f;
  118. }
  119. void ConvexFeature::testVertex(const Point3F& v,CollisionList* cList,bool flip, F32 tol)
  120. {
  121. // Test vertex against all faces
  122. const Face* face = mFaceList.begin();
  123. const Face* end = mFaceList.end();
  124. for (; face != end; face++) {
  125. if (cList->getCount() >= CollisionList::MaxCollisions)
  126. return;
  127. const Point3F& p0 = mVertexList[face->vertex[0]];
  128. const Point3F& p1 = mVertexList[face->vertex[1]];
  129. const Point3F& p2 = mVertexList[face->vertex[2]];
  130. // Point near the plane?
  131. F32 distance = mDot(face->normal,v - p0);
  132. if (distance > tol || distance < -tol)
  133. continue;
  134. // Make sure it's within the bounding edges
  135. if (isInside(v,p0,p1,face->normal) && isInside(v,p1,p2,face->normal) &&
  136. isInside(v,p2,p0,face->normal)) {
  137. // Add collision to this face
  138. Collision& info = cList->increment();
  139. info.point = v;
  140. info.normal = face->normal;
  141. if (flip)
  142. info.normal.neg();
  143. info.material = material;
  144. info.object = object;
  145. info.distance = distance;
  146. }
  147. }
  148. }
  149. void ConvexFeature::testEdge(ConvexFeature* cf,const Point3F& s1, const Point3F& e1, CollisionList* cList, F32 tol)
  150. {
  151. F32 tolSquared = tol*tol;
  152. // Test edges against edges
  153. const Edge* edge = mEdgeList.begin();
  154. const Edge* end = mEdgeList.end();
  155. for (; edge != end; edge++) {
  156. if (cList->getCount() >= CollisionList::MaxCollisions)
  157. return;
  158. const Point3F& s2 = mVertexList[edge->vertex[0]];
  159. const Point3F& e2 = mVertexList[edge->vertex[1]];
  160. // Get the distance and closest points
  161. Point3F i1,i2;
  162. F32 distance = sqrDistanceEdges(s1, e1, s2, e2, &i1, &i2);
  163. if (distance > tolSquared)
  164. continue;
  165. distance = mSqrt(distance);
  166. // Need to figure out how to orient the collision normal.
  167. // The current test involves checking to see whether the collision
  168. // points are contained within the convex volumes, which is slow.
  169. if (inVolume(i1) || cf->inVolume(i2))
  170. distance = -distance;
  171. // Contact normal
  172. VectorF normal = i1 - i2;
  173. if ( mIsZero( distance ) )
  174. normal.zero();
  175. else
  176. normal *= 1 / distance;
  177. // Return a collision
  178. Collision& info = cList->increment();
  179. info.point = i1;
  180. info.normal = normal;
  181. info.distance = distance;
  182. info.material = material;
  183. info.object = object;
  184. }
  185. }
  186. bool ConvexFeature::inVolume(const Point3F& v)
  187. {
  188. // Test the point to see if it's inside the volume
  189. const Face* face = mFaceList.begin();
  190. const Face* end = mFaceList.end();
  191. for (; face != end; face++) {
  192. const Point3F& p0 = mVertexList[face->vertex[0]];
  193. if (mDot(face->normal,v - p0) > 0)
  194. return false;
  195. }
  196. return true;
  197. }
  198. //----------------------------------------------------------------------------
  199. // Collision State management
  200. //----------------------------------------------------------------------------
  201. //----------------------------------------------------------------------------
  202. CollisionStateList::CollisionStateList()
  203. {
  204. mPrev = mNext = this;
  205. mState = NULL;
  206. }
  207. void CollisionStateList::linkAfter(CollisionStateList* ptr)
  208. {
  209. mPrev = ptr;
  210. mNext = ptr->mNext;
  211. ptr->mNext = this;
  212. mNext->mPrev = this;
  213. }
  214. void CollisionStateList::unlink()
  215. {
  216. mPrev->mNext = mNext;
  217. mNext->mPrev = mPrev;
  218. mPrev = mNext = this;
  219. }
  220. CollisionStateList* CollisionStateList::alloc()
  221. {
  222. if (!sFreeList.isEmpty()) {
  223. CollisionStateList* nxt = sFreeList.mNext;
  224. nxt->unlink();
  225. nxt->mState = NULL;
  226. return nxt;
  227. }
  228. return constructInPlace((CollisionStateList*)sChunker.alloc(sizeof(CollisionStateList)));
  229. }
  230. void CollisionStateList::free()
  231. {
  232. unlink();
  233. linkAfter(&sFreeList);
  234. }
  235. //----------------------------------------------------------------------------
  236. CollisionWorkingList::CollisionWorkingList()
  237. {
  238. wLink.mPrev = wLink.mNext = this;
  239. rLink.mPrev = rLink.mNext = this;
  240. }
  241. void CollisionWorkingList::wLinkAfter(CollisionWorkingList* ptr)
  242. {
  243. wLink.mPrev = ptr;
  244. wLink.mNext = ptr->wLink.mNext;
  245. ptr->wLink.mNext = this;
  246. wLink.mNext->wLink.mPrev = this;
  247. }
  248. void CollisionWorkingList::rLinkAfter(CollisionWorkingList* ptr)
  249. {
  250. rLink.mPrev = ptr;
  251. rLink.mNext = ptr->rLink.mNext;
  252. ptr->rLink.mNext = this;
  253. rLink.mNext->rLink.mPrev = this;
  254. }
  255. void CollisionWorkingList::unlink()
  256. {
  257. wLink.mPrev->wLink.mNext = wLink.mNext;
  258. wLink.mNext->wLink.mPrev = wLink.mPrev;
  259. wLink.mPrev = wLink.mNext = this;
  260. rLink.mPrev->rLink.mNext = rLink.mNext;
  261. rLink.mNext->rLink.mPrev = rLink.mPrev;
  262. rLink.mPrev = rLink.mNext = this;
  263. }
  264. CollisionWorkingList* CollisionWorkingList::alloc()
  265. {
  266. if (sFreeList.wLink.mNext != &sFreeList) {
  267. CollisionWorkingList* nxt = sFreeList.wLink.mNext;
  268. nxt->unlink();
  269. return nxt;
  270. }
  271. return constructInPlace((CollisionWorkingList*)sChunker.alloc(sizeof(CollisionWorkingList)));
  272. }
  273. void CollisionWorkingList::free()
  274. {
  275. unlink();
  276. wLinkAfter(&sFreeList);
  277. }
  278. //----------------------------------------------------------------------------
  279. // Convex Base Class
  280. //----------------------------------------------------------------------------
  281. U32 Convex::sTag = (U32)-1;
  282. //----------------------------------------------------------------------------
  283. Convex::Convex()
  284. {
  285. mNext = mPrev = this;
  286. mTag = 0;
  287. }
  288. Convex::~Convex()
  289. {
  290. // Unlink from Convex Database
  291. unlink();
  292. // Delete collision states
  293. while (mList.mNext != &mList)
  294. delete mList.mNext->mState;
  295. // Free up working list
  296. while (mWorking.wLink.mNext != &mWorking)
  297. mWorking.wLink.mNext->free();
  298. // Free up references
  299. while (mReference.rLink.mNext != &mReference)
  300. mReference.rLink.mNext->free();
  301. }
  302. //----------------------------------------------------------------------------
  303. void Convex::collectGarbage()
  304. {
  305. // Delete unreferenced Convex Objects
  306. for (Convex* itr = mNext; itr != this; itr = itr->mNext) {
  307. if (itr->mReference.rLink.mNext == &itr->mReference) {
  308. Convex* ptr = itr;
  309. itr = itr->mPrev;
  310. delete ptr;
  311. }
  312. }
  313. }
  314. void Convex::nukeList()
  315. {
  316. // Delete all Convex Objects
  317. for (Convex* itr = mNext; itr != this; itr = itr->mNext) {
  318. Convex* ptr = itr;
  319. itr = itr->mPrev;
  320. delete ptr;
  321. }
  322. }
  323. void Convex::registerObject(Convex *convex)
  324. {
  325. convex->linkAfter(this);
  326. }
  327. //----------------------------------------------------------------------------
  328. void Convex::linkAfter(Convex* ptr)
  329. {
  330. mPrev = ptr;
  331. mNext = ptr->mNext;
  332. ptr->mNext = this;
  333. mNext->mPrev = this;
  334. }
  335. void Convex::unlink()
  336. {
  337. mPrev->mNext = mNext;
  338. mNext->mPrev = mPrev;
  339. mPrev = mNext = this;
  340. }
  341. //----------------------------------------------------------------------------
  342. Point3F Convex::support(const VectorF&) const
  343. {
  344. return Point3F(0,0,0);
  345. }
  346. void Convex::getFeatures(const MatrixF&,const VectorF&,ConvexFeature* f)
  347. {
  348. f->object = NULL;
  349. }
  350. const MatrixF& Convex::getTransform() const
  351. {
  352. return mObject->getTransform();
  353. }
  354. const Point3F& Convex::getScale() const
  355. {
  356. return mObject->getScale();
  357. }
  358. Box3F Convex::getBoundingBox() const
  359. {
  360. return mObject->getWorldBox();
  361. }
  362. Box3F Convex::getBoundingBox(const MatrixF& mat, const Point3F& scale) const
  363. {
  364. Box3F wBox = mObject->getObjBox();
  365. wBox.minExtents.convolve(scale);
  366. wBox.maxExtents.convolve(scale);
  367. mat.mul(wBox);
  368. return wBox;
  369. }
  370. //----------------------------------------------------------------------------
  371. void Convex::addToWorkingList(Convex* ptr)
  372. {
  373. CollisionWorkingList* cl = CollisionWorkingList::alloc();
  374. cl->wLinkAfter(&mWorking);
  375. cl->rLinkAfter(&ptr->mReference);
  376. cl->mConvex = ptr;
  377. };
  378. //----------------------------------------------------------------------------
  379. void Convex::updateWorkingList(const Box3F& box, const U32 colMask)
  380. {
  381. PROFILE_SCOPE( Convex_UpdateWorkingList );
  382. sTag++;
  383. // Clear objects off the working list that are no longer intersecting
  384. for (CollisionWorkingList* itr = mWorking.wLink.mNext; itr != &mWorking; itr = itr->wLink.mNext) {
  385. itr->mConvex->mTag = sTag;
  386. if ((!box.isOverlapped(itr->mConvex->getBoundingBox())) || (!itr->mConvex->getObject()->isCollisionEnabled())) {
  387. CollisionWorkingList* cl = itr;
  388. itr = itr->wLink.mPrev;
  389. cl->free();
  390. }
  391. }
  392. // Special processing for the terrain and interiors...
  393. AssertFatal(mObject->getContainer(), "Must be in a container!");
  394. SimpleQueryList sql;
  395. mObject->getContainer()->findObjects(box, colMask,SimpleQueryList::insertionCallback, &sql);
  396. for (U32 i = 0; i < sql.mList.size(); i++)
  397. sql.mList[i]->buildConvex(box, this);
  398. }
  399. void Convex::clearWorkingList()
  400. {
  401. PROFILE_SCOPE( Convex_ClearWorkingList );
  402. sTag++;
  403. for (CollisionWorkingList* itr = mWorking.wLink.mNext; itr != &mWorking; itr = itr->wLink.mNext)
  404. {
  405. itr->mConvex->mTag = sTag;
  406. CollisionWorkingList* cl = itr;
  407. itr = itr->wLink.mPrev;
  408. cl->free();
  409. }
  410. }
  411. // ---------------------------------------------------------------------------
  412. void Convex::updateStateList(const MatrixF& mat, const Point3F& scale, const Point3F* displacement)
  413. {
  414. PROFILE_SCOPE( Convex_UpdateStateList );
  415. Box3F box1 = getBoundingBox(mat, scale);
  416. box1.minExtents -= Point3F(1, 1, 1);
  417. box1.maxExtents += Point3F(1, 1, 1);
  418. if (displacement) {
  419. Point3F oldMin = box1.minExtents;
  420. Point3F oldMax = box1.maxExtents;
  421. box1.minExtents.setMin(oldMin + *displacement);
  422. box1.minExtents.setMin(oldMax + *displacement);
  423. box1.maxExtents.setMax(oldMin + *displacement);
  424. box1.maxExtents.setMax(oldMax + *displacement);
  425. }
  426. sTag++;
  427. // Destroy states which are no longer intersecting
  428. for (CollisionStateList* itr = mList.mNext; itr != &mList; itr = itr->mNext) {
  429. Convex* cv = (itr->mState->a == this)? itr->mState->b: itr->mState->a;
  430. cv->mTag = sTag;
  431. if (!box1.isOverlapped(cv->getBoundingBox())) {
  432. CollisionState* cs = itr->mState;
  433. itr = itr->mPrev;
  434. delete cs;
  435. }
  436. }
  437. // Add collision states for new overlapping objects
  438. for (CollisionWorkingList* itr0 = mWorking.wLink.mNext; itr0 != &mWorking; itr0 = itr0->wLink.mNext) {
  439. Convex* cv = itr0->mConvex;
  440. if (cv->mTag != sTag && box1.isOverlapped(cv->getBoundingBox())) {
  441. CollisionState* state = new GjkCollisionState;
  442. state->set(this,cv,mat,cv->getTransform());
  443. state->mLista->linkAfter(&mList);
  444. state->mListb->linkAfter(&cv->mList);
  445. }
  446. }
  447. }
  448. //----------------------------------------------------------------------------
  449. CollisionState* Convex::findClosestState(const MatrixF& mat, const Point3F& scale, const F32 dontCareDist)
  450. {
  451. PROFILE_SCOPE( Convex_FindClosestState );
  452. updateStateList(mat, scale);
  453. F32 dist = +1E30f;
  454. CollisionState *st = 0;
  455. // Prepare scaled version of transform
  456. MatrixF axform = mat;
  457. axform.scale(scale);
  458. MatrixF axforminv(true);
  459. MatrixF temp(mat);
  460. axforminv.scale(Point3F(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z));
  461. temp.affineInverse();
  462. axforminv.mul(temp);
  463. for (CollisionStateList* itr = mList.mNext; itr != &mList; itr = itr->mNext)
  464. {
  465. CollisionState* state = itr->mState;
  466. if (state->mLista != itr)
  467. state->swap();
  468. // Prepare scaled version of transform
  469. MatrixF bxform = state->b->getTransform();
  470. temp = bxform;
  471. Point3F bscale = state->b->getScale();
  472. bxform.scale(bscale);
  473. MatrixF bxforminv(true);
  474. bxforminv.scale(Point3F(1.0f/bscale.x, 1.0f/bscale.y, 1.0f/bscale.z));
  475. temp.affineInverse();
  476. bxforminv.mul(temp);
  477. //
  478. F32 dd = state->distance(axform, bxform, dontCareDist, &axforminv, &bxforminv);
  479. if (dd < dist)
  480. {
  481. dist = dd;
  482. st = state;
  483. }
  484. }
  485. if (dist < dontCareDist)
  486. return st;
  487. else
  488. return NULL;
  489. }
  490. //----------------------------------------------------------------------------
  491. bool Convex::getCollisionInfo(const MatrixF& mat, const Point3F& scale, CollisionList* cList,F32 tol)
  492. {
  493. PROFILE_SCOPE( Convex_GetCollisionInfo );
  494. // Making these static prevents needless Vector resizing that occurs
  495. // in the ConvexFeature constructor.
  496. static ConvexFeature fa;
  497. static ConvexFeature fb;
  498. for ( CollisionStateList* itr = mList.mNext;
  499. itr != &mList;
  500. itr = itr->mNext)
  501. {
  502. CollisionState* state = itr->mState;
  503. if (state->mLista != itr)
  504. state->swap();
  505. if (state->dist <= tol)
  506. {
  507. fa.reset();
  508. fb.reset();
  509. VectorF v;
  510. // The idea is that we need to scale the matrix, so we need to
  511. // make a copy of it, before we can pass it in to getFeatures.
  512. // This is used to scale us for comparison against the other
  513. // convex, which is correctly scaled.
  514. MatrixF omat = mat;
  515. omat.scale(scale);
  516. MatrixF imat = omat;
  517. imat.inverse();
  518. imat.mulV(-state->v,&v);
  519. getFeatures(omat,v,&fa);
  520. imat = state->b->getTransform();
  521. imat.scale(state->b->getScale());
  522. MatrixF bxform = imat;
  523. imat.inverse();
  524. imat.mulV(state->v,&v);
  525. state->b->getFeatures(bxform,v,&fb);
  526. fa.collide(fb,cList,tol);
  527. }
  528. }
  529. return (cList->getCount() != 0);
  530. }
  531. void Convex::getPolyList(AbstractPolyList*)
  532. {
  533. }
  534. void Convex::renderWorkingList()
  535. {
  536. //bool rendered = false;
  537. CollisionWorkingList& rList = getWorkingList();
  538. CollisionWorkingList* pList = rList.wLink.mNext;
  539. while (pList != &rList) {
  540. Convex* pConvex = pList->mConvex;
  541. pConvex->render();
  542. //rendered = true;
  543. pList = pList->wLink.mNext;
  544. }
  545. //Con::warnf( "convex rendered - %s", rendered ? "YES" : "NO" );
  546. }
  547. void Convex::render()
  548. {
  549. ConcretePolyList polyList;
  550. getPolyList( &polyList );
  551. polyList.render();
  552. }
  553. //-----------------------------------------------------------------------------
  554. // This function based on code originally written for the book:
  555. // 3D Game Engine Design, by David H. Eberly
  556. //
  557. F32 sqrDistanceEdges(const Point3F& start0, const Point3F& end0,
  558. const Point3F& start1, const Point3F& end1,
  559. Point3F* is, Point3F* it)
  560. {
  561. Point3F direction0 = end0 - start0;
  562. F32 fA00 = direction0.lenSquared();
  563. Point3F direction1 = end1 - start1;
  564. F32 fA11 = direction1.lenSquared();
  565. F32 fA01 = -mDot(direction0, direction1);
  566. Point3F kDiff = start0 - start1;
  567. F32 fC = kDiff.lenSquared();
  568. F32 fB0 = mDot(kDiff, direction0);
  569. F32 fDet = mFabs(fA00*fA11 - fA01*fA01);
  570. // Since the endpoints are tested as vertices, we're not interested
  571. // in parallel lines, and intersections that don't involve end-points.
  572. if (fDet >= 0.00001) {
  573. // Calculate time of intersection for each line
  574. F32 fB1 = -mDot(kDiff, direction1);
  575. F32 fS = fA01*fB1-fA11*fB0;
  576. F32 fT = fA01*fB0-fA00*fB1;
  577. // Only interested in collisions that don't involve the end points
  578. if (fS >= 0.0 && fS <= fDet && fT >= 0.0 && fT <= fDet) {
  579. F32 fInvDet = 1.0 / fDet;
  580. fS *= fInvDet;
  581. fT *= fInvDet;
  582. F32 fSqrDist = (fS*(fA00*fS + fA01*fT + 2.0*fB0) +
  583. fT*(fA01*fS + fA11*fT + 2.0*fB1) + fC);
  584. // Intersection points.
  585. *is = start0 + direction0 * fS;
  586. *it = start1 + direction1 * fT;
  587. return mFabs(fSqrDist);
  588. }
  589. }
  590. // Return a large number in the cases where endpoints are involved.
  591. return 1e10f;
  592. }