172 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			172 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | /*
 | ||
|  | Bullet Continuous Collision Detection and Physics Library | ||
|  | Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
 | ||
|  | 
 | ||
|  | 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 "btGhostObject.h"
 | ||
|  | #include "btCollisionWorld.h"
 | ||
|  | #include "BulletCollision/CollisionShapes/btConvexShape.h"
 | ||
|  | #include "LinearMath/btAabbUtil2.h"
 | ||
|  | 
 | ||
|  | btGhostObject::btGhostObject() | ||
|  | { | ||
|  | 	m_internalType = CO_GHOST_OBJECT; | ||
|  | } | ||
|  | 
 | ||
|  | btGhostObject::~btGhostObject() | ||
|  | { | ||
|  | 	///btGhostObject should have been removed from the world, so no overlapping objects
 | ||
|  | 	btAssert(!m_overlappingObjects.size()); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) | ||
|  | { | ||
|  | 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||
|  | 	btAssert(otherObject); | ||
|  | 	///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
 | ||
|  | 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||
|  | 	if (index==m_overlappingObjects.size()) | ||
|  | 	{ | ||
|  | 		//not found
 | ||
|  | 		m_overlappingObjects.push_back(otherObject); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy) | ||
|  | { | ||
|  | 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||
|  | 	btAssert(otherObject); | ||
|  | 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||
|  | 	if (index<m_overlappingObjects.size()) | ||
|  | 	{ | ||
|  | 		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1]; | ||
|  | 		m_overlappingObjects.pop_back(); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | btPairCachingGhostObject::btPairCachingGhostObject() | ||
|  | { | ||
|  | 	m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); | ||
|  | } | ||
|  | 
 | ||
|  | btPairCachingGhostObject::~btPairCachingGhostObject() | ||
|  | { | ||
|  | 	m_hashPairCache->~btHashedOverlappingPairCache(); | ||
|  | 	btAlignedFree( m_hashPairCache ); | ||
|  | } | ||
|  | 
 | ||
|  | void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) | ||
|  | { | ||
|  | 	btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle(); | ||
|  | 	btAssert(actualThisProxy); | ||
|  | 
 | ||
|  | 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||
|  | 	btAssert(otherObject); | ||
|  | 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||
|  | 	if (index==m_overlappingObjects.size()) | ||
|  | 	{ | ||
|  | 		m_overlappingObjects.push_back(otherObject); | ||
|  | 		m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1) | ||
|  | { | ||
|  | 	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; | ||
|  | 	btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle(); | ||
|  | 	btAssert(actualThisProxy); | ||
|  | 
 | ||
|  | 	btAssert(otherObject); | ||
|  | 	int index = m_overlappingObjects.findLinearSearch(otherObject); | ||
|  | 	if (index<m_overlappingObjects.size()) | ||
|  | 	{ | ||
|  | 		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1]; | ||
|  | 		m_overlappingObjects.pop_back(); | ||
|  | 		m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void	btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const | ||
|  | { | ||
|  | 	btTransform	convexFromTrans,convexToTrans; | ||
|  | 	convexFromTrans = convexFromWorld; | ||
|  | 	convexToTrans = convexToWorld; | ||
|  | 	btVector3 castShapeAabbMin, castShapeAabbMax; | ||
|  | 	/* Compute AABB that encompasses angular movement */ | ||
|  | 	{ | ||
|  | 		btVector3 linVel, angVel; | ||
|  | 		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); | ||
|  | 		btTransform R; | ||
|  | 		R.setIdentity (); | ||
|  | 		R.setRotation (convexFromTrans.getRotation()); | ||
|  | 		castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/// 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_overlappingObjects.size();i++) | ||
|  | 	{ | ||
|  | 		btCollisionObject*	collisionObject= m_overlappingObjects[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)) | ||
|  | 			{ | ||
|  | 				btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans, | ||
|  | 					collisionObject, | ||
|  | 						collisionObject->getCollisionShape(), | ||
|  | 						collisionObject->getWorldTransform(), | ||
|  | 						resultCallback, | ||
|  | 						allowedCcdPenetration); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | void	btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const | ||
|  | { | ||
|  | 	btTransform rayFromTrans; | ||
|  | 	rayFromTrans.setIdentity(); | ||
|  | 	rayFromTrans.setOrigin(rayFromWorld); | ||
|  | 	btTransform  rayToTrans; | ||
|  | 	rayToTrans.setIdentity(); | ||
|  | 	rayToTrans.setOrigin(rayToWorld); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	int i; | ||
|  | 	for (i=0;i<m_overlappingObjects.size();i++) | ||
|  | 	{ | ||
|  | 		btCollisionObject*	collisionObject= m_overlappingObjects[i]; | ||
|  | 		//only perform raycast if filterMask matches
 | ||
|  | 		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))  | ||
|  | 		{ | ||
|  | 			btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, | ||
|  | 							collisionObject, | ||
|  | 								collisionObject->getCollisionShape(), | ||
|  | 								collisionObject->getWorldTransform(), | ||
|  | 								resultCallback); | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 |