SpuMinkowskiPenetrationDepthSolver.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 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.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. #include "SpuMinkowskiPenetrationDepthSolver.h"
  14. #include "SpuContactResult.h"
  15. #include "SpuPreferredPenetrationDirections.h"
  16. #include "bullet/BulletCollision//NarrowPhaseCollision/btVoronoiSimplexSolver.h"
  17. #include "bullet/BulletCollision//NarrowPhaseCollision/btGjkPairDetector.h"
  18. #include "SpuCollisionShapes.h"
  19. #define NUM_UNITSPHERE_POINTS 42
  20. static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
  21. {
  22. btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
  23. btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
  24. btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
  25. btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
  26. btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
  27. btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
  28. btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
  29. btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
  30. btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
  31. btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
  32. btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
  33. btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
  34. btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
  35. btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
  36. btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
  37. btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
  38. btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
  39. btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
  40. btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
  41. btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
  42. btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
  43. btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
  44. btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
  45. btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
  46. btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
  47. btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
  48. btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
  49. btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
  50. btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
  51. btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
  52. btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
  53. btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
  54. btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
  55. btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
  56. btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
  57. btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
  58. btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
  59. btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
  60. btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
  61. btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
  62. btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
  63. btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
  64. };
  65. bool SpuMinkowskiPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver,
  66. const btConvexShape* convexA,const btConvexShape* convexB,
  67. const btTransform& transA,const btTransform& transB,
  68. btVector3& v, btVector3& pa, btVector3& pb,
  69. class btIDebugDraw* debugDraw)
  70. {
  71. #if 0
  72. (void)v;
  73. struct btIntermediateResult : public SpuContactResult
  74. {
  75. btIntermediateResult():m_hasResult(false)
  76. {
  77. }
  78. btVector3 m_normalOnBInWorld;
  79. btVector3 m_pointInWorld;
  80. btScalar m_depth;
  81. bool m_hasResult;
  82. virtual void setShapeIdentifiersA(int partId0,int index0)
  83. {
  84. (void)partId0;
  85. (void)index0;
  86. }
  87. virtual void setShapeIdentifiersB(int partId1,int index1)
  88. {
  89. (void)partId1;
  90. (void)index1;
  91. }
  92. void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
  93. {
  94. m_normalOnBInWorld = normalOnBInWorld;
  95. m_pointInWorld = pointInWorld;
  96. m_depth = depth;
  97. m_hasResult = true;
  98. }
  99. };
  100. //just take fixed number of orientation, and sample the penetration depth in that direction
  101. btScalar minProj = btScalar(BT_LARGE_FLOAT);
  102. btVector3 minNorm(0.f,0.f,0.f);
  103. btVector3 minVertex;
  104. btVector3 minA,minB;
  105. btVector3 seperatingAxisInA,seperatingAxisInB;
  106. btVector3 pInA,qInB,pWorld,qWorld,w;
  107. //#define USE_BATCHED_SUPPORT 1
  108. #ifdef USE_BATCHED_SUPPORT
  109. btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
  110. btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
  111. btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
  112. btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
  113. int i;
  114. int numSampleDirections = NUM_UNITSPHERE_POINTS;
  115. for (i=0;i<numSampleDirections;i++)
  116. {
  117. const btVector3& norm = sPenetrationDirections[i];
  118. seperatingAxisInABatch[i] = (-norm) * transA.getBasis() ;
  119. seperatingAxisInBBatch[i] = norm * transB.getBasis() ;
  120. }
  121. {
  122. int numPDA = convexA->getNumPreferredPenetrationDirections();
  123. if (numPDA)
  124. {
  125. for (int i=0;i<numPDA;i++)
  126. {
  127. btVector3 norm;
  128. convexA->getPreferredPenetrationDirection(i,norm);
  129. norm = transA.getBasis() * norm;
  130. sPenetrationDirections[numSampleDirections] = norm;
  131. seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
  132. seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
  133. numSampleDirections++;
  134. }
  135. }
  136. }
  137. {
  138. int numPDB = convexB->getNumPreferredPenetrationDirections();
  139. if (numPDB)
  140. {
  141. for (int i=0;i<numPDB;i++)
  142. {
  143. btVector3 norm;
  144. convexB->getPreferredPenetrationDirection(i,norm);
  145. norm = transB.getBasis() * norm;
  146. sPenetrationDirections[numSampleDirections] = norm;
  147. seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
  148. seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
  149. numSampleDirections++;
  150. }
  151. }
  152. }
  153. convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections);
  154. convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections);
  155. for (i=0;i<numSampleDirections;i++)
  156. {
  157. const btVector3& norm = sPenetrationDirections[i];
  158. seperatingAxisInA = seperatingAxisInABatch[i];
  159. seperatingAxisInB = seperatingAxisInBBatch[i];
  160. pInA = supportVerticesABatch[i];
  161. qInB = supportVerticesBBatch[i];
  162. pWorld = transA(pInA);
  163. qWorld = transB(qInB);
  164. w = qWorld - pWorld;
  165. btScalar delta = norm.dot(w);
  166. //find smallest delta
  167. if (delta < minProj)
  168. {
  169. minProj = delta;
  170. minNorm = norm;
  171. minA = pWorld;
  172. minB = qWorld;
  173. }
  174. }
  175. #else
  176. int numSampleDirections = NUM_UNITSPHERE_POINTS;
  177. ///this is necessary, otherwise the normal is not correct, and sphere will rotate forever on a sloped triangle mesh
  178. #define DO_PREFERRED_DIRECTIONS 1
  179. #ifdef DO_PREFERRED_DIRECTIONS
  180. {
  181. int numPDA = spuGetNumPreferredPenetrationDirections(shapeTypeA,convexA);
  182. if (numPDA)
  183. {
  184. for (int i=0;i<numPDA;i++)
  185. {
  186. btVector3 norm;
  187. spuGetPreferredPenetrationDirection(shapeTypeA,convexA,i,norm);
  188. norm = transA.getBasis() * norm;
  189. sPenetrationDirections[numSampleDirections] = norm;
  190. numSampleDirections++;
  191. }
  192. }
  193. }
  194. {
  195. int numPDB = spuGetNumPreferredPenetrationDirections(shapeTypeB,convexB);
  196. if (numPDB)
  197. {
  198. for (int i=0;i<numPDB;i++)
  199. {
  200. btVector3 norm;
  201. spuGetPreferredPenetrationDirection(shapeTypeB,convexB,i,norm);
  202. norm = transB.getBasis() * norm;
  203. sPenetrationDirections[numSampleDirections] = norm;
  204. numSampleDirections++;
  205. }
  206. }
  207. }
  208. #endif //DO_PREFERRED_DIRECTIONS
  209. for (int i=0;i<numSampleDirections;i++)
  210. {
  211. const btVector3& norm = sPenetrationDirections[i];
  212. seperatingAxisInA = (-norm)* transA.getBasis();
  213. seperatingAxisInB = norm* transB.getBasis();
  214. pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual( seperatingAxisInA);//, NULL);
  215. qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);//, NULL);
  216. // pInA = convexA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
  217. // qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
  218. pWorld = transA(pInA);
  219. qWorld = transB(qInB);
  220. w = qWorld - pWorld;
  221. btScalar delta = norm.dot(w);
  222. //find smallest delta
  223. if (delta < minProj)
  224. {
  225. minProj = delta;
  226. minNorm = norm;
  227. minA = pWorld;
  228. minB = qWorld;
  229. }
  230. }
  231. #endif //USE_BATCHED_SUPPORT
  232. //add the margins
  233. minA += minNorm*marginA;
  234. minB -= minNorm*marginB;
  235. //no penetration
  236. if (minProj < btScalar(0.))
  237. return false;
  238. minProj += (marginA + marginB) + btScalar(1.00);
  239. //#define DEBUG_DRAW 1
  240. #ifdef DEBUG_DRAW
  241. if (debugDraw)
  242. {
  243. btVector3 color(0,1,0);
  244. debugDraw->drawLine(minA,minB,color);
  245. color = btVector3 (1,1,1);
  246. btVector3 vec = minB-minA;
  247. btScalar prj2 = minNorm.dot(vec);
  248. debugDraw->drawLine(minA,minA+(minNorm*minProj),color);
  249. }
  250. #endif //DEBUG_DRAW
  251. btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
  252. btScalar offsetDist = minProj;
  253. btVector3 offset = minNorm * offsetDist;
  254. SpuClosestPointInput input;
  255. input.m_convexVertexData[0] = convexVertexDataA;
  256. input.m_convexVertexData[1] = convexVertexDataB;
  257. btVector3 newOrg = transA.getOrigin() + offset;
  258. btTransform displacedTrans = transA;
  259. displacedTrans.setOrigin(newOrg);
  260. input.m_transformA = displacedTrans;
  261. input.m_transformB = transB;
  262. input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj;
  263. btIntermediateResult res;
  264. gjkdet.getClosestPoints(input,res,0);
  265. btScalar correctedMinNorm = minProj - res.m_depth;
  266. //the penetration depth is over-estimated, relax it
  267. btScalar penetration_relaxation= btScalar(1.);
  268. minNorm*=penetration_relaxation;
  269. if (res.m_hasResult)
  270. {
  271. pa = res.m_pointInWorld - minNorm * correctedMinNorm;
  272. pb = res.m_pointInWorld;
  273. #ifdef DEBUG_DRAW
  274. if (debugDraw)
  275. {
  276. btVector3 color(1,0,0);
  277. debugDraw->drawLine(pa,pb,color);
  278. }
  279. #endif//DEBUG_DRAW
  280. } else {
  281. // could not seperate shapes
  282. //btAssert (false);
  283. }
  284. return res.m_hasResult;
  285. #endif
  286. return false;
  287. }