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 "btConvexConcaveCollisionAlgorithm.h" 00018 #include "BulletCollision/CollisionDispatch/btCollisionObject.h" 00019 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" 00020 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" 00021 #include "BulletCollision/CollisionShapes/btConcaveShape.h" 00022 #include "BulletCollision/CollisionDispatch/btManifoldResult.h" 00023 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" 00024 #include "BulletCollision/CollisionShapes/btTriangleShape.h" 00025 #include "BulletCollision/CollisionShapes/btSphereShape.h" 00026 #include "LinearMath/btIDebugDraw.h" 00027 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" 00028 00029 btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) 00030 : btActivatingCollisionAlgorithm(ci,body0,body1), 00031 m_isSwapped(isSwapped), 00032 m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) 00033 { 00034 } 00035 00036 btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() 00037 { 00038 } 00039 00040 void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) 00041 { 00042 if (m_btConvexTriangleCallback.m_manifoldPtr) 00043 { 00044 manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); 00045 } 00046 } 00047 00048 00049 btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): 00050 m_dispatcher(dispatcher), 00051 m_dispatchInfoPtr(0) 00052 { 00053 m_convexBody = isSwapped? body1:body0; 00054 m_triBody = isSwapped? body0:body1; 00055 00056 // 00057 // create the manifold from the dispatcher 'manifold pool' 00058 // 00059 m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); 00060 00061 clearCache(); 00062 } 00063 00064 btConvexTriangleCallback::~btConvexTriangleCallback() 00065 { 00066 clearCache(); 00067 m_dispatcher->releaseManifold( m_manifoldPtr ); 00068 00069 } 00070 00071 00072 void btConvexTriangleCallback::clearCache() 00073 { 00074 m_dispatcher->clearManifold(m_manifoldPtr); 00075 } 00076 00077 00078 00079 void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) 00080 { 00081 00082 //just for debugging purposes 00083 //printf("triangle %d",m_triangleCount++); 00084 00085 00086 //aabb filter is already applied! 00087 00088 btCollisionAlgorithmConstructionInfo ci; 00089 ci.m_dispatcher1 = m_dispatcher; 00090 00091 btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody); 00092 00093 00094 00096 if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe )) 00097 { 00098 btVector3 color(1,1,0); 00099 btTransform& tr = ob->getWorldTransform(); 00100 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); 00101 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); 00102 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); 00103 00104 //btVector3 center = triangle[0] + triangle[1]+triangle[2]; 00105 //center *= btScalar(0.333333); 00106 //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); 00107 //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); 00108 //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); 00109 00110 } 00111 00112 00113 //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject); 00114 00115 if (m_convexBody->getCollisionShape()->isConvex()) 00116 { 00117 btTriangleShape tm(triangle[0],triangle[1],triangle[2]); 00118 tm.setMargin(m_collisionMarginTriangle); 00119 00120 btCollisionShape* tmpShape = ob->getCollisionShape(); 00121 ob->internalSetTemporaryCollisionShape( &tm ); 00122 00123 btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); 00124 00125 if (m_resultOut->getBody0Internal() == m_triBody) 00126 { 00127 m_resultOut->setShapeIdentifiersA(partId,triangleIndex); 00128 } 00129 else 00130 { 00131 m_resultOut->setShapeIdentifiersB(partId,triangleIndex); 00132 } 00133 00134 colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); 00135 colAlgo->~btCollisionAlgorithm(); 00136 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); 00137 ob->internalSetTemporaryCollisionShape( tmpShape); 00138 } 00139 00140 00141 } 00142 00143 00144 00145 void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 00146 { 00147 m_dispatchInfoPtr = &dispatchInfo; 00148 m_collisionMarginTriangle = collisionMarginTriangle; 00149 m_resultOut = resultOut; 00150 00151 //recalc aabbs 00152 btTransform convexInTriangleSpace; 00153 convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform(); 00154 btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape()); 00155 //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape); 00156 convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); 00157 btScalar extraMargin = collisionMarginTriangle; 00158 btVector3 extra(extraMargin,extraMargin,extraMargin); 00159 00160 m_aabbMax += extra; 00161 m_aabbMin -= extra; 00162 00163 } 00164 00165 void btConvexConcaveCollisionAlgorithm::clearCache() 00166 { 00167 m_btConvexTriangleCallback.clearCache(); 00168 00169 } 00170 00171 void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 00172 { 00173 00174 00175 btCollisionObject* convexBody = m_isSwapped ? body1 : body0; 00176 btCollisionObject* triBody = m_isSwapped ? body0 : body1; 00177 00178 if (triBody->getCollisionShape()->isConcave()) 00179 { 00180 00181 00182 btCollisionObject* triOb = triBody; 00183 btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape()); 00184 00185 if (convexBody->getCollisionShape()->isConvex()) 00186 { 00187 btScalar collisionMarginTriangle = concaveShape->getMargin(); 00188 00189 resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr); 00190 m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); 00191 00192 //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. 00193 //m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr); 00194 00195 m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); 00196 00197 concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); 00198 00199 resultOut->refreshContactPoints(); 00200 00201 } 00202 00203 } 00204 00205 } 00206 00207 00208 btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 00209 { 00210 (void)resultOut; 00211 (void)dispatchInfo; 00212 btCollisionObject* convexbody = m_isSwapped ? body1 : body0; 00213 btCollisionObject* triBody = m_isSwapped ? body0 : body1; 00214 00215 00216 //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) 00217 00218 //only perform CCD above a certain threshold, this prevents blocking on the long run 00219 //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... 00220 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); 00221 if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) 00222 { 00223 return btScalar(1.); 00224 } 00225 00226 //const btVector3& from = convexbody->m_worldTransform.getOrigin(); 00227 //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); 00228 //todo: only do if the motion exceeds the 'radius' 00229 00230 btTransform triInv = triBody->getWorldTransform().inverse(); 00231 btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); 00232 btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); 00233 00234 struct LocalTriangleSphereCastCallback : public btTriangleCallback 00235 { 00236 btTransform m_ccdSphereFromTrans; 00237 btTransform m_ccdSphereToTrans; 00238 btTransform m_meshTransform; 00239 00240 btScalar m_ccdSphereRadius; 00241 btScalar m_hitFraction; 00242 00243 00244 LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) 00245 :m_ccdSphereFromTrans(from), 00246 m_ccdSphereToTrans(to), 00247 m_ccdSphereRadius(ccdSphereRadius), 00248 m_hitFraction(hitFraction) 00249 { 00250 } 00251 00252 00253 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) 00254 { 00255 (void)partId; 00256 (void)triangleIndex; 00257 //do a swept sphere for now 00258 btTransform ident; 00259 ident.setIdentity(); 00260 btConvexCast::CastResult castResult; 00261 castResult.m_fraction = m_hitFraction; 00262 btSphereShape pointShape(m_ccdSphereRadius); 00263 btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); 00264 btVoronoiSimplexSolver simplexSolver; 00265 btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); 00266 //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); 00267 //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); 00268 //local space? 00269 00270 if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, 00271 ident,ident,castResult)) 00272 { 00273 if (m_hitFraction > castResult.m_fraction) 00274 m_hitFraction = castResult.m_fraction; 00275 } 00276 00277 } 00278 00279 }; 00280 00281 00282 00283 00284 00285 if (triBody->getCollisionShape()->isConcave()) 00286 { 00287 btVector3 rayAabbMin = convexFromLocal.getOrigin(); 00288 rayAabbMin.setMin(convexToLocal.getOrigin()); 00289 btVector3 rayAabbMax = convexFromLocal.getOrigin(); 00290 rayAabbMax.setMax(convexToLocal.getOrigin()); 00291 btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); 00292 rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); 00293 rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); 00294 00295 btScalar curHitFraction = btScalar(1.); //is this available? 00296 LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, 00297 convexbody->getCcdSweptSphereRadius(),curHitFraction); 00298 00299 raycastCallback.m_hitFraction = convexbody->getHitFraction(); 00300 00301 btCollisionObject* concavebody = triBody; 00302 00303 btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); 00304 00305 if (triangleMesh) 00306 { 00307 triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); 00308 } 00309 00310 00311 00312 if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) 00313 { 00314 convexbody->setHitFraction( raycastCallback.m_hitFraction); 00315 return raycastCallback.m_hitFraction; 00316 } 00317 } 00318 00319 return btScalar(1.); 00320 00321 }