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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 |