1)Added SCE Physics Effects boxBoxDistance
BulletMultiThreaded/NarrowPhaseCollision makes use of this boxBoxDistance. Cache some values in src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp, to avoid DMA transfers 2) Added btConvexSeparatingDistanceUtil: this allows caching of separating distance/vector as early-out to avoid convex-convex collision detection. btConvexSeparatingDistanceUtil is used in src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp and can be controlled by btDispatcherInfo.m_useConvexConservativeDistanceUtil/m_convexConservativeDistanceThreshold 3) Use BulletMultiThreaded/vectormath/scalar/cpp/vectormath/scalar/cpp/vectormath_aos.h as fallback for non-PlayStation 3 Cell SPU/PPU platforms (used by boxBoxDistance). Note there are other implementations in Extras/vectormath folder, that are potentially faster for IBM Cell SDK 3.0 SPU (libspe2)
This commit is contained in:
158
src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h
Normal file
158
src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __BOX_H__
|
||||
#define __BOX_H__
|
||||
|
||||
#include <math.h>
|
||||
#include <vectormath_aos.h>
|
||||
|
||||
using namespace Vectormath::Aos;
|
||||
|
||||
enum FeatureType { F, E, V };
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Box
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class Box
|
||||
{
|
||||
public:
|
||||
Vector3 half;
|
||||
|
||||
inline Box()
|
||||
{}
|
||||
inline Box(Vector3 half_);
|
||||
inline Box(float hx, float hy, float hz);
|
||||
|
||||
inline void Set(Vector3 half_);
|
||||
inline void Set(float hx, float hy, float hz);
|
||||
|
||||
inline Vector3 GetAABB(const Matrix3& rotation) const;
|
||||
};
|
||||
|
||||
inline
|
||||
Box::Box(Vector3 half_)
|
||||
{
|
||||
Set(half_);
|
||||
}
|
||||
|
||||
inline
|
||||
Box::Box(float hx, float hy, float hz)
|
||||
{
|
||||
Set(hx, hy, hz);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
Box::Set(Vector3 half_)
|
||||
{
|
||||
half = half_;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
Box::Set(float hx, float hy, float hz)
|
||||
{
|
||||
half = Vector3(hx, hy, hz);
|
||||
}
|
||||
|
||||
inline
|
||||
Vector3
|
||||
Box::GetAABB(const Matrix3& rotation) const
|
||||
{
|
||||
return absPerElem(rotation) * half;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// BoxPoint
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
class BoxPoint
|
||||
{
|
||||
public:
|
||||
BoxPoint() : localPoint(0.0f) {}
|
||||
|
||||
Point3 localPoint;
|
||||
FeatureType featureType;
|
||||
int featureIdx;
|
||||
|
||||
inline void setVertexFeature(int plusX, int plusY, int plusZ);
|
||||
inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1);
|
||||
inline void setFaceFeature(int dim, int plus);
|
||||
|
||||
inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const;
|
||||
inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const;
|
||||
inline void getFaceFeature(int & dim, int & plus) const;
|
||||
};
|
||||
|
||||
inline
|
||||
void
|
||||
BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ)
|
||||
{
|
||||
featureType = V;
|
||||
featureIdx = plusX << 2 | plusY << 1 | plusZ;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1)
|
||||
{
|
||||
featureType = E;
|
||||
|
||||
if (dim0 > dim1) {
|
||||
featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0;
|
||||
} else {
|
||||
featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
BoxPoint::setFaceFeature(int dim, int plus)
|
||||
{
|
||||
featureType = F;
|
||||
featureIdx = plus << 2 | dim;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const
|
||||
{
|
||||
plusX = featureIdx >> 2;
|
||||
plusY = featureIdx >> 1 & 1;
|
||||
plusZ = featureIdx & 1;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const
|
||||
{
|
||||
plus0 = featureIdx >> 5;
|
||||
dim0 = featureIdx >> 3 & 3;
|
||||
plus1 = featureIdx >> 2 & 1;
|
||||
dim1 = featureIdx & 3;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
BoxPoint::getFaceFeature(int & dim, int & plus) const
|
||||
{
|
||||
plus = featureIdx >> 2;
|
||||
dim = featureIdx & 3;
|
||||
}
|
||||
|
||||
#endif /* __BOX_H__ */
|
||||
@@ -26,7 +26,8 @@
|
||||
#include "SpuEpaPenetrationDepthSolver.h"
|
||||
#include "SpuGjkPairDetector.h"
|
||||
#include "SpuVoronoiSimplexSolver.h"
|
||||
|
||||
#include "boxBoxDistance.h"
|
||||
#include "Util/Vectormath2Bullet.h"
|
||||
#include "SpuCollisionShapes.h" //definition of SpuConvexPolyhedronVertexData
|
||||
|
||||
#ifdef __SPU__
|
||||
@@ -89,11 +90,14 @@ bool gUseEpa = false;
|
||||
#include <LibSN_SPU.h>
|
||||
#endif //USE_SN_TUNER
|
||||
|
||||
#if defined (__CELLOS_LV2__) || defined (USE_LIBSPE2)
|
||||
#if defined (__SPU__) || defined (USE_LIBSPE2)
|
||||
#include <spu_printf.h>
|
||||
#else
|
||||
#define IGNORE_ALIGNMENT 1
|
||||
#define spu_printf printf
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define spu_printf printf
|
||||
|
||||
#endif
|
||||
|
||||
//int gNumConvexPoints0=0;
|
||||
@@ -101,14 +105,7 @@ bool gUseEpa = false;
|
||||
///Make sure no destructors are called on this memory
|
||||
struct CollisionTask_LocalStoreMemory
|
||||
{
|
||||
ATTRIBUTE_ALIGNED16(char bufferProxy0[sizeof(btBroadphaseProxy)+16]);
|
||||
ATTRIBUTE_ALIGNED16(char bufferProxy1[sizeof(btBroadphaseProxy)+16]);
|
||||
|
||||
ATTRIBUTE_ALIGNED16(btBroadphaseProxy* gProxyPtr0);
|
||||
ATTRIBUTE_ALIGNED16(btBroadphaseProxy* gProxyPtr1);
|
||||
|
||||
//ATTRIBUTE_ALIGNED16(btCollisionObject gColObj0);
|
||||
//ATTRIBUTE_ALIGNED16(btCollisionObject gColObj1);
|
||||
|
||||
ATTRIBUTE_ALIGNED16(char gColObj0 [sizeof(btCollisionObject)+16]);
|
||||
ATTRIBUTE_ALIGNED16(char gColObj1 [sizeof(btCollisionObject)+16]);
|
||||
|
||||
@@ -472,18 +469,19 @@ void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTa
|
||||
//try generic GJK
|
||||
|
||||
SpuVoronoiSimplexSolver vsSolver;
|
||||
SpuEpaPenetrationDepthSolver epaPenetrationSolver;
|
||||
SpuMinkowskiPenetrationDepthSolver minkowskiPenetrationSolver;
|
||||
SpuConvexPenetrationDepthSolver* penetrationSolver;
|
||||
|
||||
#ifdef ENABLE_EPA
|
||||
SpuEpaPenetrationDepthSolver epaPenetrationSolver;
|
||||
if (gUseEpa)
|
||||
{
|
||||
penetrationSolver = &epaPenetrationSolver;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
penetrationSolver = &minkowskiPenetrationSolver;
|
||||
}
|
||||
|
||||
|
||||
///DMA in the vertices for convex shapes
|
||||
ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]);
|
||||
ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]);
|
||||
@@ -582,12 +580,12 @@ SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collis
|
||||
register int dmaSize;
|
||||
register ppu_address_t dmaPpuAddress2;
|
||||
|
||||
dmaSize = sizeof(btCollisionObject);
|
||||
dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.gProxyPtr0->m_clientObject;
|
||||
dmaSize = sizeof(btCollisionObject);//btTransform);
|
||||
dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.gSpuContactManifoldAlgo.getCollisionObject0();
|
||||
cellDmaGet(&lsMem.gColObj0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0);
|
||||
|
||||
dmaSize = sizeof(btCollisionObject);
|
||||
dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.gProxyPtr1->m_clientObject;
|
||||
dmaSize = sizeof(btCollisionObject);//btTransform);
|
||||
dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.gSpuContactManifoldAlgo.getCollisionObject1();
|
||||
cellDmaGet(&lsMem.gColObj1, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0);
|
||||
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2));
|
||||
@@ -796,8 +794,9 @@ void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTas
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
spuContacts.flush();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -912,6 +911,7 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
|
||||
#endif //DEBUG_SPU_COLLISION_DETECTION
|
||||
|
||||
|
||||
/*
|
||||
dmaSize = sizeof(btBroadphaseProxy);
|
||||
dmaPpuAddress2 = (ppu_address_t)pair.m_pProxy0;
|
||||
//stallingUnalignedDmaSmallGet(lsMem.gProxyPtr0, dmaPpuAddress2 , dmaSize);
|
||||
@@ -923,6 +923,8 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
|
||||
tmpPtr = cellDmaSmallGetReadOnly(&lsMem.bufferProxy1, dmaPpuAddress2 , dmaSize,DMA_TAG(1), 0, 0);
|
||||
|
||||
lsMem.gProxyPtr1 = (btBroadphaseProxy*)tmpPtr;
|
||||
*/
|
||||
|
||||
|
||||
cellDmaWaitTagStatusAll(DMA_MASK(1));
|
||||
|
||||
@@ -963,11 +965,80 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
|
||||
// Get the collision objects
|
||||
dmaAndSetupCollisionObjects(collisionPairInput, lsMem);
|
||||
|
||||
if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive())
|
||||
//if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive())
|
||||
{
|
||||
handleCollisionPair(collisionPairInput, lsMem, spuContacts,
|
||||
(ppu_address_t)lsMem.getColObj0()->getCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape,
|
||||
(ppu_address_t)lsMem.getColObj1()->getCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape);
|
||||
bool boxbox = ((lsMem.gSpuContactManifoldAlgo.getShapeType0()==BOX_SHAPE_PROXYTYPE)&&
|
||||
(lsMem.gSpuContactManifoldAlgo.getShapeType1()==BOX_SHAPE_PROXYTYPE));
|
||||
if (boxbox && !gUseEpa)//for now use gUseEpa for this toggle
|
||||
{
|
||||
//getVmVector3
|
||||
//getBtVector3
|
||||
//getVmQuat
|
||||
//getBtQuat
|
||||
//getVmMatrix3
|
||||
|
||||
//getCollisionMargin0
|
||||
btScalar margin0 = lsMem.gSpuContactManifoldAlgo.getCollisionMargin0();
|
||||
btScalar margin1 = lsMem.gSpuContactManifoldAlgo.getCollisionMargin1();
|
||||
btVector3 shapeDim0 = lsMem.gSpuContactManifoldAlgo.getShapeDimensions0()+btVector3(margin0,margin0,margin0);
|
||||
btVector3 shapeDim1 = lsMem.gSpuContactManifoldAlgo.getShapeDimensions1()+btVector3(margin1,margin1,margin1);
|
||||
|
||||
Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ());
|
||||
Vector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin());
|
||||
Vector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin());
|
||||
Matrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis());
|
||||
Matrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis());
|
||||
|
||||
Transform3 transformA(vmMatrix0,vmPos0);
|
||||
Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ());
|
||||
Transform3 transformB(vmMatrix1,vmPos1);
|
||||
BoxPoint resultClosestBoxPointA;
|
||||
BoxPoint resultClosestBoxPointB;
|
||||
Vector3 resultNormal;
|
||||
float distanceThreshold = gContactBreakingThreshold;//0.0f;//FLT_MAX;//use epsilon?
|
||||
float distance = boxBoxDistance(resultNormal,resultClosestBoxPointA,resultClosestBoxPointB,
|
||||
boxA, transformA, boxB,transformB,distanceThreshold);
|
||||
|
||||
|
||||
if(distance < distanceThreshold)
|
||||
{
|
||||
//spu_printf("boxbox dist = %f\n",distance);
|
||||
btPersistentManifold* spuManifold=&lsMem.gPersistentManifold;
|
||||
btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr;
|
||||
ppu_address_t manifoldAddress = (ppu_address_t)manifold;
|
||||
|
||||
//spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped);
|
||||
spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(),
|
||||
lsMem.getColObj1()->getWorldTransform(),
|
||||
lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(),
|
||||
lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(),
|
||||
collisionPairInput.m_isSwapped);
|
||||
|
||||
btVector3 normalInB = -getBtVector3(resultNormal);
|
||||
|
||||
btVector3 pointOnB = collisionPairInput.m_worldTransform1(getBtVector3(resultClosestBoxPointB.localPoint));
|
||||
|
||||
//transform pointOnB to worldspace?
|
||||
|
||||
spuContacts.addContactPoint(
|
||||
normalInB,
|
||||
pointOnB,
|
||||
distance);
|
||||
//normalInB,
|
||||
//pointOnB+positionOffset,
|
||||
//distance);
|
||||
//SET_CONTACT_POINT(cp[0],distance,-testNormal,
|
||||
// boxPointA,relTransformA,primIndexA,
|
||||
// boxPointB,relTransformB,primIndexB);
|
||||
spuContacts.flush();
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
handleCollisionPair(collisionPairInput, lsMem, spuContacts,
|
||||
(ppu_address_t)lsMem.getColObj0()->getCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape,
|
||||
(ppu_address_t)lsMem.getColObj1()->getCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -981,5 +1052,6 @@ void processCollisionTask(void* userPtr, void* lsMemPtr)
|
||||
}// for
|
||||
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BOXBOXDISTANCE_H__
|
||||
#define __BOXBOXDISTANCE_H__
|
||||
|
||||
|
||||
#include "Box.h"
|
||||
|
||||
using namespace Vectormath::Aos;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// boxBoxDistance:
|
||||
//
|
||||
// description:
|
||||
// this computes info that can be used for the collision response of two boxes. when the boxes
|
||||
// do not overlap, the points are set to the closest points of the boxes, and a positive
|
||||
// distance between them is returned. if the boxes do overlap, a negative distance is returned
|
||||
// and the points are set to two points that would touch after the boxes are translated apart.
|
||||
// the contact normal gives the direction to repel or separate the boxes when they touch or
|
||||
// overlap (it's being approximated here as one of the 15 "separating axis" directions).
|
||||
//
|
||||
// returns:
|
||||
// positive or negative distance between two boxes.
|
||||
//
|
||||
// args:
|
||||
// Vector3& normal: set to a unit contact normal pointing from box A to box B.
|
||||
//
|
||||
// BoxPoint& boxPointA, BoxPoint& boxPointB:
|
||||
// set to a closest point or point of penetration on each box.
|
||||
//
|
||||
// Box boxA, Box boxB:
|
||||
// boxes, represented as 3 half-widths
|
||||
//
|
||||
// const Transform3& transformA, const Transform3& transformB:
|
||||
// box transformations, in world coordinates
|
||||
//
|
||||
// float distanceThreshold:
|
||||
// the algorithm will exit early if it finds that the boxes are more distant than this
|
||||
// threshold, and not compute a contact normal or points. if this distance returned
|
||||
// exceeds the threshold, all the other output data may not have been computed. by
|
||||
// default, this is set to MAX_FLOAT so it will have no effect.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
float
|
||||
boxBoxDistance(Vector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB,
|
||||
Box boxA, const Transform3 & transformA, Box boxB,
|
||||
const Transform3 & transformB,
|
||||
float distanceThreshold = FLT_MAX );
|
||||
|
||||
#endif /* __BOXBOXDISTANCE_H__ */
|
||||
Reference in New Issue
Block a user