2010-09-09 19:41:14 +00:00
|
|
|
|
/********************************************************************************
|
|
|
|
|
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
|
|
|
|
|
* Copyright (c) 2010 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. *
|
|
|
|
|
********************************************************************************/
|
2009-07-03 12:17:18 +00:00
|
|
|
|
|
|
|
|
|
#ifndef CONTACT_H
|
|
|
|
|
#define CONTACT_H
|
|
|
|
|
|
|
|
|
|
// Libraries
|
2010-05-03 22:40:32 +00:00
|
|
|
|
#include "../typeDefinitions.h"
|
2009-07-03 12:17:18 +00:00
|
|
|
|
#include "Constraint.h"
|
2010-09-07 20:08:54 +00:00
|
|
|
|
#include "../body/RigidBody.h"
|
2009-07-03 12:17:18 +00:00
|
|
|
|
#include "../mathematics/mathematics.h"
|
2010-09-07 20:08:54 +00:00
|
|
|
|
#include <GL/freeglut.h> // TODO : Remove this in the final version
|
|
|
|
|
#include <GL/gl.h> // TODO : Remove this in the final version
|
2009-07-03 12:17:18 +00:00
|
|
|
|
|
|
|
|
|
// ReactPhysics3D namespace
|
|
|
|
|
namespace reactphysics3d {
|
|
|
|
|
|
2010-03-28 21:54:41 +00:00
|
|
|
|
// Constants
|
2010-08-27 10:00:25 +00:00
|
|
|
|
const double FRICTION_COEFFICIENT = 0.3; // Friction coefficient
|
|
|
|
|
const double PENETRATION_FACTOR = 0.0; // Penetration factor (between 0 and 1) which specify the importance of the
|
2010-03-28 21:54:41 +00:00
|
|
|
|
// penetration depth in order to calculate the correct impulse for the contact
|
|
|
|
|
|
2009-07-03 12:17:18 +00:00
|
|
|
|
/* -------------------------------------------------------------------
|
|
|
|
|
Class Contact :
|
|
|
|
|
This class represents a collision contact between two bodies in
|
|
|
|
|
the physics engine. The contact class inherits from the
|
2010-03-10 22:28:40 +00:00
|
|
|
|
Constraint class. The collision detection system computes
|
2009-07-03 12:17:18 +00:00
|
|
|
|
contact informations that will be used to perform the collision
|
2010-03-28 21:54:41 +00:00
|
|
|
|
response. Each contact contains only one contact point. A contact
|
|
|
|
|
constraint has two auxiliary constraints in order two represent
|
|
|
|
|
the two friction forces at the contact surface.
|
2009-07-03 12:17:18 +00:00
|
|
|
|
-------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
class Contact : public Constraint {
|
2010-02-18 22:26:48 +00:00
|
|
|
|
protected :
|
2010-03-28 21:54:41 +00:00
|
|
|
|
const Vector3D normal; // Normal vector of the contact (From body1 toward body2)
|
|
|
|
|
const double penetrationDepth; // Penetration depth
|
|
|
|
|
const Vector3D point; // Contact point
|
2010-03-10 22:28:40 +00:00
|
|
|
|
std::vector<Vector3D> frictionVectors; // Two orthogonal vectors that span the tangential friction plane
|
2010-09-07 20:08:54 +00:00
|
|
|
|
double mu_mc_g;
|
|
|
|
|
|
2010-03-10 22:28:40 +00:00
|
|
|
|
void computeFrictionVectors(); // Compute the two friction vectors that span the tangential friction plane
|
2009-07-03 12:17:18 +00:00
|
|
|
|
|
|
|
|
|
public :
|
2010-03-28 21:54:41 +00:00
|
|
|
|
Contact(Body* const body1, Body* const body2, const Vector3D& normal, double penetrationDepth, const Vector3D& point); // Constructor
|
|
|
|
|
virtual ~Contact(); // Destructor
|
2009-07-03 12:17:18 +00:00
|
|
|
|
|
2010-09-07 20:08:54 +00:00
|
|
|
|
Vector3D getNormal() const; // Return the normal vector of the contact
|
|
|
|
|
Vector3D getPoint() const; // Return the contact point
|
|
|
|
|
virtual void computeJacobian(int noBody, Matrix& jacobian) const; // Compute a part of the jacobian for a given body
|
|
|
|
|
virtual void computeAuxJacobian(int noBody, int noAuxConstraint, Matrix& auxJacobian) const; // Compute a part of the jacobian for an auxiliary constraint
|
|
|
|
|
virtual double computeLowerBound() const; // Compute the lowerbound of the constraint
|
|
|
|
|
virtual double computeUpperBound() const; // Compute the upperbound of the constraint
|
|
|
|
|
virtual void computeAuxLowerBounds(int beginIndex, Vector& auxLowerBounds) const; // Compute the lowerbounds for the auxiliary constraints
|
|
|
|
|
virtual void computeAuxUpperBounds(int beginIndex, Vector& auxLowerBounds) const; // Compute the upperbounds for the auxiliary constraints
|
|
|
|
|
virtual double computeErrorValue() const; // Compute the error value for the constraint
|
|
|
|
|
virtual void computeAuxErrorValues(int beginIndex, Vector& errorValues) const; // Compute the errors values of the auxiliary constraints
|
|
|
|
|
uint getNbAuxConstraints() const; // Return the number of auxiliary constraints
|
|
|
|
|
double getPenetrationDepth() const; // Return the penetration depth
|
|
|
|
|
void draw() const; // TODO : Delete this (Used to debug collision detection)
|
2009-07-03 12:17:18 +00:00
|
|
|
|
};
|
|
|
|
|
|
2010-03-28 21:54:41 +00:00
|
|
|
|
// Compute the two unit orthogonal vectors "v1" and "v2" that span the tangential friction plane
|
2010-03-10 22:28:40 +00:00
|
|
|
|
// The two vectors have to be such that : v1 x v2 = contactNormal
|
|
|
|
|
inline void Contact::computeFrictionVectors() {
|
2010-02-18 22:26:48 +00:00
|
|
|
|
// Delete the current friction vectors
|
|
|
|
|
frictionVectors.clear();
|
|
|
|
|
|
2010-03-28 21:54:41 +00:00
|
|
|
|
// Compute the first orthogonal vector
|
|
|
|
|
Vector3D vector1 = normal.getOneOrthogonalVector();
|
|
|
|
|
frictionVectors.push_back(vector1);
|
|
|
|
|
|
|
|
|
|
// Compute the second orthogonal vector using the cross product
|
|
|
|
|
frictionVectors.push_back(normal.crossProduct(vector1));
|
2010-02-18 22:26:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-03 12:17:18 +00:00
|
|
|
|
// Return the normal vector of the contact
|
2009-11-29 21:55:41 +00:00
|
|
|
|
inline Vector3D Contact::getNormal() const {
|
|
|
|
|
return normal;
|
2009-08-06 12:10:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-06 19:39:33 +00:00
|
|
|
|
// Return the contact points
|
2010-03-28 21:54:41 +00:00
|
|
|
|
inline Vector3D Contact::getPoint() const {
|
|
|
|
|
return point;
|
2010-02-06 19:39:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 20:08:54 +00:00
|
|
|
|
// Return the penetration depth of the contact
|
2010-06-11 21:23:47 +00:00
|
|
|
|
inline double Contact::getPenetrationDepth() const {
|
|
|
|
|
return penetrationDepth;
|
|
|
|
|
}
|
2010-02-06 19:39:33 +00:00
|
|
|
|
|
2010-09-07 20:08:54 +00:00
|
|
|
|
// This method computes a part of the jacobian matrix for a given body.
|
|
|
|
|
// The argument "noBody" is 1 or 2 and corresponds to which one of the two
|
|
|
|
|
// bodies of the constraint we will compute the jacobian part. The argument
|
|
|
|
|
// "jacobian" is a 1x6 jacobian matrix of the constraint corresponding to one of
|
|
|
|
|
// the two bodies of the constraint.
|
|
|
|
|
inline void Contact::computeJacobian(int noBody, Matrix& jacobian) const {
|
|
|
|
|
RigidBody* rigidBody;
|
|
|
|
|
Vector3D rCrossN;
|
|
|
|
|
Vector3D r;
|
|
|
|
|
Vector3D norm = normal;
|
|
|
|
|
|
|
|
|
|
assert(noBody == 1 || noBody == 2);
|
|
|
|
|
assert(jacobian.getNbRow() == 1 && jacobian.getNbColumn() == 6);
|
|
|
|
|
|
|
|
|
|
if (noBody == 1) {
|
|
|
|
|
rigidBody = dynamic_cast<RigidBody*>(body1);
|
|
|
|
|
assert(rigidBody);
|
|
|
|
|
r = point - rigidBody->getPosition();
|
|
|
|
|
rCrossN = r.crossProduct(normal).getOpposite();
|
|
|
|
|
norm = normal.getOpposite();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
rigidBody = dynamic_cast<RigidBody*>(body2);
|
|
|
|
|
assert(rigidBody);
|
|
|
|
|
r = point - rigidBody->getPosition();
|
|
|
|
|
rCrossN = r.crossProduct(normal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the jacobian matrix for the body 1
|
|
|
|
|
jacobian.setValue(0, 0, norm.getX());
|
|
|
|
|
jacobian.setValue(0, 1, norm.getY());
|
|
|
|
|
jacobian.setValue(0, 2, norm.getZ());
|
|
|
|
|
jacobian.setValue(0, 3, rCrossN.getX());
|
|
|
|
|
jacobian.setValue(0, 4, rCrossN.getY());
|
|
|
|
|
jacobian.setValue(0, 5, rCrossN.getZ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute a part of the jacobian matrix for an auxiliary constraint (given by "noAuxConstraint")
|
|
|
|
|
// and one of the two bodies (given by "noBody") of the contact. The argument "noBody" is 1 or 2 and
|
|
|
|
|
// argument auxJacobian is a 1x6 matrix.
|
|
|
|
|
inline void Contact::computeAuxJacobian(int noBody, int noAuxConstraint, Matrix& auxJacobian) const {
|
|
|
|
|
Vector3D r;
|
|
|
|
|
Vector3D rCrossU;
|
|
|
|
|
RigidBody* rigidBody;
|
|
|
|
|
double sign;
|
|
|
|
|
|
|
|
|
|
assert(noBody == 1 || noBody == 2);
|
|
|
|
|
assert(noAuxConstraint == 1 || noAuxConstraint == 2);
|
|
|
|
|
assert(auxJacobian.getNbRow() == 1 && auxJacobian.getNbColumn() == 6);
|
|
|
|
|
|
|
|
|
|
if (noBody == 1) {
|
|
|
|
|
rigidBody = dynamic_cast<RigidBody*>(body1);
|
|
|
|
|
assert(rigidBody);
|
|
|
|
|
r = point - rigidBody->getPosition();
|
|
|
|
|
sign = -1.0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
rigidBody = dynamic_cast<RigidBody*>(body2);
|
|
|
|
|
assert(rigidBody);
|
|
|
|
|
r = point - rigidBody->getPosition();
|
|
|
|
|
sign = 1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rCrossU = r.crossProduct(frictionVectors[noAuxConstraint-1]);
|
|
|
|
|
|
|
|
|
|
auxJacobian.setValue(0, 0, sign * frictionVectors[noAuxConstraint-1].getX());
|
|
|
|
|
auxJacobian.setValue(0, 1, sign * frictionVectors[noAuxConstraint-1].getY());
|
|
|
|
|
auxJacobian.setValue(0, 2, sign * frictionVectors[noAuxConstraint-1].getZ());
|
|
|
|
|
auxJacobian.setValue(0, 3, sign * rCrossU.getX());
|
|
|
|
|
auxJacobian.setValue(0, 4, sign * rCrossU.getY());
|
|
|
|
|
auxJacobian.setValue(0, 5, sign * rCrossU.getZ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the lowerbounds for the auxiliary constraints
|
|
|
|
|
inline double Contact::computeLowerBound() const {
|
|
|
|
|
return 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the upperbounds for the auxiliary constraints
|
|
|
|
|
inline double Contact::computeUpperBound() const {
|
|
|
|
|
return INFINITY_CONST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the lowerbounds for the auxiliary constraints. This method fills the "auxLowerBounds"
|
|
|
|
|
// vector starting at the index "beginIndex" in this vector.
|
|
|
|
|
inline void Contact::computeAuxLowerBounds(int beginIndex, Vector& auxLowerBounds) const {
|
|
|
|
|
assert(beginIndex + nbAuxConstraints <= auxLowerBounds.getNbComponent());
|
|
|
|
|
|
|
|
|
|
auxLowerBounds.setValue(beginIndex, -mu_mc_g);
|
|
|
|
|
auxLowerBounds.setValue(beginIndex + 1, -mu_mc_g);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the upperbounds for the auxiliary constraints. This method fills the "auxUpperBounds"
|
|
|
|
|
// vector starting at the index "beginIndex" in this vector.
|
|
|
|
|
inline void Contact::computeAuxUpperBounds(int beginIndex, Vector& auxUpperBounds) const {
|
|
|
|
|
assert(beginIndex + nbAuxConstraints <= auxUpperBounds.getNbComponent());
|
|
|
|
|
|
|
|
|
|
auxUpperBounds.setValue(beginIndex, mu_mc_g);
|
|
|
|
|
auxUpperBounds.setValue(beginIndex + 1, mu_mc_g);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the error value for the constraint
|
|
|
|
|
inline double Contact::computeErrorValue() const {
|
|
|
|
|
RigidBody* rigidBody1 = dynamic_cast<RigidBody*>(body1);
|
|
|
|
|
RigidBody* rigidBody2 = dynamic_cast<RigidBody*>(body2);
|
|
|
|
|
|
|
|
|
|
assert(rigidBody1);
|
|
|
|
|
assert(rigidBody2);
|
|
|
|
|
|
|
|
|
|
Vector3D velocity1 = rigidBody1->getLinearVelocity();
|
|
|
|
|
Vector3D velocity2 = rigidBody2->getLinearVelocity();
|
|
|
|
|
double restitutionCoeff = rigidBody1->getRestitution() * rigidBody2->getRestitution();
|
|
|
|
|
double errorValue = restitutionCoeff * (normal.scalarProduct(velocity1) - normal.scalarProduct(velocity2)) + PENETRATION_FACTOR * penetrationDepth;
|
|
|
|
|
return errorValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the errors values of the auxiliary constraints
|
|
|
|
|
inline void Contact::computeAuxErrorValues(int beginIndex, Vector& errorValues) const {
|
|
|
|
|
assert(beginIndex + nbAuxConstraints <= errorValues.getNbComponent());
|
|
|
|
|
|
|
|
|
|
errorValues.setValue(beginIndex, 0.0);
|
|
|
|
|
errorValues.setValue(beginIndex + 1, 0.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO : Delete this (Used to debug collision detection)
|
|
|
|
|
inline void Contact::draw() const {
|
|
|
|
|
glColor3f(1.0, 0.0, 0.0);
|
|
|
|
|
glutSolidSphere(0.3, 20, 20);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-03 12:17:18 +00:00
|
|
|
|
} // End of the ReactPhysics3D namespace
|
|
|
|
|
|
|
|
|
|
#endif
|