btPersistentManifold.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
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                 //calculate 4 possible cases areas, and take biggest area
00092                 //also need to keep 'deepest'
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                 //sort cache so best points come first, based on area
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                 //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
00232                 if (!validContactDistance(manifoldPoint))
00233                 {
00234                         removeContactPoint(i);
00235                 } else
00236                 {
00237                         //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
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                                 //contact point processed callback
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 

Generated on Mon Feb 15 22:17:05 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1