added parallel solver (work in progress) and made modifications to demo/constraints to allow for getting the type without using virtual functions (needed on CELL SPU processors)
This commit is contained in:
@@ -26,6 +26,9 @@ subject to the following restrictions:
|
|||||||
//#define USE_CUSTOM_NEAR_CALLBACK 1
|
//#define USE_CUSTOM_NEAR_CALLBACK 1
|
||||||
//#define CENTER_OF_MASS_SHIFT 1
|
//#define CENTER_OF_MASS_SHIFT 1
|
||||||
|
|
||||||
|
//#define USE_PARALLEL_SOLVER 1 //experimental parallel solver
|
||||||
|
//#define USE_PARALLEL_DISPATCHER 1
|
||||||
|
|
||||||
//following define allows to compare/replace Bullet's constraint solver with ODE quickstep
|
//following define allows to compare/replace Bullet's constraint solver with ODE quickstep
|
||||||
//this define requires to either add the libquickstep library (win32, see msvc/8/libquickstep.vcproj) or manually add the files from Extras/quickstep
|
//this define requires to either add the libquickstep library (win32, see msvc/8/libquickstep.vcproj) or manually add the files from Extras/quickstep
|
||||||
//#define COMPARE_WITH_QUICKSTEP 1
|
//#define COMPARE_WITH_QUICKSTEP 1
|
||||||
@@ -38,6 +41,15 @@ subject to the following restrictions:
|
|||||||
#endif //REGISTER_BOX_BOX
|
#endif //REGISTER_BOX_BOX
|
||||||
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
|
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
|
||||||
|
|
||||||
|
#ifdef USE_PARALLEL_DISPATCHER
|
||||||
|
#include "../../Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
|
||||||
|
#include "../../Extras/BulletMultiThreaded/Win32ThreadSupport.h"
|
||||||
|
#include "../../Extras/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
|
||||||
|
#include "../../Extras/BulletMultiThreaded/SpuParallelSolver.h"
|
||||||
|
#include "../../Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.h"
|
||||||
|
#endif//USE_PARALLEL_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
#ifdef COMPARE_WITH_QUICKSTEP
|
#ifdef COMPARE_WITH_QUICKSTEP
|
||||||
#include "../Extras/quickstep/OdeConstraintSolver.h"
|
#include "../Extras/quickstep/OdeConstraintSolver.h"
|
||||||
#endif //COMPARE_WITH_QUICKSTEP
|
#endif //COMPARE_WITH_QUICKSTEP
|
||||||
@@ -351,7 +363,33 @@ void CcdPhysicsDemo::initPhysics()
|
|||||||
m_azi = 90.f;
|
m_azi = 90.f;
|
||||||
#endif //DO_BENCHMARK_PYRAMIDS
|
#endif //DO_BENCHMARK_PYRAMIDS
|
||||||
|
|
||||||
btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
|
btCollisionDispatcher* dispatcher=0;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_PARALLEL_DISPATCHER
|
||||||
|
|
||||||
|
#ifdef USE_WIN32_THREADING
|
||||||
|
|
||||||
|
int maxNumOutstandingTasks = 4;//number of maximum outstanding tasks
|
||||||
|
Win32ThreadSupport* threadSupportCollision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo(
|
||||||
|
"collision",
|
||||||
|
processCollisionTask,
|
||||||
|
createCollisionLocalStoreMemory,
|
||||||
|
maxNumOutstandingTasks));
|
||||||
|
#else
|
||||||
|
///todo other platform threading
|
||||||
|
///Playstation 3 SPU (SPURS) version is available through PS3 Devnet
|
||||||
|
///Libspe2 SPU support will be available soon
|
||||||
|
///pthreads version
|
||||||
|
///you can hook it up to your custom task scheduler by deriving from btThreadSupportInterface
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
dispatcher = new SpuGatheringCollisionDispatcher(threadSupportCollision,maxNumOutstandingTasks);
|
||||||
|
// dispatcher = new btCollisionDispatcher();
|
||||||
|
#else
|
||||||
|
dispatcher = new btCollisionDispatcher();
|
||||||
|
#endif //USE_PARALLEL_DISPATCHER
|
||||||
|
|
||||||
#ifdef USE_CUSTOM_NEAR_CALLBACK
|
#ifdef USE_CUSTOM_NEAR_CALLBACK
|
||||||
//this is optional
|
//this is optional
|
||||||
@@ -379,11 +417,24 @@ void CcdPhysicsDemo::initPhysics()
|
|||||||
#ifdef COMPARE_WITH_QUICKSTEP
|
#ifdef COMPARE_WITH_QUICKSTEP
|
||||||
btConstraintSolver* solver = new OdeConstraintSolver();
|
btConstraintSolver* solver = new OdeConstraintSolver();
|
||||||
#else
|
#else
|
||||||
//default constraint solver
|
|
||||||
|
|
||||||
|
#ifdef USE_PARALLEL_SOLVER
|
||||||
|
|
||||||
|
Win32ThreadSupport* threadSupportSolver = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo(
|
||||||
|
"solver",
|
||||||
|
processSolverTask,
|
||||||
|
createSolverLocalStoreMemory,
|
||||||
|
maxNumOutstandingTasks));
|
||||||
|
|
||||||
|
btConstraintSolver* solver = new btParallelSequentialImpulseSolver(threadSupportSolver,maxNumOutstandingTasks);
|
||||||
|
#else
|
||||||
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
|
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
|
||||||
//default solverMode is SOLVER_RANDMIZE_ORDER. Warmstarting seems not to improve convergence, see
|
//default solverMode is SOLVER_RANDMIZE_ORDER. Warmstarting seems not to improve convergence, see
|
||||||
//solver->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER);
|
//solver->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER);
|
||||||
|
|
||||||
|
#endif //USE_PARALLEL_SOLVER
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USER_DEFINED_FRICTION_MODEL
|
#ifdef USER_DEFINED_FRICTION_MODEL
|
||||||
@@ -392,6 +443,7 @@ void CcdPhysicsDemo::initPhysics()
|
|||||||
#endif //USER_DEFINED_FRICTION_MODEL
|
#endif //USER_DEFINED_FRICTION_MODEL
|
||||||
|
|
||||||
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver);
|
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver);
|
||||||
|
m_dynamicsWorld->getDispatchInfo().m_enableSPU = true;
|
||||||
m_dynamicsWorld->setGravity(btVector3(0,-10,0));
|
m_dynamicsWorld->setGravity(btVector3(0,-10,0));
|
||||||
|
|
||||||
m_dynamicsWorld->setDebugDrawer(&debugDrawer);
|
m_dynamicsWorld->setDebugDrawer(&debugDrawer);
|
||||||
|
|||||||
568
Extras/BulletMultiThreaded/SpuParallelSolver.cpp
Normal file
568
Extras/BulletMultiThreaded/SpuParallelSolver.cpp
Normal file
@@ -0,0 +1,568 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library - Parallel solver
|
||||||
|
Copyright (c) 2007 Starbreeze Studios
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Written by: Marten Svanfeldt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SpuParallelSolver.h"
|
||||||
|
|
||||||
|
//#include "SpuFakeDma.h"
|
||||||
|
#include "SpuSync.h"
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||||
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
|
||||||
|
#include "LinearMath/btMinMax.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
||||||
|
|
||||||
|
#include "SpuSolverTask/SpuParallellSolverTask.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PARALLEL_SOLVER_BODIES_PER_TASK = 64,
|
||||||
|
PARALLEL_SOLVER_CELLS_PER_TASK = SPU_HASH_NUMCELLS >> 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-- Hash handling
|
||||||
|
static void recordDependency(SpuSolverHash* hash, unsigned int i, unsigned int j)
|
||||||
|
{
|
||||||
|
hash->m_dependencyMatrix[i][j >> 5] |= (1 << (j & 31));
|
||||||
|
hash->m_dependencyMatrix[j][i >> 5] |= (1 << (i & 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clear the given hash
|
||||||
|
static void clearHash (SpuSolverHash* hash)
|
||||||
|
{
|
||||||
|
size_t hashSize = sizeof(SpuSolverHash);
|
||||||
|
memset(hash, 0, hashSize);
|
||||||
|
|
||||||
|
// Setup basic dependency
|
||||||
|
for (int i = 0; i < SPU_HASH_NUMCELLS; ++i)
|
||||||
|
{
|
||||||
|
hash->m_dependencyMatrix[i][i >> 5] |= (1 << (i & 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set some ones to "unused cells"
|
||||||
|
for (int i = SPU_HASH_WORDWIDTH-SPU_HASH_NUMUNUSEDBITS; i < SPU_HASH_WORDWIDTH; ++i)
|
||||||
|
{
|
||||||
|
hash->m_currentMask[0][SPU_HASH_NUMCELLDWORDS-1] |= (1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool getDependency(SpuSolverHash* hash, unsigned int i, unsigned int j)
|
||||||
|
{
|
||||||
|
return (hash->m_dependencyMatrix[i][j >> 5] & (1 << (j & 31))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int getObjectIndex (btCollisionObject* object)
|
||||||
|
{
|
||||||
|
btVector3 center = object->getWorldTransform().getOrigin();
|
||||||
|
int cx = (int)floorf(center.x() / SPU_HASH_PHYSSIZE);
|
||||||
|
int cy = (int)floorf(center.y() / SPU_HASH_PHYSSIZE);
|
||||||
|
int cz = (int)floorf(center.z() / SPU_HASH_PHYSSIZE);
|
||||||
|
|
||||||
|
return spuGetHashCellIndex(cx, cy, cz);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btParallelSequentialImpulseSolver::btParallelSequentialImpulseSolver (btThreadSupportInterface* threadIf, int maxOutstandingTasks)
|
||||||
|
: m_numberOfContacts(0), m_taskScheduler (threadIf, maxOutstandingTasks)
|
||||||
|
{
|
||||||
|
m_solverHash = new SpuSolverHash;
|
||||||
|
clearHash(m_solverHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
btParallelSequentialImpulseSolver::~btParallelSequentialImpulseSolver ()
|
||||||
|
{
|
||||||
|
delete m_solverHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btParallelSequentialImpulseSolver::prepareSolve(int numBodies, int numManifolds)
|
||||||
|
{
|
||||||
|
m_sortedManifolds.reserve(numManifolds);
|
||||||
|
m_allObjects.reserve(numBodies);
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar btParallelSequentialImpulseSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc)
|
||||||
|
{
|
||||||
|
if (!numManifolds && !numConstraints)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < numManifolds; ++i)
|
||||||
|
{
|
||||||
|
btPersistentManifold* currManifold = manifold[i];
|
||||||
|
btRigidBody* rb0 = (btRigidBody*)currManifold->getBody0();
|
||||||
|
btRigidBody* rb1 = (btRigidBody*)currManifold->getBody1();
|
||||||
|
|
||||||
|
currManifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record and mark the manifolds to the cells
|
||||||
|
for (int i = 0; i < numManifolds; ++i)
|
||||||
|
{
|
||||||
|
// Compute a hash cell for this manifold
|
||||||
|
btPersistentManifold* currManifold = manifold[i];
|
||||||
|
|
||||||
|
btCollisionObject *ownerObject, *otherObject;
|
||||||
|
|
||||||
|
btRigidBody* rb0 = (btRigidBody*)currManifold->getBody0();
|
||||||
|
btRigidBody* rb1 = (btRigidBody*)currManifold->getBody1();
|
||||||
|
|
||||||
|
if (rb0->getIslandTag() >= 0)
|
||||||
|
{
|
||||||
|
ownerObject = rb0;
|
||||||
|
otherObject = rb1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ownerObject = rb1;
|
||||||
|
otherObject = rb0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the cell
|
||||||
|
unsigned int ownerCellIdx = getObjectIndex(ownerObject);
|
||||||
|
ManifoldCellHolder holder = {ownerCellIdx, currManifold};
|
||||||
|
m_sortedManifolds.push_back(holder);
|
||||||
|
m_solverHash->m_Hash[ownerCellIdx].m_numManifolds++;
|
||||||
|
|
||||||
|
// Record dependency
|
||||||
|
if (rb0->getIslandTag() >= 0 && rb1->getIslandTag() >= 0)
|
||||||
|
{
|
||||||
|
unsigned int otherCellIdx = getObjectIndex(otherObject);
|
||||||
|
recordDependency(m_solverHash, ownerCellIdx, otherCellIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save statistics
|
||||||
|
int numContacts = currManifold->getNumContacts();
|
||||||
|
m_solverHash->m_Hash[ownerCellIdx].m_numContacts += numContacts;
|
||||||
|
m_numberOfContacts += numContacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record and mark constraints to the cells
|
||||||
|
for (int i = 0; i < numConstraints; ++i)
|
||||||
|
{
|
||||||
|
// Compute a hash cell for this manifold
|
||||||
|
btTypedConstraint* currConstraint = constraints[i];
|
||||||
|
|
||||||
|
if (!constraintTypeSupported(currConstraint->getConstraintType()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
btCollisionObject *ownerObject, *otherObject;
|
||||||
|
|
||||||
|
btRigidBody* rb0 = &currConstraint->getRigidBodyA();
|
||||||
|
btRigidBody* rb1 = &currConstraint->getRigidBodyB();
|
||||||
|
|
||||||
|
if (rb0->getIslandTag() >= 0)
|
||||||
|
{
|
||||||
|
ownerObject = rb0;
|
||||||
|
otherObject = rb1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ownerObject = rb1;
|
||||||
|
otherObject = rb0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the cell
|
||||||
|
unsigned int ownerCellIdx = getObjectIndex(ownerObject);
|
||||||
|
ConstraintCellHolder holder = {ownerCellIdx, currConstraint->getConstraintType(), currConstraint};
|
||||||
|
m_sortedConstraints.push_back(holder);
|
||||||
|
m_solverHash->m_Hash[ownerCellIdx].m_numConstraints++;
|
||||||
|
|
||||||
|
// Record dependency
|
||||||
|
if (rb0 && rb1 && rb0->getIslandTag() >= 0 && rb1->getIslandTag() >= 0)
|
||||||
|
{
|
||||||
|
unsigned int otherCellIdx = getObjectIndex(otherObject);
|
||||||
|
recordDependency(m_solverHash, ownerCellIdx, otherCellIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save all RBs
|
||||||
|
for (int i = 0; i < numBodies; ++i)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = bodies[i];
|
||||||
|
//unsigned int cellIdx = getObjectIndex(obj);
|
||||||
|
|
||||||
|
btRigidBody* rb = btRigidBody::upcast(obj);
|
||||||
|
m_allObjects.push_back(rb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class CellHolderPredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SIMD_FORCE_INLINE bool operator() ( const T& lhs, const T& rhs )
|
||||||
|
{
|
||||||
|
return lhs.m_hashCellIndex < rhs.m_hashCellIndex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void printDependencyMatrix(SpuSolverHash* hash)
|
||||||
|
{
|
||||||
|
for (int r = 0; r < SPU_HASH_NUMCELLS; ++r)
|
||||||
|
{
|
||||||
|
for (int c = 0; c < SPU_HASH_NUMCELLS; ++c)
|
||||||
|
{
|
||||||
|
if (getDependency(hash, r, c))
|
||||||
|
{
|
||||||
|
printf("1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solver caches
|
||||||
|
btAlignedObjectArray<SpuSolverBody> solverBodyPool_persist;
|
||||||
|
btAlignedObjectArray<uint32_t> solverBodyOffsetList_persist;
|
||||||
|
btAlignedObjectArray<SpuSolverInternalConstraint> solverInternalConstraintPool_persist;
|
||||||
|
btAlignedObjectArray<SpuSolverConstraint> solverConstraintPool_persist;
|
||||||
|
|
||||||
|
|
||||||
|
void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc)
|
||||||
|
{
|
||||||
|
if (!m_numberOfContacts && !m_sortedConstraints.size())
|
||||||
|
{
|
||||||
|
m_sortedManifolds.clear();
|
||||||
|
m_sortedConstraints.clear();
|
||||||
|
m_allObjects.clear();
|
||||||
|
clearHash(m_solverHash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//printDependencyMatrix(m_solverHash);
|
||||||
|
|
||||||
|
// Sort the manifolds list
|
||||||
|
int numManifolds = m_sortedManifolds.size();
|
||||||
|
m_sortedManifolds.heapSort(CellHolderPredicate<ManifoldCellHolder>());
|
||||||
|
|
||||||
|
// Sort the constraint list
|
||||||
|
int numConstraints = m_sortedConstraints.size();
|
||||||
|
m_sortedConstraints.heapSort(CellHolderPredicate<ConstraintCellHolder>());
|
||||||
|
|
||||||
|
|
||||||
|
// Sort the body list
|
||||||
|
int numBodies = m_allObjects.size();
|
||||||
|
|
||||||
|
// Reassign the hash offset
|
||||||
|
uint32_t emptyCellMask[SPU_HASH_NUMCELLDWORDS] = {0};
|
||||||
|
int numBodyOffsets = 0;
|
||||||
|
{
|
||||||
|
int manifoldRunner = 0;
|
||||||
|
int bodyOffsetRunner = 0;
|
||||||
|
int internalConstraintRunner = 0;
|
||||||
|
int constraintRunner = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < SPU_HASH_NUMCELLS; ++i)
|
||||||
|
{
|
||||||
|
bool empty = true;
|
||||||
|
|
||||||
|
SpuSolverHashCell& hashCell = m_solverHash->m_Hash[i];
|
||||||
|
hashCell.m_solverBodyOffsetListOffset = bodyOffsetRunner;
|
||||||
|
|
||||||
|
if (hashCell.m_numManifolds)
|
||||||
|
{
|
||||||
|
hashCell.m_manifoldListOffset = manifoldRunner;
|
||||||
|
manifoldRunner += hashCell.m_numManifolds;
|
||||||
|
|
||||||
|
bodyOffsetRunner += hashCell.m_numManifolds*2;
|
||||||
|
}
|
||||||
|
if (hashCell.m_numContacts)
|
||||||
|
{
|
||||||
|
hashCell.m_internalConstraintListOffset = internalConstraintRunner*3;
|
||||||
|
internalConstraintRunner += hashCell.m_numContacts;
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashCell.m_numConstraints)
|
||||||
|
{
|
||||||
|
hashCell.m_constraintListOffset = constraintRunner;
|
||||||
|
constraintRunner += hashCell.m_numConstraints;
|
||||||
|
|
||||||
|
bodyOffsetRunner += hashCell.m_numConstraints*2;
|
||||||
|
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
emptyCellMask[i >> 5] |= (empty ? (1 << (i&31)) : 0);
|
||||||
|
// Align the bodyOffsetRunner to a whole number of 4 for right alignment in the list
|
||||||
|
bodyOffsetRunner = (bodyOffsetRunner+3)&~0x3;
|
||||||
|
}
|
||||||
|
|
||||||
|
numBodyOffsets = bodyOffsetRunner;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup rigid bodies
|
||||||
|
// Allocate temporary data
|
||||||
|
solverBodyPool_persist.resize(numBodies + numManifolds + numConstraints);
|
||||||
|
SpuSolverBody* solverBodyPool = &solverBodyPool_persist[0];
|
||||||
|
|
||||||
|
solverBodyOffsetList_persist.resize(numBodyOffsets);
|
||||||
|
uint32_t* solverBodyOffsetList = &solverBodyOffsetList_persist[0];
|
||||||
|
|
||||||
|
solverInternalConstraintPool_persist.resize(m_numberOfContacts*3);
|
||||||
|
SpuSolverInternalConstraint* solverInternalConstraintPool = &solverInternalConstraintPool_persist[0];
|
||||||
|
|
||||||
|
solverConstraintPool_persist.resize(numConstraints);
|
||||||
|
SpuSolverConstraint* solverConstraintPool = &solverConstraintPool_persist[0];
|
||||||
|
|
||||||
|
// Setup all the moving rigid bodies
|
||||||
|
{
|
||||||
|
int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK;
|
||||||
|
int bodiesToSchedule = numBodies;
|
||||||
|
int startBody = 0;
|
||||||
|
|
||||||
|
while (bodiesToSchedule > 0)
|
||||||
|
{
|
||||||
|
// Schedule a bunch of hash cells
|
||||||
|
int numBodiesInTask = bodiesToSchedule > bodiesPerTask ? bodiesPerTask : bodiesToSchedule;
|
||||||
|
|
||||||
|
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
|
||||||
|
|
||||||
|
desc->m_solverCommand = CMD_SOLVER_SETUP_BODIES;
|
||||||
|
desc->m_solverData.m_solverHash = m_solverHash;
|
||||||
|
desc->m_solverData.m_solverBodyList = solverBodyPool;
|
||||||
|
|
||||||
|
desc->m_commandData.m_bodySetup.m_startBody = startBody;
|
||||||
|
desc->m_commandData.m_bodySetup.m_numBodies = numBodiesInTask;
|
||||||
|
desc->m_commandData.m_bodySetup.m_rbList = &m_allObjects[0];
|
||||||
|
|
||||||
|
m_taskScheduler.issueTask();
|
||||||
|
bodiesToSchedule -= numBodiesInTask;
|
||||||
|
startBody += numBodiesInTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_taskScheduler.flushTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manifold setup
|
||||||
|
{
|
||||||
|
int cellsPerTask = PARALLEL_SOLVER_CELLS_PER_TASK;
|
||||||
|
int cellsToSchedule = SPU_HASH_NUMCELLS;
|
||||||
|
int startCell = 0;
|
||||||
|
|
||||||
|
while (cellsToSchedule > 0)
|
||||||
|
{
|
||||||
|
int numCellsInTask = cellsToSchedule > cellsPerTask ? cellsPerTask : cellsToSchedule;
|
||||||
|
|
||||||
|
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
|
||||||
|
|
||||||
|
desc->m_solverCommand = CMD_SOLVER_MANIFOLD_SETUP;
|
||||||
|
desc->m_solverData.m_solverHash = m_solverHash;
|
||||||
|
desc->m_solverData.m_solverBodyList = solverBodyPool;
|
||||||
|
desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList;
|
||||||
|
desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool;
|
||||||
|
desc->m_solverData.m_solverConstraintList = solverConstraintPool;
|
||||||
|
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_startCell = startCell;
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_numCells = numCellsInTask;
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_numBodies = numBodies;
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_numManifolds = numManifolds;
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_manifoldHolders = &m_sortedManifolds[0];
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_constraintHolders = &m_sortedConstraints[0];
|
||||||
|
desc->m_commandData.m_manifoldSetup.m_solverInfo = info;
|
||||||
|
|
||||||
|
m_taskScheduler.issueTask();
|
||||||
|
cellsToSchedule -= numCellsInTask;
|
||||||
|
startCell += numCellsInTask;
|
||||||
|
}
|
||||||
|
m_taskScheduler.flushTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128);
|
||||||
|
for (int iter = 0; iter < info.m_numIterations; ++iter)
|
||||||
|
{
|
||||||
|
btSpinlock lock (spinVar);
|
||||||
|
lock.Init();
|
||||||
|
|
||||||
|
// Clear the "processed cells" part of the hash
|
||||||
|
memcpy(m_solverHash->m_currentMask[0], emptyCellMask, sizeof(uint32_t)*SPU_HASH_NUMCELLDWORDS);
|
||||||
|
|
||||||
|
for (int task = 0; task < m_taskScheduler.getMaxOutstandingTasks(); ++task)
|
||||||
|
{
|
||||||
|
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
|
||||||
|
desc->m_solverCommand = CMD_SOLVER_SOLVE_ITERATE;
|
||||||
|
|
||||||
|
desc->m_solverData.m_solverHash = m_solverHash;
|
||||||
|
desc->m_solverData.m_solverBodyList = solverBodyPool;
|
||||||
|
desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList;
|
||||||
|
desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool;
|
||||||
|
desc->m_solverData.m_solverConstraintList = solverConstraintPool;
|
||||||
|
|
||||||
|
desc->m_commandData.m_iterate.m_spinLockVar = spinVar;
|
||||||
|
|
||||||
|
m_taskScheduler.issueTask();
|
||||||
|
}
|
||||||
|
m_taskScheduler.flushTasks();
|
||||||
|
}
|
||||||
|
btAlignedFree((void*)spinVar);
|
||||||
|
|
||||||
|
// Write back velocity
|
||||||
|
{
|
||||||
|
int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK;
|
||||||
|
int bodiesToSchedule = numBodies;
|
||||||
|
int startBody = 0;
|
||||||
|
|
||||||
|
while (bodiesToSchedule > 0)
|
||||||
|
{
|
||||||
|
// Schedule a bunch of hash cells
|
||||||
|
int numBodiesInTask = bodiesToSchedule > bodiesPerTask ? bodiesPerTask : bodiesToSchedule;
|
||||||
|
|
||||||
|
SpuSolverTaskDesc* desc = m_taskScheduler.getTask();
|
||||||
|
|
||||||
|
desc->m_solverCommand = CMD_SOLVER_COPYBACK_BODIES;
|
||||||
|
desc->m_solverData.m_solverHash = m_solverHash;
|
||||||
|
desc->m_solverData.m_solverBodyList = solverBodyPool;
|
||||||
|
|
||||||
|
desc->m_commandData.m_bodyCopyback.m_startBody = startBody;
|
||||||
|
desc->m_commandData.m_bodyCopyback.m_numBodies = numBodiesInTask;
|
||||||
|
desc->m_commandData.m_bodyCopyback.m_rbList = &m_allObjects[0];
|
||||||
|
|
||||||
|
m_taskScheduler.issueTask();
|
||||||
|
bodiesToSchedule -= numBodiesInTask;
|
||||||
|
startBody += numBodiesInTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_taskScheduler.flushTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
m_sortedManifolds.resize(0);
|
||||||
|
m_sortedConstraints.resize(0);
|
||||||
|
m_allObjects.resize(0);
|
||||||
|
clearHash(m_solverHash);
|
||||||
|
|
||||||
|
|
||||||
|
m_numberOfContacts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btParallelSequentialImpulseSolver::reset()
|
||||||
|
{
|
||||||
|
m_sortedManifolds.clear();
|
||||||
|
m_allObjects.clear();
|
||||||
|
m_numberOfContacts = 0;
|
||||||
|
clearHash(m_solverHash);
|
||||||
|
|
||||||
|
solverBodyPool_persist.clear();
|
||||||
|
solverBodyOffsetList_persist.clear();
|
||||||
|
solverConstraintPool_persist.clear();
|
||||||
|
solverInternalConstraintPool_persist.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SolverTaskScheduler::SolverTaskScheduler(btThreadSupportInterface* threadIf, int maxOutstandingTasks)
|
||||||
|
: m_threadInterface (threadIf), m_maxNumOutstandingTasks (maxOutstandingTasks > SPU_MAX_SPUS ? SPU_MAX_SPUS : maxOutstandingTasks),
|
||||||
|
m_currentTask (0), m_numBusyTasks (0)
|
||||||
|
{
|
||||||
|
m_taskDescriptors.resize(m_maxNumOutstandingTasks);
|
||||||
|
m_taskBusy.resize(m_maxNumOutstandingTasks);
|
||||||
|
|
||||||
|
m_threadInterface->startSPU();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SolverTaskScheduler::~SolverTaskScheduler()
|
||||||
|
{
|
||||||
|
m_threadInterface->stopSPU();
|
||||||
|
}
|
||||||
|
|
||||||
|
SpuSolverTaskDesc* SolverTaskScheduler::getTask()
|
||||||
|
{
|
||||||
|
int taskIdx = -1;
|
||||||
|
|
||||||
|
if (m_taskBusy[m_currentTask])
|
||||||
|
{
|
||||||
|
//try to find a new one
|
||||||
|
for (unsigned int i = 0; i < m_maxNumOutstandingTasks; ++i)
|
||||||
|
{
|
||||||
|
if (!m_taskBusy[i])
|
||||||
|
{
|
||||||
|
taskIdx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskIdx < 0)
|
||||||
|
{
|
||||||
|
// Have to wait
|
||||||
|
unsigned int taskId;
|
||||||
|
unsigned int outputSize;
|
||||||
|
|
||||||
|
m_threadInterface->waitForResponse(&taskId, &outputSize);
|
||||||
|
|
||||||
|
m_taskBusy[taskId] = false;
|
||||||
|
m_numBusyTasks--;
|
||||||
|
|
||||||
|
taskIdx = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentTask = taskIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SpuSolverTaskDesc* result = &m_taskDescriptors[m_currentTask];
|
||||||
|
memset(result, 0, sizeof(SpuSolverTaskDesc));
|
||||||
|
result->m_taskId = m_currentTask;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SolverTaskScheduler::issueTask()
|
||||||
|
{
|
||||||
|
m_taskBusy[m_currentTask] = true;
|
||||||
|
m_numBusyTasks++;
|
||||||
|
|
||||||
|
SpuSolverTaskDesc& desc = m_taskDescriptors[m_currentTask];
|
||||||
|
|
||||||
|
m_threadInterface->sendRequest(1, (uint32_t)&desc, m_currentTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SolverTaskScheduler::flushTasks()
|
||||||
|
{
|
||||||
|
while (m_numBusyTasks > 0)
|
||||||
|
{
|
||||||
|
unsigned int taskId;
|
||||||
|
unsigned int outputSize;
|
||||||
|
|
||||||
|
m_threadInterface->waitForResponse(&taskId, &outputSize);
|
||||||
|
|
||||||
|
m_taskBusy[taskId] = false;
|
||||||
|
m_numBusyTasks--;
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Extras/BulletMultiThreaded/SpuParallelSolver.h
Normal file
75
Extras/BulletMultiThreaded/SpuParallelSolver.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library - Parallel solver
|
||||||
|
Copyright (c) 2007 Starbreeze Studios
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Written by: Marten Svanfeldt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPU_PARALLELSOLVER_H
|
||||||
|
#define SPU_PARALLELSOLVER_H
|
||||||
|
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
|
||||||
|
#include "btThreadSupportInterface.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
class SolverTaskScheduler
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
class btThreadSupportInterface* m_threadInterface;
|
||||||
|
unsigned int m_maxNumOutstandingTasks;
|
||||||
|
|
||||||
|
unsigned int m_currentTask;
|
||||||
|
unsigned int m_numBusyTasks;
|
||||||
|
|
||||||
|
btAlignedObjectArray<struct SpuSolverTaskDesc> m_taskDescriptors;
|
||||||
|
btAlignedObjectArray<bool> m_taskBusy;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SolverTaskScheduler (btThreadSupportInterface* threadIf, int maxOutstandingTasks);
|
||||||
|
~SolverTaskScheduler ();
|
||||||
|
|
||||||
|
struct SpuSolverTaskDesc* getTask ();
|
||||||
|
|
||||||
|
void issueTask();
|
||||||
|
void flushTasks();
|
||||||
|
|
||||||
|
unsigned int getMaxOutstandingTasks()
|
||||||
|
{
|
||||||
|
return m_maxNumOutstandingTasks;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class btParallelSequentialImpulseSolver : public btConstraintSolver
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
struct SpuSolverHash* m_solverHash;
|
||||||
|
btAlignedObjectArray<struct ManifoldCellHolder> m_sortedManifolds;
|
||||||
|
btAlignedObjectArray<struct ConstraintCellHolder> m_sortedConstraints;
|
||||||
|
btAlignedObjectArray<class btRigidBody*> m_allObjects;
|
||||||
|
|
||||||
|
int m_numberOfContacts;
|
||||||
|
|
||||||
|
SolverTaskScheduler m_taskScheduler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
btParallelSequentialImpulseSolver (btThreadSupportInterface* threadIf, int maxOutstandingTasks);
|
||||||
|
virtual ~btParallelSequentialImpulseSolver();
|
||||||
|
|
||||||
|
virtual void prepareSolve (int numBodies, int numManifolds);
|
||||||
|
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc);
|
||||||
|
virtual void allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc);
|
||||||
|
virtual void reset ();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
112
Extras/BulletMultiThreaded/SpuSync.h
Normal file
112
Extras/BulletMultiThreaded/SpuSync.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2007 Starbreeze Studios
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Written by: Marten Svanfeldt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPU_SYNC_H
|
||||||
|
#define SPU_SYNC_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "PlatformDefinitions.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#ifdef _XBOX
|
||||||
|
#include <Xtl.h>
|
||||||
|
#else
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class btSpinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//typedef volatile LONG SpinVariable;
|
||||||
|
typedef CRITICAL_SECTION SpinVariable;
|
||||||
|
|
||||||
|
btSpinlock (SpinVariable* var)
|
||||||
|
: spinVariable (var)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Init ()
|
||||||
|
{
|
||||||
|
//*spinVariable = 0;
|
||||||
|
InitializeCriticalSection(spinVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lock ()
|
||||||
|
{
|
||||||
|
EnterCriticalSection(spinVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unlock ()
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(spinVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpinVariable* spinVariable;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined (__CELLOS_LV2__)
|
||||||
|
|
||||||
|
//#include <cell/atomic.h>
|
||||||
|
#include <cell/sync/mutex.h>
|
||||||
|
|
||||||
|
class btSpinlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef CellSyncMutex SpinVariable;
|
||||||
|
|
||||||
|
btSpinlock (SpinVariable* var)
|
||||||
|
: spinVariable (var)
|
||||||
|
{}
|
||||||
|
#ifndef SPU
|
||||||
|
void Init ()
|
||||||
|
{
|
||||||
|
//*spinVariable = 1;
|
||||||
|
cellSyncMutexInitialize(spinVariable);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SPU
|
||||||
|
void Lock ()
|
||||||
|
{
|
||||||
|
// lock semaphore
|
||||||
|
/*while (cellAtomicTestAndDecr32(atomic_buf, (uint64_t)spinVariable) == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
};*/
|
||||||
|
cellSyncMutexLock((uint64_t)spinVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unlock ()
|
||||||
|
{
|
||||||
|
//cellAtomicIncr32(atomic_buf, (uint64_t)spinVariable);
|
||||||
|
cellSyncMutexUnlock((uint64_t)spinVariable);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpinVariable* spinVariable;
|
||||||
|
uint32_t atomic_buf[32] __attribute__((aligned(128)));
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -23,13 +23,14 @@ Written by: Marcus Hennix
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
btConeTwistConstraint::btConeTwistConstraint()
|
btConeTwistConstraint::btConeTwistConstraint()
|
||||||
|
:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,
|
btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,
|
||||||
const btTransform& rbAFrame,const btTransform& rbBFrame)
|
const btTransform& rbAFrame,const btTransform& rbBFrame)
|
||||||
:btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
|
:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
|
||||||
m_angularOnly(false)
|
m_angularOnly(false)
|
||||||
{
|
{
|
||||||
// flip axis for correct angles
|
// flip axis for correct angles
|
||||||
@@ -49,7 +50,7 @@ btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame)
|
btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame)
|
||||||
:btTypedConstraint(rbA),m_rbAFrame(rbAFrame),
|
:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame),
|
||||||
m_angularOnly(false)
|
m_angularOnly(false)
|
||||||
{
|
{
|
||||||
m_rbBFrame = m_rbAFrame;
|
m_rbBFrame = m_rbAFrame;
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ class btRigidBody;
|
|||||||
///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
|
///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
|
||||||
class btConeTwistConstraint : public btTypedConstraint
|
class btConeTwistConstraint : public btTypedConstraint
|
||||||
{
|
{
|
||||||
|
#ifdef IN_PARALLELL_SOLVER
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
|
btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
|
||||||
|
|
||||||
btTransform m_rbAFrame;
|
btTransform m_rbAFrame;
|
||||||
|
|||||||
@@ -35,12 +35,15 @@ public:
|
|||||||
|
|
||||||
virtual ~btConstraintSolver() {}
|
virtual ~btConstraintSolver() {}
|
||||||
|
|
||||||
|
virtual void prepareSolve (int numBodies, int numManifolds) {;}
|
||||||
|
|
||||||
///solve a group of constraints
|
///solve a group of constraints
|
||||||
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0;
|
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0;
|
||||||
|
|
||||||
|
virtual void allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) {;}
|
||||||
|
|
||||||
///clear internal cached data and reset random seed
|
///clear internal cached data and reset random seed
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,21 @@ subject to the following restrictions:
|
|||||||
#ifndef CONTACT_SOLVER_INFO
|
#ifndef CONTACT_SOLVER_INFO
|
||||||
#define CONTACT_SOLVER_INFO
|
#define CONTACT_SOLVER_INFO
|
||||||
|
|
||||||
|
struct btContactSolverInfoData
|
||||||
|
{
|
||||||
|
btScalar m_tau;
|
||||||
|
btScalar m_damping;
|
||||||
|
btScalar m_friction;
|
||||||
|
btScalar m_timeStep;
|
||||||
|
btScalar m_restitution;
|
||||||
|
int m_numIterations;
|
||||||
|
btScalar m_maxErrorReduction;
|
||||||
|
btScalar m_sor;
|
||||||
|
btScalar m_erp;
|
||||||
|
|
||||||
struct btContactSolverInfo
|
};
|
||||||
|
|
||||||
|
struct btContactSolverInfo : public btContactSolverInfoData
|
||||||
{
|
{
|
||||||
|
|
||||||
inline btContactSolverInfo()
|
inline btContactSolverInfo()
|
||||||
@@ -32,15 +45,6 @@ struct btContactSolverInfo
|
|||||||
m_sor = btScalar(1.3);
|
m_sor = btScalar(1.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
btScalar m_tau;
|
|
||||||
btScalar m_damping;
|
|
||||||
btScalar m_friction;
|
|
||||||
btScalar m_timeStep;
|
|
||||||
btScalar m_restitution;
|
|
||||||
int m_numIterations;
|
|
||||||
btScalar m_maxErrorReduction;
|
|
||||||
btScalar m_sor;
|
|
||||||
btScalar m_erp;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,12 @@ static const int kAxisB[] = { 2, 2, 1 };
|
|||||||
#define GENERIC_D6_DISABLE_WARMSTARTING 1
|
#define GENERIC_D6_DISABLE_WARMSTARTING 1
|
||||||
|
|
||||||
btGeneric6DofConstraint::btGeneric6DofConstraint()
|
btGeneric6DofConstraint::btGeneric6DofConstraint()
|
||||||
|
:btTypedConstraint(D6_CONSTRAINT_TYPE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
|
btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
|
||||||
: btTypedConstraint(rbA, rbB)
|
: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)
|
||||||
, m_frameInA(frameInA)
|
, m_frameInA(frameInA)
|
||||||
, m_frameInB(frameInB)
|
, m_frameInB(frameInB)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ subject to the following restrictions:
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
btHingeConstraint::btHingeConstraint():
|
btHingeConstraint::btHingeConstraint()
|
||||||
|
: btTypedConstraint (HINGE_CONSTRAINT_TYPE),
|
||||||
m_enableAngularMotor(false)
|
m_enableAngularMotor(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
|
btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
|
||||||
btVector3& axisInA,btVector3& axisInB)
|
btVector3& axisInA,btVector3& axisInB)
|
||||||
:btTypedConstraint(rbA,rbB),
|
:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),
|
||||||
m_angularOnly(false),
|
m_angularOnly(false),
|
||||||
m_enableAngularMotor(false)
|
m_enableAngularMotor(false)
|
||||||
{
|
{
|
||||||
@@ -70,7 +71,7 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const bt
|
|||||||
|
|
||||||
|
|
||||||
btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA)
|
btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA)
|
||||||
:btTypedConstraint(rbA), m_angularOnly(false), m_enableAngularMotor(false)
|
:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
// since no frame is given, assume this to be zero angle and just pick rb transform axis
|
// since no frame is given, assume this to be zero angle and just pick rb transform axis
|
||||||
@@ -113,7 +114,7 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,
|
|||||||
|
|
||||||
btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB,
|
btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB,
|
||||||
const btTransform& rbAFrame, const btTransform& rbBFrame)
|
const btTransform& rbAFrame, const btTransform& rbBFrame)
|
||||||
:btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
|
:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
|
||||||
m_angularOnly(false),
|
m_angularOnly(false),
|
||||||
m_enableAngularMotor(false)
|
m_enableAngularMotor(false)
|
||||||
{
|
{
|
||||||
@@ -134,7 +135,7 @@ m_enableAngularMotor(false)
|
|||||||
|
|
||||||
|
|
||||||
btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
|
btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
|
||||||
:btTypedConstraint(rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
|
:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
|
||||||
m_angularOnly(false),
|
m_angularOnly(false),
|
||||||
m_enableAngularMotor(false)
|
m_enableAngularMotor(false)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ class btRigidBody;
|
|||||||
/// axis defines the orientation of the hinge axis
|
/// axis defines the orientation of the hinge axis
|
||||||
class btHingeConstraint : public btTypedConstraint
|
class btHingeConstraint : public btTypedConstraint
|
||||||
{
|
{
|
||||||
|
#ifdef IN_PARALLELL_SOLVER
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
|
btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
|
||||||
btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
|
btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
|
||||||
|
|
||||||
|
|||||||
@@ -21,18 +21,19 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
|
|
||||||
btPoint2PointConstraint::btPoint2PointConstraint()
|
btPoint2PointConstraint::btPoint2PointConstraint()
|
||||||
|
:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB)
|
btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB)
|
||||||
:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB)
|
:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA)
|
btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA)
|
||||||
:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA))
|
:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ struct btConstraintSetting
|
|||||||
/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
|
/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
|
||||||
class btPoint2PointConstraint : public btTypedConstraint
|
class btPoint2PointConstraint : public btTypedConstraint
|
||||||
{
|
{
|
||||||
|
#ifdef IN_PARALLELL_SOLVER
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
|
btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
|
||||||
|
|
||||||
btVector3 m_pivotInA;
|
btVector3 m_pivotInA;
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef BT_PREFER_SIMD
|
||||||
|
typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
|
#endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
static btRigidBody s_fixed(0, 0,0);
|
static btRigidBody s_fixed(0, 0,0);
|
||||||
|
|
||||||
btTypedConstraint::btTypedConstraint()
|
btTypedConstraint::btTypedConstraint(btTypedConstraintType type)
|
||||||
: m_userConstraintType(-1),
|
: m_constraintType (type),
|
||||||
|
m_userConstraintType(-1),
|
||||||
m_userConstraintId(-1),
|
m_userConstraintId(-1),
|
||||||
m_rbA(s_fixed),
|
m_rbA(s_fixed),
|
||||||
m_rbB(s_fixed),
|
m_rbB(s_fixed),
|
||||||
@@ -28,8 +29,9 @@ m_appliedImpulse(btScalar(0.))
|
|||||||
{
|
{
|
||||||
s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
|
s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
|
||||||
}
|
}
|
||||||
btTypedConstraint::btTypedConstraint(btRigidBody& rbA)
|
btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
|
||||||
: m_userConstraintType(-1),
|
: m_constraintType (type),
|
||||||
|
m_userConstraintType(-1),
|
||||||
m_userConstraintId(-1),
|
m_userConstraintId(-1),
|
||||||
m_rbA(rbA),
|
m_rbA(rbA),
|
||||||
m_rbB(s_fixed),
|
m_rbB(s_fixed),
|
||||||
@@ -40,8 +42,9 @@ m_appliedImpulse(btScalar(0.))
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btTypedConstraint::btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB)
|
btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB)
|
||||||
: m_userConstraintType(-1),
|
: m_constraintType (type),
|
||||||
|
m_userConstraintType(-1),
|
||||||
m_userConstraintId(-1),
|
m_userConstraintId(-1),
|
||||||
m_rbA(rbA),
|
m_rbA(rbA),
|
||||||
m_rbB(rbB),
|
m_rbB(rbB),
|
||||||
|
|||||||
@@ -19,12 +19,23 @@ subject to the following restrictions:
|
|||||||
class btRigidBody;
|
class btRigidBody;
|
||||||
#include "LinearMath/btScalar.h"
|
#include "LinearMath/btScalar.h"
|
||||||
|
|
||||||
|
enum btTypedConstraintType
|
||||||
|
{
|
||||||
|
POINT2POINT_CONSTRAINT_TYPE,
|
||||||
|
HINGE_CONSTRAINT_TYPE,
|
||||||
|
CONETWIST_CONSTRAINT_TYPE,
|
||||||
|
D6_CONSTRAINT_TYPE,
|
||||||
|
VEHICLE_CONSTRAINT_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
///TypedConstraint is the baseclass for Bullet constraints and vehicles
|
///TypedConstraint is the baseclass for Bullet constraints and vehicles
|
||||||
class btTypedConstraint
|
class btTypedConstraint
|
||||||
{
|
{
|
||||||
int m_userConstraintType;
|
int m_userConstraintType;
|
||||||
int m_userConstraintId;
|
int m_userConstraintId;
|
||||||
|
|
||||||
|
btTypedConstraintType m_constraintType;
|
||||||
|
|
||||||
btTypedConstraint& operator=(btTypedConstraint& other)
|
btTypedConstraint& operator=(btTypedConstraint& other)
|
||||||
{
|
{
|
||||||
btAssert(0);
|
btAssert(0);
|
||||||
@@ -40,11 +51,11 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
btTypedConstraint();
|
btTypedConstraint(btTypedConstraintType type);
|
||||||
virtual ~btTypedConstraint() {};
|
virtual ~btTypedConstraint() {};
|
||||||
btTypedConstraint(btRigidBody& rbA);
|
btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA);
|
||||||
|
|
||||||
btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB);
|
btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB);
|
||||||
|
|
||||||
virtual void buildJacobian() = 0;
|
virtual void buildJacobian() = 0;
|
||||||
|
|
||||||
@@ -83,14 +94,19 @@ public:
|
|||||||
m_userConstraintId = uid;
|
m_userConstraintId = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getUserConstraintId()
|
int getUserConstraintId() const
|
||||||
{
|
{
|
||||||
return m_userConstraintId;
|
return m_userConstraintId;
|
||||||
}
|
}
|
||||||
btScalar getAppliedImpulse()
|
btScalar getAppliedImpulse() const
|
||||||
{
|
{
|
||||||
return m_appliedImpulse;
|
return m_appliedImpulse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btTypedConstraintType getConstraintType () const
|
||||||
|
{
|
||||||
|
return m_constraintType;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //TYPED_CONSTRAINT_H
|
#endif //TYPED_CONSTRAINT_H
|
||||||
|
|||||||
@@ -526,12 +526,12 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
|||||||
|
|
||||||
InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc);
|
InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc);
|
||||||
|
|
||||||
|
m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
|
||||||
|
|
||||||
/// solve all the constraints for this island
|
/// solve all the constraints for this island
|
||||||
m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback);
|
m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback);
|
||||||
|
|
||||||
|
m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,8 +74,9 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b
|
|||||||
|
|
||||||
btContactSolverInfo infoGlobal;
|
btContactSolverInfo infoGlobal;
|
||||||
infoGlobal.m_timeStep = timeStep;
|
infoGlobal.m_timeStep = timeStep;
|
||||||
|
m_constraintSolver->prepareSolve(0,numManifolds);
|
||||||
m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc);
|
m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc);
|
||||||
|
m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
///integrate transforms
|
///integrate transforms
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
static btRigidBody s_fixedObject( 0,0,0);
|
static btRigidBody s_fixedObject( 0,0,0);
|
||||||
|
|
||||||
btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
|
btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
|
||||||
:m_vehicleRaycaster(raycaster),
|
: btTypedConstraint(VEHICLE_CONSTRAINT_TYPE),
|
||||||
|
m_vehicleRaycaster(raycaster),
|
||||||
m_pitchControl(btScalar(0.))
|
m_pitchControl(btScalar(0.))
|
||||||
{
|
{
|
||||||
m_chassisBody = chassis;
|
m_chassisBody = chassis;
|
||||||
|
|||||||
@@ -19,16 +19,19 @@ subject to the following restrictions:
|
|||||||
#include "btScalar.h"
|
#include "btScalar.h"
|
||||||
#include "btSimdMinMax.h"
|
#include "btSimdMinMax.h"
|
||||||
|
|
||||||
|
class btQuadWordStorage
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
btScalar m_x;
|
||||||
|
btScalar m_y;
|
||||||
|
btScalar m_z;
|
||||||
|
btScalar m_unusedW;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
///btQuadWord is base-class for vectors, points
|
///btQuadWord is base-class for vectors, points
|
||||||
class btQuadWord
|
class btQuadWord : public btQuadWordStorage
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
btScalar m_x;
|
|
||||||
btScalar m_y;
|
|
||||||
btScalar m_z;
|
|
||||||
btScalar m_unusedW;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; }
|
// SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; }
|
||||||
@@ -88,16 +91,19 @@ class btQuadWord
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z)
|
SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q)
|
||||||
:m_x(x),m_y(y),m_z(z)
|
|
||||||
//todo, remove this in release/simd ?
|
|
||||||
,m_unusedW(btScalar(0.))
|
|
||||||
{
|
{
|
||||||
|
*((btQuadWordStorage*)this) = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z)
|
||||||
|
{
|
||||||
|
m_x = x, m_y = y, m_z = z, m_unusedW = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
|
SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
|
||||||
:m_x(x),m_y(y),m_z(z),m_unusedW(w)
|
|
||||||
{
|
{
|
||||||
|
m_x = x, m_y = y, m_z = z, m_unusedW = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE btVector3
|
SIMD_FORCE_INLINE btVector3
|
||||||
quatRotate(btQuaternion& rotation, btVector3& v)
|
quatRotate(const btQuaternion& rotation, const btVector3& v)
|
||||||
{
|
{
|
||||||
btQuaternion q = rotation * v;
|
btQuaternion q = rotation * v;
|
||||||
q *= rotation.inverse();
|
q *= rotation.inverse();
|
||||||
@@ -293,7 +293,7 @@ quatRotate(btQuaternion& rotation, btVector3& v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE btQuaternion
|
SIMD_FORCE_INLINE btQuaternion
|
||||||
shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
|
shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
|
||||||
{
|
{
|
||||||
btVector3 c = v0.cross(v1);
|
btVector3 c = v0.cross(v1);
|
||||||
btScalar d = v0.dot(v1);
|
btScalar d = v0.dot(v1);
|
||||||
@@ -308,7 +308,7 @@ shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make
|
|||||||
}
|
}
|
||||||
|
|
||||||
SIMD_FORCE_INLINE btQuaternion
|
SIMD_FORCE_INLINE btQuaternion
|
||||||
shortestArcQuatNormalize(btVector3& v0,btVector3& v1)
|
shortestArcQuatNormalize(btVector3 v0,btVector3 v1)
|
||||||
{
|
{
|
||||||
v0.normalize();
|
v0.normalize();
|
||||||
v1.normalize();
|
v1.normalize();
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ class btVector3 : public btQuadWord {
|
|||||||
public:
|
public:
|
||||||
SIMD_FORCE_INLINE btVector3() {}
|
SIMD_FORCE_INLINE btVector3() {}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q)
|
||||||
|
: btQuadWord(q)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
|
SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
|
||||||
|
|||||||
Reference in New Issue
Block a user