Files
bullet3/Extras/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp
2007-06-13 01:04:43 +00:00

163 lines
5.3 KiB
C++

/* [SCE CONFIDENTIAL DOCUMENT]
* PLAYSTATION(R)3 SPU Optimized Bullet Physics Library (http://bulletphysics.com)
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* All Rights Reserved.
*/
#include "SpuContactResult.h"
//#define DEBUG_SPU_COLLISION_DETECTION 1
#include "SpuContactResult.h"
SpuContactResult::SpuContactResult()
{
m_manifoldAddress = 0;
m_spuManifold = NULL;
m_RequiresWriteBack = false;
}
SpuContactResult::~SpuContactResult()
{
g_manifoldDmaExport.swapBuffers();
}
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, uint64_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1)
{
// spu_printf("SpuContactResult::setContactInfo\n");
m_rootWorldTransform0 = worldTrans0;
m_rootWorldTransform1 = worldTrans1;
m_manifoldAddress = manifoldAddress;
m_spuManifold = spuManifold;
}
void SpuContactResult::setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
{
}
///return true if it requires a dma transfer back
bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
const btVector3& pointInWorld,
float depth,
btPersistentManifold* manifoldPtr,
btTransform& transA,
btTransform& transB
)
{
float contactTreshold = manifoldPtr->getContactBreakingThreshold();
//spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: contactTreshold %f\n",contactTreshold);
#endif //DEBUG_SPU_COLLISION_DETECTION
if (depth > manifoldPtr->getContactBreakingThreshold())
return false;
//provide inverses or just calculate?
btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
btVector3 localA = transAInv(pointA );
btVector3 localB = transBInv(pointInWorld);
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
int insertIndex = manifoldPtr->getCacheEntry(newPt);
if (insertIndex >= 0)
{
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
// return true;
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: same contact detected, nothing done\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
// This is not needed, just use the old info! saves a DMA transfer as well
} else
{
newPt.m_combinedFriction = 0.25f;//calculateCombinedFriction(m_body0,m_body1);
newPt.m_combinedRestitution = 0.0f;//calculateCombinedRestitution(m_body0,m_body1);
/*
//potential TODO: SPU callbacks, either immediate (local on the SPU), or deferred
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
(m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
{
//experimental feature info, for per-triangle material etc.
(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
}
*/
manifoldPtr->AddManifoldPoint(newPt);
return true;
}
return false;
}
void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold)
{
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
g_manifoldDmaExport.swapBuffers();
g_manifoldDmaExport.backBufferDmaPut((uint64_t)mmManifold, sizeof(btPersistentManifold), DMA_TAG(9));
// Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon?
//no, the swapBuffers does the wait
}
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btPoint3& pointInWorld,float depth)
{
// spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
#ifdef DEBUG_SPU_COLLISION_DETECTION
// int sman = sizeof(rage::phManifold);
// spu_printf("sizeof_manifold = %i\n",sman);
#endif //DEBUG_SPU_COLLISION_DETECTION
btPersistentManifold* localManifold = m_spuManifold;
btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
//process the contact point
const bool retVal = ManifoldResultAddContactPoint(normalB,
pointWrld,
depth,
localManifold,
m_rootWorldTransform0,
m_rootWorldTransform1
);
m_RequiresWriteBack = m_RequiresWriteBack || retVal;
}
void SpuContactResult::flush()
{
if (m_RequiresWriteBack)
{
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Start rage::phManifold Write (Put) DMA\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
// spu_printf("writeDoubleBufferedManifold\n");
writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress);
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Finished (Put) DMA\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
}
m_spuManifold = NULL;
m_RequiresWriteBack = false;
}