2012-12-12 18:28:52 +00:00
|
|
|
/********************************************************************************
|
|
|
|
* 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. *
|
|
|
|
* *
|
|
|
|
********************************************************************************/
|
|
|
|
|
|
|
|
#ifndef CONTACT_MANIFOLD_H
|
2013-02-26 21:43:45 +00:00
|
|
|
#define CONTACT_MANIFOLD_H
|
2012-12-12 18:28:52 +00:00
|
|
|
|
|
|
|
// Libraries
|
2013-02-26 21:43:45 +00:00
|
|
|
#include <vector>
|
|
|
|
#include "../body/Body.h"
|
|
|
|
#include "../constraint/ContactPoint.h"
|
2012-12-12 18:28:52 +00:00
|
|
|
|
2013-02-26 21:43:45 +00:00
|
|
|
// ReactPhysics3D namespace
|
2012-12-12 18:28:52 +00:00
|
|
|
namespace reactphysics3d {
|
|
|
|
|
2013-02-26 21:43:45 +00:00
|
|
|
// Constants
|
|
|
|
const uint MAX_CONTACT_POINTS_IN_MANIFOLD = 4; // Maximum number of contacts in the manifold
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
|
|
Class ContactManifold :
|
|
|
|
This class represents the set of contact points between two bodies.
|
|
|
|
The contact manifold is implemented in a way to cache the contact
|
|
|
|
points among the frames for better stability following the
|
|
|
|
"Contact Generation" presentation of Erwin Coumans at GDC 2010
|
|
|
|
conference (bullet.googlecode.com/files/GDC10_Coumans_Erwin_Contact.pdf).
|
|
|
|
Some code of this class is based on the implementation of the
|
|
|
|
btPersistentManifold class from Bullet physics engine (www.http://bulletphysics.org).
|
|
|
|
The contacts between two bodies are added one after the other in the cache.
|
|
|
|
When the cache is full, we have to remove one point. The idea is to keep
|
|
|
|
the point with the deepest penetration depth and also to keep the
|
|
|
|
points producing the larger area (for a more stable contact manifold).
|
|
|
|
The new added point is always kept.
|
|
|
|
-------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
class ContactManifold {
|
|
|
|
|
|
|
|
private:
|
2012-12-12 18:28:52 +00:00
|
|
|
|
|
|
|
// -------------------- Attributes -------------------- //
|
|
|
|
|
2013-02-26 21:43:45 +00:00
|
|
|
// Pointer to the first body
|
|
|
|
Body* const mBody1;
|
2012-12-12 18:28:52 +00:00
|
|
|
|
2013-02-26 21:43:45 +00:00
|
|
|
// Pointer to the second body
|
|
|
|
Body* const mBody2;
|
|
|
|
|
|
|
|
// Contact points in the manifold
|
|
|
|
ContactPoint* mContactPoints[MAX_CONTACT_POINTS_IN_MANIFOLD];
|
|
|
|
|
|
|
|
// Number of contacts in the cache
|
|
|
|
uint mNbContactPoints;
|
2012-12-12 18:28:52 +00:00
|
|
|
|
2013-02-16 15:14:04 +00:00
|
|
|
// First friction vector of the contact manifold
|
2013-02-26 21:43:45 +00:00
|
|
|
Vector3 mFrictionVector1;
|
2013-02-16 15:14:04 +00:00
|
|
|
|
|
|
|
// Second friction vector of the contact manifold
|
2013-02-26 21:43:45 +00:00
|
|
|
Vector3 mFrictionVector2;
|
2013-02-16 15:14:04 +00:00
|
|
|
|
|
|
|
// First friction constraint accumulated impulse
|
2013-02-26 21:43:45 +00:00
|
|
|
decimal mFrictionImpulse1;
|
2013-02-16 15:14:04 +00:00
|
|
|
|
|
|
|
// Second friction constraint accumulated impulse
|
2013-02-26 21:43:45 +00:00
|
|
|
decimal mFrictionImpulse2;
|
2013-02-16 15:14:04 +00:00
|
|
|
|
|
|
|
// Twist friction constraint accumulated impulse
|
2013-02-26 21:43:45 +00:00
|
|
|
decimal mFrictionTwistImpulse;
|
|
|
|
|
|
|
|
// Reference to the memory pool with the contacts
|
|
|
|
MemoryPool<ContactPoint>& mMemoryPoolContacts;
|
|
|
|
|
|
|
|
// -------------------- Methods -------------------- //
|
|
|
|
|
|
|
|
// Private copy-constructor
|
|
|
|
ContactManifold(const ContactManifold& contactManifold);
|
|
|
|
|
|
|
|
// Private assignment operator
|
|
|
|
ContactManifold& operator=(const ContactManifold& contactManifold);
|
|
|
|
|
|
|
|
// Return the index of maximum area
|
|
|
|
int getMaxArea(decimal area0, decimal area1, decimal area2, decimal area3) const;
|
|
|
|
|
|
|
|
// Return the index of the contact with the larger penetration depth
|
|
|
|
int getIndexOfDeepestPenetration(ContactPoint* newContact) const;
|
|
|
|
|
|
|
|
// Return the index that will be removed
|
|
|
|
int getIndexToRemove(int indexMaxPenetration, const Vector3& newPoint) const;
|
|
|
|
|
|
|
|
// Remove a contact point from the manifold
|
|
|
|
void removeContactPoint(int index);
|
|
|
|
|
|
|
|
// Return true if two vectors are approximatively equal
|
|
|
|
bool isApproxEqual(const Vector3& vector1, const Vector3& vector2) const;
|
|
|
|
|
|
|
|
public:
|
2013-02-16 15:14:04 +00:00
|
|
|
|
2012-12-12 18:28:52 +00:00
|
|
|
// -------------------- Methods -------------------- //
|
|
|
|
|
|
|
|
// Constructor
|
2013-02-26 21:43:45 +00:00
|
|
|
ContactManifold(Body* const mBody1, Body* const mBody2,
|
|
|
|
MemoryPool<ContactPoint>& mMemoryPoolContacts);
|
|
|
|
|
|
|
|
// Destructor
|
|
|
|
~ContactManifold();
|
|
|
|
|
|
|
|
// Add a contact point to the manifold
|
|
|
|
void addContactPoint(ContactPoint* contact);
|
|
|
|
|
|
|
|
// Update the contact manifold
|
|
|
|
void update(const Transform& transform1, const Transform& transform2);
|
|
|
|
|
|
|
|
// Clear the contact manifold
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
// Return the number of contact points in the manifold
|
|
|
|
uint getNbContactPoints() const;
|
|
|
|
|
|
|
|
// Return the first friction vector at the center of the contact manifold
|
|
|
|
const Vector3& getFrictionVector1() const;
|
|
|
|
|
|
|
|
// set the first friction vector at the center of the contact manifold
|
|
|
|
void setFrictionVector1(const Vector3& mFrictionVector1);
|
|
|
|
|
|
|
|
// Return the second friction vector at the center of the contact manifold
|
|
|
|
const Vector3& getFrictionVector2() const;
|
|
|
|
|
|
|
|
// set the second friction vector at the center of the contact manifold
|
|
|
|
void setFrictionVector2(const Vector3& mFrictionVector2);
|
|
|
|
|
|
|
|
// Return the first friction accumulated impulse
|
|
|
|
decimal getFrictionImpulse1() const;
|
|
|
|
|
|
|
|
// Set the first friction accumulated impulse
|
|
|
|
void setFrictionImpulse1(decimal frictionImpulse1);
|
|
|
|
|
|
|
|
// Return the second friction accumulated impulse
|
|
|
|
decimal getFrictionImpulse2() const;
|
|
|
|
|
|
|
|
// Set the second friction accumulated impulse
|
|
|
|
void setFrictionImpulse2(decimal frictionImpulse2);
|
|
|
|
|
|
|
|
// Return the friction twist accumulated impulse
|
|
|
|
decimal getFrictionTwistImpulse() const;
|
|
|
|
|
|
|
|
// Set the friction twist accumulated impulse
|
|
|
|
void setFrictionTwistImpulse(decimal frictionTwistImpulse);
|
|
|
|
|
|
|
|
// Return a contact point of the manifold
|
|
|
|
ContactPoint* getContactPoint(uint index) const;
|
2012-12-12 18:28:52 +00:00
|
|
|
};
|
|
|
|
|
2013-02-26 21:43:45 +00:00
|
|
|
// Return the number of contact points in the manifold
|
|
|
|
inline uint ContactManifold::getNbContactPoints() const {
|
|
|
|
return mNbContactPoints;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the first friction vector at the center of the contact manifold
|
|
|
|
inline const Vector3& ContactManifold::getFrictionVector1() const {
|
|
|
|
return mFrictionVector1;
|
2012-12-12 18:28:52 +00:00
|
|
|
}
|
|
|
|
|
2013-02-26 21:43:45 +00:00
|
|
|
// set the first friction vector at the center of the contact manifold
|
|
|
|
inline void ContactManifold::setFrictionVector1(const Vector3& frictionVector1) {
|
|
|
|
mFrictionVector1 = frictionVector1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the second friction vector at the center of the contact manifold
|
|
|
|
inline const Vector3& ContactManifold::getFrictionVector2() const {
|
|
|
|
return mFrictionVector2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the second friction vector at the center of the contact manifold
|
|
|
|
inline void ContactManifold::setFrictionVector2(const Vector3& frictionVector2) {
|
|
|
|
mFrictionVector2 = frictionVector2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the first friction accumulated impulse
|
|
|
|
inline decimal ContactManifold::getFrictionImpulse1() const {
|
|
|
|
return mFrictionImpulse1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the first friction accumulated impulse
|
|
|
|
inline void ContactManifold::setFrictionImpulse1(decimal frictionImpulse1) {
|
|
|
|
mFrictionImpulse1 = frictionImpulse1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the second friction accumulated impulse
|
|
|
|
inline decimal ContactManifold::getFrictionImpulse2() const {
|
|
|
|
return mFrictionImpulse2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the second friction accumulated impulse
|
|
|
|
inline void ContactManifold::setFrictionImpulse2(decimal frictionImpulse2) {
|
|
|
|
mFrictionImpulse2 = frictionImpulse2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the friction twist accumulated impulse
|
|
|
|
inline decimal ContactManifold::getFrictionTwistImpulse() const {
|
|
|
|
return mFrictionTwistImpulse;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the friction twist accumulated impulse
|
|
|
|
inline void ContactManifold::setFrictionTwistImpulse(decimal frictionTwistImpulse) {
|
|
|
|
mFrictionTwistImpulse = frictionTwistImpulse;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return a contact point of the manifold
|
|
|
|
inline ContactPoint* ContactManifold::getContactPoint(uint index) const {
|
|
|
|
assert(index >= 0 && index < mNbContactPoints);
|
|
|
|
return mContactPoints[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return true if two vectors are approximatively equal
|
|
|
|
inline bool ContactManifold::isApproxEqual(const Vector3& vector1,
|
|
|
|
const Vector3& vector2) const {
|
|
|
|
const decimal epsilon = decimal(0.1);
|
|
|
|
return (approxEqual(vector1.getX(), vector2.getX(), epsilon) &&
|
|
|
|
approxEqual(vector1.getY(), vector2.getY(), epsilon) &&
|
|
|
|
approxEqual(vector1.getZ(), vector2.getZ(), epsilon));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2012-12-12 18:28:52 +00:00
|
|
|
#endif
|
2013-02-26 21:43:45 +00:00
|
|
|
|