Blender V2.61 - r43446
|
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