/******************************************************************************** * ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * * Copyright (c) 2010-2012 Daniel Chappuis * ********************************************************************************* * * * 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. * * * ********************************************************************************/ // Libraries #include "ConstraintSolver.h" #include "DynamicsWorld.h" #include "../body/RigidBody.h" using namespace reactphysics3d; using namespace std; // Constructor ConstraintSolver::ConstraintSolver(DynamicsWorld* world) :world(world), nbConstraints(0), nbIterations(10) { } // Destructor ConstraintSolver::~ConstraintSolver() { } // Initialize the constraint solver before each solving void ConstraintSolver::initialize() { nbConstraints = 0; // TOOD : Use better allocation here mContactConstraints = new ContactConstraint[world->getNbContactManifolds()]; uint nbContactConstraints = 0; // For each contact manifold of the world vector::iterator it; for (it = world->getContactManifoldsBeginIterator(); it != world->getContactManifoldsEndIterator(); ++it) { ContactManifold contactManifold = *it; // For each contact point of the contact manifold for (uint c=0; cisActive()) { RigidBody* body1 = contact->getBody1(); RigidBody* body2 = contact->getBody2(); activeConstraints.push_back(contact); // Add the two bodies of the constraint in the constraintBodies list mConstraintBodies.insert(body1); mConstraintBodies.insert(body2); // Fill in the body number maping mMapBodyToIndex.insert(make_pair(body1, mMapBodyToIndex.size())); mMapBodyToIndex.insert(make_pair(body2, mMapBodyToIndex.size())); // Update the size of the jacobian matrix nbConstraints += contact->getNbConstraints(); ContactConstraint constraint = mContactConstraints[nbContactConstraints]; constraint.indexBody1 = mMapBodyToIndex[body1]; constraint.indexBody2 = mMapBodyToIndex[body2]; constraint.inverseInertiaTensorBody1 = body1->getInertiaTensorInverseWorld(); constraint.inverseInertiaTensorBody2 = body2->getInertiaTensorInverseWorld(); constraint.isBody1Moving = body1->getIsMotionEnabled(); constraint.isBody2Moving = body2->getIsMotionEnabled(); constraint.massInverseBody1 = body1->getMassInverse(); constraint.massInverseBody2 = body2->getMassInverse(); nbContactConstraints++; } } } // Compute the number of bodies that are part of some active constraint nbBodies = mMapBodyToIndex.size(); assert(nbConstraints > 0 && nbConstraints <= NB_MAX_CONSTRAINTS); assert(nbBodies > 0 && nbBodies <= NB_MAX_BODIES); } // Fill in all the matrices needed to solve the LCP problem // Notice that all the active constraints should have been evaluated first void ConstraintSolver::fillInMatrices(decimal dt) { Constraint* constraint; decimal oneOverDt = 1.0 / dt; // For each active constraint int noConstraint = 0; for (int c=0; ccomputeJacobian(noConstraint, J_sp); // Fill in the body mapping matrix for(int i=0; igetNbConstraints(); i++) { bodyMapping[noConstraint+i][0] = constraint->getBody1(); bodyMapping[noConstraint+i][1] = constraint->getBody2(); } // Fill in the limit vectors for the constraint constraint->computeLowerBound(noConstraint, lowerBounds); constraint->computeUpperBound(noConstraint, upperBounds); // Fill in the error vector constraint->computeErrorValue(noConstraint, errorValues); // Get the cached lambda values of the constraint for (int i=0; igetNbConstraints(); i++) { lambdaInit[noConstraint + i] = constraint->getCachedLambda(i); } // If the constraint is a contact if (constraint->getType() == CONTACT) { Contact* contact = dynamic_cast(constraint); // Add the Baumgarte error correction term for contacts decimal slop = 0.005; if (contact->getPenetrationDepth() > slop) { errorValues[noConstraint] += 0.2 * oneOverDt * std::max(double(contact->getPenetrationDepth() - slop), 0.0); } } noConstraint += constraint->getNbConstraints(); } // For each current body that is implied in some constraint RigidBody* rigidBody; RigidBody* body; uint b=0; for (set::iterator it = mConstraintBodies.begin(); it != mConstraintBodies.end(); ++it, b++) { body = *it; uint bodyNumber = mMapBodyToIndex[body]; // TODO : Use polymorphism and remove this downcasting rigidBody = dynamic_cast(body); assert(rigidBody); // Compute the vector V1 with initial velocities values Vector3 linearVelocity = rigidBody->getLinearVelocity(); Vector3 angularVelocity = rigidBody->getAngularVelocity(); int bodyIndexArray = 6 * bodyNumber; V1[bodyIndexArray] = linearVelocity[0]; V1[bodyIndexArray + 1] = linearVelocity[1]; V1[bodyIndexArray + 2] = linearVelocity[2]; V1[bodyIndexArray + 3] = angularVelocity[0]; V1[bodyIndexArray + 4] = angularVelocity[1]; V1[bodyIndexArray + 5] = angularVelocity[2]; // Compute the vector Vconstraint with final constraint velocities Vconstraint[bodyIndexArray] = 0.0; Vconstraint[bodyIndexArray + 1] = 0.0; Vconstraint[bodyIndexArray + 2] = 0.0; Vconstraint[bodyIndexArray + 3] = 0.0; Vconstraint[bodyIndexArray + 4] = 0.0; Vconstraint[bodyIndexArray + 5] = 0.0; // Compute the vector with forces and torques values Vector3 externalForce = rigidBody->getExternalForce(); Vector3 externalTorque = rigidBody->getExternalTorque(); Fext[bodyIndexArray] = externalForce[0]; Fext[bodyIndexArray + 1] = externalForce[1]; Fext[bodyIndexArray + 2] = externalForce[2]; Fext[bodyIndexArray + 3] = externalTorque[0]; Fext[bodyIndexArray + 4] = externalTorque[1]; Fext[bodyIndexArray + 5] = externalTorque[2]; // Initialize the mass and inertia tensor matrices Minv_sp_inertia[bodyNumber].setAllValues(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); Minv_sp_mass_diag[bodyNumber] = 0.0; // If the motion of the rigid body is enabled if (rigidBody->getIsMotionEnabled()) { Minv_sp_inertia[bodyNumber] = rigidBody->getInertiaTensorInverseWorld(); Minv_sp_mass_diag[bodyNumber] = rigidBody->getMassInverse(); } } } // Compute the vector b void ConstraintSolver::computeVectorB(decimal dt) { uint indexBody1, indexBody2; decimal oneOverDT = 1.0 / dt; for (uint c = 0; cgetNbConstraints(); i++) { // Get the lambda value that have just been computed activeConstraints[c]->setCachedLambda(i, lambda[noConstraint + i]); } noConstraint += activeConstraints[c]->getNbConstraints(); } }