1650 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1650 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
Bullet Continuous Collision Detection and Physics Library
 | 
						|
Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
 | 
						|
 | 
						|
This software is provided 'as-is', without any express or implied warranty.
 | 
						|
In no event will the authors be held liable for any damages arising from the use of this software.
 | 
						|
Permission is granted to anyone to use this software for any purpose,
 | 
						|
including commercial applications, and to alter it and redistribute it freely,
 | 
						|
subject to the following restrictions:
 | 
						|
 | 
						|
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.
 | 
						|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
 | 
						|
3. This notice may not be removed or altered from any source distribution.
 | 
						|
*/
 | 
						|
 | 
						|
#include "btCollisionWorld.h"
 | 
						|
#include "btCollisionDispatcher.h"
 | 
						|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
 | 
						|
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
 | 
						|
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
 | 
						|
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
 | 
						|
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
 | 
						|
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
 | 
						|
#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
 | 
						|
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
 | 
						|
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
 | 
						|
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
 | 
						|
#include "LinearMath/btAabbUtil2.h"
 | 
						|
#include "LinearMath/btQuickprof.h"
 | 
						|
#include "LinearMath/btSerializer.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
 | 
						|
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
 | 
						|
 | 
						|
//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
 | 
						|
 | 
						|
 | 
						|
//#define USE_BRUTEFORCE_RAYBROADPHASE 1
 | 
						|
//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation'  or 'updateAabbs' before using a rayTest
 | 
						|
//#define RECALCULATE_AABB_RAYCAST 1
 | 
						|
 | 
						|
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
 | 
						|
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
 | 
						|
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
 | 
						|
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
 | 
						|
 | 
						|
 | 
						|
///for debug drawing
 | 
						|
 | 
						|
//for debug rendering
 | 
						|
#include "BulletCollision/CollisionShapes/btBoxShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btConeShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btCylinderShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btSphereShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
 | 
						|
 | 
						|
 | 
						|
 | 
						|
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
 | 
						|
:m_dispatcher1(dispatcher),
 | 
						|
m_broadphasePairCache(pairCache),
 | 
						|
m_debugDrawer(0),
 | 
						|
