Blender V2.61 - r43446

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
00214 
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