btPersistentManifold.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "btPersistentManifold.h"
00018 #include "LinearMath/btTransform.h"
00019
00020
00021 btScalar gContactBreakingThreshold = btScalar(0.02);
00022 ContactDestroyedCallback gContactDestroyedCallback = 0;
00023 ContactProcessedCallback gContactProcessedCallback = 0;
00024
00025
00026
00027 btPersistentManifold::btPersistentManifold()
00028 :btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
00029 m_body0(0),
00030 m_body1(0),
00031 m_cachedPoints (0),
00032 m_index1a(0)
00033 {
00034 }
00035
00036
00037
00038
00039 #ifdef DEBUG_PERSISTENCY
00040 #include <stdio.h>
00041 void btPersistentManifold::DebugPersistency()
00042 {
00043 int i;
00044 printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
00045 for (i=0;i<m_cachedPoints;i++)
00046 {
00047 printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
00048 }
00049 }
00050 #endif //DEBUG_PERSISTENCY
00051
00052 void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
00053 {
00054
00055 void* oldPtr = pt.m_userPersistentData;
00056 if (oldPtr)
00057 {
00058 #ifdef DEBUG_PERSISTENCY
00059 int i;
00060 int occurance = 0;
00061 for (i=0;i<m_cachedPoints;i++)
00062 {
00063 if (m_pointCache[i].m_userPersistentData == oldPtr)
00064 {
00065 occurance++;
00066 if (occurance>1)
00067 printf("error in clearUserCache\n");
00068 }
00069 }
00070 btAssert(occurance<=0);
00071 #endif //DEBUG_PERSISTENCY
00072
00073 if (pt.m_userPersistentData && gContactDestroyedCallback)
00074 {
00075 (*gContactDestroyedCallback)(pt.m_userPersistentData);
00076 pt.m_userPersistentData = 0;
00077 }
00078
00079 #ifdef DEBUG_PERSISTENCY
00080 DebugPersistency();
00081 #endif
00082 }
00083
00084
00085 }
00086
00087
00088 int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
00089 {
00090
00091
00092
00093
00094 int maxPenetrationIndex = -1;
00095 #define KEEP_DEEPEST_POINT 1
00096 #ifdef KEEP_DEEPEST_POINT
00097 btScalar maxPenetration = pt.getDistance();
00098 for (int i=0;i<4;i++)
00099 {
00100 if (m_pointCache[i].getDistance() < maxPenetration)
00101 {
00102 maxPenetrationIndex = i;
00103 maxPenetration = m_pointCache[i].getDistance();
00104 }
00105 }
00106 #endif //KEEP_DEEPEST_POINT
00107
00108 btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
00109 if (maxPenetrationIndex != 0)
00110 {
00111 btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
00112 btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
00113 btVector3 cross = a0.cross(b0);
00114 res0 = cross.length2();
00115 }
00116 if (maxPenetrationIndex != 1)
00117 {
00118 btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
00119 btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
00120 btVector3 cross = a1.cross(b1);
00121 res1 = cross.length2();
00122 }
00123
00124 if (maxPenetrationIndex != 2)
00125 {
00126 btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
00127 btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
00128 btVector3 cross = a2.cross(b2);
00129 res2 = cross.length2();
00130 }
00131
00132 if (maxPenetrationIndex != 3)
00133 {
00134 btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
00135 btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
00136 btVector3 cross = a3.cross(b3);
00137 res3 = cross.length2();
00138 }
00139
00140 btVector4 maxvec(res0,res1,res2,res3);
00141 int biggestarea = maxvec.closestAxis4();
00142 return biggestarea;
00143 }
00144
00145
00146 int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
00147 {
00148 btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
00149 int size = getNumContacts();
00150 int nearestPoint = -1;
00151 for( int i = 0; i < size; i++ )
00152 {
00153 const btManifoldPoint &mp = m_pointCache[i];
00154
00155 btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
00156 const btScalar distToManiPoint = diffA.dot(diffA);
00157 if( distToManiPoint < shortestDist )
00158 {
00159 shortestDist = distToManiPoint;
00160 nearestPoint = i;
00161 }
00162 }
00163 return nearestPoint;
00164 }
00165
00166 int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint)
00167 {
00168 btAssert(validContactDistance(newPoint));
00169
00170 int insertIndex = getNumContacts();
00171 if (insertIndex == MANIFOLD_CACHE_SIZE)
00172 {
00173 #if MANIFOLD_CACHE_SIZE >= 4
00174
00175 insertIndex = sortCachedPoints(newPoint);
00176 #else
00177 insertIndex = 0;
00178 #endif
00179 clearUserCache(m_pointCache[insertIndex]);
00180
00181 } else
00182 {
00183 m_cachedPoints++;
00184
00185
00186 }
00187 if (insertIndex<0)
00188 insertIndex=0;
00189
00190 btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
00191 m_pointCache[insertIndex] = newPoint;
00192 return insertIndex;
00193 }
00194
00195 btScalar btPersistentManifold::getContactBreakingThreshold() const
00196 {
00197 return m_contactBreakingThreshold;
00198 }
00199
00200
00201
00202 void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
00203 {
00204 int i;
00205 #ifdef DEBUG_PERSISTENCY
00206 printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
00207 trA.getOrigin().getX(),
00208 trA.getOrigin().getY(),
00209 trA.getOrigin().getZ(),
00210 trB.getOrigin().getX(),
00211 trB.getOrigin().getY(),
00212 trB.getOrigin().getZ());
00213 #endif //DEBUG_PERSISTENCY
00215 for (i=getNumContacts()-1;i>=0;i--)
00216 {
00217 btManifoldPoint &manifoldPoint = m_pointCache[i];
00218 manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
00219 manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
00220 manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
00221 manifoldPoint.m_lifeTime++;
00222 }
00223
00225 btScalar distance2d;
00226 btVector3 projectedDifference,projectedPoint;
00227 for (i=getNumContacts()-1;i>=0;i--)
00228 {
00229
00230 btManifoldPoint &manifoldPoint = m_pointCache[i];
00231
00232 if (!validContactDistance(manifoldPoint))
00233 {
00234 removeContactPoint(i);
00235 } else
00236 {
00237
00238 projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
00239 projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
00240 distance2d = projectedDifference.dot(projectedDifference);
00241 if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
00242 {
00243 removeContactPoint(i);
00244 } else
00245 {
00246
00247 if (gContactProcessedCallback)
00248 (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
00249 }
00250 }
00251 }
00252 #ifdef DEBUG_PERSISTENCY
00253 DebugPersistency();
00254 #endif //
00255 }
00256
00257
00258
00259
00260