m_forceUpdateAllAabbs(true)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
btCollisionWorld::~btCollisionWorld()
 | 
						|
{
 | 
						|
 | 
						|
	//clean up remaining objects
 | 
						|
	int i;
 | 
						|
	for (i=0;i<m_collisionObjects.size();i++)
 | 
						|
	{
 | 
						|
		btCollisionObject* collisionObject= m_collisionObjects[i];
 | 
						|
 | 
						|
		btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
 | 
						|
		if (bp)
 | 
						|
		{
 | 
						|
			//
 | 
						|
			// only clear the cached algorithms
 | 
						|
			//
 | 
						|
			getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
 | 
						|
			getBroadphase()->destroyProxy(bp,m_dispatcher1);
 | 
						|
			collisionObject->setBroadphaseHandle(0);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
 | 
						|
{
 | 
						|
 | 
						|
	btAssert(collisionObject);
 | 
						|
 | 
						|
	//check that the object isn't already added
 | 
						|
	btAssert( m_collisionObjects.findLinearSearch(collisionObject)  == m_collisionObjects.size());
 | 
						|
    btAssert(collisionObject->getWorldArrayIndex() == -1);  // do not add the same object to more than one collision world
 | 
						|
 | 
						|
    collisionObject->setWorldArrayIndex(m_collisionObjects.size());
 | 
						|
	m_collisionObjects.push_back(collisionObject);
 | 
						|
 | 
						|
	//calculate new AABB
 | 
						|
	btTransform trans = collisionObject->getWorldTransform();
 | 
						|
 | 
						|
	btVector3	minAabb;
 | 
						|
	btVector3	maxAabb;
 | 
						|
	collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
 | 
						|
 | 
						|
	int type = collisionObject->getCollisionShape()->getShapeType();
 | 
						|
	collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
 | 
						|
		minAabb,
 | 
						|
		maxAabb,
 | 
						|
		type,
 | 
						|
		collisionObject,
 | 
						|
		collisionFilterGroup,
 | 
						|
		collisionFilterMask,
 | 
						|
		m_dispatcher1))	;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
 | 
						|
{
 | 
						|
	btVector3 minAabb,maxAabb;
 | 
						|
	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
 | 
						|
	//need to increase the aabb for contact thresholds
 | 
						|
	btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
 | 
						|
	minAabb -= contactThreshold;
 | 
						|
	maxAabb += contactThreshold;
 | 
						|
 | 
						|
	if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
 | 
						|
	{
 | 
						|
		btVector3 minAabb2,maxAabb2;
 | 
						|
		colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
 | 
						|
		minAabb2 -= contactThreshold;
 | 
						|
		maxAabb2 += contactThreshold;
 | 
						|
		minAabb.setMin(minAabb2);
 | 
						|
		maxAabb.setMax(maxAabb2);
 | 
						|
	}
 | 
						|
 | 
						|
	btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
 | 
						|
 | 
						|
	//moving objects should be moderately sized, probably something wrong if not
 | 
						|
	if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
 | 
						|
	{
 | 
						|
		bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
 | 
						|
	} else
 | 
						|
	{
 | 
						|
		//something went wrong, investigate
 | 
						|
		//this assert is unwanted in 3D modelers (danger of loosing work)
 | 
						|
		colObj->setActivationState(DISABLE_SIMULATION);
 | 
						|
 | 
						|
		static bool reportMe = true;
 | 
						|
		if (reportMe && m_debugDrawer)
 | 
						|
		{
 | 
						|
			reportMe = false;
 | 
						|
			m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
 | 
						|
			m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
 | 
						|
			m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
 | 
						|
			m_debugDrawer->reportErrorWarning("Thanks.\n");
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void	btCollisionWorld::updateAabbs()
 | 
						|
{
 | 
						|
	BT_PROFILE("updateAabbs");
 | 
						|
 | 
						|
	btTransform predictedTrans;
 | 
						|
	for ( int i=0;i<m_collisionObjects.size();i++)
 | 
						|
	{
 | 
						|
		btCollisionObject* colObj = m_collisionObjects[i];
 | 
						|
        btAssert(colObj->getWorldArrayIndex() == i);
 | 
						|
 | 
						|
		//only update aabb of active objects
 | 
						|
		if (m_forceUpdateAllAabbs || colObj->isActive())
 | 
						|
		{
 | 
						|
			updateSingleAabb(colObj);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::computeOverlappingPairs()
 | 
						|
{
 | 
						|
	BT_PROFILE("calculateOverlappingPairs");
 | 
						|
	m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
 | 
						|
}
 | 
						|
 | 
						|
void	btCollisionWorld::performDiscreteCollisionDetection()
 | 
						|
{
 | 
						|
	BT_PROFILE("performDiscreteCollisionDetection");
 | 
						|
 | 
						|
	btDispatcherInfo& dispatchInfo = getDispatchInfo();
 | 
						|
 | 
						|
	updateAabbs();
 | 
						|
 | 
						|
	computeOverlappingPairs();
 | 
						|
 | 
						|
	btDispatcher* dispatcher = getDispatcher();
 | 
						|
	{
 | 
						|
		BT_PROFILE("dispatchAllCollisionPairs");
 | 
						|
		if (dispatcher)
 | 
						|
			dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
 | 
						|
{
 | 
						|
 | 
						|
 | 
						|
	//bool removeFromBroadphase = false;
 | 
						|
 | 
						|
	{
 | 
						|
 | 
						|
		btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
 | 
						|
		if (bp)
 | 
						|
		{
 | 
						|
			//
 | 
						|
			// only clear the cached algorithms
 | 
						|
			//
 | 
						|
			getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
 | 
						|
			getBroadphase()->destroyProxy(bp,m_dispatcher1);
 | 
						|
			collisionObject->setBroadphaseHandle(0);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
    int iObj = collisionObject->getWorldArrayIndex();
 | 
						|
//    btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
 | 
						|
    if (iObj >= 0 && iObj < m_collisionObjects.size())
 | 
						|
    {
 | 
						|
        btAssert(collisionObject == m_collisionObjects[iObj]);
 | 
						|
        m_collisionObjects.swap(iObj, m_collisionObjects.size()-1);
 | 
						|
        m_collisionObjects.pop_back();
 | 
						|
        if (iObj < m_collisionObjects.size())
 | 
						|
        {
 | 
						|
            m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        // slow linear search
 | 
						|
        //swapremove
 | 
						|
        m_collisionObjects.remove(collisionObject);
 | 
						|
    }
 | 
						|
    collisionObject->setWorldArrayIndex(-1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
 | 
						|
										btCollisionObject* collisionObject,
 | 
						|
										const btCollisionShape* collisionShape,
 | 
						|
										const btTransform& colObjWorldTransform,
 | 
						|
										RayResultCallback& resultCallback)
 | 
						|
{
 | 
						|
	btCollisionObjectWrapper colObWrap(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
 | 
						|
	btCollisionWorld::rayTestSingleInternal(rayFromTrans,rayToTrans,&colObWrap,resultCallback);
 | 
						|
}
 | 
						|
 | 
						|
void	btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
 | 
						|
										const btCollisionObjectWrapper* collisionObjectWrap,
 | 
						|
										RayResultCallback& resultCallback)
 | 
						|
{
 | 
						|
	btSphereShape pointShape(btScalar(0.0));
 | 
						|
	pointShape.setMargin(0.f);
 | 
						|
	const btConvexShape* castShape = &pointShape;
 | 
						|
	const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
 | 
						|
	const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
 | 
						|
 | 
						|
	if (collisionShape->isConvex())
 | 
						|
	{
 | 
						|
		//		BT_PROFILE("rayTestConvex");
 | 
						|
		btConvexCast::CastResult castResult;
 | 
						|
		castResult.m_fraction = resultCallback.m_closestHitFraction;
 | 
						|
 | 
						|
		btConvexShape* convexShape = (btConvexShape*) collisionShape;
 | 
						|
		btVoronoiSimplexSolver	simplexSolver;
 | 
						|
		btSubsimplexConvexCast subSimplexConvexCaster(castShape,convexShape,&simplexSolver);
 | 
						|
		
 | 
						|
		btGjkConvexCast	gjkConvexCaster(castShape,convexShape,&simplexSolver);
 | 
						|
		
 | 
						|
		//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
 | 
						|
 | 
						|
		btConvexCast* convexCasterPtr = 0;
 | 
						|
		//use kF_UseSubSimplexConvexCastRaytest by default
 | 
						|
		if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest)
 | 
						|
			convexCasterPtr = &gjkConvexCaster;
 | 
						|
		else
 | 
						|
			convexCasterPtr = &subSimplexConvexCaster;
 | 
						|
		
 | 
						|
		btConvexCast& convexCaster = *convexCasterPtr;
 | 
						|
 | 
						|
		if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
 | 
						|
		{
 | 
						|
			//add hit
 | 
						|
			if (castResult.m_normal.length2() > btScalar(0.0001))
 | 
						|
			{
 | 
						|
				if (castResult.m_fraction < resultCallback.m_closestHitFraction)
 | 
						|
				{
 | 
						|
					//todo: figure out what this is about. When is rayFromTest.getBasis() not identity?
 | 
						|
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
 | 
						|
					//rotate normal into worldspace
 | 
						|
					castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
 | 
						|
#endif //USE_SUBSIMPLEX_CONVEX_CAST
 | 
						|
 | 
						|
					castResult.m_normal.normalize();
 | 
						|
					btCollisionWorld::LocalRayResult localRayResult
 | 
						|
						(
 | 
						|
						collisionObjectWrap->getCollisionObject(),
 | 
						|
						0,
 | 
						|
						castResult.m_normal,
 | 
						|
						castResult.m_fraction
 | 
						|
						);
 | 
						|
 | 
						|
					bool normalInWorldSpace = true;
 | 
						|
					resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
 | 
						|
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (collisionShape->isConcave())
 | 
						|
		{
 | 
						|
 | 
						|
			//ConvexCast::CastResult
 | 
						|
				struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
 | 
						|
				{
 | 
						|
					btCollisionWorld::RayResultCallback* m_resultCallback;
 | 
						|
					const btCollisionObject*	m_collisionObject;
 | 
						|
					const btConcaveShape*	m_triangleMesh;
 | 
						|
 | 
						|
					btTransform m_colObjWorldTransform;
 | 
						|
 | 
						|
					BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
 | 
						|
					btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,const btConcaveShape*	triangleMesh,const btTransform& colObjWorldTransform):
 | 
						|
						//@BP Mod
 | 
						|
						btTriangleRaycastCallback(from,to, resultCallback->m_flags),
 | 
						|
							m_resultCallback(resultCallback),
 | 
						|
							m_collisionObject(collisionObject),
 | 
						|
							m_triangleMesh(triangleMesh),
 | 
						|
							m_colObjWorldTransform(colObjWorldTransform)
 | 
						|
						{
 | 
						|
						}
 | 
						|
 | 
						|
 | 
						|
					virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
 | 
						|
					{
 | 
						|
						btCollisionWorld::LocalShapeInfo	shapeInfo;
 | 
						|
						shapeInfo.m_shapePart = partId;
 | 
						|
						shapeInfo.m_triangleIndex = triangleIndex;
 | 
						|
 | 
						|
						btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
 | 
						|
 | 
						|
						btCollisionWorld::LocalRayResult rayResult
 | 
						|
							(m_collisionObject,
 | 
						|
							&shapeInfo,
 | 
						|
							hitNormalWorld,
 | 
						|
							hitFraction);
 | 
						|
 | 
						|
						bool	normalInWorldSpace = true;
 | 
						|
						return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
 | 
						|
					}
 | 
						|
 | 
						|
				};
 | 
						|
 | 
						|
			btTransform worldTocollisionObject = colObjWorldTransform.inverse();
 | 
						|
			btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
 | 
						|
			btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
 | 
						|
 | 
						|
			//			BT_PROFILE("rayTestConcave");
 | 
						|
			if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
 | 
						|
			{
 | 
						|
				///optimized version for btBvhTriangleMeshShape
 | 
						|
				btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
 | 
						|
				
 | 
						|
				BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),triangleMesh,colObjWorldTransform);
 | 
						|
				rcb.m_hitFraction = resultCallback.m_closestHitFraction;
 | 
						|
				triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				//generic (slower) case
 | 
						|
				btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
 | 
						|
 | 
						|
				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
 | 
						|
 | 
						|
				btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
 | 
						|
				btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
 | 
						|
 | 
						|
				//ConvexCast::CastResult
 | 
						|
 | 
						|
				struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
 | 
						|
				{
 | 
						|
					btCollisionWorld::RayResultCallback* m_resultCallback;
 | 
						|
					const btCollisionObject*	m_collisionObject;
 | 
						|
					btConcaveShape*	m_triangleMesh;
 | 
						|
 | 
						|
					btTransform m_colObjWorldTransform;
 | 
						|
 | 
						|
					BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
 | 
						|
						btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape*	triangleMesh, const btTransform& colObjWorldTransform):
 | 
						|
					//@BP Mod
 | 
						|
					btTriangleRaycastCallback(from,to, resultCallback->m_flags),
 | 
						|
						m_resultCallback(resultCallback),
 | 
						|
						m_collisionObject(collisionObject),
 | 
						|
						m_triangleMesh(triangleMesh),
 | 
						|
						m_colObjWorldTransform(colObjWorldTransform)
 | 
						|
					{
 | 
						|
					}
 | 
						|
 | 
						|
 | 
						|
					virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
 | 
						|
					{
 | 
						|
						btCollisionWorld::LocalShapeInfo	shapeInfo;
 | 
						|
						shapeInfo.m_shapePart = partId;
 | 
						|
						shapeInfo.m_triangleIndex = triangleIndex;
 | 
						|
 | 
						|
						btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
 | 
						|
 | 
						|
						btCollisionWorld::LocalRayResult rayResult
 | 
						|
							(m_collisionObject,
 | 
						|
							&shapeInfo,
 | 
						|
							hitNormalWorld,
 | 
						|
							hitFraction);
 | 
						|
 | 
						|
						bool	normalInWorldSpace = true;
 | 
						|
						return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
 | 
						|
					}
 | 
						|
 | 
						|
				};
 | 
						|
 | 
						|
 | 
						|
				BridgeTriangleRaycastCallback	rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
 | 
						|
				rcb.m_hitFraction = resultCallback.m_closestHitFraction;
 | 
						|
 | 
						|
				btVector3 rayAabbMinLocal = rayFromLocal;
 | 
						|
				rayAabbMinLocal.setMin(rayToLocal);
 | 
						|
				btVector3 rayAabbMaxLocal = rayFromLocal;
 | 
						|
				rayAabbMaxLocal.setMax(rayToLocal);
 | 
						|
 | 
						|
				concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			//			BT_PROFILE("rayTestCompound");
 | 
						|
			if (collisionShape->isCompound())
 | 
						|
			{
 | 
						|
				struct LocalInfoAdder2 : public RayResultCallback
 | 
						|
				{
 | 
						|
					RayResultCallback* m_userCallback;
 | 
						|
					int m_i;
 | 
						|
					
 | 
						|
					LocalInfoAdder2 (int i, RayResultCallback *user)
 | 
						|
						: m_userCallback(user), m_i(i)
 | 
						|
					{ 
 | 
						|
						m_closestHitFraction = m_userCallback->m_closestHitFraction;
 | 
						|
						m_flags = m_userCallback->m_flags;
 | 
						|
					}
 | 
						|
					virtual bool needsCollision(btBroadphaseProxy* p) const
 | 
						|
					{
 | 
						|
						return m_userCallback->needsCollision(p);
 | 
						|
					}
 | 
						|
 | 
						|
					virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b)
 | 
						|
					{
 | 
						|
						btCollisionWorld::LocalShapeInfo shapeInfo;
 | 
						|
						shapeInfo.m_shapePart = -1;
 | 
						|
						shapeInfo.m_triangleIndex = m_i;
 | 
						|
						if (r.m_localShapeInfo == NULL)
 | 
						|
							r.m_localShapeInfo = &shapeInfo;
 | 
						|
 | 
						|
						const btScalar result = m_userCallback->addSingleResult(r, b);
 | 
						|
						m_closestHitFraction = m_userCallback->m_closestHitFraction;
 | 
						|
						return result;
 | 
						|
					}
 | 
						|
				};
 | 
						|
				
 | 
						|
				struct RayTester : btDbvt::ICollide
 | 
						|
				{
 | 
						|
					const btCollisionObject* m_collisionObject;
 | 
						|
					const btCompoundShape* m_compoundShape;
 | 
						|
					const btTransform& m_colObjWorldTransform;
 | 
						|
					const btTransform& m_rayFromTrans;
 | 
						|
					const btTransform& m_rayToTrans;
 | 
						|
					RayResultCallback& m_resultCallback;
 | 
						|
					
 | 
						|
					RayTester(const btCollisionObject* collisionObject,
 | 
						|
							const btCompoundShape* compoundShape,
 | 
						|
							const btTransform& colObjWorldTransform,
 | 
						|
							const btTransform& rayFromTrans,
 | 
						|
							const btTransform& rayToTrans,
 | 
						|
							RayResultCallback& resultCallback):
 | 
						|
						m_collisionObject(collisionObject),
 | 
						|
						m_compoundShape(compoundShape),
 | 
						|
						m_colObjWorldTransform(colObjWorldTransform),
 | 
						|
						m_rayFromTrans(rayFromTrans),
 | 
						|
						m_rayToTrans(rayToTrans),
 | 
						|
						m_resultCallback(resultCallback)
 | 
						|
					{
 | 
						|
						
 | 
						|
					}
 | 
						|
					
 | 
						|
					void ProcessLeaf(int i)
 | 
						|
					{
 | 
						|
						const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
 | 
						|
						const btTransform& childTrans = m_compoundShape->getChildTransform(i);
 | 
						|
						btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
 | 
						|
						
 | 
						|
						btCollisionObjectWrapper tmpOb(0,childCollisionShape,m_collisionObject,childWorldTrans,-1,i);
 | 
						|
						// replace collision shape so that callback can determine the triangle
 | 
						|
 | 
						|
						
 | 
						|
 | 
						|
						LocalInfoAdder2 my_cb(i, &m_resultCallback);
 | 
						|
 | 
						|
						rayTestSingleInternal(
 | 
						|
							m_rayFromTrans,
 | 
						|
							m_rayToTrans,
 | 
						|
							&tmpOb,
 | 
						|
							my_cb);
 | 
						|
						
 | 
						|
					}
 | 
						|
				
 | 
						|
					void Process(const btDbvtNode* leaf)
 | 
						|
					{
 | 
						|
						ProcessLeaf(leaf->dataAsInt);
 | 
						|
					}
 | 
						|
				};
 | 
						|
				
 | 
						|
				const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
 | 
						|
				const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
 | 
						|
 | 
						|
 | 
						|
				RayTester rayCB(
 | 
						|
					collisionObjectWrap->getCollisionObject(),
 | 
						|
					compoundShape,
 | 
						|
					colObjWorldTransform,
 | 
						|
					rayFromTrans,
 | 
						|
					rayToTrans,
 | 
						|
					resultCallback);
 | 
						|
#ifndef	DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
 | 
						|
				if (dbvt)
 | 
						|
				{
 | 
						|
					btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
 | 
						|
					btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
 | 
						|
					btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB);
 | 
						|
				}
 | 
						|
				else
 | 
						|
#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
 | 
						|
				{
 | 
						|
					for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
 | 
						|
					{
 | 
						|
						rayCB.ProcessLeaf(i);
 | 
						|
					}	
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void	btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
 | 
						|
											btCollisionObject* collisionObject,
 | 
						|
											const btCollisionShape* collisionShape,
 | 
						|
											const btTransform& colObjWorldTransform,
 | 
						|
											ConvexResultCallback& resultCallback, btScalar allowedPenetration)
 | 
						|
{
 | 
						|
	btCollisionObjectWrapper tmpOb(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
 | 
						|
	btCollisionWorld::objectQuerySingleInternal(castShape,convexFromTrans,convexToTrans,&tmpOb,resultCallback,allowedPenetration);
 | 
						|
}
 | 
						|
 | 
						|
void	btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
 | 
						|
											const btCollisionObjectWrapper* colObjWrap,
 | 
						|
											ConvexResultCallback& resultCallback, btScalar allowedPenetration)
 | 
						|
{
 | 
						|
	const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
 | 
						|
	const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
 | 
						|
 | 
						|
	if (collisionShape->isConvex())
 | 
						|
	{
 | 
						|
		//BT_PROFILE("convexSweepConvex");
 | 
						|
		btConvexCast::CastResult castResult;
 | 
						|
		castResult.m_allowedPenetration = allowedPenetration;
 | 
						|
		castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//??
 | 
						|
 | 
						|
		btConvexShape* convexShape = (btConvexShape*) collisionShape;
 | 
						|
		btVoronoiSimplexSolver	simplexSolver;
 | 
						|
		btGjkEpaPenetrationDepthSolver	gjkEpaPenetrationSolver;
 | 
						|
 | 
						|
		btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
 | 
						|
		//btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
 | 
						|
		//btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
 | 
						|
 | 
						|
		btConvexCast* castPtr = &convexCaster1;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
 | 
						|
		{
 | 
						|
			//add hit
 | 
						|
			if (castResult.m_normal.length2() > btScalar(0.0001))
 | 
						|
			{
 | 
						|
				if (castResult.m_fraction < resultCallback.m_closestHitFraction)
 | 
						|
				{
 | 
						|
					castResult.m_normal.normalize();
 | 
						|
					btCollisionWorld::LocalConvexResult localConvexResult
 | 
						|
						(
 | 
						|
						colObjWrap->getCollisionObject(),
 | 
						|
						0,
 | 
						|
						castResult.m_normal,
 | 
						|
						castResult.m_hitPoint,
 | 
						|
						castResult.m_fraction
 | 
						|
						);
 | 
						|
 | 
						|
					bool normalInWorldSpace = true;
 | 
						|
					resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
 | 
						|
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (collisionShape->isConcave())
 | 
						|
		{
 | 
						|
			if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
 | 
						|
			{
 | 
						|
				//BT_PROFILE("convexSweepbtBvhTriangleMesh");
 | 
						|
				btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
 | 
						|
				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
 | 
						|
				btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
 | 
						|
				btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
 | 
						|
				// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
 | 
						|
				btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
 | 
						|
 | 
						|
				//ConvexCast::CastResult
 | 
						|
				struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
 | 
						|
				{
 | 
						|
					btCollisionWorld::ConvexResultCallback* m_resultCallback;
 | 
						|
					const btCollisionObject*	m_collisionObject;
 | 
						|
					btTriangleMeshShape*	m_triangleMesh;
 | 
						|
 | 
						|
					BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
 | 
						|
						btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape*	triangleMesh, const btTransform& triangleToWorld):
 | 
						|
					btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
 | 
						|
						m_resultCallback(resultCallback),
 | 
						|
						m_collisionObject(collisionObject),
 | 
						|
						m_triangleMesh(triangleMesh)
 | 
						|
					{
 | 
						|
					}
 | 
						|
 | 
						|
 | 
						|
					virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
 | 
						|
					{
 | 
						|
						btCollisionWorld::LocalShapeInfo	shapeInfo;
 | 
						|
						shapeInfo.m_shapePart = partId;
 | 
						|
						shapeInfo.m_triangleIndex = triangleIndex;
 | 
						|
						if (hitFraction <= m_resultCallback->m_closestHitFraction)
 | 
						|
						{
 | 
						|
 | 
						|
							btCollisionWorld::LocalConvexResult convexResult
 | 
						|
								(m_collisionObject,
 | 
						|
								&shapeInfo,
 | 
						|
								hitNormalLocal,
 | 
						|
								hitPointLocal,
 | 
						|
								hitFraction);
 | 
						|
 | 
						|
							bool	normalInWorldSpace = true;
 | 
						|
 | 
						|
 | 
						|
							return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
 | 
						|
						}
 | 
						|
						return hitFraction;
 | 
						|
					}
 | 
						|
 | 
						|
				};
 | 
						|
 | 
						|
				BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),triangleMesh, colObjWorldTransform);
 | 
						|
				tccb.m_hitFraction = resultCallback.m_closestHitFraction;
 | 
						|
				tccb.m_allowedPenetration = allowedPenetration;
 | 
						|
				btVector3 boxMinLocal, boxMaxLocal;
 | 
						|
				castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
 | 
						|
				triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
 | 
						|
			} else
 | 
						|
			{
 | 
						|
				if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
 | 
						|
				{
 | 
						|
					btConvexCast::CastResult castResult;
 | 
						|
					castResult.m_allowedPenetration = allowedPenetration;
 | 
						|
					castResult.m_fraction = resultCallback.m_closestHitFraction;
 | 
						|
					btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape;
 | 
						|
					btContinuousConvexCollision convexCaster1(castShape,planeShape);
 | 
						|
					btConvexCast* castPtr = &convexCaster1;
 | 
						|
 | 
						|
					if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
 | 
						|
					{
 | 
						|
						//add hit
 | 
						|
						if (castResult.m_normal.length2() > btScalar(0.0001))
 | 
						|
						{
 | 
						|
							if (castResult.m_fraction < resultCallback.m_closestHitFraction)
 | 
						|
							{
 | 
						|
								castResult.m_normal.normalize();
 | 
						|
								btCollisionWorld::LocalConvexResult localConvexResult
 | 
						|
									(
 | 
						|
									colObjWrap->getCollisionObject(),
 | 
						|
									0,
 | 
						|
									castResult.m_normal,
 | 
						|
									castResult.m_hitPoint,
 | 
						|
									castResult.m_fraction
 | 
						|
									);
 | 
						|
 | 
						|
								bool normalInWorldSpace = true;
 | 
						|
								resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
 | 
						|
							}
 | 
						|
						}
 | 
						|
					}
 | 
						|
 | 
						|
				} else
 | 
						|
				{
 | 
						|
					//BT_PROFILE("convexSweepConcave");
 | 
						|
					btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
 | 
						|
					btTransform worldTocollisionObject = colObjWorldTransform.inverse();
 | 
						|
					btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
 | 
						|
					btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
 | 
						|
					// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
 | 
						|
					btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
 | 
						|
 | 
						|
					//ConvexCast::CastResult
 | 
						|
					struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
 | 
						|
					{
 | 
						|
						btCollisionWorld::ConvexResultCallback* m_resultCallback;
 | 
						|
						const btCollisionObject*	m_collisionObject;
 | 
						|
						btConcaveShape*	m_triangleMesh;
 | 
						|
 | 
						|
						BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
 | 
						|
							btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape*	triangleMesh, const btTransform& triangleToWorld):
 | 
						|
						btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
 | 
						|
							m_resultCallback(resultCallback),
 | 
						|
							m_collisionObject(collisionObject),
 | 
						|
							m_triangleMesh(triangleMesh)
 | 
						|
						{
 | 
						|
						}
 | 
						|
 | 
						|
 | 
						|
						virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
 | 
						|
						{
 | 
						|
							btCollisionWorld::LocalShapeInfo	shapeInfo;
 | 
						|
							shapeInfo.m_shapePart = partId;
 | 
						|
							shapeInfo.m_triangleIndex = triangleIndex;
 | 
						|
							if (hitFraction <= m_resultCallback->m_closestHitFraction)
 | 
						|
							{
 | 
						|
 | 
						|
								btCollisionWorld::LocalConvexResult convexResult
 | 
						|
									(m_collisionObject,
 | 
						|
									&shapeInfo,
 | 
						|
									hitNormalLocal,
 | 
						|
									hitPointLocal,
 | 
						|
									hitFraction);
 | 
						|
 | 
						|
								bool	normalInWorldSpace = true;
 | 
						|
 | 
						|
								return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
 | 
						|
							}
 | 
						|
							return hitFraction;
 | 
						|
						}
 | 
						|
 | 
						|
					};
 | 
						|
 | 
						|
					BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
 | 
						|
					tccb.m_hitFraction = resultCallback.m_closestHitFraction;
 | 
						|
					tccb.m_allowedPenetration = allowedPenetration;
 | 
						|
					btVector3 boxMinLocal, boxMaxLocal;
 | 
						|
					castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
 | 
						|
 | 
						|
					btVector3 rayAabbMinLocal = convexFromLocal;
 | 
						|
					rayAabbMinLocal.setMin(convexToLocal);
 | 
						|
					btVector3 rayAabbMaxLocal = convexFromLocal;
 | 
						|
					rayAabbMaxLocal.setMax(convexToLocal);
 | 
						|
					rayAabbMinLocal += boxMinLocal;
 | 
						|
					rayAabbMaxLocal += boxMaxLocal;
 | 
						|
					concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			if (collisionShape->isCompound())
 | 
						|
			{
 | 
						|
				struct	btCompoundLeafCallback : btDbvt::ICollide
 | 
						|
				{
 | 
						|
					btCompoundLeafCallback(
 | 
						|
										   const btCollisionObjectWrapper* colObjWrap,
 | 
						|
										   const btConvexShape* castShape,
 | 
						|
										   const btTransform& convexFromTrans,
 | 
						|
										   const btTransform& convexToTrans,
 | 
						|
										   btScalar allowedPenetration,
 | 
						|
										   const btCompoundShape* compoundShape,
 | 
						|
										   const btTransform& colObjWorldTransform,
 | 
						|
										   ConvexResultCallback& resultCallback)
 | 
						|
					: 
 | 
						|
					  m_colObjWrap(colObjWrap),
 | 
						|
						m_castShape(castShape),
 | 
						|
						m_convexFromTrans(convexFromTrans),
 | 
						|
						m_convexToTrans(convexToTrans),
 | 
						|
						m_allowedPenetration(allowedPenetration),
 | 
						|
						m_compoundShape(compoundShape),
 | 
						|
						m_colObjWorldTransform(colObjWorldTransform),
 | 
						|
						m_resultCallback(resultCallback) {
 | 
						|
					}
 | 
						|
 | 
						|
				  const btCollisionObjectWrapper* m_colObjWrap;
 | 
						|
					const btConvexShape* m_castShape;
 | 
						|
					const btTransform& m_convexFromTrans;
 | 
						|
					const btTransform& m_convexToTrans;
 | 
						|
					btScalar m_allowedPenetration;
 | 
						|
					const btCompoundShape* m_compoundShape;
 | 
						|
					const btTransform& m_colObjWorldTransform;
 | 
						|
					ConvexResultCallback& m_resultCallback;
 | 
						|
 | 
						|
				public:
 | 
						|
 | 
						|
					void		ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
 | 
						|
					{
 | 
						|
						btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
 | 
						|
 | 
						|
						struct	LocalInfoAdder : public ConvexResultCallback {
 | 
						|
							ConvexResultCallback* m_userCallback;
 | 
						|
							int m_i;
 | 
						|
 | 
						|
							LocalInfoAdder(int i, ConvexResultCallback *user)
 | 
						|
								: m_userCallback(user), m_i(i)
 | 
						|
							{
 | 
						|
								m_closestHitFraction = m_userCallback->m_closestHitFraction;
 | 
						|
							}
 | 
						|
							virtual bool needsCollision(btBroadphaseProxy* p) const
 | 
						|
							{
 | 
						|
								return m_userCallback->needsCollision(p);
 | 
						|
							}
 | 
						|
							virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult&	r, bool b)
 | 
						|
							{
 | 
						|
								btCollisionWorld::LocalShapeInfo	shapeInfo;
 | 
						|
								shapeInfo.m_shapePart = -1;
 | 
						|
								shapeInfo.m_triangleIndex = m_i;
 | 
						|
								if (r.m_localShapeInfo == NULL)
 | 
						|
									r.m_localShapeInfo = &shapeInfo;
 | 
						|
								const btScalar result = m_userCallback->addSingleResult(r, b);
 | 
						|
								m_closestHitFraction = m_userCallback->m_closestHitFraction;
 | 
						|
								return result;
 | 
						|
 | 
						|
							}
 | 
						|
						};
 | 
						|
 | 
						|
						LocalInfoAdder my_cb(index, &m_resultCallback);
 | 
						|
 | 
						|
						btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
 | 
						|
 | 
						|
						objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
 | 
						|
					}
 | 
						|
 | 
						|
					void		Process(const btDbvtNode* leaf)
 | 
						|
					{
 | 
						|
						// Processing leaf node
 | 
						|
						int index = leaf->dataAsInt;
 | 
						|
 | 
						|
						btTransform childTrans = m_compoundShape->getChildTransform(index);
 | 
						|
						const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
 | 
						|
 | 
						|
						ProcessChild(index, childTrans, childCollisionShape);
 | 
						|
					}
 | 
						|
				};
 | 
						|
 | 
						|
				BT_PROFILE("convexSweepCompound");
 | 
						|
				const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
 | 
						|
 | 
						|
				btVector3 fromLocalAabbMin, fromLocalAabbMax;
 | 
						|
				btVector3 toLocalAabbMin, toLocalAabbMax;
 | 
						|
 | 
						|
				castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
 | 
						|
				castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
 | 
						|
 | 
						|
				fromLocalAabbMin.setMin(toLocalAabbMin);
 | 
						|
				fromLocalAabbMax.setMax(toLocalAabbMax);
 | 
						|
 | 
						|
				btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
 | 
						|
					  allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
 | 
						|
 | 
						|
				const btDbvt* tree = compoundShape->getDynamicAabbTree();
 | 
						|
				if (tree) {
 | 
						|
					const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
 | 
						|
					tree->collideTV(tree->m_root, bounds, callback);
 | 
						|
				} else {
 | 
						|
					int i;
 | 
						|
					for (i=0;i<compoundShape->getNumChildShapes();i++)
 | 
						|
					{
 | 
						|
						const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
 | 
						|
						btTransform childTrans = compoundShape->getChildTransform(i);
 | 
						|
						callback.ProcessChild(i, childTrans, childCollisionShape);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
struct btSingleRayCallback : public btBroadphaseRayCallback
 | 
						|
{
 | 
						|
 | 
						|
	btVector3	m_rayFromWorld;
 | 
						|
	btVector3	m_rayToWorld;
 | 
						|
	btTransform	m_rayFromTrans;
 | 
						|
	btTransform	m_rayToTrans;
 | 
						|
	btVector3	m_hitNormal;
 | 
						|
 | 
						|
	const btCollisionWorld*	m_world;
 | 
						|
	btCollisionWorld::RayResultCallback&	m_resultCallback;
 | 
						|
 | 
						|
	btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
 | 
						|
		:m_rayFromWorld(rayFromWorld),
 | 
						|
		m_rayToWorld(rayToWorld),
 | 
						|
		m_world(world),
 | 
						|
		m_resultCallback(resultCallback)
 | 
						|
	{
 | 
						|
		m_rayFromTrans.setIdentity();
 | 
						|
		m_rayFromTrans.setOrigin(m_rayFromWorld);
 | 
						|
		m_rayToTrans.setIdentity();
 | 
						|
		m_rayToTrans.setOrigin(m_rayToWorld);
 | 
						|
 | 
						|
		btVector3 rayDir = (rayToWorld-rayFromWorld);
 | 
						|
 | 
						|
		rayDir.normalize ();
 | 
						|
		///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
 | 
						|
		m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
 | 
						|
		m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
 | 
						|
		m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
 | 
						|
		m_signs[0] = m_rayDirectionInverse[0] < 0.0;
 | 
						|
		m_signs[1] = m_rayDirectionInverse[1] < 0.0;
 | 
						|
		m_signs[2] = m_rayDirectionInverse[2] < 0.0;
 | 
						|
 | 
						|
		m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
	virtual bool	process(const btBroadphaseProxy* proxy)
 | 
						|
	{
 | 
						|
		///terminate further ray tests, once the closestHitFraction reached zero
 | 
						|
		if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
 | 
						|
			return false;
 | 
						|
 | 
						|
		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
 | 
						|
 | 
						|
		//only perform raycast if filterMask matches
 | 
						|
		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
 | 
						|
		{
 | 
						|
			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
 | 
						|
			//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
 | 
						|
#if 0
 | 
						|
#ifdef RECALCULATE_AABB
 | 
						|
			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
 | 
						|
			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
 | 
						|
#else
 | 
						|
			//getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
 | 
						|
			const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
 | 
						|
			const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
			//btScalar hitLambda = m_resultCallback.m_closestHitFraction;
 | 
						|
			//culling already done by broadphase
 | 
						|
			//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
 | 
						|
			{
 | 
						|
				m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
 | 
						|
					collisionObject,
 | 
						|
					collisionObject->getCollisionShape(),
 | 
						|
					collisionObject->getWorldTransform(),
 | 
						|
					m_resultCallback);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
void	btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
 | 
						|
{
 | 
						|
	//BT_PROFILE("rayTest");
 | 
						|
	/// use the broadphase to accelerate the search for objects, based on their aabb
 | 
						|
	/// and for each object with ray-aabb overlap, perform an exact ray test
 | 
						|
	btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
 | 
						|
 | 
						|
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
 | 
						|
	m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
 | 
						|
#else
 | 
						|
	for (int i=0;i<this->getNumCollisionObjects();i++)
 | 
						|
	{
 | 
						|
		rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
 | 
						|
	}	
 | 
						|
#endif //USE_BRUTEFORCE_RAYBROADPHASE
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
struct btSingleSweepCallback : public btBroadphaseRayCallback
 | 
						|
{
 | 
						|
 | 
						|
	btTransform	m_convexFromTrans;
 | 
						|
	btTransform	m_convexToTrans;
 | 
						|
	btVector3	m_hitNormal;
 | 
						|
	const btCollisionWorld*	m_world;
 | 
						|
	btCollisionWorld::ConvexResultCallback&	m_resultCallback;
 | 
						|
	btScalar	m_allowedCcdPenetration;
 | 
						|
	const btConvexShape* m_castShape;
 | 
						|
 | 
						|
 | 
						|
	btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration)
 | 
						|
		:m_convexFromTrans(convexFromTrans),
 | 
						|
		m_convexToTrans(convexToTrans),
 | 
						|
		m_world(world),
 | 
						|
		m_resultCallback(resultCallback),
 | 
						|
		m_allowedCcdPenetration(allowedPenetration),
 | 
						|
		m_castShape(castShape)
 | 
						|
	{
 | 
						|
		btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin());
 | 
						|
		btVector3 rayDir = unnormalizedRayDir.normalized();
 | 
						|
		///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
 | 
						|
		m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
 | 
						|
		m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
 | 
						|
		m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
 | 
						|
		m_signs[0] = m_rayDirectionInverse[0] < 0.0;
 | 
						|
		m_signs[1] = m_rayDirectionInverse[1] < 0.0;
 | 
						|
		m_signs[2] = m_rayDirectionInverse[2] < 0.0;
 | 
						|
 | 
						|
		m_lambda_max = rayDir.dot(unnormalizedRayDir);
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	virtual bool	process(const btBroadphaseProxy* proxy)
 | 
						|
	{
 | 
						|
		///terminate further convex sweep tests, once the closestHitFraction reached zero
 | 
						|
		if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
 | 
						|
			return false;
 | 
						|
 | 
						|
		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
 | 
						|
 | 
						|
		//only perform raycast if filterMask matches
 | 
						|
		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
 | 
						|
			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
 | 
						|
			m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans,
 | 
						|
				collisionObject,
 | 
						|
				collisionObject->getCollisionShape(),
 | 
						|
				collisionObject->getWorldTransform(),
 | 
						|
				m_resultCallback,
 | 
						|
				m_allowedCcdPenetration);
 | 
						|
		}
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
 | 
						|
{
 | 
						|
 | 
						|
	BT_PROFILE("convexSweepTest");
 | 
						|
	/// use the broadphase to accelerate the search for objects, based on their aabb
 | 
						|
	/// and for each object with ray-aabb overlap, perform an exact ray test
 | 
						|
	/// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
 | 
						|
 | 
						|
 | 
						|
 | 
						|
	btTransform	convexFromTrans,convexToTrans;
 | 
						|
	convexFromTrans = convexFromWorld;
 | 
						|
	convexToTrans = convexToWorld;
 | 
						|
	btVector3 castShapeAabbMin, castShapeAabbMax;
 | 
						|
	/* Compute AABB that encompasses angular movement */
 | 
						|
	{
 | 
						|
		btVector3 linVel, angVel;
 | 
						|
		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
 | 
						|
		btVector3 zeroLinVel;
 | 
						|
		zeroLinVel.setValue(0,0,0);
 | 
						|
		btTransform R;
 | 
						|
		R.setIdentity ();
 | 
						|
		R.setRotation (convexFromTrans.getRotation());
 | 
						|
		castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
 | 
						|
	}
 | 
						|
 | 
						|
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
 | 
						|
 | 
						|
	btSingleSweepCallback	convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration);
 | 
						|
 | 
						|
	m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax);
 | 
						|
 | 
						|
#else
 | 
						|
	/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
 | 
						|
	// do a ray-shape query using convexCaster (CCD)
 | 
						|
	int i;
 | 
						|
	for (i=0;i<m_collisionObjects.size();i++)
 | 
						|
	{
 | 
						|
		btCollisionObject*	collisionObject= m_collisionObjects[i];
 | 
						|
		//only perform raycast if filterMask matches
 | 
						|
		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
 | 
						|
			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
 | 
						|
			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
 | 
						|
			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
 | 
						|
			AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
 | 
						|
			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
 | 
						|
			btVector3 hitNormal;
 | 
						|
			if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
 | 
						|
			{
 | 
						|
				objectQuerySingle(castShape, convexFromTrans,convexToTrans,
 | 
						|
					collisionObject,
 | 
						|
					collisionObject->getCollisionShape(),
 | 
						|
					collisionObject->getWorldTransform(),
 | 
						|
					resultCallback,
 | 
						|
					allowedCcdPenetration);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
#endif //USE_BRUTEFORCE_RAYBROADPHASE
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
struct btBridgedManifoldResult : public btManifoldResult
 | 
						|
{
 | 
						|
 | 
						|
	btCollisionWorld::ContactResultCallback&	m_resultCallback;
 | 
						|
 | 
						|
	btBridgedManifoldResult( const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap,btCollisionWorld::ContactResultCallback& resultCallback )
 | 
						|
		:btManifoldResult(obj0Wrap,obj1Wrap),
 | 
						|
		m_resultCallback(resultCallback)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
 | 
						|
	{
 | 
						|
		bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
 | 
						|
		btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
 | 
						|
		btVector3 localA;
 | 
						|
		btVector3 localB;
 | 
						|
		if (isSwapped)
 | 
						|
		{
 | 
						|
			localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
 | 
						|
			localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
 | 
						|
		} else
 | 
						|
		{
 | 
						|
			localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
 | 
						|
			localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
 | 
						|
		}
 | 
						|
		
 | 
						|
		btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
 | 
						|
		newPt.m_positionWorldOnA = pointA;
 | 
						|
		newPt.m_positionWorldOnB = pointInWorld;
 | 
						|
		
 | 
						|
	   //BP mod, store contact triangles.
 | 
						|
		if (isSwapped)
 | 
						|
		{
 | 
						|
			newPt.m_partId0 = m_partId1;
 | 
						|
			newPt.m_partId1 = m_partId0;
 | 
						|
			newPt.m_index0  = m_index1;
 | 
						|
			newPt.m_index1  = m_index0;
 | 
						|
		} else
 | 
						|
		{
 | 
						|
			newPt.m_partId0 = m_partId0;
 | 
						|
			newPt.m_partId1 = m_partId1;
 | 
						|
			newPt.m_index0  = m_index0;
 | 
						|
			newPt.m_index1  = m_index1;
 | 
						|
		}
 | 
						|
 | 
						|
		//experimental feature info, for per-triangle material etc.
 | 
						|
		const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
 | 
						|
		const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
 | 
						|
		m_resultCallback.addSingleResult(newPt,obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
 | 
						|
 | 
						|
	}
 | 
						|
	
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
struct btSingleContactCallback : public btBroadphaseAabbCallback
 | 
						|
{
 | 
						|
 | 
						|
	btCollisionObject* m_collisionObject;
 | 
						|
	btCollisionWorld*	m_world;
 | 
						|
	btCollisionWorld::ContactResultCallback&	m_resultCallback;
 | 
						|
	
 | 
						|
	
 | 
						|
	btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
 | 
						|
		:m_collisionObject(collisionObject),
 | 
						|
		m_world(world),
 | 
						|
		m_resultCallback(resultCallback)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	virtual bool	process(const btBroadphaseProxy* proxy)
 | 
						|
	{
 | 
						|
		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
 | 
						|
		if (collisionObject == m_collisionObject)
 | 
						|
			return true;
 | 
						|
 | 
						|
		//only perform raycast if filterMask matches
 | 
						|
		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
 | 
						|
		{
 | 
						|
			btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1);
 | 
						|
			btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1);
 | 
						|
 | 
						|
			btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1,0, BT_CLOSEST_POINT_ALGORITHMS);
 | 
						|
			if (algorithm)
 | 
						|
			{
 | 
						|
				btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback);
 | 
						|
				//discrete collision detection query
 | 
						|
				
 | 
						|
				algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult);
 | 
						|
 | 
						|
				algorithm->~btCollisionAlgorithm();
 | 
						|
				m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
 | 
						|
///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
 | 
						|
void	btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback)
 | 
						|
{
 | 
						|
	btVector3 aabbMin,aabbMax;
 | 
						|
	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax);
 | 
						|
	btSingleContactCallback	contactCB(colObj,this,resultCallback);
 | 
						|
	
 | 
						|
	m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
 | 
						|
///it reports one or more contact points (including the one with deepest penetration)
 | 
						|
void	btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
 | 
						|
{
 | 
						|
	btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1);
 | 
						|
	btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1);
 | 
						|
 | 
						|
	btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
 | 
						|
	if (algorithm)
 | 
						|
	{
 | 
						|
		btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback);
 | 
						|
		contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
 | 
						|
		//discrete collision detection query
 | 
						|
		algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult);
 | 
						|
 | 
						|
		algorithm->~btCollisionAlgorithm();
 | 
						|
		getDispatcher()->freeCollisionAlgorithm(algorithm);
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
 | 
						|
{
 | 
						|
	btIDebugDraw*	m_debugDrawer;
 | 
						|
	btVector3	m_color;
 | 
						|
	btTransform	m_worldTrans;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
	DebugDrawcallback(btIDebugDraw*	debugDrawer,const btTransform& worldTrans,const btVector3& color) :
 | 
						|
	  m_debugDrawer(debugDrawer),
 | 
						|
		  m_color(color),
 | 
						|
		  m_worldTrans(worldTrans)
 | 
						|
	  {
 | 
						|
	  }
 | 
						|
 | 
						|
	  virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
 | 
						|
	  {
 | 
						|
		  processTriangle(triangle,partId,triangleIndex);
 | 
						|
	  }
 | 
						|
 | 
						|
	  virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
 | 
						|
	  {
 | 
						|
		  (void)partId;
 | 
						|
		  (void)triangleIndex;
 | 
						|
 | 
						|
		  btVector3 wv0,wv1,wv2;
 | 
						|
		  wv0 = m_worldTrans*triangle[0];
 | 
						|
		  wv1 = m_worldTrans*triangle[1];
 | 
						|
		  wv2 = m_worldTrans*triangle[2];
 | 
						|
		  btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.);
 | 
						|
          
 | 
						|
          if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals )
 | 
						|
          {
 | 
						|
		    btVector3 normal = (wv1-wv0).cross(wv2-wv0);
 | 
						|
		    normal.normalize();
 | 
						|
		    btVector3 normalColor(1,1,0);
 | 
						|
		    m_debugDrawer->drawLine(center,center+normal,normalColor);
 | 
						|
          }
 | 
						|
		  m_debugDrawer->drawLine(wv0,wv1,m_color);
 | 
						|
		  m_debugDrawer->drawLine(wv1,wv2,m_color);
 | 
						|
		  m_debugDrawer->drawLine(wv2,wv0,m_color);
 | 
						|
	  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
 | 
						|
{
 | 
						|
	// Draw a small simplex at the center of the object
 | 
						|
	if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
 | 
						|
	{
 | 
						|
		getDebugDrawer()->drawTransform(worldTransform,.1);
 | 
						|
	}
 | 
						|
 | 
						|
	if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
 | 
						|
	{
 | 
						|
		const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
 | 
						|
		for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
 | 
						|
		{
 | 
						|
			btTransform childTrans = compoundShape->getChildTransform(i);
 | 
						|
			const btCollisionShape* colShape = compoundShape->getChildShape(i);
 | 
						|
			debugDrawObject(worldTransform*childTrans,colShape,color);
 | 
						|
		}
 | 
						|
 | 
						|
	} else
 | 
						|
	{
 | 
						|
 | 
						|
        switch (shape->getShapeType())
 | 
						|
        {
 | 
						|
 | 
						|
        case BOX_SHAPE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
 | 
						|
                btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
 | 
						|
                getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
 | 
						|
        case SPHERE_SHAPE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
 | 
						|
                btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
 | 
						|
 | 
						|
                getDebugDrawer()->drawSphere(radius, worldTransform, color);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        case MULTI_SPHERE_SHAPE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
 | 
						|
 | 
						|
                btTransform childTransform;
 | 
						|
                childTransform.setIdentity();
 | 
						|
 | 
						|
                for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
 | 
						|
                {
 | 
						|
                    childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
 | 
						|
                    getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
 | 
						|
                }
 | 
						|
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        case CAPSULE_SHAPE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
 | 
						|
 | 
						|
                btScalar radius = capsuleShape->getRadius();
 | 
						|
                btScalar halfHeight = capsuleShape->getHalfHeight();
 | 
						|
 | 
						|
                int upAxis = capsuleShape->getUpAxis();
 | 
						|
                getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        case CONE_SHAPE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
 | 
						|
                btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
 | 
						|
                btScalar height = coneShape->getHeight();//+coneShape->getMargin();
 | 
						|
 | 
						|
                int upAxis= coneShape->getConeUpIndex();
 | 
						|
                getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
 | 
						|
                break;
 | 
						|
 | 
						|
            }
 | 
						|
        case CYLINDER_SHAPE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
 | 
						|
                int upAxis = cylinder->getUpAxis();
 | 
						|
                btScalar radius = cylinder->getRadius();
 | 
						|
                btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
 | 
						|
                getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
 | 
						|
        case STATIC_PLANE_PROXYTYPE:
 | 
						|
            {
 | 
						|
                const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
 | 
						|
                btScalar planeConst = staticPlaneShape->getPlaneConstant();
 | 
						|
                const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
 | 
						|
                getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color);
 | 
						|
                break;
 | 
						|
 | 
						|
            }
 | 
						|
        default:
 | 
						|
            {
 | 
						|
 | 
						|
                /// for polyhedral shapes
 | 
						|
                if (shape->isPolyhedral())
 | 
						|
                {
 | 
						|
                    btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
 | 
						|
                    
 | 
						|
                    int i;
 | 
						|
                    if (polyshape->getConvexPolyhedron())
 | 
						|
                    {
 | 
						|
                        const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
 | 
						|
                        for (i=0;i<poly->m_faces.size();i++)
 | 
						|
                        {
 | 
						|
                            btVector3 centroid(0,0,0);
 | 
						|
                            int numVerts = poly->m_faces[i].m_indices.size();
 | 
						|
                            if (numVerts)
 | 
						|
                            {
 | 
						|
                                int lastV = poly->m_faces[i].m_indices[numVerts-1];
 | 
						|
                                for (int v=0;v<poly->m_faces[i].m_indices.size();v++)
 | 
						|
                                {
 | 
						|
                                    int curVert = poly->m_faces[i].m_indices[v];
 | 
						|
                                    centroid+=poly->m_vertices[curVert];
 | 
						|
                                    getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color);
 | 
						|
                                    lastV = curVert;
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                            centroid*= btScalar(1.f)/btScalar(numVerts);
 | 
						|
                            if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
 | 
						|
                            {
 | 
						|
                                btVector3 normalColor(1,1,0);
 | 
						|
                                btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]);
 | 
						|
                                getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor);
 | 
						|
                            }
 | 
						|
                            
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        
 | 
						|
                    } else
 | 
						|
                    {
 | 
						|
                        for (i=0;i<polyshape->getNumEdges();i++)
 | 
						|
                        {
 | 
						|
                            btVector3 a,b;
 | 
						|
                            polyshape->getEdge(i,a,b);
 | 
						|
                            btVector3 wa = worldTransform * a;
 | 
						|
                            btVector3 wb = worldTransform * b;
 | 
						|
                            getDebugDrawer()->drawLine(wa,wb,color);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    
 | 
						|
                    
 | 
						|
                }
 | 
						|
                    
 | 
						|
                if (shape->isConcave())
 | 
						|
                {
 | 
						|
                    btConcaveShape* concaveMesh = (btConcaveShape*) shape;
 | 
						|
 | 
						|
                    ///@todo pass camera, for some culling? no -> we are not a graphics lib
 | 
						|
                    btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
 | 
						|
                    btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
 | 
						|
 | 
						|
                    DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
 | 
						|
                    concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
 | 
						|
 | 
						|
                }
 | 
						|
 | 
						|
                if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
 | 
						|
                {
 | 
						|
                    btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
 | 
						|
                    //todo: pass camera for some culling			
 | 
						|
                    btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
 | 
						|
                    btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
 | 
						|
                    //DebugDrawcallback drawCallback;
 | 
						|
                    DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
 | 
						|
                    convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
 | 
						|
                }
 | 
						|
 | 
						|
 | 
						|
                
 | 
						|
            }
 | 
						|
       
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::debugDrawWorld()
 | 
						|
{
 | 
						|
	if (getDebugDrawer())
 | 
						|
	{
 | 
						|
		getDebugDrawer()->clearLines();
 | 
						|
 | 
						|
		btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
 | 
						|
 | 
						|
		if ( getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
 | 
						|
		{
 | 
						|
		
 | 
						|
 | 
						|
			if (getDispatcher())
 | 
						|
			{
 | 
						|
				int numManifolds = getDispatcher()->getNumManifolds();
 | 
						|
			
 | 
						|
				for (int i=0;i<numManifolds;i++)
 | 
						|
				{
 | 
						|
					btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
 | 
						|
					//btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
 | 
						|
					//btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
 | 
						|
 | 
						|
					int numContacts = contactManifold->getNumContacts();
 | 
						|
					for (int j=0;j<numContacts;j++)
 | 
						|
					{
 | 
						|
						btManifoldPoint& cp = contactManifold->getContactPoint(j);
 | 
						|
						getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),defaultColors.m_contactPoint);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)))
 | 
						|
		{
 | 
						|
			int i;
 | 
						|
 | 
						|
			for (  i=0;i<m_collisionObjects.size();i++)
 | 
						|
			{
 | 
						|
				btCollisionObject* colObj = m_collisionObjects[i];
 | 
						|
				if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0)
 | 
						|
				{
 | 
						|
					if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
 | 
						|
					{
 | 
						|
						btVector3 color(btScalar(0.4),btScalar(0.4),btScalar(0.4));
 | 
						|
 | 
						|
						switch(colObj->getActivationState())
 | 
						|
						{
 | 
						|
						case  ACTIVE_TAG:
 | 
						|
							color = defaultColors.m_activeObject; break;
 | 
						|
						case ISLAND_SLEEPING:
 | 
						|
							color =  defaultColors.m_deactivatedObject;break;
 | 
						|
						case WANTS_DEACTIVATION:
 | 
						|
							color = defaultColors.m_wantsDeactivationObject;break;
 | 
						|
						case DISABLE_DEACTIVATION:
 | 
						|
							color = defaultColors.m_disabledDeactivationObject;break;
 | 
						|
						case DISABLE_SIMULATION:
 | 
						|
							color = defaultColors.m_disabledSimulationObject;break;
 | 
						|
						default:
 | 
						|
							{
 | 
						|
								color = btVector3(btScalar(.3),btScalar(0.3),btScalar(0.3));
 | 
						|
							}
 | 
						|
						};
 | 
						|
 | 
						|
						colObj->getCustomDebugColor(color);
 | 
						|
 | 
						|
						debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
 | 
						|
					}
 | 
						|
					if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
 | 
						|
					{
 | 
						|
						btVector3 minAabb,maxAabb;
 | 
						|
						btVector3 colorvec = defaultColors.m_aabb;
 | 
						|
						colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
 | 
						|
						btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
 | 
						|
						minAabb -= contactThreshold;
 | 
						|
						maxAabb += contactThreshold;
 | 
						|
 | 
						|
						btVector3 minAabb2,maxAabb2;
 | 
						|
 | 
						|
						if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
 | 
						|
						{
 | 
						|
							colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
 | 
						|
							minAabb2 -= contactThreshold;
 | 
						|
							maxAabb2 += contactThreshold;
 | 
						|
							minAabb.setMin(minAabb2);
 | 
						|
							maxAabb.setMax(maxAabb2);
 | 
						|
						}
 | 
						|
 | 
						|
						m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	///keep track of shapes already serialized
 | 
						|
	btHashMap<btHashPtr,btCollisionShape*>	serializedShapes;
 | 
						|
 | 
						|
	for (i=0;i<m_collisionObjects.size();i++)
 | 
						|
	{
 | 
						|
		btCollisionObject* colObj = m_collisionObjects[i];
 | 
						|
		btCollisionShape* shape = colObj->getCollisionShape();
 | 
						|
 | 
						|
		if (!serializedShapes.find(shape))
 | 
						|
		{
 | 
						|
			serializedShapes.insert(shape,shape);
 | 
						|
			shape->serializeSingleShape(serializer);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//serialize all collision objects
 | 
						|
	for (i=0;i<m_collisionObjects.size();i++)
 | 
						|
	{
 | 
						|
		btCollisionObject* colObj = m_collisionObjects[i];
 | 
						|
		if ((colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT) || (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK))
 | 
						|
		{
 | 
						|
			colObj->serializeSingleObject(serializer);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void	btCollisionWorld::serialize(btSerializer* serializer)
 | 
						|
{
 | 
						|
 | 
						|
	serializer->startSerialization();
 | 
						|
	
 | 
						|
	serializeCollisionObjects(serializer);
 | 
						|
	
 | 
						|
	serializer->finishSerialization();
 | 
						|
}
 | 
						|
 |