Add PhysicsEffects to Extras. The build is only tested on Windows and Android.

The Android/NEON optimized version of Physics Effects is thanks to Graham Rhodes and Anthony Hamilton, See Issue 587
This commit is contained in:
erwin.coumans
2012-03-05 04:59:58 +00:00
parent 6cf8dfc202
commit a93a661b94
462 changed files with 86626 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
/*
Applied Research Associates Inc. (c)2011
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/low_level/collision/pfx_batched_ray_cast.h"
#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
// MULTIPLE THREADS
//----------------------------------------------------------------------------
// pfxCastRaysStartTaskEntry
//
/// The thread PfxTaskEntry function used to cast rays in parallel.
//----------------------------------------------------------------------------
void pfxCastRaysStartTaskEntry(PfxTaskArg *arg)
{
PfxRayCastParam &param = *((PfxRayCastParam*)arg->io);
PfxRayInput *rayInputs = (PfxRayInput*)arg->data[0];
PfxRayOutput *rayOutputs = (PfxRayOutput*)arg->data[1];
PfxUInt32 iFirstRay = arg->data[2];
PfxUInt32 iEndRay = arg->data[3];
for(PfxUInt32 i = iFirstRay; i < iEndRay; i++)
{
pfxCastSingleRay(rayInputs[i], rayOutputs[i], param);
}
}
//----------------------------------------------------------------------------
// pfxCastRays
//
/// Perform cast rays in parallel using a task manager.
///
/// @param rayInputs [in] Array of rays to cast
/// @param rayOutputs [out] On return contains output of ray casts
/// @param param Information about ray cast
/// @param taskManager Pointer to the thread task manager to use
//----------------------------------------------------------------------------
void pfxCastRays(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays,
PfxRayCastParam &param,PfxTaskManager *taskManager)
{
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesX));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesY));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZ));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesXb));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesYb));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZb));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetCollidables));
SCE_PFX_PUSH_MARKER("pfxCastRays");
PfxUInt32 maxBatchSize = numRays / (PfxUInt32)(taskManager->getNumTasks());
PfxUInt32 iEnd = maxBatchSize, iStart = 0;
int task = 0;
taskManager->setTaskEntry((void*)pfxCastRaysStartTaskEntry);
for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize)
{
taskManager->startTask(task, static_cast<void*>(&param), (PfxUInt32)rayInputs, (PfxUInt32)rayOutputs, iStart, iEnd);
}
// send final task
iEnd = numRays;
taskManager->startTask(taskManager->getNumTasks() - 1, static_cast<void*>(&param), iStart, iEnd, 0, 0);
// wait for tasks to complete
PfxUInt32 data1, data2, data3, data4;
for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++)
taskManager->waitTask(task, data1, data2, data3, data4);
SCE_PFX_POP_MARKER();
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,47 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/low_level/collision/pfx_batched_ray_cast.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
// SINGLE THREAD
void pfxCastRaysStart(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays,PfxRayCastParam &param)
{
for(int i=0;i<numRays;i++) {
pfxCastSingleRay(rayInputs[i],rayOutputs[i],param);
}
}
void pfxCastRays(PfxRayInput *rayInputs,PfxRayOutput *rayOutputs,int numRays,PfxRayCastParam &param)
{
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesX));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesY));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZ));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesXb));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesYb));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZb));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates));
SCE_PFX_ALWAYS_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetCollidables));
pfxCastRaysStart(rayInputs,rayOutputs,numRays,param);
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,166 @@
/*
Applied Research Associates Inc. (c)2011
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h"
#include "../../../include/physics_effects/base_level/collision/pfx_shape_iterator.h"
#include "../../../include/physics_effects/low_level/collision/pfx_collision_detection.h"
#include "../../base_level/broadphase/pfx_check_collidable.h"
#include "../../base_level/collision/pfx_contact_cache.h"
#include "pfx_detect_collision_func.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
// This function is implemented in pfx_collision_detection_single.cpp
extern int pfxCheckParamOfDetectCollision(PfxDetectCollisionParam &param);
///////////////////////////////////////////////////////////////////////////////
// MULTIPLE THREADS
#define SCE_PFX_CONTACT_THRESHOLD 0.0f
//----------------------------------------------------------------------------
// pfxDetectCollisionTaskEntry
//
/// The thread PfxTaskEntry function used to perform narrow phase collision
/// detection in parallel.
//----------------------------------------------------------------------------
void pfxDetectCollisionTaskEntry(PfxTaskArg *arg)
{
PfxDetectCollisionParam &param = *((PfxDetectCollisionParam*)arg->io);
PfxUInt32 iFirstContactPair = arg->data[0];
PfxUInt32 iEndContactPair = arg->data[1];
PfxConstraintPair *contactPairs = param.contactPairs;
PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds;
PfxRigidState *offsetRigidStates = param.offsetRigidStates;
PfxCollidable *offsetCollidables = param.offsetCollidables;
PfxUInt32 numRigidBodies = param.numRigidBodies;
for(PfxUInt32 i = iFirstContactPair; i < iEndContactPair; i++)
{
const PfxBroadphasePair &pair = contactPairs[i];
if(!pfxCheckCollidableInCollision(pair))
continue;
PfxUInt32 iContact = pfxGetContactId(pair);
PfxUInt32 iA = pfxGetObjectIdA(pair);
PfxUInt32 iB = pfxGetObjectIdB(pair);
PfxContactManifold &contact = offsetContactManifolds[iContact];
SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA());
SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB());
PfxRigidState &stateA = offsetRigidStates[iA];
PfxRigidState &stateB = offsetRigidStates[iB];
PfxCollidable &collA = offsetCollidables[iA];
PfxCollidable &collB = offsetCollidables[iB];
PfxTransform3 tA0(stateA.getOrientation(), stateA.getPosition());
PfxTransform3 tB0(stateB.getOrientation(), stateB.getPosition());
PfxContactCache contactCache;
PfxShapeIterator itrShapeA(collA);
for(PfxUInt32 j=0;j<collA.getNumShapes();j++,++itrShapeA)
{
const PfxShape &shapeA = *itrShapeA;
PfxTransform3 offsetTrA = shapeA.getOffsetTransform();
PfxTransform3 worldTrA = tA0 * offsetTrA;
PfxShapeIterator itrShapeB(collB);
for(PfxUInt32 k=0;k<collB.getNumShapes();k++,++itrShapeB)
{
const PfxShape &shapeB = *itrShapeB;
PfxTransform3 offsetTrB = shapeB.getOffsetTransform();
PfxTransform3 worldTrB = tB0 * offsetTrB;
if( (shapeA.getContactFilterSelf()&shapeB.getContactFilterTarget()) &&
(shapeA.getContactFilterTarget()&shapeB.getContactFilterSelf()) )
{
pfxGetDetectCollisionFunc(shapeA.getType(),shapeB.getType())(
contactCache,
shapeA,offsetTrA,worldTrA,j,
shapeB,offsetTrB,worldTrB,k,
SCE_PFX_CONTACT_THRESHOLD);
}
}
}
for(int j=0;j<contactCache.getNumContacts();j++)
{
const PfxCachedContactPoint &cp = contactCache.getContactPoint(j);
contact.addContactPoint(
cp.m_distance,
cp.m_normal,
cp.m_localPointA,
cp.m_localPointB,
cp.m_subData
);
}
}
}
//----------------------------------------------------------------------------
// pfxDetectCollision
//
/// Perform narrow phase collision detection in parallel using a task
/// manager.
///
/// @param param Information about pairs that may be colliding
/// @param taskManager Pointer to the thread task manager to use
///
/// @return SCE_PFX_OK if successful, otherwise, returns an error code.
//----------------------------------------------------------------------------
PfxInt32 pfxDetectCollision(PfxDetectCollisionParam &param, PfxTaskManager *taskManager)
{
PfxInt32 ret = pfxCheckParamOfDetectCollision(param);
if(ret != SCE_PFX_OK)
return ret;
SCE_PFX_PUSH_MARKER("pfxDetectCollision");
PfxUInt32 maxBatchSize = param.numContactPairs / (PfxUInt32)(taskManager->getNumTasks());
PfxUInt32 iEnd = maxBatchSize, iStart = 0;
int task = 0;
taskManager->setTaskEntry((void*)pfxDetectCollisionTaskEntry);
for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize)
{
taskManager->startTask(task, static_cast<void*>(&param), iStart, iEnd, 0, 0);
}
// send final task
iEnd = param.numContactPairs;
taskManager->startTask(taskManager->getNumTasks() - 1, static_cast<void*>(&param), iStart, iEnd, 0, 0);
// wait for tasks to complete
PfxUInt32 data1, data2, data3, data4;
for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++)
taskManager->waitTask(task, data1, data2, data3, data4);
SCE_PFX_POP_MARKER();
return SCE_PFX_OK;
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,125 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h"
#include "../../../include/physics_effects/base_level/collision/pfx_shape_iterator.h"
#include "../../../include/physics_effects/low_level/collision/pfx_collision_detection.h"
#include "../../base_level/broadphase/pfx_check_collidable.h"
#include "../../base_level/collision/pfx_contact_cache.h"
#include "pfx_detect_collision_func.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
int pfxCheckParamOfDetectCollision(PfxDetectCollisionParam &param)
{
if(!param.contactPairs || !param.offsetContactManifolds || !param.offsetRigidStates|| !param.offsetCollidables ) return SCE_PFX_ERR_INVALID_VALUE;
if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) ||
!SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetCollidables)) return SCE_PFX_ERR_INVALID_ALIGN;
return SCE_PFX_OK;
}
///////////////////////////////////////////////////////////////////////////////
// SINGLE THREAD
#define SCE_PFX_CONTACT_THRESHOLD 0.0f
PfxInt32 pfxDetectCollision(PfxDetectCollisionParam &param)
{
PfxInt32 ret = pfxCheckParamOfDetectCollision(param);
if(ret != SCE_PFX_OK)
return ret;
SCE_PFX_PUSH_MARKER("pfxDetectCollision");
PfxConstraintPair *contactPairs = param.contactPairs;
PfxUInt32 numContactPairs = param.numContactPairs;
PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds;
PfxRigidState *offsetRigidStates = param.offsetRigidStates;
PfxCollidable *offsetCollidables = param.offsetCollidables;
PfxUInt32 numRigidBodies = param.numRigidBodies;
for(PfxUInt32 i=0;i<numContactPairs;i++) {
const PfxBroadphasePair &pair = contactPairs[i];
if(!pfxCheckCollidableInCollision(pair)) {
continue;
}
PfxUInt32 iContact = pfxGetContactId(pair);
PfxUInt32 iA = pfxGetObjectIdA(pair);
PfxUInt32 iB = pfxGetObjectIdB(pair);
PfxContactManifold &contact = offsetContactManifolds[iContact];
SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA());
SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB());
PfxRigidState &stateA = offsetRigidStates[iA];
PfxRigidState &stateB = offsetRigidStates[iB];
PfxCollidable &collA = offsetCollidables[iA];
PfxCollidable &collB = offsetCollidables[iB];
PfxTransform3 tA0(stateA.getOrientation(), stateA.getPosition());
PfxTransform3 tB0(stateB.getOrientation(), stateB.getPosition());
PfxContactCache contactCache;
PfxShapeIterator itrShapeA(collA);
for(PfxUInt32 j=0;j<collA.getNumShapes();j++,++itrShapeA) {
const PfxShape &shapeA = *itrShapeA;
PfxTransform3 offsetTrA = shapeA.getOffsetTransform();
PfxTransform3 worldTrA = tA0 * offsetTrA;
PfxShapeIterator itrShapeB(collB);
for(PfxUInt32 k=0;k<collB.getNumShapes();k++,++itrShapeB) {
const PfxShape &shapeB = *itrShapeB;
PfxTransform3 offsetTrB = shapeB.getOffsetTransform();
PfxTransform3 worldTrB = tB0 * offsetTrB;
if( (shapeA.getContactFilterSelf()&shapeB.getContactFilterTarget()) &&
(shapeA.getContactFilterTarget()&shapeB.getContactFilterSelf()) ) {
pfxGetDetectCollisionFunc(shapeA.getType(),shapeB.getType())(
contactCache,
shapeA,offsetTrA,worldTrA,j,
shapeB,offsetTrB,worldTrB,k,
SCE_PFX_CONTACT_THRESHOLD);
}
}
}
for(int j=0;j<contactCache.getNumContacts();j++) {
const PfxCachedContactPoint &cp = contactCache.getContactPoint(j);
contact.addContactPoint(
cp.m_distance,
cp.m_normal,
cp.m_localPointA,
cp.m_localPointB,
cp.m_subData
);
}
}
SCE_PFX_POP_MARKER();
(void) numRigidBodies;
return SCE_PFX_OK;
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,449 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/collision/pfx_shape.h"
#include "../../base_level/collision/pfx_contact_box_box.h"
#include "../../base_level/collision/pfx_contact_box_capsule.h"
#include "../../base_level/collision/pfx_contact_box_sphere.h"
#include "../../base_level/collision/pfx_contact_capsule_capsule.h"
#include "../../base_level/collision/pfx_contact_capsule_sphere.h"
#include "../../base_level/collision/pfx_contact_sphere_sphere.h"
#include "../../base_level/collision/pfx_gjk_solver.h"
#include "../../base_level/collision/pfx_contact_large_tri_mesh.h"
#include "../../base_level/collision/pfx_gjk_support_func.h"
#include "pfx_detect_collision_func.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
// Collision Detection Function
void detectCollisionDummy(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)contacts;
(void)shapeA,(void)offsetTransformA,(void)worldTransformA,(void)shapeIdA;
(void)shapeB,(void)offsetTransformB,(void)worldTransformB,(void)shapeIdB;
(void)contactThreshold;
}
void detectCollisionBoxBox(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxBox boxA = shapeA.getBox();
PfxBox boxB = shapeB.getBox();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactBoxBox(nml,pA,pB,&boxA,worldTransformA,&boxB,worldTransformB);
if(d < contactThreshold) {
contacts.addContactPoint(d,-nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionBoxCapsule(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxBox boxA = shapeA.getBox();
PfxCapsule capsuleB = shapeB.getCapsule();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactBoxCapsule(nml,pA,pB,&boxA,worldTransformA,&capsuleB,worldTransformB);
if(d < contactThreshold) {
contacts.addContactPoint(d,-nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionBoxSphere(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxBox boxA = shapeA.getBox();
PfxSphere sphereB = shapeB.getSphere();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactBoxSphere(nml,pA,pB,&boxA,worldTransformA,&sphereB,worldTransformB);
if(d < contactThreshold) {
contacts.addContactPoint(d,-nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionCapsuleBox(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxCapsule capsuleA = shapeA.getCapsule();
PfxBox boxB = shapeB.getBox();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactBoxCapsule(nml,pB,pA,&boxB,worldTransformB,&capsuleA,worldTransformA);
if(d < contactThreshold) {
contacts.addContactPoint(d,nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionCapsuleCapsule(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxCapsule capsuleA = shapeA.getCapsule();
PfxCapsule capsuleB = shapeB.getCapsule();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactCapsuleCapsule(nml,pA,pB,&capsuleA,worldTransformA,&capsuleB,worldTransformB);
if(d < contactThreshold) {
contacts.addContactPoint(d,-nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionCapsuleSphere(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxCapsule capsuleA = shapeA.getCapsule();
PfxSphere sphereB = shapeB.getSphere();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactCapsuleSphere(nml,pA,pB,&capsuleA,worldTransformA,&sphereB,worldTransformB);
if(d < contactThreshold) {
contacts.addContactPoint(d,-nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionSphereBox(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxSphere sphereA = shapeA.getSphere();
PfxBox boxB = shapeB.getBox();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactBoxSphere(nml,pB,pA,&boxB,worldTransformB,&sphereA,worldTransformA);
if(d < contactThreshold) {
contacts.addContactPoint(d,nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionSphereCapsule(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxSphere sphereA = shapeA.getSphere();
PfxCapsule capsuleB = shapeB.getCapsule();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactCapsuleSphere(nml,pB,pA,&capsuleB,worldTransformB,&sphereA,worldTransformA);
if(d < contactThreshold) {
contacts.addContactPoint(d,nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionSphereSphere(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxSphere sphereA = shapeA.getSphere();
PfxSphere sphereB = shapeB.getSphere();
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxFloat d = pfxContactSphereSphere(nml,pA,pB,&sphereA,worldTransformA,&sphereB,worldTransformB);
if(d < contactThreshold) {
contacts.addContactPoint(d,-nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionGjk(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
PfxFloat d = SCE_PFX_FLT_MAX;
PfxVector3 nml;
PfxPoint3 pA,pB;
PfxGjkSolver gjk;
if(shapeA.getType() == kPfxShapeCylinder) {
PfxCylinder cylinderA = shapeA.getCylinder();
if(shapeB.getType() == kPfxShapeSphere) {
PfxSphere sphereB = shapeB.getSphere();
gjk.setup((void*)&cylinderA,(void*)&sphereB,pfxGetSupportVertexCylinder,pfxGetSupportVertexSphere);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeBox) {
PfxBox boxB = shapeB.getBox();
gjk.setup((void*)&cylinderA,(void*)&boxB,pfxGetSupportVertexCylinder,pfxGetSupportVertexBox);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeCapsule) {
PfxCapsule capsuleB = shapeB.getCapsule();
gjk.setup((void*)&cylinderA,(void*)&capsuleB,pfxGetSupportVertexCylinder,pfxGetSupportVertexCapsule);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeCylinder) {
PfxCylinder cylinderB = shapeB.getCylinder();
gjk.setup((void*)&cylinderA,(void*)&cylinderB,pfxGetSupportVertexCylinder,pfxGetSupportVertexCylinder);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeConvexMesh) {
const PfxConvexMesh *convexB = shapeB.getConvexMesh();
gjk.setup((void*)&cylinderA,(void*)convexB,pfxGetSupportVertexCylinder,pfxGetSupportVertexConvex);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
}
else if(shapeB.getType() == kPfxShapeCylinder) {
PfxCylinder cylinderB = shapeB.getCylinder();
if(shapeA.getType() == kPfxShapeSphere) {
PfxSphere sphereA = shapeA.getSphere();
gjk.setup((void*)&sphereA,(void*)&cylinderB,pfxGetSupportVertexSphere,pfxGetSupportVertexCylinder);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeA.getType() == kPfxShapeBox) {
PfxBox boxA = shapeA.getBox();
gjk.setup((void*)&boxA,(void*)&cylinderB,pfxGetSupportVertexBox,pfxGetSupportVertexCylinder);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeA.getType() == kPfxShapeCapsule) {
PfxCapsule capsuleA = shapeA.getCapsule();
gjk.setup((void*)&capsuleA,(void*)&cylinderB,pfxGetSupportVertexCapsule,pfxGetSupportVertexCylinder);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeA.getType() == kPfxShapeConvexMesh) {
const PfxConvexMesh *convexA = shapeA.getConvexMesh();
gjk.setup((void*)convexA,(void*)&cylinderB,pfxGetSupportVertexConvex,pfxGetSupportVertexCylinder);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
}
else if(shapeA.getType() == kPfxShapeConvexMesh) {
const PfxConvexMesh *convexA = shapeA.getConvexMesh();
if(shapeB.getType() == kPfxShapeSphere) {
PfxSphere sphereB = shapeB.getSphere();
gjk.setup((void*)convexA,(void*)&sphereB,pfxGetSupportVertexConvex,pfxGetSupportVertexSphere);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeBox) {
PfxBox boxB = shapeB.getBox();
gjk.setup((void*)convexA,(void*)&boxB,pfxGetSupportVertexConvex,pfxGetSupportVertexBox);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeCapsule) {
PfxCapsule capsuleB = shapeB.getCapsule();
gjk.setup((void*)convexA,(void*)&capsuleB,pfxGetSupportVertexConvex,pfxGetSupportVertexCapsule);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeCylinder) {
PfxCylinder cylinderB = shapeB.getCylinder();
gjk.setup((void*)convexA,(void*)&cylinderB,pfxGetSupportVertexConvex,pfxGetSupportVertexCylinder);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeB.getType() == kPfxShapeConvexMesh) {
const PfxConvexMesh *convexB = shapeB.getConvexMesh();
gjk.setup((void*)convexA,(void*)convexB,pfxGetSupportVertexConvex,pfxGetSupportVertexConvex);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
}
else if(shapeB.getType() == kPfxShapeConvexMesh) {
const PfxConvexMesh *convexB = shapeB.getConvexMesh();
if(shapeA.getType() == kPfxShapeSphere) {
PfxSphere sphereA = shapeA.getSphere();
gjk.setup((void*)&sphereA,(void*)convexB,pfxGetSupportVertexSphere,pfxGetSupportVertexConvex);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeA.getType() == kPfxShapeBox) {
PfxBox boxA = shapeA.getBox();
gjk.setup((void*)&boxA,(void*)convexB,pfxGetSupportVertexBox,pfxGetSupportVertexConvex);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeA.getType() == kPfxShapeCapsule) {
PfxCapsule capsuleA = shapeA.getCapsule();
gjk.setup((void*)&capsuleA,(void*)convexB,pfxGetSupportVertexCapsule,pfxGetSupportVertexConvex);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
else if(shapeA.getType() == kPfxShapeConvexMesh) {
const PfxConvexMesh *convexA = shapeA.getConvexMesh();
gjk.setup((void*)convexA,(void*)convexB,pfxGetSupportVertexConvex,pfxGetSupportVertexConvex);
d = gjk.collide(nml,pA,pB,worldTransformA,worldTransformB,SCE_PFX_FLT_MAX);
}
}
if(d < contactThreshold) {
contacts.addContactPoint(d,nml,offsetTransformA*pA,offsetTransformB*pB,PfxSubData());
}
}
void detectCollisionLargeTriMesh(
PfxContactCache &contacts,
const PfxShape &shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape &shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold)
{
(void)shapeIdA,(void)shapeIdB;
if(shapeA.getType() == kPfxShapeLargeTriMesh) {
const PfxLargeTriMesh *lmeshA = shapeA.getLargeTriMesh();
PfxContactCache localContacts;
pfxContactLargeTriMesh(localContacts,
lmeshA,worldTransformA,
shapeB,worldTransformB,
contactThreshold);
for(int i=0;i<localContacts.getNumContacts();i++) {
contacts.addContactPoint(
localContacts.getDistance(i),
localContacts.getNormal(i),
offsetTransformA * localContacts.getLocalPointA(i),
offsetTransformB * localContacts.getLocalPointB(i),
localContacts.getSubData(i));
}
}
else if(shapeB.getType() == kPfxShapeLargeTriMesh) {
const PfxLargeTriMesh *lmeshB = shapeB.getLargeTriMesh();
PfxContactCache localContacts;
pfxContactLargeTriMesh(localContacts,
lmeshB,worldTransformB,
shapeA,worldTransformA,
contactThreshold);
for(int i=0;i<localContacts.getNumContacts();i++) {
contacts.addContactPoint(
localContacts.getDistance(i),
-localContacts.getNormal(i),
offsetTransformA * localContacts.getLocalPointB(i),
offsetTransformB * localContacts.getLocalPointA(i),
localContacts.getSubData(i));
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Collision Detection Function Table
pfx_detect_collision_func funcTbl_detectCollision[kPfxShapeCount][kPfxShapeCount] = {
{detectCollisionSphereSphere ,detectCollisionSphereBox ,detectCollisionSphereCapsule ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionLargeTriMesh, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionBoxSphere ,detectCollisionBoxBox ,detectCollisionBoxCapsule ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionLargeTriMesh, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionCapsuleSphere ,detectCollisionCapsuleBox ,detectCollisionCapsuleCapsule ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionLargeTriMesh, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionGjk ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionLargeTriMesh, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionGjk ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionGjk ,detectCollisionLargeTriMesh, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionLargeTriMesh ,detectCollisionLargeTriMesh,detectCollisionLargeTriMesh ,detectCollisionLargeTriMesh,detectCollisionLargeTriMesh ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
{detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy ,detectCollisionDummy, detectCollisionDummy},
};
///////////////////////////////////////////////////////////////////////////////
// Collision Detection Function Table Interface
pfx_detect_collision_func pfxGetDetectCollisionFunc(PfxUInt8 shapeTypeA,PfxUInt8 shapeTypeB)
{
SCE_PFX_ASSERT(shapeTypeA<kPfxShapeCount);
SCE_PFX_ASSERT(shapeTypeB<kPfxShapeCount);
return funcTbl_detectCollision[shapeTypeA][shapeTypeB];
}
int pfxSetDetectCollisionFunc(PfxUInt8 shapeTypeA,PfxUInt8 shapeTypeB,pfx_detect_collision_func func)
{
if(shapeTypeA >= kPfxShapeCount || shapeTypeB >= kPfxShapeCount) {
return SCE_PFX_ERR_OUT_OF_RANGE;
}
funcTbl_detectCollision[shapeTypeA][shapeTypeB] = func;
return SCE_PFX_OK;
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,37 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#ifndef _SCE_PFX_DETECT_COLLISION_FUNC_H
#define _SCE_PFX_DETECT_COLLISION_FUNC_H
#include "../../base_level/collision/pfx_contact_cache.h"
namespace sce {
namespace PhysicsEffects {
typedef void (*pfx_detect_collision_func)(
PfxContactCache &contacts,
const PfxShape & shapeA,const PfxTransform3 &offsetTransformA,const PfxTransform3 &worldTransformA,int shapeIdA,
const PfxShape & shapeB,const PfxTransform3 &offsetTransformB,const PfxTransform3 &worldTransformB,int shapeIdB,
float contactThreshold);
pfx_detect_collision_func pfxGetDetectCollisionFunc(PfxUInt8 shapeTypeA,PfxUInt8 shapeTypeB);
int pfxSetDetectCollisionFunc(PfxUInt8 shapeTypeA,PfxUInt8 shapeTypeB,pfx_detect_collision_func func);
} //namespace PhysicsEffects
} //namespace sce
#endif // _SCE_PFX_DETECT_COLLISION_FUNC_H

View File

@@ -0,0 +1,129 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/collision/pfx_shape.h"
#include "../../base_level/collision/pfx_intersect_ray_box.h"
#include "../../base_level/collision/pfx_intersect_ray_sphere.h"
#include "../../base_level/collision/pfx_intersect_ray_capsule.h"
#include "../../base_level/collision/pfx_intersect_ray_cylinder.h"
#include "../../base_level/collision/pfx_intersect_ray_convex.h"
#include "../../base_level/collision/pfx_intersect_ray_large_tri_mesh.h"
#include "pfx_intersect_ray_func.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
// Ray Intersection Function Table
PfxBool intersectRayFuncDummy(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
(void)ray,(void)out,(void)shape,(void)transform;
return false;
}
PfxBool intersectRayFuncBox(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
return pfxIntersectRayBox(ray,out,shape.getBox(),transform);
}
PfxBool intersectRayFuncSphere(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
return pfxIntersectRaySphere(ray,out,shape.getSphere(),transform);
}
PfxBool intersectRayFuncCapsule(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
return pfxIntersectRayCapsule(ray,out,shape.getCapsule(),transform);
}
PfxBool intersectRayFuncCylinder(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
return pfxIntersectRayCylinder(ray,out,shape.getCylinder(),transform);
}
PfxBool intersectRayFuncConvex(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
const PfxConvexMesh *convex = shape.getConvexMesh();
PfxBool ret = pfxIntersectRayConvex(ray,out,(const void*)convex,transform);
return ret;
}
PfxBool intersectRayFuncLargeTriMesh(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform)
{
const PfxLargeTriMesh *lmesh = shape.getLargeTriMesh();
PfxBool ret = pfxIntersectRayLargeTriMesh(ray,out,(const void*)lmesh,transform);
return ret;
}
PfxIntersectRayFunc funcTbl_intersectRay[kPfxShapeCount] = {
intersectRayFuncSphere,
intersectRayFuncBox,
intersectRayFuncCapsule,
intersectRayFuncCylinder,
intersectRayFuncConvex,
intersectRayFuncLargeTriMesh,
intersectRayFuncDummy,
intersectRayFuncDummy,
intersectRayFuncDummy,
intersectRayFuncDummy,
intersectRayFuncDummy,
intersectRayFuncDummy,
};
///////////////////////////////////////////////////////////////////////////////
// Ray Intersection Function Table Interface
PfxIntersectRayFunc pfxGetIntersectRayFunc(PfxUInt8 shapeType)
{
return funcTbl_intersectRay[shapeType];
}
PfxInt32 pfxSetIntersectRayFunc(PfxUInt8 shapeType,PfxIntersectRayFunc func)
{
if(shapeType >= kPfxShapeCount) {
return SCE_PFX_ERR_OUT_OF_RANGE;
}
funcTbl_intersectRay[shapeType] = func;
return SCE_PFX_OK;
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,36 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#ifndef _SCE_PFX_INTERSECT_RAY_FUNC_H
#define _SCE_PFX_INTERSECT_RAY_FUNC_H
#include "../../../include/physics_effects/base_level/collision/pfx_ray.h"
namespace sce {
namespace PhysicsEffects {
typedef PfxBool (*PfxIntersectRayFunc)(
const PfxRayInput &ray,PfxRayOutput &out,
const PfxShape &shape,const PfxTransform3 &transform);
PfxIntersectRayFunc pfxGetIntersectRayFunc(PfxUInt8 shapeType);
PfxInt32 pfxSetIntersectRayFunc(PfxUInt8 shapeType,PfxIntersectRayFunc func);
} //namespace PhysicsEffects
} //namespace sce
#endif /* _SCE_PFX_INTERSECT_RAY_FUNC_H */

