PageRenderTime 61ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/gdx-tokamak/jni/tokamak/dcd.cpp

http://libgdx.googlecode.com/
C++ | 1600 lines | 1091 code | 423 blank | 86 comment | 167 complexity | c63f7373842a860b7f004fa5b1b2b6ae MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0, GPL-3.0, LGPL-2.1
  1. /*************************************************************************
  2. * *
  3. * Tokamak Physics Engine, Copyright (C) 2002-2007 David Lam. *
  4. * All rights reserved. Email: david@tokamakphysics.com *
  5. * Web: www.tokamakphysics.com *
  6. * *
  7. * This library is distributed in the hope that it will be useful, *
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
  10. * LICENSE.TXT for more details. *
  11. * *
  12. *************************************************************************/
  13. #include "tokamak.h"
  14. #include "containers.h"
  15. #include "scenery.h"
  16. #include "collision.h"
  17. #include "collision2.h"
  18. #include "constraint.h"
  19. #include "rigidbody.h"
  20. #include "scenery.h"
  21. #include "stack.h"
  22. #include "simulator.h"
  23. #include "message.h"
  24. #include "dcd.h"
  25. const s32 BOX_NUM_FACES = 6;
  26. const s32 BOX_NUM_VERTS = 8;
  27. const s32 BOX_NUM_EDGES = 12;
  28. const s32 TRI_NUM_FACES = 2;
  29. const s32 TRI_NUM_VERTS = 3;
  30. const s32 TRI_NUM_EDGES = 3;
  31. s32 _num_edge_test;
  32. s32 _num_face_test;
  33. static neByte _boxNeighbourFaces[][4] = {{2,3,4,5},{2,3,4,5},{0,1,4,5},{0,1,4,5},{0,1,2,3},{0,1,2,3}};
  34. static neByte _boxNeighbourVerts[][4] = {{2,3,6,7},{0,1,4,5},{4,5,6,7},{0,1,2,3},{1,3,5,7},{0,2,4,6}};
  35. static neByte _boxNeighbourEdges[][4] = {{0,1,2,3},{4,5,6,7},{0,4,8,9},{1,5,10,11},{2,8,6,10},{3,7,9,11}};
  36. static neByte _boxVertNeighbourEdges[][4] = {{5,7,11,0xff},{5,6,10,0xff},{1,3,11,0xff},{1,2,10,0xff},{4,7,9,0xff},{4,6,8,0xff},{0,3,9,0xff},{0,2,8,0xff}};
  37. static neV3 _boxNormals[BOX_NUM_FACES] = {{0,1,0,0},{0,-1,0,0},{1,0,0,0},{-1,0,0,0},{0,0,1,0},{0,0,-1,0}};
  38. static neV3 _boxVertexPos0[BOX_NUM_VERTS] = {{-1,-1,-1,0},{-1,-1,1,0},{-1,1,-1,0},{-1,1,1,0},{1,-1,-1,0},{1,-1,1,0},{1,1,-1,0},{1,1,1,0}};
  39. static neV3 _boxVertexPosP[BOX_NUM_VERTS];
  40. static neV3 _boxVertexPosQ[BOX_NUM_VERTS];
  41. static neBool _visited[100];
  42. DCDFace BoxFaces[BOX_NUM_FACES] =
  43. {
  44. {_boxNeighbourFaces[0],_boxNeighbourVerts[0],_boxNeighbourEdges[0]}, //0
  45. {_boxNeighbourFaces[1],_boxNeighbourVerts[1],_boxNeighbourEdges[1]}, //1
  46. {_boxNeighbourFaces[2],_boxNeighbourVerts[2],_boxNeighbourEdges[2]}, //2
  47. {_boxNeighbourFaces[3],_boxNeighbourVerts[3],_boxNeighbourEdges[3]}, //3
  48. {_boxNeighbourFaces[4],_boxNeighbourVerts[4],_boxNeighbourEdges[4]}, //4
  49. {_boxNeighbourFaces[5],_boxNeighbourVerts[5],_boxNeighbourEdges[5]}, //5
  50. };
  51. DCDVert BoxVertices[BOX_NUM_VERTS] =
  52. {
  53. {_boxVertNeighbourEdges[0],}, //0
  54. {_boxVertNeighbourEdges[1],}, //1
  55. {_boxVertNeighbourEdges[2],}, //2
  56. {_boxVertNeighbourEdges[3],}, //3
  57. {_boxVertNeighbourEdges[4],}, //4
  58. {_boxVertNeighbourEdges[5],}, //5
  59. {_boxVertNeighbourEdges[6],}, //6
  60. {_boxVertNeighbourEdges[7],}, //7
  61. };
  62. DCDEdge BoxEdges[BOX_NUM_EDGES] =
  63. {
  64. {0,2,6,7}, //0
  65. {0,3,2,3}, //1
  66. {0,4,3,7}, //2
  67. {0,5,2,6}, //3
  68. {1,2,4,5}, //4
  69. {1,3,0,1}, //5
  70. {1,4,1,5}, //6
  71. {1,5,0,4}, //7
  72. {2,4,5,7}, //8
  73. {2,5,4,6}, //9
  74. {3,4,1,3}, //10
  75. {3,5,0,2}, //11
  76. };
  77. static neByte _triNeigbhourFaces[TRI_NUM_FACES][1] = {{0}, {1}};
  78. static neByte _triNeighbourVerts[TRI_NUM_FACES][3] = {{0,1,2},{0,1,2}};
  79. static neByte _triNeighbourEdges[TRI_NUM_FACES][3] = {{0,1,2},{0,1,2}};
  80. static neByte _triVertNeighbourEdges[TRI_NUM_VERTS][3] = {{0,2, 0xff},{0, 1, 0xff},{1, 2, 0xff}};
  81. static neV3 _triNormals[TRI_NUM_FACES];
  82. static neV3 _triVertexPos[3];
  83. DCDFace TriFaces[TRI_NUM_FACES] =
  84. {
  85. {_triNeigbhourFaces[0],_triNeighbourVerts[0],_triNeighbourEdges[0]},
  86. {_triNeigbhourFaces[1],_triNeighbourVerts[1],_triNeighbourEdges[1]},
  87. };
  88. DCDVert TriVertices[TRI_NUM_VERTS] =
  89. {
  90. {_triVertNeighbourEdges[0]},
  91. {_triVertNeighbourEdges[1]},
  92. {_triVertNeighbourEdges[2]},
  93. };
  94. DCDEdge TriEdges[TRI_NUM_EDGES] =
  95. {
  96. {0,1,0,1},
  97. {0,1,1,2},
  98. {0,1,2,0},
  99. };
  100. neV3 TriEdgeDir[TRI_NUM_EDGES];
  101. void DCDMesh::SetConvex(const TConvex & convex, neV3 * vertArray)
  102. {
  103. if (convex.type == TConvex::BOX)
  104. {
  105. numFaces = BOX_NUM_FACES;
  106. numVerts = BOX_NUM_VERTS;
  107. //numEdges = BOX_NUM_EDGES;
  108. normals = _boxNormals;
  109. faces = BoxFaces;
  110. verts = BoxVertices;
  111. edges = BoxEdges;
  112. if (vertArray)
  113. vertices = vertArray;
  114. numNeighbour = 4;
  115. }
  116. else if (convex.type == TConvex::CONVEXDCD)
  117. {
  118. numFaces = *(int*)convex.as.convexDCD.convexData;
  119. numVerts = *((int*)convex.as.convexDCD.convexData+1);
  120. //numEdges = *((int*)convex.as.convexDCD.convexData+2);
  121. f32 * np = (f32 *)(convex.as.convexDCD.convexData + 4 * sizeof(int));
  122. normals = (neV3*)np;
  123. vertices = (neV3*)(np + 4 * numFaces);
  124. faces = (DCDFace*)(vertices + numVerts);
  125. verts = (DCDVert*)((neByte*)faces + sizeof(DCDFace) * numFaces);
  126. edges = (DCDEdge*)((neByte*)verts + sizeof(DCDVert) * numVerts);
  127. numNeighbour = 3;
  128. }
  129. else if (convex.type == TConvex::TRIANGLE)
  130. {
  131. numFaces = TRI_NUM_FACES;
  132. numVerts = TRI_NUM_VERTS;
  133. normals = _triNormals;
  134. vertices = _triVertexPos;
  135. faces = TriFaces;
  136. verts = TriVertices;
  137. edges = TriEdges;
  138. numNeighbour = 3;
  139. }
  140. }
  141. neV3 DCDMesh::GetVertOnFace(s32 faceIndex, s32 vertIndex)
  142. {
  143. return vertices[faces[faceIndex].neighbourVerts[vertIndex]];
  144. }
  145. neV3 DCDMesh::GetVert(s32 vertIndex)
  146. {
  147. return vertices[vertIndex];
  148. }
  149. neV3 DCDMesh::GetNormal(s32 faceIndex)
  150. {
  151. return normals[faceIndex];
  152. }
  153. /*neByte DCDMesh::FaceGetNumFaceNeighbour(s32 faceIndex)
  154. {
  155. return faces[faceIndex].numberFaceNeighbour;
  156. }
  157. */neByte DCDMesh::FaceGetFaceNeighbour(s32 faceIndex, s32 neighbourIndex)
  158. {
  159. return faces[faceIndex].neighbourFaces[neighbourIndex];
  160. }
  161. neByte DCDMesh::FaceGetEdgeNeighbour(s32 faceIndex, s32 neighbourIndex)
  162. {
  163. return faces[faceIndex].neighbourEdges[neighbourIndex];
  164. }
  165. /*neByte DCDMesh::VertGetNumEdgeNeighbour(s32 vertIndex)
  166. {
  167. return verts[vertIndex].numberEdgeNeighbour;
  168. }
  169. */neByte DCDMesh::VertGetEdgeNeighbour(s32 vertIndex, s32 neighbourIndex)
  170. {
  171. return verts[vertIndex].neighbourEdges[neighbourIndex];
  172. }
  173. neByte DCDMesh::EdgeGetVert1(s32 edgeIndex)
  174. {
  175. return edges[edgeIndex].v1;
  176. }
  177. neByte DCDMesh::EdgeGetVert2(s32 edgeIndex)
  178. {
  179. return edges[edgeIndex].v2;
  180. }
  181. const s32 NUM_STACK_SIZE = 200;
  182. bool CalcContactEE(const neV3 & edgeA0,
  183. const neV3 & edgeA1,
  184. const neV3 & edgeB0,
  185. const neV3 & edgeB1, neV3 & contactA, neV3 & contactB);
  186. struct EdgeStackRecord
  187. {
  188. s32 edgeP;
  189. s32 edgeQ;
  190. };
  191. class EdgeStack
  192. {
  193. public:
  194. void Init()
  195. {
  196. tos = 0;
  197. }
  198. void Push(s32 edgeP, s32 edgeQ)
  199. {
  200. ASSERT(tos < NUM_STACK_SIZE);
  201. for (s32 i = 0; i < tos; i++)
  202. {
  203. if ((eStack[i].edgeP == edgeP && eStack[i].edgeQ == edgeQ) ||
  204. (eStack[i].edgeP == edgeQ && eStack[i].edgeQ == edgeP))
  205. return;
  206. }
  207. eStack[tos].edgeP = edgeP;
  208. eStack[tos].edgeQ = edgeQ;
  209. tos++;
  210. }
  211. bool Pop(s32 & edgeP, s32 & edgeQ)
  212. {
  213. ASSERT(tos > 0);
  214. tos--;
  215. edgeP = eStack[tos].edgeP;
  216. edgeQ = eStack[tos].edgeQ;
  217. return true;
  218. }
  219. neBool IsEmpty()
  220. {
  221. return tos == 0;
  222. }
  223. private:
  224. s32 tos;
  225. EdgeStackRecord eStack[NUM_STACK_SIZE];
  226. };
  227. EdgeStack gEdgeStack;
  228. neV3 BigC;
  229. f32 BigCLength;
  230. class Face
  231. {
  232. public:
  233. // face is defined as normal.Dot(p) = k
  234. neV3 normal;
  235. f32 k;
  236. };
  237. class DCDObj
  238. {
  239. public:
  240. //TConvex * convex;
  241. neBool isBox;
  242. DCDMesh mesh;
  243. neT3 * trans;
  244. Face GetFace(s32 faceIndex)
  245. {
  246. Face face0;
  247. face0.normal = trans->rot * mesh.normals[faceIndex];
  248. neV3 tmp1 = (*trans) * mesh.GetVertOnFace(faceIndex, 0);
  249. //face0.k = face0.normal.Dot(trans->pos) + mesh.normals[faceIndex].v[3] * -1.0f;
  250. face0.k = face0.normal.Dot(tmp1);
  251. return face0;
  252. }
  253. neV3 GetVertWorld(s32 vertIndex)
  254. {
  255. neV3 vert = (*trans) * mesh.vertices[vertIndex];
  256. return vert;
  257. }
  258. neV3 GetNegVertWorld(s32 vertIndex)
  259. {
  260. neV3 vert = GetVertWorld(vertIndex) * -1.0f;
  261. return vert;
  262. }
  263. NEINLINE neV3 GetWorldNormalByEdge1(s32 edgeIndex)
  264. {
  265. neV3 ret; ret = trans->rot * mesh.normals[mesh.edges[edgeIndex].f1];
  266. return ret;
  267. }
  268. NEINLINE neV3 GetWorldNormalByEdge2(s32 edgeIndex)
  269. {
  270. neV3 ret; ret = trans->rot * mesh.normals[mesh.edges[edgeIndex].f2];
  271. return ret;
  272. }
  273. NEINLINE s32 GetSupportPoint(const neV3 & norm)
  274. {
  275. if (isBox)
  276. return GetSupportPointBox(norm);
  277. else
  278. return GetSupportPointMesh(norm);
  279. return 0;
  280. }
  281. NEINLINE void GetWorldEdgeVerts(s32 edgeIndex, neV3 & av, neV3 & bv)
  282. {
  283. neV3 tmp;
  284. tmp = mesh.vertices[mesh.edges[edgeIndex].v1];
  285. av = (*trans) * tmp;
  286. tmp = mesh.vertices[mesh.edges[edgeIndex].v2];
  287. bv = (*trans) * tmp;
  288. }
  289. neV3 FaceGetWorldNormal(s32 faceIndex)
  290. {
  291. return trans->rot * mesh.GetNormal(faceIndex);
  292. }
  293. private:
  294. s32 GetSupportPointBox(const neV3 & norm)
  295. {
  296. neV3 localNorm = trans->rot.TransposeMulV3(norm);
  297. localNorm *= -1.0f;
  298. s32 ret = 0;
  299. if (localNorm[0] >= 0.0f)
  300. {
  301. if (localNorm[1] >= 0.0f)
  302. {
  303. if (localNorm[2] >= 0.0f)
  304. ret = 7;
  305. else
  306. ret = 6;
  307. }
  308. else
  309. {
  310. if (localNorm[2] >= 0.0f)
  311. ret = 5;
  312. else
  313. ret = 4;
  314. }
  315. }
  316. else
  317. {
  318. if (localNorm[1] >= 0.0f)
  319. {
  320. if (localNorm[2] >= 0.0f)
  321. ret = 3;
  322. else
  323. ret = 2;
  324. }
  325. else
  326. {
  327. if (localNorm[2] >= 0.0f)
  328. ret = 1;
  329. else
  330. ret = 0;
  331. }
  332. }
  333. return ret;
  334. }
  335. s32 GetSupportPointMesh(const neV3 & norm)
  336. {
  337. neV3 localNorm = trans->rot.TransposeMulV3(norm);
  338. localNorm *= -1.0f;
  339. s32 ret = 0;
  340. f32 maxd = -1.0e6f;
  341. neByte neighbourEdge;
  342. neBool moving;
  343. do {
  344. moving = false;
  345. s32 i = 0;
  346. //while (i < mesh.verts[ret].numberEdgeNeighbour)
  347. do
  348. {
  349. s32 currentVert;
  350. neighbourEdge = mesh.verts[ret].neighbourEdges[i];
  351. if (neighbourEdge == 0xff)
  352. break;
  353. if (mesh.edges[neighbourEdge].v1 == ret)
  354. currentVert = mesh.edges[neighbourEdge].v2;
  355. else
  356. currentVert = mesh.edges[neighbourEdge].v1;
  357. //if (currentVert > 10)
  358. // ASSERT(0);
  359. f32 dot = mesh.vertices[currentVert].Dot(localNorm);
  360. if (dot > maxd)
  361. {
  362. maxd = dot;
  363. ret = currentVert;
  364. moving = 1;
  365. break;
  366. }
  367. i++;
  368. } while (true);
  369. } while(moving);
  370. return ret;
  371. /*
  372. for (s32 i = 0; i < mesh.numVerts; i++)
  373. {
  374. f32 dot = mesh.vertices[i].Dot(localNorm);
  375. if (dot > maxd)
  376. {
  377. maxd = dot;
  378. ret = i;
  379. }
  380. }
  381. return ret;
  382. */
  383. }
  384. };
  385. f32 funcD(const Face & face)
  386. {
  387. f32 k = face.k;
  388. neV3 N;
  389. N = face.normal;
  390. if (face.k < 0.0f)
  391. {
  392. k = -face.k;
  393. N *= -1.0f;
  394. }
  395. f32 den = k - N.Dot(BigC);
  396. den = BigCLength * den;
  397. ASSERT(!neIsConsiderZero(den));
  398. f32 ret = -k / den;
  399. return ret;
  400. }
  401. f32 SignedDistance(const Face & faceP, const neV3 & vertQ , Face & faceM)
  402. {
  403. faceM = faceP;
  404. f32 dot = faceP.normal.Dot(vertQ);
  405. faceM.k += (dot);
  406. return funcD(faceM);
  407. }
  408. class SearchResult
  409. {
  410. public:
  411. enum Type
  412. {
  413. FACE,
  414. VERTEX,
  415. EDGE,
  416. } ;
  417. SearchResult(const TConvex & convexA, neT3 * transA, const TConvex & convexB, neT3 * transB, neV3 * vertArrayA, neV3 * vertArrayB)
  418. {
  419. objA.mesh.SetConvex(convexA, vertArrayA);
  420. objA.isBox = (convexA.type == TConvex::BOX);
  421. objA.trans = transA;
  422. objB.mesh.SetConvex(convexB, vertArrayB);
  423. objB.isBox = (convexB.type == TConvex::BOX);
  424. objB.trans = transB;
  425. dMax = -1.0e6f;
  426. }
  427. neBool TestFace(s32 face0Index, neBool & assigned)
  428. {
  429. assigned = false;
  430. _visited[face0Index] = true;
  431. Face face0 = objA.GetFace(face0Index);
  432. neByte _indexB = objB.GetSupportPoint(face0.normal);
  433. neV3 vertB;
  434. vertB = objB.GetNegVertWorld(_indexB);
  435. Face newFace;
  436. f32 d = SignedDistance(face0, vertB, newFace);
  437. if (d >= 0.0f)
  438. return false;
  439. if (d <= dMax)
  440. return true;
  441. dMax = d;
  442. typeA = SearchResult::FACE;
  443. typeB = SearchResult::VERTEX;
  444. indexA = face0Index;
  445. indexB = _indexB;
  446. face = newFace;
  447. assigned = true;
  448. _num_face_test++;
  449. return true;
  450. }
  451. neBool SearchFV(s32 initialFace, neBool & assigned);
  452. neBool SearchEE(s32 flag /*0 or 1*/, s32 aIndex, s32 bIndex, neBool & assigned);
  453. neBool SearchEETri(s32 flag /*0 or 1*/, s32 aIndex, s32 bIndex, neBool & assigned);
  454. DCDObj objA;
  455. Type typeA;
  456. s32 indexA;
  457. DCDObj objB;
  458. Type typeB;
  459. s32 indexB;
  460. Face face;
  461. f32 dMax;
  462. };
  463. neBool SearchResult::SearchFV(s32 initialFace, neBool & assigned)
  464. {
  465. for (s32 i = 0; i < objA.mesh.numFaces; i++)
  466. {
  467. _visited[i] = false;
  468. if (objA.isBox)
  469. {
  470. objA.mesh.normals[i].v[3] = objA.mesh.vertices[objA.mesh.faces[i].neighbourVerts[0]].Dot(objA.mesh.normals[i]) * -1.0f;
  471. }
  472. }
  473. if (!TestFace(initialFace, assigned))
  474. return false;
  475. //ASSERT(assigned);
  476. neBool found = true;
  477. s32 currentFace = initialFace;
  478. while (found)
  479. {
  480. found = false;
  481. for (s32 ii = 0; ii < objA.mesh.numNeighbour; ii++)
  482. {
  483. s32 i = objA.mesh.FaceGetFaceNeighbour(currentFace, ii);
  484. if (_visited[i])
  485. continue;
  486. neBool _assigned;
  487. if (!TestFace(i, _assigned))
  488. return false;
  489. if (_assigned)
  490. found = true;
  491. }
  492. if (found)
  493. {
  494. currentFace = indexA;
  495. }
  496. }
  497. return true;
  498. }
  499. f32 Determinant(const neV3 & a, const neV3 & b, const neV3 & c)
  500. {
  501. f32 t1 = a[0] * b[1] * c[2];
  502. f32 t2 = a[1] * b[0] * c[2];
  503. f32 t3 = a[0] * b[2] * c[1];
  504. f32 t4 = a[2] * b[1] * c[0];
  505. f32 t5 = a[1] * b[2] * c[0];
  506. f32 t6 = a[2] * b[0] * c[1];
  507. f32 ret = t1 - t2 - t3 - t4 + t5 + t6;
  508. return ret;
  509. }
  510. neBool SearchResult::SearchEE(s32 flag, s32 aIndex, s32 bIndex, neBool & assigned)
  511. {
  512. assigned = false;
  513. gEdgeStack.Init();
  514. neByte edgeIndex;
  515. if (flag == 0) //fv
  516. {
  517. for (s32 i = 0; i < objA.mesh.numNeighbour; i++)
  518. {
  519. int j = 0;
  520. while ((edgeIndex = objB.mesh.VertGetEdgeNeighbour(bIndex, j)) != 0xff)
  521. {
  522. gEdgeStack.Push(objA.mesh.FaceGetEdgeNeighbour(aIndex, i),
  523. objB.mesh.VertGetEdgeNeighbour(bIndex, j));
  524. j++;
  525. }
  526. }
  527. }
  528. else //vf
  529. {
  530. s32 i = 0;
  531. while ((edgeIndex = objA.mesh.VertGetEdgeNeighbour(aIndex, i)) != 0xff)
  532. {
  533. for (s32 j = 0; j < objB.mesh.numNeighbour; j++)
  534. {
  535. gEdgeStack.Push(objA.mesh.VertGetEdgeNeighbour(aIndex, i),
  536. objB.mesh.FaceGetEdgeNeighbour(bIndex, j));
  537. }
  538. i++;
  539. }
  540. }
  541. while (!gEdgeStack.IsEmpty())
  542. {
  543. _num_edge_test++;
  544. s32 edgeP, edgeQ;
  545. gEdgeStack.Pop(edgeP, edgeQ);
  546. // does the edge form a face
  547. neV3 a = objA.GetWorldNormalByEdge1(edgeP);
  548. neV3 b = objA.GetWorldNormalByEdge2(edgeP);
  549. neV3 c = objB.GetWorldNormalByEdge1(edgeQ) * -1.0f;
  550. neV3 d = objB.GetWorldNormalByEdge2(edgeQ) * -1.0f;
  551. f32 cba = Determinant(c,b,a);
  552. f32 dba = Determinant(d,b,a);
  553. f32 prod0 = cba * dba;
  554. if (prod0 >= 0.0f/*-1.0e-6f*/)
  555. {
  556. continue;
  557. }
  558. f32 adc = Determinant(a,d,c);
  559. f32 bdc = Determinant(b,d,c);
  560. f32 prod1 = adc * bdc;
  561. if (prod1 >= 0.0f/*-1.0e-6f*/)
  562. {
  563. continue;
  564. }
  565. f32 prod2 = cba * bdc;
  566. if (prod2 <= 0.0f/*1.0e-6f*/)
  567. {
  568. continue;
  569. }
  570. neV3 ai, bi;
  571. neV3 naj, nbj;
  572. objA.GetWorldEdgeVerts(edgeP, ai, bi);
  573. objB.GetWorldEdgeVerts(edgeQ, naj, nbj);
  574. naj *= -1.0f; nbj *= -1.0f;
  575. neV3 ainaj = ai + naj;
  576. neV3 ainbj = ai + nbj;
  577. neV3 binaj = bi + naj;
  578. //neV3 binbj = bi + nbj;
  579. neV3 diff1 = ainaj - ainbj;
  580. neV3 diff2 = ainaj - binaj ;
  581. Face testFace;
  582. testFace.normal = diff1.Cross(diff2);
  583. f32 len = testFace.normal.Length();
  584. if (neIsConsiderZero(len))
  585. {
  586. continue;
  587. }
  588. testFace.normal *= (1.0f / len);
  589. testFace.k = testFace.normal.Dot(ainaj);
  590. f32 testD = funcD(testFace);
  591. if (testD >= 0)
  592. return false;
  593. if (testD <= dMax)
  594. continue;
  595. assigned = true;
  596. dMax = testD;
  597. face = testFace;
  598. indexA = edgeP;
  599. indexB = edgeQ;
  600. typeA = SearchResult::EDGE;
  601. typeB = SearchResult::EDGE;
  602. // push
  603. s32 i, j;
  604. s32 vindex;
  605. vindex = objB.mesh.EdgeGetVert1(edgeQ);
  606. i = 0;
  607. while ((j = objB.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  608. {
  609. if (j != edgeQ)
  610. gEdgeStack.Push(edgeP, j);
  611. i++;
  612. }
  613. vindex = objB.mesh.EdgeGetVert2(edgeQ);
  614. i = 0;
  615. while ((j = objB.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  616. {
  617. if (j != edgeQ)
  618. gEdgeStack.Push(edgeP, j);
  619. i++;
  620. }
  621. vindex = objA.mesh.EdgeGetVert1(edgeP);
  622. i = 0;
  623. while((j = objA.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  624. {
  625. if (j != edgeP)
  626. gEdgeStack.Push(j, edgeQ);
  627. i++;
  628. }
  629. vindex = objA.mesh.EdgeGetVert2(edgeP);
  630. //for (i = 0; i < objA.mesh.VertGetNumEdgeNeighbour(vindex); i++)
  631. i = 0;
  632. while ((j = objA.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  633. {
  634. if (j != edgeP)
  635. gEdgeStack.Push(j, edgeQ);
  636. i++;
  637. }
  638. /*
  639. if (testD <= dMax)
  640. continue;
  641. assigned = true;
  642. dMax = testD;
  643. face = testFace;
  644. indexA = edgeP;
  645. indexB = edgeQ;
  646. typeA = SearchResult::EDGE;
  647. typeB = SearchResult::EDGE;
  648. */ }
  649. return true;
  650. }
  651. neBool SearchResult::SearchEETri(s32 flag, s32 aIndex, s32 bIndex, neBool & assigned)
  652. {
  653. assigned = false;
  654. gEdgeStack.Init();
  655. neByte edgeIndex;
  656. if (flag == 0) //fv
  657. {
  658. // face of convex A
  659. // vertex of triangle B
  660. for (s32 i = 0; i < objA.mesh.numNeighbour; i++) // for each edge neighbour of Face aIndex
  661. {
  662. int j = 0;
  663. while ((edgeIndex = objB.mesh.VertGetEdgeNeighbour(bIndex, j)) != 0xff)
  664. {
  665. gEdgeStack.Push(objA.mesh.FaceGetEdgeNeighbour(aIndex, i),
  666. objB.mesh.VertGetEdgeNeighbour(bIndex, j));
  667. j++;
  668. }
  669. }
  670. }
  671. else //vf
  672. {
  673. //vertex of convex A
  674. //face of triangle B
  675. s32 i = 0;
  676. //for each edge neighbour incident to Vertex aIndex
  677. while ((edgeIndex = objA.mesh.VertGetEdgeNeighbour(aIndex, i)) != 0xff)
  678. {
  679. for (s32 j = 0; j < objB.mesh.numNeighbour; j++)
  680. {
  681. gEdgeStack.Push(objA.mesh.VertGetEdgeNeighbour(aIndex, i),
  682. objB.mesh.FaceGetEdgeNeighbour(bIndex, j));
  683. }
  684. i++;
  685. }
  686. }
  687. while (!gEdgeStack.IsEmpty())
  688. {
  689. _num_edge_test++;
  690. s32 edgeP, edgeQ;
  691. gEdgeStack.Pop(edgeP, edgeQ);
  692. // does the edge form a face
  693. neV3 a = objA.GetWorldNormalByEdge1(edgeP);
  694. neV3 b = objA.GetWorldNormalByEdge2(edgeP);
  695. neV3 c = objB.GetWorldNormalByEdge1(edgeQ) * -1.0f;
  696. neV3 d = objB.GetWorldNormalByEdge2(edgeQ) * -1.0f;
  697. c += (TriEdgeDir[edgeQ] * 0.01f);
  698. d += (TriEdgeDir[edgeQ] * 0.01f);
  699. c.Normalize();
  700. d.Normalize();
  701. f32 cba = Determinant(c,b,a);
  702. f32 dba = Determinant(d,b,a);
  703. f32 prod0 = cba * dba;
  704. if (prod0 >= -1.0e-6f)
  705. {
  706. continue;
  707. }
  708. f32 adc = Determinant(a,d,c);
  709. f32 bdc = Determinant(b,d,c);
  710. f32 prod1 = adc * bdc;
  711. if (prod1 >= -1.0e-6f)
  712. {
  713. continue;
  714. }
  715. f32 prod2 = cba * bdc;
  716. if (prod2 <= 1.0e-6f)
  717. {
  718. continue;
  719. }
  720. neV3 ai, bi;
  721. neV3 naj, nbj;
  722. objA.GetWorldEdgeVerts(edgeP, ai, bi);
  723. objB.GetWorldEdgeVerts(edgeQ, naj, nbj);
  724. naj *= -1.0f; nbj *= -1.0f;
  725. neV3 ainaj = ai + naj;
  726. neV3 ainbj = ai + nbj;
  727. neV3 binaj = bi + naj;
  728. //neV3 binbj = bi + nbj;
  729. neV3 diff1 = ainaj - ainbj;
  730. neV3 diff2 = ainaj - binaj ;
  731. Face testFace;
  732. testFace.normal = diff1.Cross(diff2);
  733. f32 len = testFace.normal.Length();
  734. if (neIsConsiderZero(len))
  735. {
  736. continue;
  737. }
  738. testFace.normal *= (1.0f / len);
  739. testFace.k = testFace.normal.Dot(ainaj);
  740. f32 testD = funcD(testFace);
  741. if (testD >= 0)
  742. return false;
  743. if (testD <= dMax)
  744. continue;
  745. assigned = true;
  746. dMax = testD;
  747. face = testFace;
  748. indexA = edgeP;
  749. indexB = edgeQ;
  750. typeA = SearchResult::EDGE;
  751. typeB = SearchResult::EDGE;
  752. // push
  753. s32 i, j;
  754. s32 vindex;
  755. vindex = objB.mesh.EdgeGetVert1(edgeQ);
  756. i = 0;
  757. while ((j = objB.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  758. {
  759. if (j != edgeQ)
  760. gEdgeStack.Push(edgeP, j);
  761. i++;
  762. }
  763. vindex = objB.mesh.EdgeGetVert2(edgeQ);
  764. i = 0;
  765. while ((j = objB.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  766. {
  767. if (j != edgeQ)
  768. gEdgeStack.Push(edgeP, j);
  769. i++;
  770. }
  771. vindex = objA.mesh.EdgeGetVert1(edgeP);
  772. i = 0;
  773. while((j = objA.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  774. {
  775. if (j != edgeP)
  776. gEdgeStack.Push(j, edgeQ);
  777. i++;
  778. }
  779. vindex = objA.mesh.EdgeGetVert2(edgeP);
  780. //for (i = 0; i < objA.mesh.VertGetNumEdgeNeighbour(vindex); i++)
  781. i = 0;
  782. while ((j = objA.mesh.VertGetEdgeNeighbour(vindex, i)) != 0xff)
  783. {
  784. if (j != edgeP)
  785. gEdgeStack.Push(j, edgeQ);
  786. i++;
  787. }
  788. }
  789. return true;
  790. }
  791. bool TestDCD(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB, const neV3 & backupVector)
  792. {
  793. _num_edge_test = 0;
  794. _num_face_test = 0;
  795. result.penetrate = false;
  796. neV3 aPoint = transA.pos;
  797. neV3 av; av.Set(0.1f);
  798. aPoint += av;
  799. neV3 bPoint = transB.pos;
  800. av.Set(0.2f);
  801. bPoint += av;
  802. BigC = aPoint - bPoint;
  803. BigCLength = BigC.Length();
  804. neV3 * aVertArray, * bVertArray;
  805. if (convexA.type == TConvex::BOX)
  806. {
  807. for (s32 i = 0; i < BOX_NUM_VERTS; i++)
  808. {
  809. _boxVertexPosP[i] = _boxVertexPos0[i] * convexA.as.box.boxSize;
  810. }
  811. aVertArray = _boxVertexPosP;
  812. }
  813. if (convexB.type == TConvex::BOX)
  814. {
  815. for (s32 i = 0; i < BOX_NUM_VERTS; i++)
  816. {
  817. _boxVertexPosQ[i] = _boxVertexPos0[i] * convexB.as.box.boxSize;
  818. }
  819. bVertArray = _boxVertexPosQ;
  820. }
  821. SearchResult srFV(convexA, &transA, convexB, &transB, aVertArray, bVertArray);
  822. neBool showDebug = 0;
  823. neBool showDebug2 = (srFV.objA.mesh.numVerts > 8 && srFV.objB.mesh.numVerts > 8);
  824. neBool assigned;
  825. neBool res = srFV.SearchFV(0, assigned);
  826. if (!res)
  827. {
  828. if (showDebug)
  829. {TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);}
  830. return false;
  831. }
  832. SearchResult srVF(convexB, &transB, convexA, &transA, bVertArray, aVertArray);
  833. srVF.dMax = srFV.dMax;
  834. BigC *= -1.0f;
  835. s32 whichF = srFV.objB.mesh.edges[srFV.objB.mesh.verts[srFV.indexB].neighbourEdges[0]].f1;
  836. res = srVF.SearchFV(whichF, assigned);
  837. if (!res)
  838. {
  839. if (showDebug)
  840. {TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);}
  841. return false;
  842. }
  843. bool need2Swap = false;
  844. SearchResult srEE(convexA, &transA, convexB, &transB, aVertArray, bVertArray);
  845. s32 eeflag = 0;
  846. s32 pindex, qindex;
  847. if (srVF.dMax > srFV.dMax)
  848. {
  849. need2Swap = true;
  850. srEE.dMax = srVF.dMax;
  851. eeflag = 1;
  852. pindex = srVF.indexB;
  853. qindex = srVF.indexA;
  854. }
  855. else
  856. {
  857. srEE.dMax = srFV.dMax;
  858. pindex = srFV.indexA;
  859. qindex = srFV.indexB;
  860. }
  861. BigC *= -1.0f;
  862. if (!srEE.SearchEE(eeflag, pindex, qindex, assigned))
  863. {
  864. if (showDebug)
  865. {TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);}
  866. return false;
  867. }
  868. if (showDebug2)
  869. {
  870. TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);
  871. }
  872. if (!assigned)
  873. {
  874. if (!need2Swap)
  875. {
  876. ASSERT(srFV.typeA == SearchResult::FACE && srFV.typeB == SearchResult::VERTEX);
  877. result.penetrate = true;
  878. result.collisionFrame[2] = srFV.face.normal * -1.0f;
  879. result.depth = srFV.face.k;
  880. result.contactB = srFV.objB.GetVertWorld(srFV.indexB);
  881. result.contactA = result.contactB + srFV.face.normal * srFV.face.k;
  882. }
  883. else
  884. {
  885. ASSERT(srVF.typeA == SearchResult::FACE && srVF.typeB == SearchResult::VERTEX);
  886. result.penetrate = true;
  887. result.collisionFrame[2] = srVF.face.normal;
  888. result.depth = srVF.face.k;
  889. result.contactA = srVF.objB.GetVertWorld(srVF.indexB);
  890. result.contactB = result.contactA + srVF.face.normal * srVF.face.k;
  891. }
  892. }
  893. else
  894. {
  895. ASSERT(srEE.typeA == SearchResult::EDGE &&
  896. srEE.typeB == SearchResult::EDGE);
  897. neV3 edgeA[2];
  898. neV3 edgeB[2];
  899. srEE.objA.GetWorldEdgeVerts(srEE.indexA, edgeA[0], edgeA[1]);
  900. srEE.objB.GetWorldEdgeVerts(srEE.indexB, edgeB[0], edgeB[1]);
  901. bool r = CalcContactEE(edgeA[0], edgeA[1], edgeB[0], edgeB[1], result.contactA, result.contactB);
  902. if (r)
  903. {
  904. if (srEE.face.k > 0.0f)
  905. {
  906. result.collisionFrame[2] = srEE.face.normal * -1.0f;
  907. result.depth = srEE.face.k;
  908. }
  909. else
  910. {
  911. result.collisionFrame[2] = srEE.face.normal;
  912. result.depth = srEE.face.k * -1.0f;
  913. }
  914. result.penetrate = true;
  915. }
  916. else
  917. {
  918. return false;
  919. }
  920. }
  921. return true;
  922. }
  923. bool TestDCDTri(ConvexTestResult & res, TConvex & convexA, neT3 & transA, const neV3 & insidePoint)
  924. {
  925. res.valid = false;
  926. neV3 aPoint = transA.pos;
  927. neV3 av; av.Set(0.1f);
  928. aPoint += av;
  929. neV3 bPoint = insidePoint;
  930. BigC = aPoint - bPoint;
  931. BigCLength = BigC.Length();
  932. neV3 * aVertArray = NULL, * bVertArray = NULL;
  933. TConvex dummyB; dummyB.type = TConvex::TRIANGLE;
  934. if (convexA.type == TConvex::BOX)
  935. {
  936. for (s32 i = 0; i < BOX_NUM_VERTS; i++)
  937. {
  938. _boxVertexPosP[i] = _boxVertexPos0[i] * convexA.as.box.boxSize;
  939. }
  940. aVertArray = _boxVertexPosP;
  941. }
  942. neT3 transB; transB.SetIdentity();
  943. SearchResult srBoxFaceTriVert(convexA, &transA, dummyB, &transB, aVertArray, bVertArray);
  944. neBool assigned;
  945. neBool r = srBoxFaceTriVert.SearchFV(0, assigned);
  946. if (!r)
  947. {return false;}
  948. /* bPoint = insidePoint;// + _triNormals[1];
  949. BigC = bPoint - aPoint;
  950. BigCLength = BigC.Length();
  951. */
  952. BigC *= -1.0f;
  953. SearchResult srBoxVertTriFace(dummyB, &transB, convexA, &transA, bVertArray, aVertArray);
  954. if (!(r = srBoxVertTriFace.TestFace(0, assigned)))
  955. return false;
  956. //BigC *= -1.0f;
  957. /*
  958. bPoint = insidePoint + _triNormals[0];
  959. BigC = bPoint - aPoint;
  960. BigCLength = BigC.Length();
  961. */
  962. neBool assigned2;
  963. if (!(r = srBoxVertTriFace.TestFace(1, assigned2)))
  964. return false;
  965. assigned |= assigned2;
  966. BigC *= -1.0f;
  967. /*
  968. bPoint = insidePoint;
  969. BigC = aPoint - bPoint;
  970. BigCLength = BigC.Length();
  971. */
  972. neBool need2Swap = false;
  973. SearchResult srBoxTriEE(convexA, &transA, dummyB, &transB, aVertArray, bVertArray);
  974. s32 eeflag = 0;
  975. s32 pindex, qindex;
  976. if (srBoxVertTriFace.dMax > srBoxFaceTriVert.dMax)
  977. {
  978. need2Swap = true;
  979. srBoxTriEE.dMax = srBoxVertTriFace.dMax;
  980. eeflag = 1;
  981. pindex = srBoxVertTriFace.indexB; // vertex of Convex
  982. qindex = srBoxVertTriFace.indexA; // face of Triangle
  983. }
  984. else
  985. {
  986. srBoxTriEE.dMax = srBoxFaceTriVert.dMax;
  987. pindex = srBoxFaceTriVert.indexA; // face of Convex
  988. qindex = srBoxFaceTriVert.indexB; // vertex of Triangle
  989. }
  990. //BigC *= -1.0f;
  991. if (!srBoxTriEE.SearchEETri(eeflag, pindex, qindex, assigned))
  992. {
  993. return false;
  994. }
  995. if (!assigned)
  996. {
  997. FV_Backup:
  998. if (!need2Swap)
  999. {
  1000. ASSERT(srBoxFaceTriVert.typeA == SearchResult::FACE && srBoxFaceTriVert.typeB == SearchResult::VERTEX);
  1001. res.valid = true;
  1002. res.contactNormal = srBoxFaceTriVert.face.normal * -1.0f;
  1003. res.depth = srBoxFaceTriVert.face.k;
  1004. res.contactB = srBoxFaceTriVert.objB.GetVertWorld(srBoxFaceTriVert.indexB);
  1005. res.contactA = res.contactB + srBoxFaceTriVert.face.normal * srBoxFaceTriVert.face.k;
  1006. }
  1007. else
  1008. {
  1009. ASSERT(srBoxVertTriFace.typeA == SearchResult::FACE && srBoxVertTriFace.typeB == SearchResult::VERTEX);
  1010. res.valid = true;
  1011. res.contactNormal = srBoxVertTriFace.face.normal;
  1012. res.depth = srBoxVertTriFace.face.k;
  1013. res.contactA = srBoxVertTriFace.objB.GetVertWorld(srBoxVertTriFace.indexB);
  1014. res.contactB = res.contactA + srBoxVertTriFace.face.normal * srBoxVertTriFace.face.k;
  1015. }
  1016. }
  1017. else
  1018. {
  1019. ASSERT(srBoxTriEE.typeA == SearchResult::EDGE &&
  1020. srBoxTriEE.typeB == SearchResult::EDGE);
  1021. neV3 edgeA[2];
  1022. neV3 edgeB[2];
  1023. srBoxTriEE.objA.GetWorldEdgeVerts(srBoxTriEE.indexA, edgeA[0], edgeA[1]);
  1024. srBoxTriEE.objB.GetWorldEdgeVerts(srBoxTriEE.indexB, edgeB[0], edgeB[1]);
  1025. bool r = CalcContactEE(edgeA[0], edgeA[1], edgeB[0], edgeB[1], res.contactA, res.contactB);
  1026. if (r)
  1027. {
  1028. if (srBoxTriEE.face.k > 0.0f)
  1029. {
  1030. res.contactNormal = srBoxTriEE.face.normal * -1.0f;
  1031. res.depth = srBoxTriEE.face.k;
  1032. }
  1033. else
  1034. {
  1035. res.contactNormal = srBoxTriEE.face.normal;
  1036. res.depth = srBoxTriEE.face.k * -1.0f;
  1037. }
  1038. res.valid = true;
  1039. }
  1040. else
  1041. {
  1042. //return false;
  1043. goto FV_Backup;
  1044. }
  1045. }
  1046. return true;
  1047. }
  1048. void Convex2TerrainTest(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB)
  1049. {
  1050. neSimpleArray<s32> & _triIndex = *convexB.as.terrain.triIndex;
  1051. s32 triangleCount = _triIndex.GetUsedCount();
  1052. neArray<neTriangle_> & triangleArray = *convexB.as.terrain.triangles;
  1053. ConvexTestResult res[2];
  1054. s32 finalTriIndex = -1;
  1055. s32 currentRes = 1;
  1056. s32 testRes = 0;
  1057. res[currentRes].depth = -1.0e6f;
  1058. res[currentRes].valid = false;
  1059. res[testRes].depth = 1.0e6f;
  1060. s32 terrainMatID = 0;
  1061. neBool found = false;
  1062. #if 0
  1063. for (s32 j = 0/*triangleCount-1*/; j < triangleCount; j++)
  1064. //int j = 12;
  1065. {
  1066. neV3 points[4];
  1067. neV3 red;red.Set(1.0f);
  1068. neTriangle_ * t = &triangleArray[_triIndex[j]];
  1069. points[0] = convexB.vertices[t->indices[0]];
  1070. points[1] = convexB.vertices[t->indices[1]];
  1071. points[2] = convexB.vertices[t->indices[2]];
  1072. points[3] = convexB.vertices[t->indices[0]];
  1073. extern void DrawLine(const neV3 & colour, neV3 * startpoint, s32 count);
  1074. DrawLine(red, points, 4);
  1075. }
  1076. #endif
  1077. for (s32 i = 0; i < triangleCount; i++)
  1078. {
  1079. s32 test = _triIndex[i];
  1080. neTriangle_ * t = &triangleArray[_triIndex[i]];
  1081. _triVertexPos[0] = convexB.vertices[t->indices[0]];
  1082. _triVertexPos[1] = convexB.vertices[t->indices[1]];
  1083. _triVertexPos[2] = convexB.vertices[t->indices[2]];
  1084. neV3 diff1 = _triVertexPos[1] - _triVertexPos[0];
  1085. neV3 diff2 = _triVertexPos[2] - _triVertexPos[1];
  1086. neV3 diff3 = _triVertexPos[0] - _triVertexPos[2];
  1087. _triNormals[0] = diff1.Cross(diff2);
  1088. _triNormals[0].Normalize();
  1089. _triNormals[1] = -_triNormals[0];
  1090. _triNormals[0].v[3] = _triNormals[0].Dot(_triVertexPos[0]);
  1091. _triNormals[1].v[3] = -_triNormals[0].v[3];
  1092. TriEdgeDir[0] = _triNormals[0].Cross(diff1);
  1093. TriEdgeDir[1] = _triNormals[0].Cross(diff2);
  1094. TriEdgeDir[2] = _triNormals[0].Cross(diff3);
  1095. TriEdgeDir[0].Normalize();
  1096. TriEdgeDir[1].Normalize();
  1097. TriEdgeDir[2].Normalize();
  1098. neV3 insidePoint = _triVertexPos[0] + _triVertexPos[1] + _triVertexPos[2];
  1099. insidePoint *= (1.0f / 3.0f);
  1100. //insidePoint += (_triNormals[1] * 0.1f);
  1101. if (TestDCDTri(res[testRes], convexA, transA, insidePoint))
  1102. {
  1103. if (res[testRes].depth > res[currentRes].depth)
  1104. {
  1105. s32 tmp = testRes;
  1106. testRes = currentRes;
  1107. currentRes = tmp;
  1108. terrainMatID = t->materialID;
  1109. finalTriIndex = _triIndex[i];
  1110. found = true;
  1111. }
  1112. }
  1113. }
  1114. if (found)
  1115. {
  1116. result.penetrate = true;
  1117. result.depth = res[currentRes].depth;
  1118. result.collisionFrame[2] = res[currentRes].contactNormal;
  1119. result.materialIdB = terrainMatID;
  1120. result.contactA = res[currentRes].contactA;
  1121. result.contactB = res[currentRes].contactB;
  1122. }
  1123. else
  1124. {
  1125. result.penetrate = false;
  1126. }
  1127. }
  1128. bool CalcContactEE(const neV3 & edgeA0,
  1129. const neV3 & edgeA1,
  1130. const neV3 & edgeB0,
  1131. const neV3 & edgeB1, neV3 & contactA, neV3 & contactB)
  1132. {
  1133. f32 d1343, d4321, d1321, d4343, d2121;
  1134. f32 numer, denom, au, bu;
  1135. neV3 p13;
  1136. neV3 p43;
  1137. neV3 p21;
  1138. p13 = (edgeA0) - (edgeB0);
  1139. p43 = (edgeB1) - (edgeB0);
  1140. if ( p43.IsConsiderZero() )
  1141. {
  1142. goto CalcContactEE_Exit;
  1143. }
  1144. p21 = (edgeA1) - (edgeA0);
  1145. if ( p21.IsConsiderZero() )
  1146. {
  1147. goto CalcContactEE_Exit;
  1148. }
  1149. d1343 = p13.Dot(p43);
  1150. d4321 = p43.Dot(p21);
  1151. d1321 = p13.Dot(p21);
  1152. d4343 = p43.Dot(p43);
  1153. d2121 = p21.Dot(p21);
  1154. denom = d2121 * d4343 - d4321 * d4321;
  1155. if (neAbs(denom) < NE_ZERO)
  1156. goto CalcContactEE_Exit;
  1157. numer = d1343 * d4321 - d1321 * d4343;
  1158. au = numer / denom;
  1159. bu = (d1343 + d4321 * (au)) / d4343;
  1160. if (au < 0.0f || au >= 1.0f)
  1161. goto CalcContactEE_Exit;
  1162. if (bu < 0.0f || bu >= 1.0f)
  1163. goto CalcContactEE_Exit;
  1164. {
  1165. neV3 tmpv;
  1166. tmpv = p21 * au;
  1167. contactA = (edgeA0) + tmpv;
  1168. tmpv = p43 * bu;
  1169. contactB = (edgeB0) + tmpv;
  1170. }
  1171. return true;
  1172. CalcContactEE_Exit:
  1173. return false;
  1174. }