Пример #1
0
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.0, linVel, angVel);
		btVector3 zeroLinVel;
		zeroLinVel.setValue(0,0,0);
		btTransform R;
		R.setIdentity ();
		R.setRotation (convexFromTrans.getRotation());
		castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, 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
}
Пример #2
0
bool	Raytracer::lowlevelRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint)
{

	btScalar closestHitResults = 1.f;

	bool hasHit = false;
	btConvexCast::CastResult rayResult;
	btSphereShape pointShape(0.0f);
	btTransform rayFromTrans;
	btTransform rayToTrans;

	rayFromTrans.setIdentity();
	rayFromTrans.setOrigin(rayFrom);
	rayToTrans.setIdentity();
	rayToTrans.setOrigin(rayTo);

	for (int s=0;s<numObjects;s++)
	{
		
		//do some culling, ray versus aabb
		btVector3 aabbMin,aabbMax;
		shapePtr[s]->getAabb(transforms[s],aabbMin,aabbMax);
		btScalar hitLambda = 1.f;
		btVector3 hitNormal;
		btCollisionObject	tmpObj;
		tmpObj.setWorldTransform(transforms[s]);


		if (btRayAabb(rayFrom,rayTo,aabbMin,aabbMax,hitLambda,hitNormal))
		{
			//reset previous result

			//choose the continuous collision detection method
			btSubsimplexConvexCast convexCaster(&pointShape,shapePtr[s],&simplexSolver);
			//btGjkConvexCast convexCaster(&pointShape,shapePtr[s],&simplexSolver);
			//btContinuousConvexCollision convexCaster(&pointShape,shapePtr[s],&simplexSolver,0);

			if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,transforms[s],transforms[s],rayResult))
			{
				if (rayResult.m_fraction < closestHitResults)
				{
					closestHitResults = rayResult.m_fraction;

					worldNormal = transforms[s].getBasis() *rayResult.m_normal;
					worldNormal.normalize();
					hasHit = true;
				}
			}
		}
	}

	return hasHit;

}
Пример #3
0
bool	Raytracer::singleObjectRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint)
{

	btScalar closestHitResults = 1.f;

	ClosestRayResultCallback resultCallback(rayFrom,rayTo);

	bool hasHit = false;
	btConvexCast::CastResult rayResult;
	btSphereShape pointShape(0.0f);
	btTransform rayFromTrans;
	btTransform rayToTrans;

	rayFromTrans.setIdentity();
	rayFromTrans.setOrigin(rayFrom);
	rayToTrans.setIdentity();
	rayToTrans.setOrigin(rayTo);

	for (int s=0;s<numObjects;s++)
	{
		//comment-out next line to get all hits, instead of just the closest hit
		//resultCallback.m_closestHitFraction = 1.f;

		//do some culling, ray versus aabb
		btVector3 aabbMin,aabbMax;
		shapePtr[s]->getAabb(transforms[s],aabbMin,aabbMax);
		btScalar hitLambda = 1.f;
		btVector3 hitNormal;
		btCollisionObject	tmpObj;
		tmpObj.setWorldTransform(transforms[s]);


		if (btRayAabb(rayFrom,rayTo,aabbMin,aabbMax,hitLambda,hitNormal))
		{
			//reset previous result

			btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, &tmpObj, shapePtr[s], transforms[s], resultCallback);
			if (resultCallback.hasHit())
			{
				//float fog = 1.f - 0.1f * rayResult.m_fraction;
				resultCallback.m_hitNormalWorld.normalize();//.m_normal.normalize();
				worldNormal = resultCallback.m_hitNormalWorld;
				//worldNormal = transforms[s].getBasis() *rayResult.m_normal;
				worldNormal.normalize();
				hasHit = true;
			}
		}
	}

	return hasHit;
}
Пример #4
0
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);
            }
        }
    }

}
Пример #5
0
void	btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask)
{

	
	btTransform	rayFromTrans,rayToTrans;
	rayFromTrans.setIdentity();
	rayFromTrans.setOrigin(rayFromWorld);
	rayToTrans.setIdentity();
	
	rayToTrans.setOrigin(rayToWorld);

	/// go over all objects, and if the ray intersects their 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(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { 
			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);

			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
			btVector3 hitNormal;
			if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
			{
				rayTestSingle(rayFromTrans,rayToTrans,
					collisionObject,
						collisionObject->getCollisionShape(),
						collisionObject->getWorldTransform(),
						resultCallback);
			}	
		}
	}

}
Пример #6
0
void	processRaycastTask(void* userPtr, void* lsMemory)
{
	RaycastTask_LocalStoreMemory* localMemory = (RaycastTask_LocalStoreMemory*)lsMemory;

	SpuRaycastTaskDesc* taskDescPtr = (SpuRaycastTaskDesc*)userPtr;
	SpuRaycastTaskDesc& taskDesc = *taskDescPtr;

	SpuCollisionObjectWrapper* cows = (SpuCollisionObjectWrapper*)taskDesc.spuCollisionObjectsWrappers;

	//spu_printf("in processRaycastTask %d\n", taskDesc.numSpuCollisionObjectWrappers);
	/* for each object */
	RaycastGatheredObjectData gatheredObjectData;
	for (int objectId = 0; objectId < taskDesc.numSpuCollisionObjectWrappers; objectId++)
	{
		//spu_printf("%d / %d\n", objectId, taskDesc.numSpuCollisionObjectWrappers);
		
		/* load initial collision shape */
		GatherCollisionObjectAndShapeData (&gatheredObjectData, localMemory, (ppu_address_t)&cows[objectId]);

		if (btBroadphaseProxy::isConcave (gatheredObjectData.m_shapeType))
		{
			SpuRaycastTaskWorkUnitOut tWorkUnitsOut[SPU_RAYCAST_WORK_UNITS_PER_TASK];
			for (int rayId = 0; rayId < taskDesc.numWorkUnits; rayId++)
			{
				tWorkUnitsOut[rayId].hitFraction = 1.0;
			}

			performRaycastAgainstConcave (&gatheredObjectData, &taskDesc.workUnits[0], &tWorkUnitsOut[0], taskDesc.numWorkUnits, localMemory);

			for (int rayId = 0; rayId < taskDesc.numWorkUnits; rayId++)
			{
				const SpuRaycastTaskWorkUnit& workUnit = taskDesc.workUnits[rayId];
				if (tWorkUnitsOut[rayId].hitFraction == 1.0)
					continue;

				ATTRIBUTE_ALIGNED16(SpuRaycastTaskWorkUnitOut workUnitOut);
				dmaLoadRayOutput ((ppu_address_t)workUnit.output, &workUnitOut, 1);
				cellDmaWaitTagStatusAll(DMA_MASK(1));
				
				
				/* XXX Only support taking the closest hit for now */
				if (tWorkUnitsOut[rayId].hitFraction < workUnitOut.hitFraction)
				{
					workUnitOut.hitFraction = tWorkUnitsOut[rayId].hitFraction;
					workUnitOut.hitNormal = tWorkUnitsOut[rayId].hitNormal;
				}

				/* write ray cast data back */
				dmaStoreRayOutput ((ppu_address_t)workUnit.output, &workUnitOut, 1);
				cellDmaWaitTagStatusAll(DMA_MASK(1));
			}
		} else if (btBroadphaseProxy::isConvex (gatheredObjectData.m_shapeType)) {

			btVector3 objectBoxMin, objectBoxMax;
			computeAabb (objectBoxMin, objectBoxMax, (btConvexInternalShape*)gatheredObjectData.m_spuCollisionShape, gatheredObjectData.m_collisionShape, gatheredObjectData.m_shapeType, gatheredObjectData.m_worldTransform);
			for (unsigned int rayId = 0; rayId < taskDesc.numWorkUnits; rayId++)
			{
				const SpuRaycastTaskWorkUnit& workUnit = taskDesc.workUnits[rayId];
			
				btScalar ignored_param = 1.0;
				btVector3 ignored_normal;
				if (btRayAabb(workUnit.rayFrom, workUnit.rayTo, objectBoxMin, objectBoxMax, ignored_param, ignored_normal))
				{
					ATTRIBUTE_ALIGNED16(SpuRaycastTaskWorkUnitOut workUnitOut);
					SpuRaycastTaskWorkUnitOut tWorkUnitOut;
					tWorkUnitOut.hitFraction = 1.0;

					performRaycastAgainstConvex (&gatheredObjectData, workUnit, &tWorkUnitOut, localMemory);
					if (tWorkUnitOut.hitFraction == 1.0)
						continue;
	
					dmaLoadRayOutput ((ppu_address_t)workUnit.output, &workUnitOut, 1);
					cellDmaWaitTagStatusAll(DMA_MASK(1));

					/* XXX Only support taking the closest hit for now */
					if (tWorkUnitOut.hitFraction < workUnitOut.hitFraction)
					{
						workUnitOut.hitFraction = tWorkUnitOut.hitFraction;
						workUnitOut.hitNormal = tWorkUnitOut.hitNormal;
						/* write ray cast data back */
						dmaStoreRayOutput ((ppu_address_t)workUnit.output, &workUnitOut, 1);
						cellDmaWaitTagStatusAll(DMA_MASK(1));
					}
				}
			}

		} else if (btBroadphaseProxy::isCompound (gatheredObjectData.m_shapeType)) {
			for (unsigned int rayId = 0; rayId < taskDesc.numWorkUnits; rayId++)
			{
				const SpuRaycastTaskWorkUnit& workUnit = taskDesc.workUnits[rayId];
				ATTRIBUTE_ALIGNED16(SpuRaycastTaskWorkUnitOut workUnitOut);
				SpuRaycastTaskWorkUnitOut tWorkUnitOut;
				tWorkUnitOut.hitFraction = 1.0;

				performRaycastAgainstCompound (&gatheredObjectData, workUnit, &tWorkUnitOut, localMemory);
				if (tWorkUnitOut.hitFraction == 1.0)
					continue;

				dmaLoadRayOutput ((ppu_address_t)workUnit.output, &workUnitOut, 1);
				cellDmaWaitTagStatusAll(DMA_MASK(1));
				/* XXX Only support taking the closest hit for now */
				if (tWorkUnitOut.hitFraction < workUnitOut.hitFraction)
				{
					workUnitOut.hitFraction = tWorkUnitOut.hitFraction;
					workUnitOut.hitNormal = tWorkUnitOut.hitNormal;
				}

				/* write ray cast data back */
				dmaStoreRayOutput ((ppu_address_t)workUnit.output, &workUnitOut, 1);
				cellDmaWaitTagStatusAll(DMA_MASK(1));
			}
		}
	}
}
Пример #7
0
void	spuWalkStacklessQuantizedTreeAgainstRays(RaycastTask_LocalStoreMemory* lsMemPtr, 
						 btNodeOverlapCallback* nodeCallback,
						 const btVector3* rayFrom,
						 const btVector3* rayTo,
						 int numWorkUnits,
						 unsigned short int* quantizedQueryAabbMin,
						 unsigned short int* quantizedQueryAabbMax,
						 const btQuantizedBvhNode* rootNode,
						 int startNodeIndex,int endNodeIndex)
{
	int curIndex = startNodeIndex;
	int walkIterations = 0;
	int subTreeSize = endNodeIndex - startNodeIndex;

	int escapeIndex;

	unsigned int boxBoxOverlap, rayBoxOverlap, anyRayBoxOverlap;
	unsigned int isLeafNode;

#define RAYAABB2
#ifdef RAYAABB2
	unsigned int sign[SPU_RAYCAST_WORK_UNITS_PER_TASK][3];
	btVector3 rayInvDirection[SPU_RAYCAST_WORK_UNITS_PER_TASK];
	btScalar lambda_max[SPU_RAYCAST_WORK_UNITS_PER_TASK];
	for (int i = 0; i < numWorkUnits; i++)
	{
		btVector3 rayDirection = (rayTo[i]-rayFrom[i]);
		rayDirection.normalize ();
		lambda_max[i] = rayDirection.dot(rayTo[i]-rayFrom[i]);
		rayInvDirection[i][0] = btScalar(1.0) / rayDirection[0];
		rayInvDirection[i][1] = btScalar(1.0) / rayDirection[1];
		rayInvDirection[i][2] = btScalar(1.0) / rayDirection[2];
		sign[i][0] = rayDirection[0] < 0.0;
		sign[i][1] = rayDirection[1] < 0.0;
		sign[i][2] = rayDirection[2] < 0.0;
	}
#endif

	while (curIndex < endNodeIndex)
	{
		//catch bugs in tree data
		assert (walkIterations < subTreeSize);

		walkIterations++;

		isLeafNode = rootNode->isLeafNode();

		anyRayBoxOverlap = 0;

		for (int i = 0; i < numWorkUnits; i++)
		{
			unsigned short int* quamin = (quantizedQueryAabbMin + 3 * i);
			unsigned short int* quamax = (quantizedQueryAabbMax + 3 * i);
			boxBoxOverlap = spuTestQuantizedAabbAgainstQuantizedAabb(quamin,quamax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
			if (!boxBoxOverlap)
				continue;

			rayBoxOverlap = 0;
			btScalar param = 1.0;
			btVector3 normal;
			btVector3 bounds[2];
			bounds[0] = lsMemPtr->bvhShapeData.getOptimizedBvh()->unQuantize(rootNode->m_quantizedAabbMin);
			bounds[1] = lsMemPtr->bvhShapeData.getOptimizedBvh()->unQuantize(rootNode->m_quantizedAabbMax);
#ifdef RAYAABB2
			rayBoxOverlap = btRayAabb2 (rayFrom[i], rayInvDirection[i], sign[i], bounds, param, 0.0, lambda_max[i]);
#else
			rayBoxOverlap = btRayAabb(rayFrom[i], rayTo[i], bounds[0], bounds[1], param, normal);
#endif

#ifndef CALLBACK_ALL
			anyRayBoxOverlap = rayBoxOverlap || anyRayBoxOverlap;
			/* If we have any ray vs. box overlap and this isn't a leaf node
			   we know that we need to dig deeper
			*/
			if (!isLeafNode && anyRayBoxOverlap)
				break;

			if (isLeafNode && rayBoxOverlap)
			{
				spuRaycastNodeCallback1* callback = (spuRaycastNodeCallback1*)nodeCallback;
				callback->setWorkUnit (i);
				nodeCallback->processNode (0, rootNode->getTriangleIndex());
			}
#else
			/* If we have any ray vs. box overlap and this isn't a leaf node
			   we know that we need to dig deeper
			*/
			if (rayBoxOverlap)
			{
				anyRayBoxOverlap = 1;
				break;
			}
#endif
		}

#ifdef CALLBACK_ALL
		if (isLeafNode && anyRayBoxOverlap)
		{
			nodeCallback->processNode (0, rootNode->getTriangleIndex());
		}
#endif

		if (anyRayBoxOverlap || isLeafNode)
		{
			rootNode++;
			curIndex++;
		} else
		{
			escapeIndex = rootNode->getEscapeIndex();
			rootNode += escapeIndex;
			curIndex += escapeIndex;
		}
	}

}