|
Bullet Collision Detection & Physics Library
|
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 #include "btConvexPlaneCollisionAlgorithm.h" 00017 00018 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" 00019 #include "BulletCollision/CollisionDispatch/btCollisionObject.h" 00020 #include "BulletCollision/CollisionShapes/btConvexShape.h" 00021 #include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" 00022 00023 //#include <stdio.h> 00024 00025 btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold) 00026 : btCollisionAlgorithm(ci), 00027 m_ownManifold(false), 00028 m_manifoldPtr(mf), 00029 m_isSwapped(isSwapped), 00030 m_numPerturbationIterations(numPerturbationIterations), 00031 m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) 00032 { 00033 btCollisionObject* convexObj = m_isSwapped? col1 : col0; 00034 btCollisionObject* planeObj = m_isSwapped? col0 : col1; 00035 00036 if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) 00037 { 00038 m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj); 00039 m_ownManifold = true; 00040 } 00041 } 00042 00043 00044 btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() 00045 { 00046 if (m_ownManifold) 00047 { 00048 if (m_manifoldPtr) 00049 m_dispatcher->releaseManifold(m_manifoldPtr); 00050 } 00051 } 00052 00053 void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 00054 { 00055 btCollisionObject* convexObj = m_isSwapped? body1 : body0; 00056 btCollisionObject* planeObj = m_isSwapped? body0: body1; 00057 00058 btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); 00059 btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); 00060 00061 bool hasCollision = false; 00062 const btVector3& planeNormal = planeShape->getPlaneNormal(); 00063 const btScalar& planeConstant = planeShape->getPlaneConstant(); 00064 00065 btTransform convexWorldTransform = convexObj->getWorldTransform(); 00066 btTransform convexInPlaneTrans; 00067 convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform; 00068 //now perturbe the convex-world transform 00069 convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot); 00070 btTransform planeInConvex; 00071 planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform(); 00072 00073 btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); 00074 00075 btVector3 vtxInPlane = convexInPlaneTrans(vtx); 00076 btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); 00077 00078 btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; 00079 btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; 00080 00081 hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); 00082 resultOut->setPersistentManifold(m_manifoldPtr); 00083 if (hasCollision) 00084 { 00086 btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; 00087 btVector3 pOnB = vtxInPlaneWorld; 00088 resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); 00089 } 00090 } 00091 00092 00093 void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 00094 { 00095 (void)dispatchInfo; 00096 if (!m_manifoldPtr) 00097 return; 00098 00099 btCollisionObject* convexObj = m_isSwapped? body1 : body0; 00100 btCollisionObject* planeObj = m_isSwapped? body0: body1; 00101 00102 btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); 00103 btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); 00104 00105 bool hasCollision = false; 00106 const btVector3& planeNormal = planeShape->getPlaneNormal(); 00107 const btScalar& planeConstant = planeShape->getPlaneConstant(); 00108 btTransform planeInConvex; 00109 planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); 00110 btTransform convexInPlaneTrans; 00111 convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); 00112 00113 btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); 00114 btVector3 vtxInPlane = convexInPlaneTrans(vtx); 00115 btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); 00116 00117 btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; 00118 btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; 00119 00120 hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); 00121 resultOut->setPersistentManifold(m_manifoldPtr); 00122 if (hasCollision) 00123 { 00125 btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; 00126 btVector3 pOnB = vtxInPlaneWorld; 00127 resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); 00128 } 00129 00130 //the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones: 00131 //they keep on rolling forever because of the additional off-center contact points 00132 //so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc) 00133 if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold) 00134 { 00135 btVector3 v0,v1; 00136 btPlaneSpace1(planeNormal,v0,v1); 00137 //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects 00138 00139 const btScalar angleLimit = 0.125f * SIMD_PI; 00140 btScalar perturbeAngle; 00141 btScalar radius = convexShape->getAngularMotionDisc(); 00142 perturbeAngle = gContactBreakingThreshold / radius; 00143 if ( perturbeAngle > angleLimit ) 00144 perturbeAngle = angleLimit; 00145 00146 btQuaternion perturbeRot(v0,perturbeAngle); 00147 for (int i=0;i<m_numPerturbationIterations;i++) 00148 { 00149 btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); 00150 btQuaternion rotq(planeNormal,iterationAngle); 00151 collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut); 00152 } 00153 } 00154 00155 if (m_ownManifold) 00156 { 00157 if (m_manifoldPtr->getNumContacts()) 00158 { 00159 resultOut->refreshContactPoints(); 00160 } 00161 } 00162 } 00163 00164 btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 00165 { 00166 (void)resultOut; 00167 (void)dispatchInfo; 00168 (void)col0; 00169 (void)col1; 00170 00171 //not yet 00172 return btScalar(1.); 00173 }