View File

@@ -0,0 +1,231 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/rigidbody/pfx_rigid_state.h"
#include "../../../include/physics_effects/low_level/collision/pfx_island_generation.h"
namespace sce {
namespace PhysicsEffects {
struct PfxIslandNode {
PfxUInt32 rootId;
PfxUInt32 rank;
PfxUInt32 islandId;
PfxUInt32 isRoot;
};
struct PfxIslandUnit
{
PfxUInt32 id;
PfxIslandUnit *next;
};
struct PfxIsland
{
PfxUInt32 numNodes;
PfxUInt32 numIslands;
PfxIslandNode *nodes;
PfxIslandUnit *islandsUnits;
PfxIslandUnit **islandsHeads;
};
PfxUInt32 pfxIslandNodeFind(PfxUInt32 i,PfxIsland *island)
{
if( i != island->nodes[i].rootId ) {
island->nodes[i].rootId = pfxIslandNodeFind(island->nodes[i].rootId,island);
}
return island->nodes[i].rootId;
}
void pfxIslandNodeLink(PfxUInt32 iA,PfxUInt32 iB,PfxIsland *island)
{
if(island->nodes[iA].rank > island->nodes[iB].rank) {
island->nodes[iB].rootId = iA;
}
else if(island->nodes[iA].rank == island->nodes[iB].rank) {
island->nodes[iA].rootId = iB;
island->nodes[iB].rank++;
}
else {
island->nodes[iA].rootId = iB;
}
}
void pfxIslandNodeUnion(PfxUInt32 iA,PfxUInt32 iB,PfxIsland *island)
{
SCE_PFX_ALWAYS_ASSERT(iA<island->numNodes);
SCE_PFX_ALWAYS_ASSERT(iB<island->numNodes);
pfxIslandNodeLink(pfxIslandNodeFind(iA,island),pfxIslandNodeFind(iB,island),island);
}
PfxUInt32 pfxGetIslandBytesOfGenerateIsland(PfxUInt32 numObjects)
{
return 16 +
SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIsland)) +
SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIslandNode)*numObjects) +
SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIslandUnit*)*numObjects) +
SCE_PFX_ALLOC_BYTES_ALIGN16(sizeof(PfxIslandUnit)*numObjects);
}
SCE_PFX_FORCE_INLINE int pfxCheckParamOfGenerateIsland(const PfxGenerateIslandParam &param)
{
if(!param.islandBuff || !param.pairs) return SCE_PFX_ERR_INVALID_VALUE;
if(!SCE_PFX_PTR_IS_ALIGNED16(param.pairs)) return SCE_PFX_ERR_INVALID_ALIGN;
if(SCE_PFX_AVAILABLE_BYTES_ALIGN16(param.islandBuff,param.islandBytes) < pfxGetIslandBytesOfGenerateIsland(param.numObjects) ) return SCE_PFX_ERR_OUT_OF_BUFFER;
return SCE_PFX_OK;
}
PfxInt32 pfxGenerateIsland(PfxGenerateIslandParam &param,PfxGenerateIslandResult &result)
{
int ret = pfxCheckParamOfGenerateIsland(param);
if(ret != SCE_PFX_OK) return ret;
PfxConstraintPair *pairs = param.pairs;
PfxUInt32 numPairs = param.numPairs;
PfxUInt32 numUnits = param.numObjects;
memset(param.islandBuff,0,param.islandBytes);
PfxHeapManager pool((unsigned char*)param.islandBuff,param.islandBytes);
PfxIsland *island = (PfxIsland*)pool.allocate(sizeof(PfxIsland));
island->numIslands = 0;
island->numNodes = numUnits;
island->nodes = (PfxIslandNode*)pool.allocate(sizeof(PfxIslandNode)*numUnits);
island->islandsHeads = (PfxIslandUnit**)pool.allocate(sizeof(PfxIslandUnit*)*numUnits);
island->islandsUnits = (PfxIslandUnit*)pool.allocate(sizeof(PfxIslandUnit)*numUnits);
result.island = island;
// 初期化
for(PfxUInt32 i=0;i<island->numNodes;i++) {
island->nodes[i].rootId = i;
island->nodes[i].rank = 0;
}
return pfxAppendPairs(island,pairs,numPairs);
}
PfxUInt32 pfxGetNumIslands(const PfxIsland *islands)
{
SCE_PFX_ALWAYS_ASSERT(islands);
return islands->numIslands;
}
PfxIslandUnit *pfxGetFirstUnitInIsland(const PfxIsland *islands,PfxUInt32 islandId)
{
SCE_PFX_ALWAYS_ASSERT(islands);
SCE_PFX_ALWAYS_ASSERT(islandId < islands->numIslands);
return islands->islandsHeads[islandId];
}
PfxIslandUnit *pfxGetNextUnitInIsland(const PfxIslandUnit *islandUnit)
{
SCE_PFX_ALWAYS_ASSERT(islandUnit);
return islandUnit->next;
}
PfxUInt32 pfxGetUnitId(const PfxIslandUnit *islandUnit)
{
SCE_PFX_ALWAYS_ASSERT(islandUnit);
return islandUnit->id;
}
PfxUInt32 pfxGetIslandId(const PfxIsland *islands,PfxUInt32 unitId)
{
SCE_PFX_ALWAYS_ASSERT(islands&&unitId<islands->numNodes);
return islands->nodes[unitId].islandId;
}
PfxInt32 pfxAppendPairs(PfxIsland *island,PfxConstraintPair *pairs,PfxUInt32 numPairs)
{
if(numPairs == 0) {
return SCE_PFX_OK;
}
if(!island || !pairs) return SCE_PFX_ERR_INVALID_VALUE;
if(!SCE_PFX_PTR_IS_ALIGNED16(island) || !SCE_PFX_PTR_IS_ALIGNED16(pairs)) return SCE_PFX_ERR_INVALID_ALIGN;
// 統合
for(PfxUInt32 i=0;i<numPairs;i++) {
PfxConstraintPair &pair = pairs[i];
if(pfxGetActive(pair)) {
PfxUInt32 iA = pfxGetObjectIdA(pair);
PfxUInt32 iB = pfxGetObjectIdB(pair);
SCE_PFX_ALWAYS_ASSERT(iA<island->numNodes);
SCE_PFX_ALWAYS_ASSERT(iB<island->numNodes);
if( (SCE_PFX_MOTION_MASK_DYNAMIC(pfxGetMotionMaskA(pair)&SCE_PFX_MOTION_MASK_TYPE)) &&
(SCE_PFX_MOTION_MASK_DYNAMIC(pfxGetMotionMaskB(pair)&SCE_PFX_MOTION_MASK_TYPE)) ) {
pfxIslandNodeUnion(iA,iB,island);
}
}
}
// アイランド生成のための初期化
for(PfxUInt32 i=0;i<island->numNodes;i++) {
island->nodes[i].islandId = 0;
island->nodes[i].isRoot = 0;
island->islandsHeads[i] = NULL;
}
// 親へ直結
PfxUInt32 id = 0;
for(PfxUInt32 i=0;i<island->numNodes;i++) {
PfxUInt32 rootId = pfxIslandNodeFind(i,island);
if( island->nodes[rootId].isRoot == 0 ) {
island->nodes[rootId].islandId = id++;
island->nodes[rootId].isRoot = 1;
}
island->nodes[i].islandId = island->nodes[rootId].islandId;
}
// アイランド作成
PfxUInt32 n = 0;
for(PfxUInt32 i=0;i<island->numNodes;i++) {
PfxUInt32 islandId = island->nodes[i].islandId;
PfxIslandUnit *newUnit = &island->islandsUnits[n++];
newUnit->id = i;
if(!island->islandsHeads[islandId]) {
island->islandsHeads[islandId] = newUnit;
continue;
}
PfxIslandUnit *unit=island->islandsHeads[islandId];
island->islandsHeads[islandId] = newUnit;
newUnit->next = unit;
}
island->numIslands = id;
return SCE_PFX_OK;
}
void pfxResetIsland(PfxIsland *island)
{
SCE_PFX_ALWAYS_ASSERT(island);
island->numIslands = 0;
for(PfxUInt32 i=0;i<island->numNodes;i++) {
island->nodes[i].rootId = i;
island->nodes[i].rank = 0;
}
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,228 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h"
#include "../../../include/physics_effects/low_level/collision/pfx_ray_cast.h"
#include "../../../include/physics_effects/base_level/collision/pfx_shape_iterator.h"
#include "pfx_intersect_ray_func.h"
#include "../../base_level/collision/pfx_intersect_common.h"
namespace sce {
namespace PhysicsEffects {
void pfxRayTraverseForward(
const PfxRayInput &ray,PfxRayOutput &out,const PfxAabb16 &rayAABB,
PfxBroadphaseProxy *proxies,int numProxies,
PfxRigidState *offsetRigidStates,
PfxCollidable *offsetCollidables,
int axis,const PfxVector3 &center,const PfxVector3 &half)
{
#ifdef SCE_PFX_USE_GEOMETRY
PfxGeomSegment segment((PfxPoint3)ray.m_startPosition,ray.m_direction);
#endif
for(int i=0;i<numProxies;i++) {
PfxBroadphaseProxy &proxy = proxies[i];
// 終了条件のチェック
if(pfxGetXYZMax(rayAABB,axis) < pfxGetXYZMin(proxy,axis)) {
return;
}
PfxVector3 boundOnRay = ray.m_startPosition + out.m_variable * ray.m_direction;
PfxVector3 AABBmin = pfxConvertCoordLocalToWorld(PfxVecInt3((PfxInt32)pfxGetXMin(proxy),(PfxInt32)pfxGetYMin(proxy),(PfxInt32)pfxGetZMin(proxy)),center,half);
PfxVector3 AABBmax = pfxConvertCoordLocalToWorld(PfxVecInt3((PfxInt32)pfxGetXMax(proxy),(PfxInt32)pfxGetYMax(proxy),(PfxInt32)pfxGetZMax(proxy)),center,half);
if(boundOnRay[axis] < AABBmin[axis]) {
return;
}
// スキップ
if(pfxGetXYZMax(proxy,axis) < pfxGetXYZMin(rayAABB,axis)) {
continue;
}
PfxUInt16 rigidbodyId = pfxGetObjectId(proxy);
PfxUInt32 contactFilterSelf = pfxGetSelf(proxy);
PfxUInt32 contactFilterTarget = pfxGetTarget(proxy);
#ifdef SCE_PFX_USE_GEOMETRY
PfxFloatInVec t_(1.0f);
PfxGeomAabb aabb((PfxPoint3)AABBmin,(PfxPoint3)AABBmax);
if( (ray.m_contactFilterSelf&contactFilterTarget) && (ray.m_contactFilterTarget&contactFilterSelf) && pfxTestAabb(rayAABB,proxy) &&
intersectionPoint(segment,aabb,&t_) && t_ < out.m_variable ) {
#else
float t_=1.0f;
if( (ray.m_contactFilterSelf&contactFilterTarget) && (ray.m_contactFilterTarget&contactFilterSelf) && pfxTestAabb(rayAABB,proxy) &&
pfxIntersectRayAABBFast(ray.m_startPosition,ray.m_direction,(AABBmax+AABBmin)*0.5f,(AABBmax-AABBmin)*0.5f,t_) && t_ < out.m_variable ) {
#endif
PfxRigidState &state = offsetRigidStates[rigidbodyId];
PfxCollidable &coll = offsetCollidables[rigidbodyId];
PfxTransform3 transform(state.getOrientation(), state.getPosition());
PfxRayOutput tout = out;
PfxShapeIterator itrShape(coll);
for(PfxUInt32 j=0;j<coll.getNumShapes();j++,++itrShape) {
const PfxShape &shape = *itrShape;
PfxTransform3 shapeTr = transform * shape.getOffsetTransform();
if(pfxGetIntersectRayFunc(shape.getType())(ray,tout,shape,shapeTr) && tout.m_variable < out.m_variable) {
out = tout;
out.m_shapeId = j;
out.m_objectId = rigidbodyId;
}
}
}
}
}
void pfxRayTraverseBackward(
const PfxRayInput &ray,PfxRayOutput &out,const PfxAabb16 &rayAABB,
PfxBroadphaseProxy *proxies,int numProxies,
PfxRigidState *offsetRigidStates,
PfxCollidable *offsetCollidables,
int axis,const PfxVector3 &center,const PfxVector3 &half)
{
#ifdef SCE_PFX_USE_GEOMETRY
PfxGeomSegment segment((PfxPoint3)ray.m_startPosition,ray.m_direction);
#endif
for(int i=numProxies-1;i>=0;i--) {
PfxBroadphaseProxy &proxy = proxies[i];
// 終了条件のチェック
if(pfxGetXYZMax(proxy,axis) < pfxGetXYZMin(rayAABB,axis)) {
return;
}
PfxVector3 boundOnRay = ray.m_startPosition + out.m_variable * ray.m_direction;
PfxVector3 AABBmin = pfxConvertCoordLocalToWorld(PfxVecInt3((PfxInt32)pfxGetXMin(proxy),(PfxInt32)pfxGetYMin(proxy),(PfxInt32)pfxGetZMin(proxy)),center,half);
PfxVector3 AABBmax = pfxConvertCoordLocalToWorld(PfxVecInt3((PfxInt32)pfxGetXMax(proxy),(PfxInt32)pfxGetYMax(proxy),(PfxInt32)pfxGetZMax(proxy)),center,half);
if(AABBmax[axis] < boundOnRay[axis]) {
return;
}
// スキップ
if(pfxGetXYZMax(rayAABB,axis) < pfxGetXYZMin(proxy,axis)) {
continue;
}
PfxUInt16 rigidbodyId = pfxGetObjectId(proxy);
PfxUInt32 contactFilterSelf = pfxGetSelf(proxy);
PfxUInt32 contactFilterTarget = pfxGetTarget(proxy);
#ifdef SCE_PFX_USE_GEOMETRY
PfxFloatInVec t_(1.0f);
PfxGeomAabb aabb((PfxPoint3)AABBmin,(PfxPoint3)AABBmax);
if( (ray.m_contactFilterSelf&contactFilterTarget) && (ray.m_contactFilterTarget&contactFilterSelf) && pfxTestAabb(rayAABB,proxy) &&
intersectionPoint(segment,aabb,&t_) && t_ < out.m_variable ) {
#else
float t_=1.0f;
if( (ray.m_contactFilterSelf&contactFilterTarget) && (ray.m_contactFilterTarget&contactFilterSelf) && pfxTestAabb(rayAABB,proxy) &&
pfxIntersectRayAABBFast(ray.m_startPosition,ray.m_direction,(AABBmax+AABBmin)*0.5f,(AABBmax-AABBmin)*0.5f,t_) && t_ < out.m_variable ) {
#endif
PfxRigidState &state = offsetRigidStates[rigidbodyId];
PfxCollidable &coll = offsetCollidables[rigidbodyId];
PfxTransform3 transform(state.getOrientation(), state.getPosition());
PfxRayOutput tout = out;
PfxShapeIterator itrShape(coll);
for(PfxUInt32 j=0;j<coll.getNumShapes();j++,++itrShape) {
const PfxShape &shape = *itrShape;
PfxTransform3 shapeTr = transform * shape.getOffsetTransform();
if(pfxGetIntersectRayFunc(shape.getType())(ray,tout,shape,shapeTr) && tout.m_variable < out.m_variable) {
out = tout;
out.m_shapeId = j;
out.m_objectId = rigidbodyId;
}
}
}
}
}
void pfxCastSingleRay(const PfxRayInput &ray,PfxRayOutput &out,const PfxRayCastParam &param)
{
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesX));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesY));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZ));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesXb));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesYb));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.proxiesZb));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates));
SCE_PFX_ASSERT(SCE_PFX_PTR_IS_ALIGNED16(param.offsetCollidables));
PfxBroadphaseProxy *proxies[] = {
param.proxiesX,
param.proxiesY,
param.proxiesZ,
param.proxiesXb,
param.proxiesYb,
param.proxiesZb,
};
out.m_variable = 1.0f;
out.m_contactFlag = false;
// 探索軸
PfxVector3 chkAxisVec = absPerElem(ray.m_direction);
int axis = 0;
if(chkAxisVec[1] < chkAxisVec[0]) axis = 1;
if(chkAxisVec[2] < chkAxisVec[axis]) axis = 2;
// レイのAABB作成
PfxVector3 p1 = ray.m_startPosition;
PfxVector3 p2 = ray.m_startPosition + ray.m_direction;
PfxVecInt3 rayMin,rayMax;
pfxConvertCoordWorldToLocal(param.rangeCenter,param.rangeExtent,minPerElem(p1,p2),maxPerElem(p1,p2),rayMin,rayMax);
PfxAabb16 rayAABB;
pfxSetXMin(rayAABB,rayMin.getX());
pfxSetXMax(rayAABB,rayMax.getX());
pfxSetYMin(rayAABB,rayMin.getY());
pfxSetYMax(rayAABB,rayMax.getY());
pfxSetZMin(rayAABB,rayMin.getZ());
pfxSetZMax(rayAABB,rayMax.getZ());
// AABB探索開始
int sign = ray.m_direction[axis] < 0.0f ? -1 : 1; // 探索方向
if(sign > 0) {
pfxRayTraverseForward(
ray,out,rayAABB,
proxies[axis],param.numProxies,
param.offsetRigidStates,param.offsetCollidables,
axis,param.rangeCenter,param.rangeExtent);
}
else {
pfxRayTraverseBackward(
ray,out,rayAABB,
proxies[axis+3],param.numProxies,
param.offsetRigidStates,param.offsetCollidables,
axis,param.rangeCenter,param.rangeExtent);
}
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,115 @@
/*
Applied Research Associates Inc. (c)2011
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h"
#include "../../../include/physics_effects/base_level/sort/pfx_sort.h"
#include "../../../include/physics_effects/low_level/collision/pfx_refresh_contacts.h"
namespace sce {
namespace PhysicsEffects {
///////////////////////////////////////////////////////////////////////////////
// This function is implemented in pfx_refresh_contacts_single.cpp
extern int pfxCheckParamOfRefreshContacts(PfxRefreshContactsParam &param);
///////////////////////////////////////////////////////////////////////////////
// MULTIPLE THREADS
//----------------------------------------------------------------------------
// pfxRefreshContactsTaskEntry
//
/// The thread PfxTaskEntry function used to perform refresh contacts in
/// parallel
//----------------------------------------------------------------------------
void pfxRefreshContactsTaskEntry(PfxTaskArg *arg)
{
PfxRefreshContactsParam &param = *((PfxRefreshContactsParam*)arg->io);
PfxUInt32 iFirstContactPair = arg->data[0];
PfxUInt32 iEndContactPair = arg->data[1];
PfxConstraintPair *contactPairs = param.contactPairs;
PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds;
PfxRigidState *offsetRigidStates = param.offsetRigidStates;
PfxUInt32 numRigidBodies = param.numRigidBodies;
for(PfxUInt32 i = iFirstContactPair; i < iEndContactPair; i++)
{
PfxBroadphasePair &pair = contactPairs[i];
PfxUInt32 iContact = pfxGetContactId(pair);
PfxUInt32 iA = pfxGetObjectIdA(pair);
PfxUInt32 iB = pfxGetObjectIdB(pair);
PfxContactManifold &contact = offsetContactManifolds[iContact];
SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA());
SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB());
PfxRigidState &instA = offsetRigidStates[iA];
PfxRigidState &instB = offsetRigidStates[iB];
contact.refresh(
instA.getPosition(),instA.getOrientation(),
instB.getPosition(),instB.getOrientation() );
}
}
//----------------------------------------------------------------------------
// pfxRefreshContacts
//
/// Perform refresh contacts in parallel using a task manager.
///
/// @param param Information about contact pairs
/// @param taskManager Pointer to the thread task manager to use
///
/// @return SCE_PFX_OK if successful, otherwise, returns an error code.
//----------------------------------------------------------------------------
PfxInt32 pfxRefreshContacts(PfxRefreshContactsParam &param, PfxTaskManager *taskManager)
{
PfxInt32 ret = pfxCheckParamOfRefreshContacts(param);
if(ret != SCE_PFX_OK) return ret;
SCE_PFX_PUSH_MARKER("pfxRefreshContacts");
PfxUInt32 maxBatchSize = param.numContactPairs / (PfxUInt32)(taskManager->getNumTasks());
PfxUInt32 iEnd = maxBatchSize, iStart = 0;
int task = 0;
taskManager->setTaskEntry((void*)pfxRefreshContactsTaskEntry);
for (task = 0; task < taskManager->getNumTasks() - 1; task++, iStart += maxBatchSize, iEnd += maxBatchSize)
{
taskManager->startTask(task, static_cast<void*>(&param), iStart, iEnd, 0, 0);
}
// send final task
iEnd = param.numContactPairs;
taskManager->startTask(taskManager->getNumTasks() - 1, static_cast<void*>(&param), iStart, iEnd, 0, 0);
// wait for tasks to complete
PfxUInt32 data1, data2, data3, data4;
for (PfxUInt32 i = 0; i < taskManager->getNumTasks(); i++)
taskManager->waitTask(task, data1, data2, data3, data4);
SCE_PFX_POP_MARKER();
return SCE_PFX_OK;
}
} //namespace PhysicsEffects
} //namespace sce

View File

@@ -0,0 +1,76 @@
/*
Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
Physics Effects is open software; you can redistribute it and/or
modify it under the terms of the BSD License.
Physics Effects is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.
A copy of the BSD License is distributed with
Physics Effects under the filename: physics_effects_license.txt
*/
#include "../../../include/physics_effects/base_level/base/pfx_perf_counter.h"
#include "../../../include/physics_effects/base_level/sort/pfx_sort.h"
#include "../../../include/physics_effects/low_level/collision/pfx_refresh_contacts.h"
namespace sce {
namespace PhysicsEffects {
int pfxCheckParamOfRefreshContacts(PfxRefreshContactsParam &param)
{
if(!param.contactPairs || !param.offsetContactManifolds || !param.offsetRigidStates ) return SCE_PFX_ERR_INVALID_VALUE;
if(!SCE_PFX_PTR_IS_ALIGNED16(param.contactPairs) || !SCE_PFX_PTR_IS_ALIGNED16(param.offsetContactManifolds) ||
!SCE_PFX_PTR_IS_ALIGNED16(param.offsetRigidStates)) return SCE_PFX_ERR_INVALID_ALIGN;
return SCE_PFX_OK;
}
///////////////////////////////////////////////////////////////////////////////
// SINGLE THREAD
PfxInt32 pfxRefreshContacts(PfxRefreshContactsParam &param)
{
PfxInt32 ret = pfxCheckParamOfRefreshContacts(param);
if(ret != SCE_PFX_OK) return ret;
SCE_PFX_PUSH_MARKER("pfxRefreshContacts");
PfxConstraintPair *contactPairs = param.contactPairs;
PfxUInt32 numContactPairs = param.numContactPairs;
PfxContactManifold *offsetContactManifolds = param.offsetContactManifolds;
PfxRigidState *offsetRigidStates = param.offsetRigidStates;
PfxUInt32 numRigidBodies = param.numRigidBodies;
for(PfxUInt32 i=0;i<numContactPairs;i++) {
PfxBroadphasePair &pair = contactPairs[i];
PfxUInt32 iContact = pfxGetContactId(pair);
PfxUInt32 iA = pfxGetObjectIdA(pair);
PfxUInt32 iB = pfxGetObjectIdB(pair);
PfxContactManifold &contact = offsetContactManifolds[iContact];
SCE_PFX_ALWAYS_ASSERT(iA==contact.getRigidBodyIdA());
SCE_PFX_ALWAYS_ASSERT(iB==contact.getRigidBodyIdB());
PfxRigidState &instA = offsetRigidStates[iA];
PfxRigidState &instB = offsetRigidStates[iB];
contact.refresh(
instA.getPosition(),instA.getOrientation(),
instB.getPosition(),instB.getOrientation() );
}
SCE_PFX_POP_MARKER();
(void) numRigidBodies;
return SCE_PFX_OK;
}
} //namespace PhysicsEffects
} //namespace sce