2
Bullet Continuous Collision Detection and Physics Library
3
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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.
17
#include "btPersistentManifold.h"
18
#include "LinearMath/btTransform.h"
21
btScalar gContactBreakingThreshold = btScalar(0.02);
22
ContactDestroyedCallback gContactDestroyedCallback = 0;
23
ContactProcessedCallback gContactProcessedCallback = 0;
27
btPersistentManifold::btPersistentManifold()
38
#ifdef DEBUG_PERSISTENCY
40
void btPersistentManifold::DebugPersistency()
43
printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
44
for (i=0;i<m_cachedPoints;i++)
46
printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
49
#endif //DEBUG_PERSISTENCY
51
void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
54
void* oldPtr = pt.m_userPersistentData;
57
#ifdef DEBUG_PERSISTENCY
60
for (i=0;i<m_cachedPoints;i++)
62
if (m_pointCache[i].m_userPersistentData == oldPtr)
66
printf("error in clearUserCache\n");
70
#endif //DEBUG_PERSISTENCY
72
if (pt.m_userPersistentData && gContactDestroyedCallback)
74
(*gContactDestroyedCallback)(pt.m_userPersistentData);
75
pt.m_userPersistentData = 0;
78
#ifdef DEBUG_PERSISTENCY
87
int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
90
//calculate 4 possible cases areas, and take biggest area
91
//also need to keep 'deepest'
93
int maxPenetrationIndex = -1;
94
#define KEEP_DEEPEST_POINT 1
95
#ifdef KEEP_DEEPEST_POINT
96
btScalar maxPenetration = pt.getDistance();
99
if (m_pointCache[i].getDistance() < maxPenetration)
101
maxPenetrationIndex = i;
102
maxPenetration = m_pointCache[i].getDistance();
105
#endif //KEEP_DEEPEST_POINT
107
btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
108
if (maxPenetrationIndex != 0)
110
btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
111
btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
112
btVector3 cross = a0.cross(b0);
113
res0 = cross.length2();
115
if (maxPenetrationIndex != 1)
117
btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
118
btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
119
btVector3 cross = a1.cross(b1);
120
res1 = cross.length2();
123
if (maxPenetrationIndex != 2)
125
btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
126
btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
127
btVector3 cross = a2.cross(b2);
128
res2 = cross.length2();
131
if (maxPenetrationIndex != 3)
133
btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
134
btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
135
btVector3 cross = a3.cross(b3);
136
res3 = cross.length2();
139
btVector4 maxvec(res0,res1,res2,res3);
140
int biggestarea = maxvec.closestAxis4();
145
int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
147
btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
148
int size = getNumContacts();
149
int nearestPoint = -1;
150
for( int i = 0; i < size; i++ )
152
const btManifoldPoint &mp = m_pointCache[i];
154
btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
155
const btScalar distToManiPoint = diffA.dot(diffA);
156
if( distToManiPoint < shortestDist )
158
shortestDist = distToManiPoint;
165
void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint)
167
assert(validContactDistance(newPoint));
169
int insertIndex = getNumContacts();
170
if (insertIndex == MANIFOLD_CACHE_SIZE)
172
#if MANIFOLD_CACHE_SIZE >= 4
173
//sort cache so best points come first, based on area
174
insertIndex = sortCachedPoints(newPoint);
186
replaceContactPoint(newPoint,insertIndex);
189
btScalar btPersistentManifold::getContactBreakingThreshold() const
191
return gContactBreakingThreshold;
196
void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
199
#ifdef DEBUG_PERSISTENCY
200
printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
201
trA.getOrigin().getX(),
202
trA.getOrigin().getY(),
203
trA.getOrigin().getZ(),
204
trB.getOrigin().getX(),
205
trB.getOrigin().getY(),
206
trB.getOrigin().getZ());
207
#endif //DEBUG_PERSISTENCY
208
/// first refresh worldspace positions and distance
209
for (i=getNumContacts()-1;i>=0;i--)
211
btManifoldPoint &manifoldPoint = m_pointCache[i];
212
manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
213
manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
214
manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
215
manifoldPoint.m_lifeTime++;
220
btVector3 projectedDifference,projectedPoint;
221
for (i=getNumContacts()-1;i>=0;i--)
224
btManifoldPoint &manifoldPoint = m_pointCache[i];
225
//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
226
if (!validContactDistance(manifoldPoint))
228
removeContactPoint(i);
231
//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
232
projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
233
projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
234
distance2d = projectedDifference.dot(projectedDifference);
235
if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
237
removeContactPoint(i);
240
//contact point processed callback
241
if (gContactProcessedCallback)
242
(*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
246
#ifdef DEBUG_PERSISTENCY
2
Bullet Continuous Collision Detection and Physics Library
3
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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.
17
#include "btPersistentManifold.h"
18
#include "LinearMath/btTransform.h"
21
btScalar gContactBreakingThreshold = btScalar(0.02);
22
ContactDestroyedCallback gContactDestroyedCallback = 0;
23
ContactProcessedCallback gContactProcessedCallback = 0;
27
btPersistentManifold::btPersistentManifold()
38
#ifdef DEBUG_PERSISTENCY
40
void btPersistentManifold::DebugPersistency()
43
printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
44
for (i=0;i<m_cachedPoints;i++)
46
printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
49
#endif //DEBUG_PERSISTENCY
51
void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
54
void* oldPtr = pt.m_userPersistentData;
57
#ifdef DEBUG_PERSISTENCY
60
for (i=0;i<m_cachedPoints;i++)
62
if (m_pointCache[i].m_userPersistentData == oldPtr)
66
printf("error in clearUserCache\n");
70
#endif //DEBUG_PERSISTENCY
72
if (pt.m_userPersistentData && gContactDestroyedCallback)
74
(*gContactDestroyedCallback)(pt.m_userPersistentData);
75
pt.m_userPersistentData = 0;
78
#ifdef DEBUG_PERSISTENCY
87
int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
90
//calculate 4 possible cases areas, and take biggest area
91
//also need to keep 'deepest'
93
int maxPenetrationIndex = -1;
94
#define KEEP_DEEPEST_POINT 1
95
#ifdef KEEP_DEEPEST_POINT
96
btScalar maxPenetration = pt.getDistance();
99
if (m_pointCache[i].getDistance() < maxPenetration)
101
maxPenetrationIndex = i;
102
maxPenetration = m_pointCache[i].getDistance();
105
#endif //KEEP_DEEPEST_POINT
107
btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
108
if (maxPenetrationIndex != 0)
110
btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
111
btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
112
btVector3 cross = a0.cross(b0);
113
res0 = cross.length2();
115
if (maxPenetrationIndex != 1)
117
btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
118
btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
119
btVector3 cross = a1.cross(b1);
120
res1 = cross.length2();
123
if (maxPenetrationIndex != 2)
125
btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
126
btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
127
btVector3 cross = a2.cross(b2);
128
res2 = cross.length2();
131
if (maxPenetrationIndex != 3)
133
btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
134
btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
135
btVector3 cross = a3.cross(b3);
136
res3 = cross.length2();
139
btVector4 maxvec(res0,res1,res2,res3);
140
int biggestarea = maxvec.closestAxis4();
145
int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
147
btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
148
int size = getNumContacts();
149
int nearestPoint = -1;
150
for( int i = 0; i < size; i++ )
152
const btManifoldPoint &mp = m_pointCache[i];
154
btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
155
const btScalar distToManiPoint = diffA.dot(diffA);
156
if( distToManiPoint < shortestDist )
158
shortestDist = distToManiPoint;
165
void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint)
167
assert(validContactDistance(newPoint));
169
int insertIndex = getNumContacts();
170
if (insertIndex == MANIFOLD_CACHE_SIZE)
172
#if MANIFOLD_CACHE_SIZE >= 4
173
//sort cache so best points come first, based on area
174
insertIndex = sortCachedPoints(newPoint);
186
replaceContactPoint(newPoint,insertIndex);
189
btScalar btPersistentManifold::getContactBreakingThreshold() const
191
return gContactBreakingThreshold;
196
void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
199
#ifdef DEBUG_PERSISTENCY
200
printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
201
trA.getOrigin().getX(),
202
trA.getOrigin().getY(),
203
trA.getOrigin().getZ(),
204
trB.getOrigin().getX(),
205
trB.getOrigin().getY(),
206
trB.getOrigin().getZ());
207
#endif //DEBUG_PERSISTENCY
208
/// first refresh worldspace positions and distance
209
for (i=getNumContacts()-1;i>=0;i--)
211
btManifoldPoint &manifoldPoint = m_pointCache[i];
212
manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
213
manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
214
manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
215
manifoldPoint.m_lifeTime++;
220
btVector3 projectedDifference,projectedPoint;
221
for (i=getNumContacts()-1;i>=0;i--)
224
btManifoldPoint &manifoldPoint = m_pointCache[i];
225
//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
226
if (!validContactDistance(manifoldPoint))
228
removeContactPoint(i);
231
//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
232
projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
233
projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
234
distance2d = projectedDifference.dot(projectedDifference);
235
if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
237
removeContactPoint(i);
240
//contact point processed callback
241
if (gContactProcessedCallback)
242
(*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
246
#ifdef DEBUG_PERSISTENCY