/******************************************************************************** * ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * * Copyright (c) 2011 Daniel Chappuis * ********************************************************************************* * * * Permission is hereby granted, free of charge, to any person obtaining a copy * * of this software and associated documentation files (the "Software"), to deal * * in the Software without restriction, including without limitation the rights * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * * copies of the Software, and to permit persons to whom the Software is * * furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * * THE SOFTWARE. * ********************************************************************************/ // Libraries #include "ConstraintSolver.h" #include "../body/RigidBody.h" using namespace reactphysics3d; using namespace std; // Constructor ConstraintSolver::ConstraintSolver(PhysicsWorld* world) :physicsWorld(world), nbConstraints(0), nbIterationsLCP(MAX_LCP_ITERATIONS), penetrationFactor(10.0) { } // Destructor ConstraintSolver::~ConstraintSolver() { } // Initialize the constraint solver before each solving void ConstraintSolver::initialize() { Constraint* constraint; nbConstraints = 0; // For each constraint vector::iterator it; for (it = physicsWorld->getConstraintsBeginIterator(); it != physicsWorld->getConstraintsEndIterator(); ++it) { constraint = *it; // If the constraint is active if (constraint->isActive()) { activeConstraints.push_back(constraint); // Add the two bodies of the constraint in the constraintBodies list constraintBodies.insert(constraint->getBody1()); constraintBodies.insert(constraint->getBody2()); // Fill in the body number maping bodyNumberMapping.insert(pair(constraint->getBody1(), bodyNumberMapping.size())); bodyNumberMapping.insert(pair(constraint->getBody2(), bodyNumberMapping.size())); // Update the size of the jacobian matrix nbConstraints += constraint->getNbConstraints(); } } // Compute the number of bodies that are part of some active constraint nbBodies = bodyNumberMapping.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() { Constraint* constraint; // 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, penetrationFactor); // Get the cached lambda values of the constraint for (int i=0; igetNbConstraints(); i++) { lambdaInit[noConstraint + i] = constraint->getCachedLambda(i); } noConstraint += constraint->getNbConstraints(); } // For each current body that is implied in some constraint RigidBody* rigidBody; Body* body; uint b=0; for (set::iterator it = constraintBodies.begin(); it != constraintBodies.end(); ++it, b++) { body = *it; uint bodyNumber = bodyNumberMapping.at(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(double dt) { uint indexBody1, indexBody2; double oneOverDT = 1.0 / dt; //b = errorValues * oneOverDT; 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(); } }