2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 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.
16 #include "btMinkowskiPenetrationDepthSolver.h"
17 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
18 #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
19 #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
20 #include "BulletCollision/CollisionShapes/btConvexShape.h"
22 #define NUM_UNITSPHERE_POINTS 42
24 bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
25 const btConvexShape* convexA, const btConvexShape* convexB,
26 const btTransform& transA, const btTransform& transB,
27 btVector3& v, btVector3& pa, btVector3& pb,
28 class btIDebugDraw* debugDraw)
32 bool check2d = convexA->isConvex2d() && convexB->isConvex2d();
34 struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
36 btIntermediateResult() : m_hasResult(false)
40 btVector3 m_normalOnBInWorld;
41 btVector3 m_pointInWorld;
45 virtual void setShapeIdentifiersA(int partId0, int index0)
50 virtual void setShapeIdentifiersB(int partId1, int index1)
55 void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
57 m_normalOnBInWorld = normalOnBInWorld;
58 m_pointInWorld = pointInWorld;
64 //just take fixed number of orientation, and sample the penetration depth in that direction
65 btScalar minProj = btScalar(BT_LARGE_FLOAT);
66 btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
68 btVector3 separatingAxisInA, separatingAxisInB;
69 btVector3 pInA, qInB, pWorld, qWorld, w;
72 #define USE_BATCHED_SUPPORT 1
74 #ifdef USE_BATCHED_SUPPORT
76 btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
77 btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
78 btVector3 separatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
79 btVector3 separatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
82 int numSampleDirections = NUM_UNITSPHERE_POINTS;
84 for (i = 0; i < numSampleDirections; i++)
86 btVector3 norm = getPenetrationDirections()[i];
87 separatingAxisInABatch[i] = (-norm) * transA.getBasis();
88 separatingAxisInBBatch[i] = norm * transB.getBasis();
92 int numPDA = convexA->getNumPreferredPenetrationDirections();
95 for (int i = 0; i < numPDA; i++)
98 convexA->getPreferredPenetrationDirection(i, norm);
99 norm = transA.getBasis() * norm;
100 getPenetrationDirections()[numSampleDirections] = norm;
101 separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
102 separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
103 numSampleDirections++;
109 int numPDB = convexB->getNumPreferredPenetrationDirections();
112 for (int i = 0; i < numPDB; i++)
115 convexB->getPreferredPenetrationDirection(i, norm);
116 norm = transB.getBasis() * norm;
117 getPenetrationDirections()[numSampleDirections] = norm;
118 separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
119 separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
120 numSampleDirections++;
125 convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInABatch, supportVerticesABatch, numSampleDirections);
126 convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
128 for (i = 0; i < numSampleDirections; i++)
130 btVector3 norm = getPenetrationDirections()[i];
135 if (norm.length2() > 0.01)
137 separatingAxisInA = separatingAxisInABatch[i];
138 separatingAxisInB = separatingAxisInBBatch[i];
140 pInA = supportVerticesABatch[i];
141 qInB = supportVerticesBBatch[i];
143 pWorld = transA(pInA);
144 qWorld = transB(qInB);
152 btScalar delta = norm.dot(w);
153 //find smallest delta
165 int numSampleDirections = NUM_UNITSPHERE_POINTS;
169 int numPDA = convexA->getNumPreferredPenetrationDirections();
172 for (int i = 0; i < numPDA; i++)
175 convexA->getPreferredPenetrationDirection(i, norm);
176 norm = transA.getBasis() * norm;
177 getPenetrationDirections()[numSampleDirections] = norm;
178 numSampleDirections++;
184 int numPDB = convexB->getNumPreferredPenetrationDirections();
187 for (int i = 0; i < numPDB; i++)
190 convexB->getPreferredPenetrationDirection(i, norm);
191 norm = transB.getBasis() * norm;
192 getPenetrationDirections()[numSampleDirections] = norm;
193 numSampleDirections++;
199 for (int i = 0; i < numSampleDirections; i++)
201 const btVector3& norm = getPenetrationDirections()[i];
202 separatingAxisInA = (-norm) * transA.getBasis();
203 separatingAxisInB = norm * transB.getBasis();
204 pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
205 qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
206 pWorld = transA(pInA);
207 qWorld = transB(qInB);
209 btScalar delta = norm.dot(w);
210 //find smallest delta
219 #endif //USE_BATCHED_SUPPORT
223 minA += minNorm * convexA->getMarginNonVirtual();
224 minB -= minNorm * convexB->getMarginNonVirtual();
226 if (minProj < btScalar(0.))
229 btScalar extraSeparation = 0.5f; ///scale dependent
230 minProj += extraSeparation + (convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
232 //#define DEBUG_DRAW 1
236 btVector3 color(0, 1, 0);
237 debugDraw->drawLine(minA, minB, color);
238 color = btVector3(1, 1, 1);
239 btVector3 vec = minB - minA;
240 btScalar prj2 = minNorm.dot(vec);
241 debugDraw->drawLine(minA, minA + (minNorm * minProj), color);
245 btGjkPairDetector gjkdet(convexA, convexB, &simplexSolver, 0);
247 btScalar offsetDist = minProj;
248 btVector3 offset = minNorm * offsetDist;
250 btGjkPairDetector::ClosestPointInput input;
252 btVector3 newOrg = transA.getOrigin() + offset;
254 btTransform displacedTrans = transA;
255 displacedTrans.setOrigin(newOrg);
257 input.m_transformA = displacedTrans;
258 input.m_transformB = transB;
259 input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); //minProj;
261 btIntermediateResult res;
262 gjkdet.setCachedSeparatingAxis(-minNorm);
263 gjkdet.getClosestPoints(input, res, debugDraw);
265 btScalar correctedMinNorm = minProj - res.m_depth;
267 //the penetration depth is over-estimated, relax it
268 btScalar penetration_relaxation = btScalar(1.);
269 minNorm *= penetration_relaxation;
273 pa = res.m_pointInWorld - minNorm * correctedMinNorm;
274 pb = res.m_pointInWorld;
280 btVector3 color(1, 0, 0);
281 debugDraw->drawLine(pa, pb, color);
285 return res.m_hasResult;
288 btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
290 static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
292 btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
293 btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
294 btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
295 btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
296 btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
297 btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
298 btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
299 btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
300 btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
301 btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
302 btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
303 btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
304 btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
305 btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
306 btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
307 btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
308 btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
309 btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
310 btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
311 btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
312 btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
313 btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
314 btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
315 btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
316 btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
317 btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
318 btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
319 btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
320 btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
321 btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
322 btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
323 btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
324 btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
325 btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
326 btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
327 btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
328 btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
329 btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
330 btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
331 btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
332 btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
333 btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
335 return sPenetrationDirections;