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 #ifndef BT_PERSISTENT_MANIFOLD_H
17 #define BT_PERSISTENT_MANIFOLD_H
19 #include "LinearMath/btVector3.h"
20 #include "LinearMath/btTransform.h"
21 #include "btManifoldPoint.h"
22 class btCollisionObject;
23 #include "LinearMath/btAlignedAllocator.h"
25 struct btCollisionResult;
26 struct btCollisionObjectDoubleData;
27 struct btCollisionObjectFloatData;
29 ///maximum contact breaking and merging threshold
30 extern btScalar gContactBreakingThreshold;
33 class btPersistentManifold;
35 typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
36 typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp, void* body0, void* body1);
37 typedef void (*ContactStartedCallback)(btPersistentManifold* const& manifold);
38 typedef void (*ContactEndedCallback)(btPersistentManifold* const& manifold);
39 extern ContactDestroyedCallback gContactDestroyedCallback;
40 extern ContactProcessedCallback gContactProcessedCallback;
41 extern ContactStartedCallback gContactStartedCallback;
42 extern ContactEndedCallback gContactEndedCallback;
45 //the enum starts at 1024 to avoid type conflicts with btTypedConstraint
46 enum btContactManifoldTypes
48 MIN_CONTACT_MANIFOLD_TYPE = 1024,
49 BT_PERSISTENT_MANIFOLD_TYPE
52 #define MANIFOLD_CACHE_SIZE 4
54 ///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
55 ///Those contact points are created by the collision narrow phase.
56 ///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
57 ///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
58 ///reduces the cache to 4 points, when more then 4 points are added, using following rules:
59 ///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
60 ///note that some pairs of objects might have more then one contact manifold.
62 //ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
63 ATTRIBUTE_ALIGNED16(class)
64 btPersistentManifold : public btTypedObject
66 btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
68 /// this two body pointers can point to the physics rigidbody class.
69 const btCollisionObject* m_body0;
70 const btCollisionObject* m_body1;
74 btScalar m_contactBreakingThreshold;
75 btScalar m_contactProcessingThreshold;
77 /// sort cached points so most isolated points come first
78 int sortCachedPoints(const btManifoldPoint& pt);
80 int findContactPoint(const btManifoldPoint* unUsed, int numUnused, const btManifoldPoint& pt);
83 BT_DECLARE_ALIGNED_ALLOCATOR();
90 btPersistentManifold();
92 btPersistentManifold(const btCollisionObject* body0, const btCollisionObject* body1, int, btScalar contactBreakingThreshold, btScalar contactProcessingThreshold)
93 : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
97 m_contactBreakingThreshold(contactBreakingThreshold),
98 m_contactProcessingThreshold(contactProcessingThreshold),
105 SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0; }
106 SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1; }
108 void setBodies(const btCollisionObject* body0, const btCollisionObject* body1)
114 void clearUserCache(btManifoldPoint & pt);
116 #ifdef DEBUG_PERSISTENCY
117 void DebugPersistency();
120 SIMD_FORCE_INLINE int getNumContacts() const
122 return m_cachedPoints;
124 /// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
125 void setNumContacts(int cachedPoints)
127 m_cachedPoints = cachedPoints;
130 SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
132 btAssert(index < m_cachedPoints);
133 return m_pointCache[index];
136 SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
138 btAssert(index < m_cachedPoints);
139 return m_pointCache[index];
142 ///@todo: get this margin from the current physics / collision environment
143 btScalar getContactBreakingThreshold() const;
145 btScalar getContactProcessingThreshold() const
147 return m_contactProcessingThreshold;
150 void setContactBreakingThreshold(btScalar contactBreakingThreshold)
152 m_contactBreakingThreshold = contactBreakingThreshold;
155 void setContactProcessingThreshold(btScalar contactProcessingThreshold)
157 m_contactProcessingThreshold = contactProcessingThreshold;
160 int getCacheEntry(const btManifoldPoint& newPoint) const;
162 int addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive = false);
164 void removeContactPoint(int index)
166 clearUserCache(m_pointCache[index]);
168 int lastUsedIndex = getNumContacts() - 1;
169 // m_pointCache[index] = m_pointCache[lastUsedIndex];
170 if (index != lastUsedIndex)
172 m_pointCache[index] = m_pointCache[lastUsedIndex];
173 //get rid of duplicated userPersistentData pointer
174 m_pointCache[lastUsedIndex].m_userPersistentData = 0;
175 m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
176 m_pointCache[lastUsedIndex].m_prevRHS = 0.f;
177 m_pointCache[lastUsedIndex].m_contactPointFlags = 0;
178 m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
179 m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
180 m_pointCache[lastUsedIndex].m_lifeTime = 0;
183 btAssert(m_pointCache[lastUsedIndex].m_userPersistentData == 0);
186 if (gContactEndedCallback && m_cachedPoints == 0)
188 gContactEndedCallback(this);
191 void replaceContactPoint(const btManifoldPoint& newPoint, int insertIndex)
193 btAssert(validContactDistance(newPoint));
195 #define MAINTAIN_PERSISTENCY 1
196 #ifdef MAINTAIN_PERSISTENCY
197 int lifeTime = m_pointCache[insertIndex].getLifeTime();
198 btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
199 btScalar prevRHS = m_pointCache[insertIndex].m_prevRHS;
200 btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
201 btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
203 bool replacePoint = true;
204 ///we keep existing contact points for friction anchors
205 ///if the friction force is within the Coulomb friction cone
206 if (newPoint.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
208 // printf("appliedImpulse=%f\n", appliedImpulse);
209 // printf("appliedLateralImpulse1=%f\n", appliedLateralImpulse1);
210 // printf("appliedLateralImpulse2=%f\n", appliedLateralImpulse2);
211 // printf("mu = %f\n", m_pointCache[insertIndex].m_combinedFriction);
212 btScalar mu = m_pointCache[insertIndex].m_combinedFriction;
213 btScalar eps = 0; //we could allow to enlarge or shrink the tolerance to check against the friction cone a bit, say 1e-7
214 btScalar a = appliedLateralImpulse1 * appliedLateralImpulse1 + appliedLateralImpulse2 * appliedLateralImpulse2;
215 btScalar b = eps + mu * appliedImpulse;
217 replacePoint = (a) > (b);
222 btAssert(lifeTime >= 0);
223 void* cache = m_pointCache[insertIndex].m_userPersistentData;
225 m_pointCache[insertIndex] = newPoint;
226 m_pointCache[insertIndex].m_userPersistentData = cache;
227 m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
228 m_pointCache[insertIndex].m_prevRHS = prevRHS;
229 m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
230 m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
233 m_pointCache[insertIndex].m_lifeTime = lifeTime;
235 clearUserCache(m_pointCache[insertIndex]);
236 m_pointCache[insertIndex] = newPoint;
241 bool validContactDistance(const btManifoldPoint& pt) const
243 return pt.m_distance1 <= getContactBreakingThreshold();
245 /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
246 void refreshContactPoints(const btTransform& trA, const btTransform& trB);
248 SIMD_FORCE_INLINE void clearManifold()
251 for (i = 0; i < m_cachedPoints; i++)
253 clearUserCache(m_pointCache[i]);
256 if (gContactEndedCallback && m_cachedPoints)
258 gContactEndedCallback(this);
263 int calculateSerializeBufferSize() const;
264 const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
265 void deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr);
266 void deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr);
271 struct btPersistentManifoldDoubleData
273 btVector3DoubleData m_pointCacheLocalPointA[4];
274 btVector3DoubleData m_pointCacheLocalPointB[4];
275 btVector3DoubleData m_pointCachePositionWorldOnA[4];
276 btVector3DoubleData m_pointCachePositionWorldOnB[4];
277 btVector3DoubleData m_pointCacheNormalWorldOnB[4];
278 btVector3DoubleData m_pointCacheLateralFrictionDir1[4];
279 btVector3DoubleData m_pointCacheLateralFrictionDir2[4];
280 double m_pointCacheDistance[4];
281 double m_pointCacheAppliedImpulse[4];
282 double m_pointCachePrevRHS[4];
283 double m_pointCacheCombinedFriction[4];
284 double m_pointCacheCombinedRollingFriction[4];
285 double m_pointCacheCombinedSpinningFriction[4];
286 double m_pointCacheCombinedRestitution[4];
287 int m_pointCachePartId0[4];
288 int m_pointCachePartId1[4];
289 int m_pointCacheIndex0[4];
290 int m_pointCacheIndex1[4];
291 int m_pointCacheContactPointFlags[4];
292 double m_pointCacheAppliedImpulseLateral1[4];
293 double m_pointCacheAppliedImpulseLateral2[4];
294 double m_pointCacheContactMotion1[4];
295 double m_pointCacheContactMotion2[4];
296 double m_pointCacheContactCFM[4];
297 double m_pointCacheCombinedContactStiffness1[4];
298 double m_pointCacheContactERP[4];
299 double m_pointCacheCombinedContactDamping1[4];
300 double m_pointCacheFrictionCFM[4];
301 int m_pointCacheLifeTime[4];
303 int m_numCachedPoints;
309 double m_contactBreakingThreshold;
310 double m_contactProcessingThreshold;
313 btCollisionObjectDoubleData *m_body0;
314 btCollisionObjectDoubleData *m_body1;
318 struct btPersistentManifoldFloatData
320 btVector3FloatData m_pointCacheLocalPointA[4];
321 btVector3FloatData m_pointCacheLocalPointB[4];
322 btVector3FloatData m_pointCachePositionWorldOnA[4];
323 btVector3FloatData m_pointCachePositionWorldOnB[4];
324 btVector3FloatData m_pointCacheNormalWorldOnB[4];
325 btVector3FloatData m_pointCacheLateralFrictionDir1[4];
326 btVector3FloatData m_pointCacheLateralFrictionDir2[4];
327 float m_pointCacheDistance[4];
328 float m_pointCacheAppliedImpulse[4];
329 float m_pointCachePrevRHS[4];
330 float m_pointCacheCombinedFriction[4];
331 float m_pointCacheCombinedRollingFriction[4];
332 float m_pointCacheCombinedSpinningFriction[4];
333 float m_pointCacheCombinedRestitution[4];
334 int m_pointCachePartId0[4];
335 int m_pointCachePartId1[4];
336 int m_pointCacheIndex0[4];
337 int m_pointCacheIndex1[4];
338 int m_pointCacheContactPointFlags[4];
339 float m_pointCacheAppliedImpulseLateral1[4];
340 float m_pointCacheAppliedImpulseLateral2[4];
341 float m_pointCacheContactMotion1[4];
342 float m_pointCacheContactMotion2[4];
343 float m_pointCacheContactCFM[4];
344 float m_pointCacheCombinedContactStiffness1[4];
345 float m_pointCacheContactERP[4];
346 float m_pointCacheCombinedContactDamping1[4];
347 float m_pointCacheFrictionCFM[4];
348 int m_pointCacheLifeTime[4];
350 int m_numCachedPoints;
356 float m_contactBreakingThreshold;
357 float m_contactProcessingThreshold;
360 btCollisionObjectFloatData *m_body0;
361 btCollisionObjectFloatData *m_body1;
366 #ifdef BT_USE_DOUBLE_PRECISION
367 #define btPersistentManifoldData btPersistentManifoldDoubleData
368 #define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
370 #define btPersistentManifoldData btPersistentManifoldFloatData
371 #define btPersistentManifoldDataName "btPersistentManifoldFloatData"
372 #endif //BT_USE_DOUBLE_PRECISION
374 #endif //BT_PERSISTENT_MANIFOLD_H