Iterate over the islands to solve the contacts and joints

This commit is contained in:
Daniel Chappuis 2013-08-31 19:03:21 +02:00
parent f1d29b5123
commit 475ec5be5f
7 changed files with 250 additions and 274 deletions

View File

@ -70,6 +70,7 @@ void RigidBody::removeJointFromJointsList(MemoryAllocator& memoryAllocator, cons
memoryAllocator.release(elementToRemove, sizeof(JointListElement)); memoryAllocator.release(elementToRemove, sizeof(JointListElement));
break; break;
} }
currentElement = currentElement->next;
} }
} }
} }

View File

@ -30,18 +30,14 @@
using namespace reactphysics3d; using namespace reactphysics3d;
// Constructor // Constructor
ConstraintSolver::ConstraintSolver(std::set<Constraint*>& joints, ConstraintSolver::ConstraintSolver(std::vector<Vector3>& positions,
std::vector<Vector3>& linearVelocities,
std::vector<Vector3>& angularVelocities,
std::vector<Vector3>& positions,
std::vector<Quaternion>& orientations, std::vector<Quaternion>& orientations,
const std::map<RigidBody*, uint>& mapBodyToVelocityIndex) const std::map<RigidBody*, uint>& mapBodyToVelocityIndex)
: mJoints(joints), mLinearVelocities(linearVelocities), : mLinearVelocities(NULL), mAngularVelocities(NULL), mPositions(positions),
mAngularVelocities(angularVelocities), mPositions(positions),
mOrientations(orientations), mOrientations(orientations),
mMapBodyToConstrainedVelocityIndex(mapBodyToVelocityIndex), mMapBodyToConstrainedVelocityIndex(mapBodyToVelocityIndex),
mIsWarmStartingActive(true), mConstraintSolverData(linearVelocities, mIsWarmStartingActive(true), mConstraintSolverData(positions, orientations,
angularVelocities, positions, orientations, mapBodyToVelocityIndex){ mapBodyToVelocityIndex){
} }
@ -50,10 +46,16 @@ ConstraintSolver::~ConstraintSolver() {
} }
// Initialize the constraint solver // Initialize the constraint solver for a given island
void ConstraintSolver::initialize(decimal dt) { void ConstraintSolver::initializeForIsland(decimal dt, Island* island) {
PROFILE("ConstraintSolver::initialize()"); PROFILE("ConstraintSolver::initializeForIsland()");
assert(mLinearVelocities != NULL);
assert(mAngularVelocities != NULL);
assert(island != NULL);
assert(island->getNbBodies() > 0);
assert(island->getNbJoints() > 0);
// Set the current time step // Set the current time step
mTimeStep = dt; mTimeStep = dt;
@ -62,54 +64,50 @@ void ConstraintSolver::initialize(decimal dt) {
mConstraintSolverData.timeStep = mTimeStep; mConstraintSolverData.timeStep = mTimeStep;
mConstraintSolverData.isWarmStartingActive = mIsWarmStartingActive; mConstraintSolverData.isWarmStartingActive = mIsWarmStartingActive;
// For each joint // For each joint of the island
std::set<Constraint*>::iterator it; Constraint** joints = island->getJoints();
for (it = mJoints.begin(); it != mJoints.end(); ++it) { for (uint i=0; i<island->getNbJoints(); i++) {
Constraint* joint = (*it);
// Get the rigid bodies of the joint
RigidBody* body1 = joint->getBody1();
RigidBody* body2 = joint->getBody2();
// Add the bodies to the set of constrained bodies
mConstraintBodies.insert(body1);
mConstraintBodies.insert(body2);
// Initialize the constraint before solving it // Initialize the constraint before solving it
joint->initBeforeSolve(mConstraintSolverData); joints[i]->initBeforeSolve(mConstraintSolverData);
// Warm-start the constraint if warm-starting is enabled // Warm-start the constraint if warm-starting is enabled
if (mIsWarmStartingActive) { if (mIsWarmStartingActive) {
joint->warmstart(mConstraintSolverData); joints[i]->warmstart(mConstraintSolverData);
} }
} }
} }
// Solve the velocity constraints // Solve the velocity constraints
void ConstraintSolver::solveVelocityConstraints() { void ConstraintSolver::solveVelocityConstraints(Island* island) {
PROFILE("ConstraintSolver::solveVelocityConstraints()"); PROFILE("ConstraintSolver::solveVelocityConstraints()");
// For each joint assert(island != NULL);
std::set<Constraint*>::iterator it; assert(island->getNbJoints() > 0);
for (it = mJoints.begin(); it != mJoints.end(); ++it) {
// For each joint of the island
Constraint** joints = island->getJoints();
for (uint i=0; i<island->getNbJoints(); i++) {
// Solve the constraint // Solve the constraint
(*it)->solveVelocityConstraint(mConstraintSolverData); joints[i]->solveVelocityConstraint(mConstraintSolverData);
} }
} }
// Solve the position constraints // Solve the position constraints
void ConstraintSolver::solvePositionConstraints() { void ConstraintSolver::solvePositionConstraints(Island* island) {
PROFILE("ConstraintSolver::solvePositionConstraints()"); PROFILE("ConstraintSolver::solvePositionConstraints()");
// For each joint assert(island != NULL);
std::set<Constraint*>::iterator it; assert(island->getNbJoints() > 0);
for (it = mJoints.begin(); it != mJoints.end(); ++it) {
// For each joint of the island
Constraint** joints = island->getJoints();
for (uint i=0; i < island->getNbJoints(); i++) {
// Solve the constraint // Solve the constraint
(*it)->solvePositionConstraint(mConstraintSolverData); joints[i]->solvePositionConstraint(mConstraintSolverData);
} }
} }

View File

@ -30,6 +30,7 @@
#include "../configuration.h" #include "../configuration.h"
#include "mathematics/mathematics.h" #include "mathematics/mathematics.h"
#include "../constraint/Constraint.h" #include "../constraint/Constraint.h"
#include "Island.h"
#include <map> #include <map>
#include <set> #include <set>
@ -47,11 +48,11 @@ struct ConstraintSolverData {
/// Current time step of the simulation /// Current time step of the simulation
decimal timeStep; decimal timeStep;
/// Reference to the bodies linear velocities /// Array with the bodies linear velocities
std::vector<Vector3>& linearVelocities; Vector3* linearVelocities;
/// Reference to the bodies angular velocities /// Array with the bodies angular velocities
std::vector<Vector3>& angularVelocities; Vector3* angularVelocities;
/// Reference to the bodies positions /// Reference to the bodies positions
std::vector<Vector3>& positions; std::vector<Vector3>& positions;
@ -67,13 +68,11 @@ struct ConstraintSolverData {
bool isWarmStartingActive; bool isWarmStartingActive;
/// Constructor /// Constructor
ConstraintSolverData(std::vector<Vector3>& refLinearVelocities, ConstraintSolverData(std::vector<Vector3>& refPositions,
std::vector<Vector3>& refAngularVelocities,
std::vector<Vector3>& refPositions,
std::vector<Quaternion>& refOrientations, std::vector<Quaternion>& refOrientations,
const std::map<RigidBody*, uint>& refMapBodyToConstrainedVelocityIndex) const std::map<RigidBody*, uint>& refMapBodyToConstrainedVelocityIndex)
:linearVelocities(refLinearVelocities), :linearVelocities(NULL),
angularVelocities(refAngularVelocities), angularVelocities(NULL),
positions(refPositions), orientations(refOrientations), positions(refPositions), orientations(refOrientations),
mapBodyToConstrainedVelocityIndex(refMapBodyToConstrainedVelocityIndex){ mapBodyToConstrainedVelocityIndex(refMapBodyToConstrainedVelocityIndex){
@ -156,19 +155,13 @@ class ConstraintSolver {
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
/// Reference to all the joints of the world /// Array of constrained linear velocities (state of the linear velocities
std::set<Constraint*>& mJoints;
/// Constrained bodies
std::set<RigidBody*> mConstraintBodies;
/// Reference to the array of constrained linear velocities (state of the linear velocities
/// after solving the constraints) /// after solving the constraints)
std::vector<Vector3>& mLinearVelocities; Vector3* mLinearVelocities;
/// Reference to the array of constrained angular velocities (state of the angular velocities /// Array of constrained angular velocities (state of the angular velocities
/// after solving the constraints) /// after solving the constraints)
std::vector<Vector3>& mAngularVelocities; Vector3* mAngularVelocities;
/// Reference to the array of bodies positions (for position error correction) /// Reference to the array of bodies positions (for position error correction)
std::vector<Vector3>& mPositions; std::vector<Vector3>& mPositions;
@ -194,24 +187,20 @@ class ConstraintSolver {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Constructor /// Constructor
ConstraintSolver(std::set<Constraint*>& joints, ConstraintSolver(std::vector<Vector3>& positions, std::vector<Quaternion>& orientations,
std::vector<Vector3>& linearVelocities,
std::vector<Vector3>& angularVelocities,
std::vector<Vector3>& positions,
std::vector<Quaternion>& orientations,
const std::map<RigidBody*, uint>& mapBodyToVelocityIndex); const std::map<RigidBody*, uint>& mapBodyToVelocityIndex);
/// Destructor /// Destructor
~ConstraintSolver(); ~ConstraintSolver();
/// Initialize the constraint solver /// Initialize the constraint solver for a given island
void initialize(decimal dt); void initializeForIsland(decimal dt, Island* island);
/// Solve the constraints /// Solve the constraints
void solveVelocityConstraints(); void solveVelocityConstraints(Island* island);
/// Solve the position constraints /// Solve the position constraints
void solvePositionConstraints(); void solvePositionConstraints(Island* island);
/// Return true if the Non-Linear-Gauss-Seidel position correction technique is active /// Return true if the Non-Linear-Gauss-Seidel position correction technique is active
bool getIsNonLinearGaussSeidelPositionCorrectionActive() const; bool getIsNonLinearGaussSeidelPositionCorrectionActive() const;
@ -219,13 +208,20 @@ class ConstraintSolver {
/// Enable/Disable the Non-Linear-Gauss-Seidel position correction technique. /// Enable/Disable the Non-Linear-Gauss-Seidel position correction technique.
void setIsNonLinearGaussSeidelPositionCorrectionActive(bool isActive); void setIsNonLinearGaussSeidelPositionCorrectionActive(bool isActive);
/// Return true if the body is in at least one constraint /// Set the constrained velocities arrays
bool isConstrainedBody(RigidBody* body) const; void setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
Vector3* constrainedAngularVelocities);
}; };
// Return true if the body is in at least one constraint // Set the constrained velocities arrays
inline bool ConstraintSolver::isConstrainedBody(RigidBody* body) const { inline void ConstraintSolver::setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
return mConstraintBodies.count(body) == 1; Vector3* constrainedAngularVelocities) {
assert(constrainedLinearVelocities != NULL);
assert(constrainedAngularVelocities != NULL);
mLinearVelocities = constrainedLinearVelocities;
mAngularVelocities = constrainedAngularVelocities;
mConstraintSolverData.linearVelocities = mLinearVelocities;
mConstraintSolverData.angularVelocities = mAngularVelocities;
} }
} }

View File

@ -36,18 +36,12 @@ using namespace std;
// Constants initialization // Constants initialization
const decimal ContactSolver::BETA = decimal(0.2); const decimal ContactSolver::BETA = decimal(0.2);
const decimal ContactSolver::BETA_SPLIT_IMPULSE = decimal(0.2); const decimal ContactSolver::BETA_SPLIT_IMPULSE = decimal(0.2);
const decimal ContactSolver::SLOP = decimal(0.01); const decimal ContactSolver::SLOP= decimal(0.01);
// Constructor // Constructor
ContactSolver::ContactSolver(std::vector<ContactManifold*>& contactManifolds, ContactSolver::ContactSolver(const std::map<RigidBody*, uint>& mapBodyToVelocityIndex)
std::vector<Vector3>& constrainedLinearVelocities, :mSplitLinearVelocities(NULL), mSplitAngularVelocities(NULL),
std::vector<Vector3>& constrainedAngularVelocities, mContactConstraints(NULL), mLinearVelocities(NULL), mAngularVelocities(NULL),
const std::map<RigidBody*, uint>& mapBodyToVelocityIndex)
:mContactManifolds(contactManifolds),
mSplitLinearVelocities(NULL), mSplitAngularVelocities(NULL),
mContactConstraints(NULL),
mLinearVelocities(constrainedLinearVelocities),
mAngularVelocities(constrainedAngularVelocities),
mMapBodyToConstrainedVelocityIndex(mapBodyToVelocityIndex), mMapBodyToConstrainedVelocityIndex(mapBodyToVelocityIndex),
mIsWarmStartingActive(true), mIsSplitImpulseActive(true), mIsWarmStartingActive(true), mIsSplitImpulseActive(true),
mIsSolveFrictionAtContactManifoldCenterActive(true) { mIsSolveFrictionAtContactManifoldCenterActive(true) {
@ -59,26 +53,32 @@ ContactSolver::~ContactSolver() {
} }
// Initialize the constraint solver // Initialize the constraint solver for a given island
void ContactSolver::initialize(decimal dt) { void ContactSolver::initializeForIsland(decimal dt, Island* island) {
PROFILE("ContactSolver::initialize()"); PROFILE("ContactSolver::initializeForIsland()");
assert(island != NULL);
assert(island->getNbBodies() > 0);
assert(island->getNbContactManifolds() > 0);
assert(mSplitLinearVelocities != NULL);
assert(mSplitAngularVelocities != NULL);
// Set the current time step // Set the current time step
mTimeStep = dt; mTimeStep = dt;
// TODO : Use better memory allocation here mNbContactManifolds = island->getNbContactManifolds();
mContactConstraints = new ContactManifoldSolver[mContactManifolds.size()];
mNbContactManifolds = 0; mContactConstraints = new ContactManifoldSolver[mNbContactManifolds];
assert(mContactConstraints != NULL);
// For each contact manifold of the world // For each contact manifold of the island
vector<ContactManifold*>::iterator it; ContactManifold** contactManifolds = island->getContactManifold();
for (it = mContactManifolds.begin(); it != mContactManifolds.end(); ++it) { for (uint i=0; i<mNbContactManifolds; i++) {
ContactManifold* externalManifold = *it; ContactManifold* externalManifold = contactManifolds[i];
ContactManifoldSolver& internalManifold = mContactConstraints[mNbContactManifolds]; ContactManifoldSolver& internalManifold = mContactConstraints[i];
assert(externalManifold->getNbContactPoints() > 0); assert(externalManifold->getNbContactPoints() > 0);
@ -86,10 +86,6 @@ void ContactSolver::initialize(decimal dt) {
RigidBody* body1 = externalManifold->getContactPoint(0)->getBody1(); RigidBody* body1 = externalManifold->getContactPoint(0)->getBody1();
RigidBody* body2 = externalManifold->getContactPoint(0)->getBody2(); RigidBody* body2 = externalManifold->getContactPoint(0)->getBody2();
// Add the two bodies of the constraint in the constraintBodies list
mConstraintBodies.insert(body1);
mConstraintBodies.insert(body2);
// Get the position of the two bodies // Get the position of the two bodies
Vector3 x1 = body1->getTransform().getPosition(); Vector3 x1 = body1->getTransform().getPosition();
Vector3 x2 = body2->getTransform().getPosition(); Vector3 x2 = body2->getTransform().getPosition();
@ -173,46 +169,12 @@ void ContactSolver::initialize(decimal dt) {
internalManifold.frictionTwistImpulse = 0.0; internalManifold.frictionTwistImpulse = 0.0;
} }
} }
mNbContactManifolds++;
} }
// Allocated memory for split impulse velocities
// TODO : Use better memory allocation here
mSplitLinearVelocities = new Vector3[mMapBodyToConstrainedVelocityIndex.size()];
mSplitAngularVelocities = new Vector3[mMapBodyToConstrainedVelocityIndex.size()];
assert(mSplitLinearVelocities != NULL);
assert(mSplitAngularVelocities != NULL);
assert(mConstraintBodies.size() > 0);
assert(mMapBodyToConstrainedVelocityIndex.size() >= mConstraintBodies.size());
assert(mLinearVelocities.size() >= mConstraintBodies.size());
assert(mAngularVelocities.size() >= mConstraintBodies.size());
// Initialize the split impulse velocities
initializeSplitImpulseVelocities();
// Fill-in all the matrices needed to solve the LCP problem // Fill-in all the matrices needed to solve the LCP problem
initializeContactConstraints(); initializeContactConstraints();
} }
// Initialize the split impulse velocities
void ContactSolver::initializeSplitImpulseVelocities() {
// For each current body that is implied in some constraint
set<RigidBody*>::iterator it;
for (it = mConstraintBodies.begin(); it != mConstraintBodies.end(); ++it) {
RigidBody* rigidBody = *it;
assert(rigidBody);
uint bodyNumber = mMapBodyToConstrainedVelocityIndex.find(rigidBody)->second;
// Initialize the split impulse velocities to zero
mSplitLinearVelocities[bodyNumber] = Vector3(0, 0, 0);
mSplitAngularVelocities[bodyNumber] = Vector3(0, 0, 0);
}
}
// Initialize the contact constraints before solving the system // Initialize the contact constraints before solving the system
void ContactSolver::initializeContactConstraints() { void ContactSolver::initializeContactConstraints() {
@ -884,18 +846,8 @@ void ContactSolver::computeFrictionVectors(const Vector3& deltaVelocity,
// Clean up the constraint solver // Clean up the constraint solver
void ContactSolver::cleanup() { void ContactSolver::cleanup() {
mConstraintBodies.clear();
if (mContactConstraints != NULL) { if (mContactConstraints != NULL) {
delete[] mContactConstraints; delete[] mContactConstraints;
mContactConstraints = NULL; mContactConstraints = NULL;
} }
if (mSplitLinearVelocities != NULL) {
delete[] mSplitLinearVelocities;
mSplitLinearVelocities = NULL;
}
if (mSplitAngularVelocities != NULL) {
delete[] mSplitAngularVelocities;
mSplitAngularVelocities = NULL;
}
} }

View File

@ -31,6 +31,7 @@
#include "../configuration.h" #include "../configuration.h"
#include "../constraint/Constraint.h" #include "../constraint/Constraint.h"
#include "ContactManifold.h" #include "ContactManifold.h"
#include "Island.h"
#include "Impulse.h" #include "Impulse.h"
#include <map> #include <map>
#include <set> #include <set>
@ -311,9 +312,6 @@ class ContactSolver {
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
/// Reference to all the contact manifold of the world
std::vector<ContactManifold*>& mContactManifolds;
/// Split linear velocities for the position contact solver (split impulse) /// Split linear velocities for the position contact solver (split impulse)
Vector3* mSplitLinearVelocities; Vector3* mSplitLinearVelocities;
@ -329,14 +327,11 @@ class ContactSolver {
/// Number of contact constraints /// Number of contact constraints
uint mNbContactManifolds; uint mNbContactManifolds;
/// Constrained bodies /// Array of linear velocities
std::set<RigidBody*> mConstraintBodies; Vector3* mLinearVelocities;
/// Reference to the array of linear velocities /// Array of angular velocities
std::vector<Vector3>& mLinearVelocities; Vector3* mAngularVelocities;
/// Reference to the array of angular velocities
std::vector<Vector3>& mAngularVelocities;
/// Reference to the map of rigid body to their index in the constrained velocities array /// Reference to the map of rigid body to their index in the constrained velocities array
const std::map<RigidBody*, uint>& mMapBodyToConstrainedVelocityIndex; const std::map<RigidBody*, uint>& mMapBodyToConstrainedVelocityIndex;
@ -353,9 +348,6 @@ class ContactSolver {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Initialize the split impulse velocities
void initializeSplitImpulseVelocities();
/// Initialize the contact constraints before solving the system /// Initialize the contact constraints before solving the system
void initializeContactConstraints(); void initializeContactConstraints();
@ -403,16 +395,21 @@ class ContactSolver {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Constructor /// Constructor
ContactSolver(std::vector<ContactManifold*>& contactManifolds, ContactSolver(const std::map<RigidBody*, uint>& mapBodyToVelocityIndex);
std::vector<Vector3>& constrainedLinearVelocities,
std::vector<Vector3>& constrainedAngularVelocities,
const std::map<RigidBody*, uint>& mapBodyToVelocityIndex);
/// Destructor /// Destructor
virtual ~ContactSolver(); virtual ~ContactSolver();
/// Initialize the constraint solver /// Initialize the constraint solver for a given island
void initialize(decimal dt); void initializeForIsland(decimal dt, Island* island);
/// Set the split velocities arrays
void setSplitVelocitiesArrays(Vector3* splitLinearVelocities,
Vector3* splitAngularVelocities);
/// Set the constrained velocities arrays
void setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
Vector3* constrainedAngularVelocities);
/// Warm start the solver. /// Warm start the solver.
void warmStart(); void warmStart();
@ -424,24 +421,6 @@ class ContactSolver {
/// Solve the contacts /// Solve the contacts
void solve(); void solve();
/// Return true if the body is in at least one constraint
bool isConstrainedBody(RigidBody* body) const;
/// Return the constrained linear velocity of a body after solving the constraints
Vector3 getConstrainedLinearVelocityOfBody(RigidBody *body);
/// Return the split linear velocity
Vector3 getSplitLinearVelocityOfBody(RigidBody* body);
/// Return the constrained angular velocity of a body after solving the constraints
Vector3 getConstrainedAngularVelocityOfBody(RigidBody* body);
/// Return the split angular velocity
Vector3 getSplitAngularVelocityOfBody(RigidBody* body);
/// Clean up the constraint solver
void cleanup();
/// Return true if the split impulses position correction technique is used for contacts /// Return true if the split impulses position correction technique is used for contacts
bool isSplitImpulseActive() const; bool isSplitImpulseActive() const;
@ -451,25 +430,27 @@ class ContactSolver {
/// Activate or deactivate the solving of friction constraints at the center of /// Activate or deactivate the solving of friction constraints at the center of
/// the contact manifold instead of solving them at each contact point /// the contact manifold instead of solving them at each contact point
void setIsSolveFrictionAtContactManifoldCenterActive(bool isActive); void setIsSolveFrictionAtContactManifoldCenterActive(bool isActive);
/// Clean up the constraint solver
void cleanup();
}; };
// Return true if the body is in at least one constraint // Set the split velocities arrays
inline bool ContactSolver::isConstrainedBody(RigidBody* body) const { inline void ContactSolver::setSplitVelocitiesArrays(Vector3* splitLinearVelocities,
return mConstraintBodies.count(body) == 1; Vector3* splitAngularVelocities) {
assert(splitLinearVelocities != NULL);
assert(splitAngularVelocities != NULL);
mSplitLinearVelocities = splitLinearVelocities;
mSplitAngularVelocities = splitAngularVelocities;
} }
// Return the split linear velocity // Set the constrained velocities arrays
inline Vector3 ContactSolver::getSplitLinearVelocityOfBody(RigidBody* body) { inline void ContactSolver::setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
assert(isConstrainedBody(body)); Vector3* constrainedAngularVelocities) {
const uint indexBody = mMapBodyToConstrainedVelocityIndex.find(body)->second; assert(constrainedLinearVelocities != NULL);
return mSplitLinearVelocities[indexBody]; assert(constrainedAngularVelocities != NULL);
} mLinearVelocities = constrainedLinearVelocities;
mAngularVelocities = constrainedAngularVelocities;
// Return the split angular velocity
inline Vector3 ContactSolver::getSplitAngularVelocityOfBody(RigidBody* body) {
assert(isConstrainedBody(body));
const uint indexBody = mMapBodyToConstrainedVelocityIndex.find(body)->second;
return mSplitAngularVelocities[indexBody];
} }
// Return true if the split impulses position correction technique is used for contacts // Return true if the split impulses position correction technique is used for contacts

View File

@ -37,15 +37,15 @@ using namespace std;
// Constructor // Constructor
DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_TIMESTEP) DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_TIMESTEP)
: CollisionWorld(), mTimer(timeStep), mGravity(gravity), mIsGravityOn(true), : CollisionWorld(), mTimer(timeStep), mGravity(gravity), mIsGravityOn(true),
mContactSolver(mContactManifolds, mConstrainedLinearVelocities, mConstrainedAngularVelocities, mConstrainedLinearVelocities(NULL), mConstrainedAngularVelocities(NULL),
mMapBodyToConstrainedVelocityIndex), mContactSolver(mMapBodyToConstrainedVelocityIndex),
mConstraintSolver(mJoints, mConstrainedLinearVelocities, mConstrainedAngularVelocities, mConstraintSolver(mConstrainedPositions, mConstrainedOrientations,
mConstrainedPositions, mConstrainedOrientations,
mMapBodyToConstrainedVelocityIndex), mMapBodyToConstrainedVelocityIndex),
mNbVelocitySolverIterations(DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS), mNbVelocitySolverIterations(DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS),
mNbPositionSolverIterations(DEFAULT_POSITION_SOLVER_NB_ITERATIONS), mNbPositionSolverIterations(DEFAULT_POSITION_SOLVER_NB_ITERATIONS),
mIsSleepingEnabled(SPLEEPING_ENABLED), mNbIslands(0), mNbIslandsCapacity(0), mIsSleepingEnabled(SPLEEPING_ENABLED), mSplitLinearVelocities(NULL),
mIslands(NULL) { mSplitAngularVelocities(NULL), mNbIslands(0), mNbIslandsCapacity(0),
mIslands(NULL), mNbBodiesCapacity(0) {
} }
@ -73,8 +73,13 @@ DynamicsWorld::~DynamicsWorld() {
mMemoryAllocator.release(mIslands, sizeof(Island*) * mNbIslandsCapacity); mMemoryAllocator.release(mIslands, sizeof(Island*) * mNbIslandsCapacity);
} }
// Free the allocated memory for the constrained velocities // Release the memory allocated for the bodies velocity arrays
cleanupConstrainedVelocitiesArray(); if (mNbBodiesCapacity > 0) {
delete[] mSplitLinearVelocities;
delete[] mSplitAngularVelocities;
delete[] mConstrainedLinearVelocities;
delete[] mConstrainedAngularVelocities;
}
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
@ -137,12 +142,6 @@ void DynamicsWorld::update() {
// Update the AABBs of the bodies // Update the AABBs of the bodies
updateRigidBodiesAABB(); updateRigidBodiesAABB();
// Cleanup of the contact solver
mContactSolver.cleanup();
// Cleanup the constrained velocities
cleanupConstrainedVelocitiesArray();
} }
// Compute and set the interpolation factor to all the bodies // Compute and set the interpolation factor to all the bodies
@ -178,11 +177,10 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
rigidBody->setAngularVelocity(newAngVelocity); rigidBody->setAngularVelocity(newAngVelocity);
// Add the split impulse velocity from Contact Solver (only used to update the position) // Add the split impulse velocity from Contact Solver (only used to update the position)
if (mContactSolver.isConstrainedBody(rigidBody) && if (mContactSolver.isSplitImpulseActive()) {
mContactSolver.isSplitImpulseActive()) {
newLinVelocity += mContactSolver.getSplitLinearVelocityOfBody(rigidBody); newLinVelocity += mSplitLinearVelocities[indexArray];
newAngVelocity += mContactSolver.getSplitAngularVelocityOfBody(rigidBody); newAngVelocity += mSplitAngularVelocities[indexArray];
} }
// Get current position and orientation of the body // Get current position and orientation of the body
@ -239,6 +237,34 @@ void DynamicsWorld::setInterpolationFactorToAllBodies() {
} }
} }
// Initialize the bodies velocities arrays for the next simulation step.
void DynamicsWorld::initVelocityArrays() {
// Allocate memory for the bodies velocity arrays
uint nbBodies = mRigidBodies.size();
if (mNbBodiesCapacity != nbBodies && nbBodies > 0) {
if (mNbBodiesCapacity > 0) {
delete[] mSplitLinearVelocities;
delete[] mSplitAngularVelocities;
}
mNbBodiesCapacity = nbBodies;
mSplitLinearVelocities = new Vector3[mNbBodiesCapacity];
mSplitAngularVelocities = new Vector3[mNbBodiesCapacity];
mConstrainedLinearVelocities = new Vector3[mNbBodiesCapacity];
mConstrainedAngularVelocities = new Vector3[mNbBodiesCapacity];
assert(mSplitLinearVelocities != NULL);
assert(mSplitAngularVelocities != NULL);
assert(mConstrainedLinearVelocities != NULL);
assert(mConstrainedAngularVelocities != NULL);
}
// Reset the velocities arrays
for (uint i=0; i<mNbBodiesCapacity; i++) {
mSplitLinearVelocities[i].setToZero();
mSplitAngularVelocities[i].setToZero();
}
}
// Integrate the velocities of rigid bodies. // Integrate the velocities of rigid bodies.
/// This method only set the temporary velocities but does not update /// This method only set the temporary velocities but does not update
/// the actual velocitiy of the bodies. The velocities updated in this method /// the actual velocitiy of the bodies. The velocities updated in this method
@ -248,19 +274,22 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
PROFILE("DynamicsWorld::integrateRigidBodiesVelocities()"); PROFILE("DynamicsWorld::integrateRigidBodiesVelocities()");
// TODO : Use better memory allocation here // Initialize the bodies velocity arrays
mConstrainedLinearVelocities = std::vector<Vector3>(mRigidBodies.size(), Vector3(0, 0, 0)); initVelocityArrays();
mConstrainedAngularVelocities = std::vector<Vector3>(mRigidBodies.size(), Vector3(0, 0, 0));
decimal dt = static_cast<decimal>(mTimer.getTimeStep()); decimal dt = static_cast<decimal>(mTimer.getTimeStep());
// Fill in the mapping of rigid body to their index in the constrained // Fill in the mapping of rigid body to their index in the constrained
// velocities arrays // velocities arrays
uint i = 0; uint i = 0;
mMapBodyToConstrainedVelocityIndex.clear();
for (std::set<RigidBody*>::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) { for (std::set<RigidBody*>::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) {
RigidBody* rigidBody = *it; RigidBody* rigidBody = *it;
mMapBodyToConstrainedVelocityIndex.insert(std::make_pair<RigidBody*, uint>(rigidBody, i)); mMapBodyToConstrainedVelocityIndex.insert(std::make_pair<RigidBody*, uint>(rigidBody, i));
assert(mSplitLinearVelocities[i] == Vector3(0, 0, 0));
assert(mSplitAngularVelocities[i] == Vector3(0, 0, 0));
// If the body is allowed to move // If the body is allowed to move
if (rigidBody->getIsMotionEnabled()) { if (rigidBody->getIsMotionEnabled()) {
@ -318,42 +347,59 @@ void DynamicsWorld::solveContactsAndConstraints() {
// Get the current time step // Get the current time step
decimal dt = static_cast<decimal>(mTimer.getTimeStep()); decimal dt = static_cast<decimal>(mTimer.getTimeStep());
// Check if there are contacts and constraints to solve // Set the velocities arrays
bool isConstraintsToSolve = !mJoints.empty(); mContactSolver.setSplitVelocitiesArrays(mSplitLinearVelocities, mSplitAngularVelocities);
bool isContactsToSolve = !mContactManifolds.empty(); mContactSolver.setConstrainedVelocitiesArrays(mConstrainedLinearVelocities,
if (!isConstraintsToSolve && !isContactsToSolve) return; mConstrainedAngularVelocities);
mConstraintSolver.setConstrainedVelocitiesArrays(mConstrainedLinearVelocities,
mConstrainedAngularVelocities);
// ---------- Solve velocity constraints for joints and contacts ---------- // // ---------- Solve velocity constraints for joints and contacts ---------- //
// If there are contacts // For each island of the world
if (isContactsToSolve) { for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) {
// Initialize the solver // Check if there are contacts and constraints to solve
mContactSolver.initialize(dt); bool isConstraintsToSolve = mIslands[islandIndex]->getNbJoints() > 0;
bool isContactsToSolve = mIslands[islandIndex]->getNbContactManifolds() > 0;
if (!isConstraintsToSolve && !isContactsToSolve) continue;
// Warm start the contact solver // If there are contacts in the current island
mContactSolver.warmStart(); if (isContactsToSolve) {
// Initialize the solver
mContactSolver.initializeForIsland(dt, mIslands[islandIndex]);
// Warm start the contact solver
mContactSolver.warmStart();
}
// If there are constraints
if (isConstraintsToSolve) {
// Initialize the constraint solver
mConstraintSolver.initializeForIsland(dt, mIslands[islandIndex]);
}
// For each iteration of the velocity solver
for (uint i=0; i<mNbVelocitySolverIterations; i++) {
// Solve the constraints
if (isConstraintsToSolve) {
mConstraintSolver.solveVelocityConstraints(mIslands[islandIndex]);
}
// Solve the contacts
if (isContactsToSolve) mContactSolver.solve();
}
// Cache the lambda values in order to use them in the next
// step and cleanup the contact solver
if (isContactsToSolve) {
mContactSolver.storeImpulses();
mContactSolver.cleanup();
}
} }
// If there are constraints
if (isConstraintsToSolve) {
// Initialize the constraint solver
mConstraintSolver.initialize(dt);
}
// For each iteration of the velocity solver
for (uint i=0; i<mNbVelocitySolverIterations; i++) {
// Solve the constraints
if (isConstraintsToSolve) mConstraintSolver.solveVelocityConstraints();
// Solve the contacts
if (isContactsToSolve) mContactSolver.solve();
}
// Cache the lambda values in order to use them in the next step
if (isContactsToSolve) mContactSolver.storeImpulses();
} }
// Solve the position error correction of the constraints // Solve the position error correction of the constraints
@ -369,37 +415,36 @@ void DynamicsWorld::solvePositionCorrection() {
// TODO : Use better memory allocation here // TODO : Use better memory allocation here
mConstrainedPositions = std::vector<Vector3>(mRigidBodies.size()); mConstrainedPositions = std::vector<Vector3>(mRigidBodies.size());
mConstrainedOrientations = std::vector<Quaternion>(mRigidBodies.size()); mConstrainedOrientations = std::vector<Quaternion>(mRigidBodies.size());
for (std::set<RigidBody*>::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) {
// If it is a constrained bodies (by a joint) // For each island of the world
if (mConstraintSolver.isConstrainedBody(*it)) { for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) {
uint index = mMapBodyToConstrainedVelocityIndex.find(*it)->second; // For each body of the island
RigidBody** bodies = mIslands[islandIndex]->getBodies();
for (uint b=0; b < mIslands[islandIndex]->getNbBodies(); b++) {
uint index = mMapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
// Get the position/orientation of the rigid body // Get the position/orientation of the rigid body
const Transform& transform = (*it)->getTransform(); const Transform& transform = bodies[b]->getTransform();
mConstrainedPositions[index] = transform.getPosition(); mConstrainedPositions[index] = transform.getPosition();
mConstrainedOrientations[index]= transform.getOrientation(); mConstrainedOrientations[index]= transform.getOrientation();
} }
}
// ---------- Solve the position error correction for the constraints ---------- // // ---------- Solve the position error correction for the constraints ---------- //
// For each iteration of the position (error correction) solver // For each iteration of the position (error correction) solver
for (uint i=0; i<mNbPositionSolverIterations; i++) { for (uint i=0; i<mNbPositionSolverIterations; i++) {
// Solve the position constraints // Solve the position constraints
mConstraintSolver.solvePositionConstraints(); mConstraintSolver.solvePositionConstraints(mIslands[islandIndex]);
} }
// ---------- Update the position/orientation of the rigid bodies ---------- // // ---------- Update the position/orientation of the rigid bodies ---------- //
for (std::set<RigidBody*>::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) { for (uint b=0; b < mIslands[islandIndex]->getNbBodies(); b++) {
// If it is a constrained bodies (by a joint) uint index = mMapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
if (mConstraintSolver.isConstrainedBody(*it)) {
uint index = mMapBodyToConstrainedVelocityIndex.find(*it)->second;
// Get the new position/orientation of the body // Get the new position/orientation of the body
const Vector3& newPosition = mConstrainedPositions[index]; const Vector3& newPosition = mConstrainedPositions[index];
@ -407,22 +452,11 @@ void DynamicsWorld::solvePositionCorrection() {
// Update the Transform of the body // Update the Transform of the body
Transform newTransform(newPosition, newOrientation.getUnit()); Transform newTransform(newPosition, newOrientation.getUnit());
(*it)->setTransform(newTransform); bodies[b]->setTransform(newTransform);
} }
} }
} }
// Cleanup the constrained velocities array at each step
void DynamicsWorld::cleanupConstrainedVelocitiesArray() {
// Clear the constrained velocites
mConstrainedLinearVelocities.clear();
mConstrainedAngularVelocities.clear();
// Clear the rigid body to velocities array index mapping
mMapBodyToConstrainedVelocityIndex.clear();
}
// Create a rigid body into the physics world // Create a rigid body into the physics world
RigidBody* DynamicsWorld::createRigidBody(const Transform& transform, decimal mass, RigidBody* DynamicsWorld::createRigidBody(const Transform& transform, decimal mass,
const Matrix3x3& inertiaTensorLocal, const Matrix3x3& inertiaTensorLocal,
@ -579,11 +613,13 @@ void DynamicsWorld::destroyJoint(Constraint* joint) {
joint->mBody1->removeJointFromJointsList(mMemoryAllocator, joint); joint->mBody1->removeJointFromJointsList(mMemoryAllocator, joint);
joint->mBody2->removeJointFromJointsList(mMemoryAllocator, joint); joint->mBody2->removeJointFromJointsList(mMemoryAllocator, joint);
size_t nbBytes = joint->getSizeInBytes();
// Call the destructor of the joint // Call the destructor of the joint
joint->Constraint::~Constraint(); joint->Constraint::~Constraint();
// Release the allocated memory // Release the allocated memory
mMemoryAllocator.release(joint, joint->getSizeInBytes()); mMemoryAllocator.release(joint, nbBytes);
} }
// Add the joint to the list of joints of the two bodies involved in the joint // Add the joint to the list of joints of the two bodies involved in the joint

View File

@ -87,11 +87,17 @@ class DynamicsWorld : public CollisionWorld {
/// Array of constrained linear velocities (state of the linear velocities /// Array of constrained linear velocities (state of the linear velocities
/// after solving the constraints) /// after solving the constraints)
std::vector<Vector3> mConstrainedLinearVelocities; Vector3* mConstrainedLinearVelocities;
/// Array of constrained angular velocities (state of the angular velocities /// Array of constrained angular velocities (state of the angular velocities
/// after solving the constraints) /// after solving the constraints)
std::vector<Vector3> mConstrainedAngularVelocities; Vector3* mConstrainedAngularVelocities;
/// Split linear velocities for the position contact solver (split impulse)
Vector3* mSplitLinearVelocities;
/// Split angular velocities for the position contact solver (split impulse)
Vector3* mSplitAngularVelocities;
/// Array of constrained rigid bodies position (for position error correction) /// Array of constrained rigid bodies position (for position error correction)
std::vector<Vector3> mConstrainedPositions; std::vector<Vector3> mConstrainedPositions;
@ -111,6 +117,9 @@ class DynamicsWorld : public CollisionWorld {
/// Array with all the islands of awaken bodies /// Array with all the islands of awaken bodies
Island** mIslands; Island** mIslands;
/// Current allocated capacity for the bodies
uint mNbBodiesCapacity;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Private copy-constructor /// Private copy-constructor
@ -132,6 +141,9 @@ class DynamicsWorld : public CollisionWorld {
/// Compute and set the interpolation factor to all bodies /// Compute and set the interpolation factor to all bodies
void setInterpolationFactorToAllBodies(); void setInterpolationFactorToAllBodies();
/// Initialize the bodies velocities arrays for the next simulation step.
void initVelocityArrays();
/// Integrate the velocities of rigid bodies. /// Integrate the velocities of rigid bodies.
void integrateRigidBodiesVelocities(); void integrateRigidBodiesVelocities();