• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4 
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:
10 
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 #ifndef BT_PERSISTENT_MANIFOLD_H
17 #define BT_PERSISTENT_MANIFOLD_H
18 
19 
20 #include "LinearMath/btVector3.h"
21 #include "LinearMath/btTransform.h"
22 #include "btManifoldPoint.h"
23 class btCollisionObject;
24 #include "LinearMath/btAlignedAllocator.h"
25 
26 struct btCollisionResult;
27 
28 ///maximum contact breaking and merging threshold
29 extern btScalar gContactBreakingThreshold;
30 
31 #ifndef SWIG
32 class btPersistentManifold;
33 
34 typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
35 typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
36 typedef void(*ContactStartedCallback)(btPersistentManifold* const &manifold);
37 typedef void(*ContactEndedCallback)(btPersistentManifold* const &manifold);
38 extern ContactDestroyedCallback	gContactDestroyedCallback;
39 extern ContactProcessedCallback gContactProcessedCallback;
40 extern ContactStartedCallback gContactStartedCallback;
41 extern ContactEndedCallback gContactEndedCallback;
42 #endif //SWIG
43 
44 //the enum starts at 1024 to avoid type conflicts with btTypedConstraint
45 enum btContactManifoldTypes
46 {
47 	MIN_CONTACT_MANIFOLD_TYPE = 1024,
48 	BT_PERSISTENT_MANIFOLD_TYPE
49 };
50 
51 #define MANIFOLD_CACHE_SIZE 4
52 
53 ///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
54 ///Those contact points are created by the collision narrow phase.
55 ///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.
56 ///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
57 ///reduces the cache to 4 points, when more then 4 points are added, using following rules:
58 ///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
59 ///note that some pairs of objects might have more then one contact manifold.
60 
61 
ATTRIBUTE_ALIGNED128(class)62 ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
63 //ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
64 {
65 
66 	btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
67 
68 	/// this two body pointers can point to the physics rigidbody class.
69 	const btCollisionObject* m_body0;
70 	const btCollisionObject* m_body1;
71 
72 	int	m_cachedPoints;
73 
74 	btScalar	m_contactBreakingThreshold;
75 	btScalar	m_contactProcessingThreshold;
76 
77 
78 	/// sort cached points so most isolated points come first
79 	int	sortCachedPoints(const btManifoldPoint& pt);
80 
81 	int		findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt);
82 
83 public:
84 
85 	BT_DECLARE_ALIGNED_ALLOCATOR();
86 
87 	int	m_companionIdA;
88 	int	m_companionIdB;
89 
90 	int m_index1a;
91 
92 	btPersistentManifold();
93 
94 	btPersistentManifold(const btCollisionObject* body0,const btCollisionObject* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
95 		: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
96 	m_body0(body0),m_body1(body1),m_cachedPoints(0),
97 		m_contactBreakingThreshold(contactBreakingThreshold),
98 		m_contactProcessingThreshold(contactProcessingThreshold)
99 	{
100 	}
101 
102 	SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0;}
103 	SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1;}
104 
105 	void	setBodies(const btCollisionObject* body0,const btCollisionObject* body1)
106 	{
107 		m_body0 = body0;
108 		m_body1 = body1;
109 	}
110 
111 	void clearUserCache(btManifoldPoint& pt);
112 
113 #ifdef DEBUG_PERSISTENCY
114 	void	DebugPersistency();
115 #endif //
116 
117 	SIMD_FORCE_INLINE int	getNumContacts() const { return m_cachedPoints;}
118 	/// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
119 	void setNumContacts(int cachedPoints)
120 	{
121 		m_cachedPoints = cachedPoints;
122 	}
123 
124 
125 	SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
126 	{
127 		btAssert(index < m_cachedPoints);
128 		return m_pointCache[index];
129 	}
130 
131 	SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
132 	{
133 		btAssert(index < m_cachedPoints);
134 		return m_pointCache[index];
135 	}
136 
137 	///@todo: get this margin from the current physics / collision environment
138 	btScalar	getContactBreakingThreshold() const;
139 
140 	btScalar	getContactProcessingThreshold() const
141 	{
142 		return m_contactProcessingThreshold;
143 	}
144 
145 	void setContactBreakingThreshold(btScalar contactBreakingThreshold)
146 	{
147 		m_contactBreakingThreshold = contactBreakingThreshold;
148 	}
149 
150 	void setContactProcessingThreshold(btScalar	contactProcessingThreshold)
151 	{
152 		m_contactProcessingThreshold = contactProcessingThreshold;
153 	}
154 
155 
156 
157 
158 	int getCacheEntry(const btManifoldPoint& newPoint) const;
159 
160 	int addManifoldPoint( const btManifoldPoint& newPoint, bool isPredictive=false);
161 
162 	void removeContactPoint (int index)
163 	{
164 		clearUserCache(m_pointCache[index]);
165 
166 		int lastUsedIndex = getNumContacts() - 1;
167 //		m_pointCache[index] = m_pointCache[lastUsedIndex];
168 		if(index != lastUsedIndex)
169 		{
170 			m_pointCache[index] = m_pointCache[lastUsedIndex];
171 			//get rid of duplicated userPersistentData pointer
172 			m_pointCache[lastUsedIndex].m_userPersistentData = 0;
173 			m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
174 			m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false;
175 			m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
176 			m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
177 			m_pointCache[lastUsedIndex].m_lifeTime = 0;
178 		}
179 
180 		btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
181 		m_cachedPoints--;
182 
183 		if (gContactEndedCallback && m_cachedPoints == 0)
184 		{
185 			gContactEndedCallback(this);
186 		}
187 	}
188 	void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex)
189 	{
190 		btAssert(validContactDistance(newPoint));
191 
192 #define MAINTAIN_PERSISTENCY 1
193 #ifdef MAINTAIN_PERSISTENCY
194 		int	lifeTime = m_pointCache[insertIndex].getLifeTime();
195 		btScalar	appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
196 		btScalar	appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
197 		btScalar	appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
198 //		bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized;
199 
200 
201 
202 		btAssert(lifeTime>=0);
203 		void* cache = m_pointCache[insertIndex].m_userPersistentData;
204 
205 		m_pointCache[insertIndex] = newPoint;
206 
207 		m_pointCache[insertIndex].m_userPersistentData = cache;
208 		m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
209 		m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
210 		m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
211 
212 		m_pointCache[insertIndex].m_appliedImpulse =  appliedImpulse;
213 		m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
214 		m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
215 
216 
217 		m_pointCache[insertIndex].m_lifeTime = lifeTime;
218 #else
219 		clearUserCache(m_pointCache[insertIndex]);
220 		m_pointCache[insertIndex] = newPoint;
221 
222 #endif
223 	}
224 
225 
226 	bool validContactDistance(const btManifoldPoint& pt) const
227 	{
228 		return pt.m_distance1 <= getContactBreakingThreshold();
229 	}
230 	/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
231 	void	refreshContactPoints(  const btTransform& trA,const btTransform& trB);
232 
233 
234 	SIMD_FORCE_INLINE	void	clearManifold()
235 	{
236 		int i;
237 		for (i=0;i<m_cachedPoints;i++)
238 		{
239 			clearUserCache(m_pointCache[i]);
240 		}
241 
242 		if (gContactEndedCallback && m_cachedPoints)
243 		{
244 			gContactEndedCallback(this);
245 		}
246 		m_cachedPoints = 0;
247 	}
248 
249 
250 
251 }
252 ;
253 
254 
255 
256 
257 
258 #endif //BT_PERSISTENT_MANIFOLD_H
259