btGImpactCollisionAlgorithm.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /*
  2. This source file is part of GIMPACT Library.
  3. For the latest info, see http://gimpact.sourceforge.net/
  4. Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
  5. email: projectileman@yahoo.com
  6. This software is provided 'as-is', without any express or implied warranty.
  7. In no event will the authors be held liable for any damages arising from the use of this software.
  8. Permission is granted to anyone to use this software for any purpose,
  9. including commercial applications, and to alter it and redistribute it freely,
  10. subject to the following restrictions:
  11. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  12. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  13. 3. This notice may not be removed or altered from any source distribution.
  14. */
  15. /*
  16. Author: Francisco Leon Najera
  17. Concave-Concave Collision
  18. */
  19. #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
  20. #include "LinearMath/btIDebugDraw.h"
  21. #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
  22. #include "BulletCollision/CollisionShapes/btBoxShape.h"
  23. #include "btGImpactCollisionAlgorithm.h"
  24. #include "btContactProcessing.h"
  25. #include "LinearMath/btQuickprof.h"
  26. //! Class for accessing the plane equation
  27. class btPlaneShape : public btStaticPlaneShape
  28. {
  29. public:
  30. btPlaneShape(const btVector3& v, float f)
  31. : btStaticPlaneShape(v, f)
  32. {
  33. }
  34. void get_plane_equation(btVector4& equation)
  35. {
  36. equation[0] = m_planeNormal[0];
  37. equation[1] = m_planeNormal[1];
  38. equation[2] = m_planeNormal[2];
  39. equation[3] = m_planeConstant;
  40. }
  41. void get_plane_equation_transformed(const btTransform& trans, btVector4& equation) const
  42. {
  43. const btVector3 normal = trans.getBasis() * m_planeNormal;
  44. equation[0] = normal[0];
  45. equation[1] = normal[1];
  46. equation[2] = normal[2];
  47. equation[3] = normal.dot(trans * (m_planeConstant * m_planeNormal));
  48. }
  49. };
  50. //////////////////////////////////////////////////////////////////////////////////////////////
  51. #ifdef TRI_COLLISION_PROFILING
  52. btClock g_triangle_clock;
  53. float g_accum_triangle_collision_time = 0;
  54. int g_count_triangle_collision = 0;
  55. void bt_begin_gim02_tri_time()
  56. {
  57. g_triangle_clock.reset();
  58. }
  59. void bt_end_gim02_tri_time()
  60. {
  61. g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
  62. g_count_triangle_collision++;
  63. }
  64. #endif //TRI_COLLISION_PROFILING
  65. //! Retrieving shapes shapes
  66. /*!
  67. Declared here due of insuficent space on Pool allocators
  68. */
  69. //!@{
  70. class GIM_ShapeRetriever
  71. {
  72. public:
  73. const btGImpactShapeInterface* m_gim_shape;
  74. btTriangleShapeEx m_trishape;
  75. btTetrahedronShapeEx m_tetrashape;
  76. public:
  77. class ChildShapeRetriever
  78. {
  79. public:
  80. GIM_ShapeRetriever* m_parent;
  81. virtual const btCollisionShape* getChildShape(int index)
  82. {
  83. return m_parent->m_gim_shape->getChildShape(index);
  84. }
  85. virtual ~ChildShapeRetriever() {}
  86. };
  87. class TriangleShapeRetriever : public ChildShapeRetriever
  88. {
  89. public:
  90. virtual btCollisionShape* getChildShape(int index)
  91. {
  92. m_parent->m_gim_shape->getBulletTriangle(index, m_parent->m_trishape);
  93. return &m_parent->m_trishape;
  94. }
  95. virtual ~TriangleShapeRetriever() {}
  96. };
  97. class TetraShapeRetriever : public ChildShapeRetriever
  98. {
  99. public:
  100. virtual btCollisionShape* getChildShape(int index)
  101. {
  102. m_parent->m_gim_shape->getBulletTetrahedron(index, m_parent->m_tetrashape);
  103. return &m_parent->m_tetrashape;
  104. }
  105. };
  106. public:
  107. ChildShapeRetriever m_child_retriever;
  108. TriangleShapeRetriever m_tri_retriever;
  109. TetraShapeRetriever m_tetra_retriever;
  110. ChildShapeRetriever* m_current_retriever;
  111. GIM_ShapeRetriever(const btGImpactShapeInterface* gim_shape)
  112. {
  113. m_gim_shape = gim_shape;
  114. //select retriever
  115. if (m_gim_shape->needsRetrieveTriangles())
  116. {
  117. m_current_retriever = &m_tri_retriever;
  118. }
  119. else if (m_gim_shape->needsRetrieveTetrahedrons())
  120. {
  121. m_current_retriever = &m_tetra_retriever;
  122. }
  123. else
  124. {
  125. m_current_retriever = &m_child_retriever;
  126. }
  127. m_current_retriever->m_parent = this;
  128. }
  129. const btCollisionShape* getChildShape(int index)
  130. {
  131. return m_current_retriever->getChildShape(index);
  132. }
  133. };
  134. //!@}
  135. #ifdef TRI_COLLISION_PROFILING
  136. //! Gets the average time in miliseconds of tree collisions
  137. float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
  138. {
  139. return btGImpactBoxSet::getAverageTreeCollisionTime();
  140. }
  141. //! Gets the average time in miliseconds of triangle collisions
  142. float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
  143. {
  144. if (g_count_triangle_collision == 0) return 0;
  145. float avgtime = g_accum_triangle_collision_time;
  146. avgtime /= (float)g_count_triangle_collision;
  147. g_accum_triangle_collision_time = 0;
  148. g_count_triangle_collision = 0;
  149. return avgtime;
  150. }
  151. #endif //TRI_COLLISION_PROFILING
  152. btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
  153. : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap)
  154. {
  155. m_manifoldPtr = NULL;
  156. m_convex_algorithm = NULL;
  157. }
  158. btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
  159. {
  160. clearCache();
  161. }
  162. void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper* body0Wrap,
  163. const btCollisionObjectWrapper* body1Wrap,
  164. const btVector3& point,
  165. const btVector3& normal,
  166. btScalar distance)
  167. {
  168. m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
  169. m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
  170. checkManifold(body0Wrap, body1Wrap);
  171. m_resultOut->addContactPoint(normal, point, distance);
  172. }
  173. void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
  174. const btCollisionObjectWrapper* body0Wrap,
  175. const btCollisionObjectWrapper* body1Wrap,
  176. const btCollisionShape* shape0,
  177. const btCollisionShape* shape1)
  178. {
  179. {
  180. btCollisionAlgorithm* algor = newAlgorithm(body0Wrap, body1Wrap);
  181. // post : checkManifold is called
  182. m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
  183. m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
  184. algor->processCollision(body0Wrap, body1Wrap, *m_dispatchInfo, m_resultOut);
  185. algor->~btCollisionAlgorithm();
  186. m_dispatcher->freeCollisionAlgorithm(algor);
  187. }
  188. }
  189. void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
  190. const btCollisionObjectWrapper* body0Wrap,
  191. const btCollisionObjectWrapper* body1Wrap,
  192. const btCollisionShape* shape0,
  193. const btCollisionShape* shape1)
  194. {
  195. m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
  196. m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
  197. btCollisionObjectWrapper ob0(body0Wrap, shape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
  198. btCollisionObjectWrapper ob1(body1Wrap, shape1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), m_part1, m_triface1);
  199. checkConvexAlgorithm(&ob0, &ob1);
  200. m_convex_algorithm->processCollision(&ob0, &ob1, *m_dispatchInfo, m_resultOut);
  201. }
  202. void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
  203. const btTransform& trans0,
  204. const btTransform& trans1,
  205. const btGImpactShapeInterface* shape0,
  206. const btGImpactShapeInterface* shape1, btPairSet& pairset)
  207. {
  208. if (shape0->hasBoxSet() && shape1->hasBoxSet())
  209. {
  210. btGImpactBoxSet::find_collision(shape0->getBoxSet(), trans0, shape1->getBoxSet(), trans1, pairset);
  211. }
  212. else
  213. {
  214. btAABB boxshape0;
  215. btAABB boxshape1;
  216. int i = shape0->getNumChildShapes();
  217. while (i--)
  218. {
  219. shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
  220. int j = shape1->getNumChildShapes();
  221. while (j--)
  222. {
  223. shape1->getChildAabb(i, trans1, boxshape1.m_min, boxshape1.m_max);
  224. if (boxshape1.has_collision(boxshape0))
  225. {
  226. pairset.push_pair(i, j);
  227. }
  228. }
  229. }
  230. }
  231. }
  232. void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
  233. const btTransform& trans0,
  234. const btTransform& trans1,
  235. const btGImpactShapeInterface* shape0,
  236. const btCollisionShape* shape1,
  237. btAlignedObjectArray<int>& collided_primitives)
  238. {
  239. btAABB boxshape;
  240. if (shape0->hasBoxSet())
  241. {
  242. btTransform trans1to0 = trans0.inverse();
  243. trans1to0 *= trans1;
  244. shape1->getAabb(trans1to0, boxshape.m_min, boxshape.m_max);
  245. shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
  246. }
  247. else
  248. {
  249. shape1->getAabb(trans1, boxshape.m_min, boxshape.m_max);
  250. btAABB boxshape0;
  251. int i = shape0->getNumChildShapes();
  252. while (i--)
  253. {
  254. shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
  255. if (boxshape.has_collision(boxshape0))
  256. {
  257. collided_primitives.push_back(i);
  258. }
  259. }
  260. }
  261. }
  262. void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
  263. const btCollisionObjectWrapper* body1Wrap,
  264. const btGImpactMeshShapePart* shape0,
  265. const btGImpactMeshShapePart* shape1,
  266. const int* pairs, int pair_count)
  267. {
  268. btTriangleShapeEx tri0;
  269. btTriangleShapeEx tri1;
  270. shape0->lockChildShapes();
  271. shape1->lockChildShapes();
  272. const int* pair_pointer = pairs;
  273. while (pair_count--)
  274. {
  275. m_triface0 = *(pair_pointer);
  276. m_triface1 = *(pair_pointer + 1);
  277. pair_pointer += 2;
  278. shape0->getBulletTriangle(m_triface0, tri0);
  279. shape1->getBulletTriangle(m_triface1, tri1);
  280. //collide two convex shapes
  281. if (tri0.overlap_test_conservative(tri1))
  282. {
  283. convex_vs_convex_collision(body0Wrap, body1Wrap, &tri0, &tri1);
  284. }
  285. }
  286. shape0->unlockChildShapes();
  287. shape1->unlockChildShapes();
  288. }
  289. void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
  290. const btCollisionObjectWrapper* body1Wrap,
  291. const btGImpactMeshShapePart* shape0,
  292. const btGImpactMeshShapePart* shape1,
  293. const int* pairs, int pair_count)
  294. {
  295. btTransform orgtrans0 = body0Wrap->getWorldTransform();
  296. btTransform orgtrans1 = body1Wrap->getWorldTransform();
  297. btPrimitiveTriangle ptri0;
  298. btPrimitiveTriangle ptri1;
  299. GIM_TRIANGLE_CONTACT contact_data;
  300. shape0->lockChildShapes();
  301. shape1->lockChildShapes();
  302. const int* pair_pointer = pairs;
  303. while (pair_count--)
  304. {
  305. m_triface0 = *(pair_pointer);
  306. m_triface1 = *(pair_pointer + 1);
  307. pair_pointer += 2;
  308. shape0->getPrimitiveTriangle(m_triface0, ptri0);
  309. shape1->getPrimitiveTriangle(m_triface1, ptri1);
  310. #ifdef TRI_COLLISION_PROFILING
  311. bt_begin_gim02_tri_time();
  312. #endif
  313. ptri0.applyTransform(orgtrans0);
  314. ptri1.applyTransform(orgtrans1);
  315. //build planes
  316. ptri0.buildTriPlane();
  317. ptri1.buildTriPlane();
  318. // test conservative
  319. if (ptri0.overlap_test_conservative(ptri1))
  320. {
  321. if (ptri0.find_triangle_collision_clip_method(ptri1, contact_data))
  322. {
  323. int j = contact_data.m_point_count;
  324. while (j--)
  325. {
  326. addContactPoint(body0Wrap, body1Wrap,
  327. contact_data.m_points[j],
  328. contact_data.m_separating_normal,
  329. -contact_data.m_penetration_depth);
  330. }
  331. }
  332. }
  333. #ifdef TRI_COLLISION_PROFILING
  334. bt_end_gim02_tri_time();
  335. #endif
  336. }
  337. shape0->unlockChildShapes();
  338. shape1->unlockChildShapes();
  339. }
  340. void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
  341. const btCollisionObjectWrapper* body0Wrap,
  342. const btCollisionObjectWrapper* body1Wrap,
  343. const btGImpactShapeInterface* shape0,
  344. const btGImpactShapeInterface* shape1)
  345. {
  346. if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
  347. {
  348. const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
  349. m_part0 = meshshape0->getMeshPartCount();
  350. while (m_part0--)
  351. {
  352. gimpact_vs_gimpact(body0Wrap, body1Wrap, meshshape0->getMeshPart(m_part0), shape1);
  353. }
  354. return;
  355. }
  356. if (shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
  357. {
  358. const btGImpactMeshShape* meshshape1 = static_cast<const btGImpactMeshShape*>(shape1);
  359. m_part1 = meshshape1->getMeshPartCount();
  360. while (m_part1--)
  361. {
  362. gimpact_vs_gimpact(body0Wrap, body1Wrap, shape0, meshshape1->getMeshPart(m_part1));
  363. }
  364. return;
  365. }
  366. btTransform orgtrans0 = body0Wrap->getWorldTransform();
  367. btTransform orgtrans1 = body1Wrap->getWorldTransform();
  368. btPairSet pairset;
  369. gimpact_vs_gimpact_find_pairs(orgtrans0, orgtrans1, shape0, shape1, pairset);
  370. if (pairset.size() == 0) return;
  371. if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
  372. shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
  373. {
  374. const btGImpactMeshShapePart* shapepart0 = static_cast<const btGImpactMeshShapePart*>(shape0);
  375. const btGImpactMeshShapePart* shapepart1 = static_cast<const btGImpactMeshShapePart*>(shape1);
  376. //specialized function
  377. #ifdef BULLET_TRIANGLE_COLLISION
  378. collide_gjk_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
  379. #else
  380. collide_sat_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
  381. #endif
  382. return;
  383. }
  384. //general function
  385. shape0->lockChildShapes();
  386. shape1->lockChildShapes();
  387. GIM_ShapeRetriever retriever0(shape0);
  388. GIM_ShapeRetriever retriever1(shape1);
  389. bool child_has_transform0 = shape0->childrenHasTransform();
  390. bool child_has_transform1 = shape1->childrenHasTransform();
  391. int i = pairset.size();
  392. while (i--)
  393. {
  394. GIM_PAIR* pair = &pairset[i];
  395. m_triface0 = pair->m_index1;
  396. m_triface1 = pair->m_index2;
  397. const btCollisionShape* colshape0 = retriever0.getChildShape(m_triface0);
  398. const btCollisionShape* colshape1 = retriever1.getChildShape(m_triface1);
  399. btTransform tr0 = body0Wrap->getWorldTransform();
  400. btTransform tr1 = body1Wrap->getWorldTransform();
  401. if (child_has_transform0)
  402. {
  403. tr0 = orgtrans0 * shape0->getChildTransform(m_triface0);
  404. }
  405. if (child_has_transform1)
  406. {
  407. tr1 = orgtrans1 * shape1->getChildTransform(m_triface1);
  408. }
  409. btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), tr0, m_part0, m_triface0);
  410. btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), tr1, m_part1, m_triface1);
  411. //collide two convex shapes
  412. convex_vs_convex_collision(&ob0, &ob1, colshape0, colshape1);
  413. }
  414. shape0->unlockChildShapes();
  415. shape1->unlockChildShapes();
  416. }
  417. void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
  418. const btCollisionObjectWrapper* body1Wrap,
  419. const btGImpactShapeInterface* shape0,
  420. const btCollisionShape* shape1, bool swapped)
  421. {
  422. if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
  423. {
  424. const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
  425. int& part = swapped ? m_part1 : m_part0;
  426. part = meshshape0->getMeshPartCount();
  427. while (part--)
  428. {
  429. gimpact_vs_shape(body0Wrap,
  430. body1Wrap,
  431. meshshape0->getMeshPart(part),
  432. shape1, swapped);
  433. }
  434. return;
  435. }
  436. #ifdef GIMPACT_VS_PLANE_COLLISION
  437. if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
  438. shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
  439. {
  440. const btGImpactMeshShapePart* shapepart = static_cast<const btGImpactMeshShapePart*>(shape0);
  441. const btStaticPlaneShape* planeshape = static_cast<const btStaticPlaneShape*>(shape1);
  442. gimpacttrimeshpart_vs_plane_collision(body0Wrap, body1Wrap, shapepart, planeshape, swapped);
  443. return;
  444. }
  445. #endif
  446. if (shape1->isCompound())
  447. {
  448. const btCompoundShape* compoundshape = static_cast<const btCompoundShape*>(shape1);
  449. gimpact_vs_compoundshape(body0Wrap, body1Wrap, shape0, compoundshape, swapped);
  450. return;
  451. }
  452. else if (shape1->isConcave())
  453. {
  454. const btConcaveShape* concaveshape = static_cast<const btConcaveShape*>(shape1);
  455. gimpact_vs_concave(body0Wrap, body1Wrap, shape0, concaveshape, swapped);
  456. return;
  457. }
  458. btTransform orgtrans0 = body0Wrap->getWorldTransform();
  459. btTransform orgtrans1 = body1Wrap->getWorldTransform();
  460. btAlignedObjectArray<int> collided_results;
  461. gimpact_vs_shape_find_pairs(orgtrans0, orgtrans1, shape0, shape1, collided_results);
  462. if (collided_results.size() == 0) return;
  463. shape0->lockChildShapes();
  464. GIM_ShapeRetriever retriever0(shape0);
  465. bool child_has_transform0 = shape0->childrenHasTransform();
  466. int i = collided_results.size();
  467. while (i--)
  468. {
  469. int child_index = collided_results[i];
  470. if (swapped)
  471. m_triface1 = child_index;
  472. else
  473. m_triface0 = child_index;
  474. const btCollisionShape* colshape0 = retriever0.getChildShape(child_index);
  475. btTransform tr0 = body0Wrap->getWorldTransform();
  476. if (child_has_transform0)
  477. {
  478. tr0 = orgtrans0 * shape0->getChildTransform(child_index);
  479. }
  480. btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
  481. const btCollisionObjectWrapper* prevObj;
  482. if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
  483. {
  484. prevObj = m_resultOut->getBody0Wrap();
  485. m_resultOut->setBody0Wrap(&ob0);
  486. }
  487. else
  488. {
  489. prevObj = m_resultOut->getBody1Wrap();
  490. m_resultOut->setBody1Wrap(&ob0);
  491. }
  492. //collide two shapes
  493. if (swapped)
  494. {
  495. shape_vs_shape_collision(body1Wrap, &ob0, shape1, colshape0);
  496. }
  497. else
  498. {
  499. shape_vs_shape_collision(&ob0, body1Wrap, colshape0, shape1);
  500. }
  501. if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
  502. {
  503. m_resultOut->setBody0Wrap(prevObj);
  504. }
  505. else
  506. {
  507. m_resultOut->setBody1Wrap(prevObj);
  508. }
  509. }
  510. shape0->unlockChildShapes();
  511. }
  512. void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
  513. const btCollisionObjectWrapper* body1Wrap,
  514. const btGImpactShapeInterface* shape0,
  515. const btCompoundShape* shape1, bool swapped)
  516. {
  517. btTransform orgtrans1 = body1Wrap->getWorldTransform();
  518. int i = shape1->getNumChildShapes();
  519. while (i--)
  520. {
  521. const btCollisionShape* colshape1 = shape1->getChildShape(i);
  522. btTransform childtrans1 = orgtrans1 * shape1->getChildTransform(i);
  523. btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), childtrans1, -1, i);
  524. const btCollisionObjectWrapper* tmp = 0;
  525. if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
  526. {
  527. tmp = m_resultOut->getBody0Wrap();
  528. m_resultOut->setBody0Wrap(&ob1);
  529. }
  530. else
  531. {
  532. tmp = m_resultOut->getBody1Wrap();
  533. m_resultOut->setBody1Wrap(&ob1);
  534. }
  535. //collide child shape
  536. gimpact_vs_shape(body0Wrap, &ob1,
  537. shape0, colshape1, swapped);
  538. if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
  539. {
  540. m_resultOut->setBody0Wrap(tmp);
  541. }
  542. else
  543. {
  544. m_resultOut->setBody1Wrap(tmp);
  545. }
  546. }
  547. }
  548. void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
  549. const btCollisionObjectWrapper* body0Wrap,
  550. const btCollisionObjectWrapper* body1Wrap,
  551. const btGImpactMeshShapePart* shape0,
  552. const btStaticPlaneShape* shape1, bool swapped)
  553. {
  554. btTransform orgtrans0 = body0Wrap->getWorldTransform();
  555. btTransform orgtrans1 = body1Wrap->getWorldTransform();
  556. const btPlaneShape* planeshape = static_cast<const btPlaneShape*>(shape1);
  557. btVector4 plane;
  558. planeshape->get_plane_equation_transformed(orgtrans1, plane);
  559. //test box against plane
  560. btAABB tribox;
  561. shape0->getAabb(orgtrans0, tribox.m_min, tribox.m_max);
  562. tribox.increment_margin(planeshape->getMargin());
  563. if (tribox.plane_classify(plane) != BT_CONST_COLLIDE_PLANE) return;
  564. shape0->lockChildShapes();
  565. btScalar margin = shape0->getMargin() + planeshape->getMargin();
  566. btVector3 vertex;
  567. int vi = shape0->getVertexCount();
  568. while (vi--)
  569. {
  570. shape0->getVertex(vi, vertex);
  571. vertex = orgtrans0(vertex);
  572. btScalar distance = vertex.dot(plane) - plane[3] - margin;
  573. if (distance < 0.0) //add contact
  574. {
  575. if (swapped)
  576. {
  577. addContactPoint(body1Wrap, body0Wrap,
  578. vertex,
  579. -plane,
  580. distance);
  581. }
  582. else
  583. {
  584. addContactPoint(body0Wrap, body1Wrap,
  585. vertex,
  586. plane,
  587. distance);
  588. }
  589. }
  590. }
  591. shape0->unlockChildShapes();
  592. }
  593. class btGImpactTriangleCallback : public btTriangleCallback
  594. {
  595. public:
  596. btGImpactCollisionAlgorithm* algorithm;
  597. const btCollisionObjectWrapper* body0Wrap;
  598. const btCollisionObjectWrapper* body1Wrap;
  599. const btGImpactShapeInterface* gimpactshape0;
  600. bool swapped;
  601. btScalar margin;
  602. virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
  603. {
  604. btTriangleShapeEx tri1(triangle[0], triangle[1], triangle[2]);
  605. tri1.setMargin(margin);
  606. if (swapped)
  607. {
  608. algorithm->setPart0(partId);
  609. algorithm->setFace0(triangleIndex);
  610. }
  611. else
  612. {
  613. algorithm->setPart1(partId);
  614. algorithm->setFace1(triangleIndex);
  615. }
  616. btCollisionObjectWrapper ob1Wrap(body1Wrap, &tri1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), partId, triangleIndex);
  617. const btCollisionObjectWrapper* tmp = 0;
  618. if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
  619. {
  620. tmp = algorithm->internalGetResultOut()->getBody0Wrap();
  621. algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
  622. }
  623. else
  624. {
  625. tmp = algorithm->internalGetResultOut()->getBody1Wrap();
  626. algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
  627. }
  628. algorithm->gimpact_vs_shape(
  629. body0Wrap, &ob1Wrap, gimpactshape0, &tri1, swapped);
  630. if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
  631. {
  632. algorithm->internalGetResultOut()->setBody0Wrap(tmp);
  633. }
  634. else
  635. {
  636. algorithm->internalGetResultOut()->setBody1Wrap(tmp);
  637. }
  638. }
  639. };
  640. void btGImpactCollisionAlgorithm::gimpact_vs_concave(
  641. const btCollisionObjectWrapper* body0Wrap,
  642. const btCollisionObjectWrapper* body1Wrap,
  643. const btGImpactShapeInterface* shape0,
  644. const btConcaveShape* shape1, bool swapped)
  645. {
  646. //create the callback
  647. btGImpactTriangleCallback tricallback;
  648. tricallback.algorithm = this;
  649. tricallback.body0Wrap = body0Wrap;
  650. tricallback.body1Wrap = body1Wrap;
  651. tricallback.gimpactshape0 = shape0;
  652. tricallback.swapped = swapped;
  653. tricallback.margin = shape1->getMargin();
  654. //getting the trimesh AABB
  655. btTransform gimpactInConcaveSpace;
  656. gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
  657. btVector3 minAABB, maxAABB;
  658. shape0->getAabb(gimpactInConcaveSpace, minAABB, maxAABB);
  659. shape1->processAllTriangles(&tricallback, minAABB, maxAABB);
  660. }
  661. void btGImpactCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
  662. {
  663. clearCache();
  664. m_resultOut = resultOut;
  665. m_dispatchInfo = &dispatchInfo;
  666. const btGImpactShapeInterface* gimpactshape0;
  667. const btGImpactShapeInterface* gimpactshape1;
  668. if (body0Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
  669. {
  670. gimpactshape0 = static_cast<const btGImpactShapeInterface*>(body0Wrap->getCollisionShape());
  671. if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
  672. {
  673. gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
  674. gimpact_vs_gimpact(body0Wrap, body1Wrap, gimpactshape0, gimpactshape1);
  675. }
  676. else
  677. {
  678. gimpact_vs_shape(body0Wrap, body1Wrap, gimpactshape0, body1Wrap->getCollisionShape(), false);
  679. }
  680. }
  681. else if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
  682. {
  683. gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
  684. gimpact_vs_shape(body1Wrap, body0Wrap, gimpactshape1, body0Wrap->getCollisionShape(), true);
  685. }
  686. // Ensure that gContactProcessedCallback is called for concave shapes.
  687. if (getLastManifold())
  688. {
  689. m_resultOut->refreshContactPoints();
  690. }
  691. }
  692. btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
  693. {
  694. return 1.f;
  695. }
  696. ///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
  697. //! Use this function for register the algorithm externally
  698. void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher* dispatcher)
  699. {
  700. static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
  701. int i;
  702. for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
  703. {
  704. dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE, i, &s_gimpact_cf);
  705. }
  706. for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
  707. {
  708. dispatcher->registerCollisionCreateFunc(i, GIMPACT_SHAPE_PROXYTYPE, &s_gimpact_cf);
  709. }
  710. }