Modifications before release

git-svn-id: https://reactphysics3d.googlecode.com/svn/trunk@454 92aac97c-a6ce-11dd-a772-7fcde58d38e6
This commit is contained in:
chappuis.daniel 2011-12-11 00:40:04 +00:00
parent 55c1168b5d
commit b82228d3ed
19 changed files with 132 additions and 552 deletions

View File

@ -32,7 +32,7 @@ using namespace reactphysics3d;
// Constructor
Body::Body(const Transform& transform, Shape* shape, double mass, long unsigned int id)
: shape(shape), transform(transform), mass(mass), id(id) {
: shape(shape), mass(mass), transform(transform), id(id) {
assert(mass > 0.0);
assert(shape);

View File

@ -94,8 +94,8 @@ void CollisionDetection::computeBroadPhase() {
// remove them from the overlapping pairs map
for (set<pair<luint, luint> >::iterator it = lastStepOverlappingPairs.begin(); it != lastStepOverlappingPairs.end(); it++) {
// Remove the overlapping pair from the memory pool
overlappingPairs.at((*it))->OverlappingPair::~OverlappingPair();
memoryPoolOverlappingPairs.freeObject(overlappingPairs.at((*it)));
overlappingPairs[(*it)]->OverlappingPair::~OverlappingPair();
memoryPoolOverlappingPairs.freeObject(overlappingPairs[(*it)]);
overlappingPairs.erase(*it);
}

View File

@ -45,12 +45,12 @@ struct ContactInfo {
public:
Body* const body1; // Pointer to the first body of the contact
Body* const body2; // Pointer to the second body of the contact
const Vector3 normal; // Normal vector the the collision contact in world space
const double penetrationDepth; // Penetration depth of the contact
const Vector3 localPoint1; // Contact point of body 1 in local space of body 1
const Vector3 localPoint2; // Contact point of body 2 in local space of body 2
const Vector3 worldPoint1; // Contact point of body 1 in world space
const Vector3 worldPoint2; // Contact point of body 2 in world space
const Vector3 normal; // Normal vector the the collision contact in world space
const double penetrationDepth; // Penetration depth of the contact
ContactInfo(Body* body1, Body* body2, const Vector3& normal, double penetrationDepth,
const Vector3& localPoint1, const Vector3& localPoint2,

View File

@ -1,431 +0,0 @@
/********************************************************************************
* 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 "SATAlgorithm.h"
#include "../../shapes/BoxShape.h"
#include "../../body/RigidBody.h"
#include "../../constraint/Contact.h"
#include "../../mathematics/Transform.h"
#include <algorithm>
#include <cfloat>
#include <cmath>
#include <cassert>
/*
// TODO : SAT Algorithm for box-box collision does not work anymore since the use of
// transform. Maybe a problem with the computation of the normal vector
// Anyway, the GJK algorithm should be used instead
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Constructor
SATAlgorithm::SATAlgorithm() {
}
// Destructor
SATAlgorithm::~SATAlgorithm() {
}
// Return true and compute a contact info if the two bounding volume collide.
// The method returns false if there is no collision between the two bounding volumes.
bool SATAlgorithm::testCollision(const Body* body1, const Body* body2, ContactInfo*& contactInfo) {
assert(body1 != body2);
const Transform& transform1 = body1->getTransform();
const Transform& transform2 = body2->getTransform();
const RigidBody* rigidBody1 = dynamic_cast<const RigidBody*>(body1);
const RigidBody* rigidBody2 = dynamic_cast<const RigidBody*>(body2);
const BoxShape* obb1 = dynamic_cast<const BoxShape*>(rigidBody1->getShape());
const BoxShape* obb2 = dynamic_cast<const BoxShape*>(rigidBody2->getShape());
// If the two bounding volumes are OBB
if (obb1 && obb2) {
// Compute the collision test between two OBB
return computeCollisionTest(obb1, transform1, obb2, transform2, contactInfo);
}
else {
return false;
}
}
// This method returns true and computes a contact info if the two OBB intersect.
// This method implements the separating algorithm between two OBBs. The goal of this method is to test if the
// two OBBs intersect or not. If they intersect we report a contact info and the method returns true. If
// they don't intersect, the method returns false. The separation axis that have to be tested for two
// OBB are the six face normals (3 for each OBB) and the nine vectors V = Ai x Bj where Ai is the ith face normal
// vector of OBB 1 and Bj is the jth face normal vector of OBB 2. We will use the notation Ai for the ith face
// normal of OBB 1 and Bj for the jth face normal of OBB 2.
bool SATAlgorithm::computeCollisionTest(const BoxShape* obb1, const Transform& transform1,
const BoxShape* obb2, const Transform& transform2, ContactInfo*& contactInfo) const {
double center; // Center of a projection interval
double radius1; // Radius of projection interval [min1, max1]
double radius2; // Radius of projection interval [min2, max2]
double min1; // Minimum of interval 1
double max1; // Maximum of interval 1
double min2; // Minimm of interval 2
double max2; // Maximum of interval 2
Vector3 normal; // Contact normal (correspond to the separation axis with the smallest positive penetration depth)
// The contact normal point out of OBB1 toward OBB2
double minPenetrationDepth = DBL_MAX; // Minimum penetration depth detected among all separated axis
const double cutoff = 0.99; // Cutoff for cosine of angles between box axes
bool existsParallelPair = false; // True if there exists two face normals that are parallel.
// This is used because if a parallel pair exists, it is sufficient
// to test only the face normals of the OBBs for separation. Two nearly
// parallel faces can lead to all face normal tests reporting no separation
// along those directions. The cross product directions are tested next, but
// Ai x Bj is nearly the zero vector and can cause a report that the two OBBs
// are not intersecting when in fact they are.
double c[3][3]; // c[i][j] = DotProduct(obb1.Ai, obb2.Bj)
double absC[3][3]; // absC[i][j] = abs(DotProduct(obb1.Ai, obb2.Bj))
double udc1[3]; // DotProduct(obb1.Ai, obb2.center - obb1.center)
double udc2[3]; // DotProduct(obb2.Ai, obb2.center - obb1.center)
//Vector3D boxDistance = obb2->getCenter() - obb1->getCenter(); // Vector between the centers of the OBBs
Vector3 boxDistance = transform2.getPosition() - transform1.getPosition(); // Vector between the centers of the OBBs
// Axis A0
for (int i=0; i<3; ++i) {
c[0][i] = transform1.getOrientation().getMatrix().getColumn(0).dot(transform2.getOrientation().getMatrix().getColumn(i));
absC[0][i] = fabs(c[0][i]);
if (absC[0][i] > cutoff) {
existsParallelPair = true;
}
}
udc1[0] = transform1.getOrientation().getMatrix().getColumn(0).dot(boxDistance);
center = udc1[0];
radius1 = obb1->getExtent().getX();
radius2 = obb2->getExtent().getX()*absC[0][0] + obb2->getExtent().getY()*absC[0][1] + obb2->getExtent().getZ() * absC[0][2];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
double penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(0), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A1
for (int i=0; i<3; ++i) {
c[1][i] = transform1.getOrientation().getMatrix().getColumn(1).dot(transform2.getOrientation().getMatrix().getColumn(i));
absC[1][i] = fabs(c[1][i]);
if (absC[1][i] > cutoff) {
existsParallelPair = true;
}
}
udc1[1] = transform1.getOrientation().getMatrix().getColumn(1).dot(boxDistance);
center = udc1[1];
radius1 = obb1->getExtent().getY();
radius2 = obb2->getExtent().getX()*absC[1][0] + obb2->getExtent().getY()*absC[1][1] + obb2->getExtent().getZ() * absC[1][2];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(1), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A2
for (int i=0; i<3; ++i) {
c[2][i] = transform1.getOrientation().getMatrix().getColumn(2).dot(transform2.getOrientation().getMatrix().getColumn(i));
absC[2][i] = fabs(c[2][i]);
if (absC[2][i] > cutoff) {
existsParallelPair = true;
}
}
udc1[2] = transform1.getOrientation().getMatrix().getColumn(2).dot(boxDistance);
center = udc1[2];
radius1 = obb1->getExtent().getZ();
radius2 = obb2->getExtent().getX()*absC[2][0] + obb2->getExtent().getY()*absC[2][1] + obb2->getExtent().getZ()*absC[2][2];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(2), boxDistance); // Compute the contact normal with the correct sign
}
// Axis B0
udc2[0] = transform2.getOrientation().getMatrix().getColumn(0).dot(boxDistance);
center = udc2[0];
radius1 = obb1->getExtent().getX()*absC[0][0] + obb1->getExtent().getY()*absC[1][0] + obb1->getExtent().getZ() * absC[2][0];
radius2 = obb2->getExtent().getX();
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform2.getOrientation().getMatrix().getColumn(0), boxDistance); // Compute the contact normal with the correct sign
}
// Axis B1
udc2[1] = transform2.getOrientation().getMatrix().getColumn(1).dot(boxDistance);
center = udc2[1];
radius1 = obb1->getExtent().getX()*absC[0][1] + obb1->getExtent().getY()*absC[1][1] + obb1->getExtent().getZ() * absC[2][1];
radius2 = obb2->getExtent().getY();
min1 = - radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform2.getOrientation().getMatrix().getColumn(1), boxDistance); // Compute the contact normal with the correct sign
}
// Axis B2
udc2[2] = transform2.getOrientation().getMatrix().getColumn(2).dot(boxDistance);
center = udc2[2];
radius1 = obb1->getExtent().getX()*absC[0][2] + obb1->getExtent().getY()*absC[1][2] + obb1->getExtent().getZ()*absC[2][2];
radius2 = obb2->getExtent().getZ();
min1 = - radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform2.getOrientation().getMatrix().getColumn(2), boxDistance); // Compute the contact normal with the correct sign
}
// If there exists a parallel pair of face normals
if (existsParallelPair) {
// There exists a parallel pair of face normals and we have already checked all the face
// normals for separation. Therefore the OBBs must intersect
// Compute the contact info
contactInfo = new ContactInfo(obb1->getBodyPointer(), obb2->getBodyPointer(), normal.getUnit(), minPenetrationDepth);
return true;
}
// Axis A0 x B0
center = udc1[2] * c[1][0] - udc1[1] * c[2][0];
radius1 = obb1->getExtent().getY() * absC[2][0] + obb1->getExtent().getZ() * absC[1][0];
radius2 = obb2->getExtent().getY() * absC[0][2] + obb2->getExtent().getZ() * absC[0][1];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(0).cross(transform2.getOrientation().getMatrix().getColumn(0)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A0 x B1
center = udc1[2] * c[1][1] - udc1[1] * c[2][1];
radius1 = obb1->getExtent().getY() * absC[2][1] + obb1->getExtent().getZ() * absC[1][1];
radius2 = obb2->getExtent().getX() * absC[0][2] + obb2->getExtent().getZ() * absC[0][0];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(0).cross(transform2.getOrientation().getMatrix().getColumn(1)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A0 x B2
center = udc1[2] * c[1][2] - udc1[1] * c[2][2];
radius1 = obb1->getExtent().getY() * absC[2][2] + obb1->getExtent().getZ() * absC[1][2];
radius2 = obb2->getExtent().getX() * absC[0][1] + obb2->getExtent().getY() * absC[0][0];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(0).cross(transform2.getOrientation().getMatrix().getColumn(2)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A1 x B0
center = udc1[0] * c[2][0] - udc1[2] * c[0][0];
radius1 = obb1->getExtent().getX() * absC[2][0] + obb1->getExtent().getZ() * absC[0][0];
radius2 = obb2->getExtent().getY() * absC[1][2] + obb2->getExtent().getZ() * absC[1][1];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(1).cross(transform2.getOrientation().getMatrix().getColumn(0)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A1 x B1
center = udc1[0] * c[2][1] - udc1[2] * c[0][1];
radius1 = obb1->getExtent().getX() * absC[2][1] + obb1->getExtent().getZ() * absC[0][1];
radius2 = obb2->getExtent().getX() * absC[1][2] + obb2->getExtent().getZ() * absC[1][0];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(1).cross(transform2.getOrientation().getMatrix().getColumn(1)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A1 x B2
center = udc1[0] * c[2][2] - udc1[2] * c[0][2];
radius1 = obb1->getExtent().getX() * absC[2][2] + obb1->getExtent().getZ() * absC[0][2];
radius2 = obb2->getExtent().getX() * absC[1][1] + obb2->getExtent().getY() * absC[1][0];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(1).cross(transform2.getOrientation().getMatrix().getColumn(2)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A2 x B0
center = udc1[1] * c[0][0] - udc1[0] * c[1][0];
radius1 = obb1->getExtent().getX() * absC[1][0] + obb1->getExtent().getY() * absC[0][0];
radius2 = obb2->getExtent().getY() * absC[2][2] + obb2->getExtent().getZ() * absC[2][1];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(2).cross(transform2.getOrientation().getMatrix().getColumn(0)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A2 x B1
center = udc1[1] * c[0][1] - udc1[0] * c[1][1];
radius1 = obb1->getExtent().getX() * absC[1][1] + obb1->getExtent().getY() * absC[0][1];
radius2 = obb2->getExtent().getX() * absC[2][2] + obb2->getExtent().getZ() * absC[2][0];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(2).cross(transform2.getOrientation().getMatrix().getColumn(1)), boxDistance); // Compute the contact normal with the correct sign
}
// Axis A2 x B2
center = udc1[1] * c[0][2] - udc1[0] * c[1][2];
radius1 = obb1->getExtent().getX() * absC[1][2] + obb1->getExtent().getY() * absC[0][2];
radius2 = obb2->getExtent().getX() * absC[2][1] + obb2->getExtent().getY() * absC[2][0];
min1 = -radius1;
max1 = radius1;
min2 = center - radius2;
max2 = center + radius2;
penetrationDepth = computePenetrationDepth(min1, max1, min2, max2);
if (penetrationDepth < 0) { // We have found a separation axis, therefore the two OBBs don't collide
return false;
}
else if (penetrationDepth < minPenetrationDepth) { // Interval 1 and 2 overlap with a smaller penetration depth on this axis
minPenetrationDepth = penetrationDepth; // Update the minimum penetration depth
normal = computeContactNormal(transform1.getOrientation().getMatrix().getColumn(2).cross(transform2.getOrientation().getMatrix().getColumn(2)), boxDistance); // Compute the contact normal with the correct sign
}
// Compute the contact info
contactInfo = new ContactInfo(obb1->getBodyPointer(), obb2->getBodyPointer(), normal.getUnit(), minPenetrationDepth);
return true;
}
// This method computes and returns the penetration depth between two intervals. This method returns the computed
// penetration depth (note that it could return a negative penetration depth if the intervals are separated.
double SATAlgorithm::computePenetrationDepth(double min1, double max1, double min2, double max2) const {
// Compute the length of both intervals
double lengthInterval1 = max1 - min1;
double lengthInterval2 = max2 - min2;
// Compute the total length of both intervals
double minExtreme = std::min(min1, min2);
double maxExtreme = std::max(max1, max2);
double lengthBothIntervals = maxExtreme - minExtreme;
// Compute the current penetration depth
return (lengthInterval1 + lengthInterval2) - lengthBothIntervals;
}
*/

View File

@ -1,80 +0,0 @@
/********************************************************************************
* 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 SAT_ALGORITHM_H
#define SAT_ALGORITHM_H
// Libraries
#include "NarrowPhaseAlgorithm.h"
#include "../../constraint/Contact.h"
#include "../../shapes/BoxShape.h"
#include "../../mathematics/Transform.h"
// ReactPhysics3D namespace
namespace reactphysics3d {
/* -------------------------------------------------------------------
Class SATAlgorithm :
This class implements a narrow-phase algorithm. This algorithm
uses a separating axis theorem (SAT) to check if two bounding
volumes collide or not. If the
two bounding volumes collide we have to create a contact object
to describe the collision contact. The idea is to check if there
exists an axis where, if we project the two bounding volumes on
this axis, the two projections are separated. If we find at
least an axis where the projections of the two bounding volumes
are separated then we know that the two bounding volumes don't
intersect.
-------------------------------------------------------------------
*/
class SATAlgorithm : public NarrowPhaseAlgorithm {
private :
bool computeCollisionTest(const BoxShape* obb1, const Transform& transform1,
const BoxShape* obb2, const Transform& transform2,
ContactInfo*& contactInfo) const; // Return true and compute a contact info if the two OBB collide
double computePenetrationDepth(double min1, double max1, double min2, double max2) const; // Compute the penetration depth of two projection intervals
Vector3 computeContactNormal(const Vector3& axis, const Vector3& distanceOfOBBs) const; // Compute a contact normal
public :
SATAlgorithm(); // Constructor
~SATAlgorithm(); // Destructor
virtual bool testCollision(const Body* body1, const Body* body2, ContactInfo*& contactInfo); // Return true and compute a contact info if the two bounding volume collide
};
// Return the contact normal with the correct sign (from obb1 toward obb2). "axis" is the axis vector direction where the
// collision occurs and "distanceOfOBBs" is the vector (obb2.center - obb1.center).
inline Vector3 SATAlgorithm::computeContactNormal(const Vector3& axis, const Vector3& distanceOfOBBs) const {
if (distanceOfOBBs.dot(axis) >= 0.0) {
return axis;
}
else {
return -axis;
}
}
} // End of the ReactPhysics3D namespace
#endif

38
src/configuration.h Normal file
View File

@ -0,0 +1,38 @@
/********************************************************************************
* 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 CONFIGURATION_H
#define CONFIGURATION_H
// Windows platform
#if defined(WIN32) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__WINDOWS__)
#define WINDOWS_OS
#elif defined(__APPLE__) // Apple platform
#define APPLE_OS
#elif defined(__linux__) || defined(linux) || defined(__linux) // Linux platform
#define LINUX_OS
#endif
#endif

View File

@ -50,7 +50,7 @@ const double OBJECT_MARGIN = 0.04; // Object margin for col
// Contact constants
const double FRICTION_COEFFICIENT = 0.4; // Friction coefficient
const double PENETRATION_FACTOR = 5.0; // Penetration factor (between 0 and 1) which specify the importance of the
const double DEFAULT_PENETRATION_FACTOR = 5.0; // Penetration factor (between 0 and 1) which specify the importance of the
// penetration depth in order to calculate the correct impulse for the contact
const double PERSISTENT_CONTACT_DIST_THRESHOLD = 0.02; // Distance threshold for two contact points for a valid persistent contact
@ -60,7 +60,7 @@ const int NB_MAX_CONSTRAINTS = 100000; // Maximum number of con
const int NB_MAX_COLLISION_PAIRS = 10000; // Maximum number of collision pairs of bodies (for memory pool allocation)
// Constraint solver constants
const uint MAX_LCP_ITERATIONS = 10; // Maximum number of iterations when solving a LCP problem
const uint DEFAULT_LCP_ITERATIONS = 15; // Number of iterations when solving a LCP problem
const double AV_COUNTER_LIMIT = 500; // Maximum number value of the avBodiesCounter or avConstraintsCounter
const double AV_PERCENT_TO_FREE = 0.5; // We will free the memory if the current nb of bodies (or constraints) is
// less than AV_PERCENT_TO_FREE * bodiesCapacity (or constraintsCapacity). This

View File

@ -33,10 +33,20 @@
#include "../constants.h"
#include "../mathematics/mathematics.h"
#include "../memory/MemoryPool.h"
#include "../configuration.h"
#include <new>
#ifdef VISUAL_DEBUG
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#if defined(VISUAL_DEBUG)
#if defined(APPLE_OS)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#elif defined(WINDOWS_OS)
#include <GL/glut.h>
#include <GL/gl.h>
#elif defined(LINUX_OS)
#include <GL/freeglut.h>
#include <GL/gl.h>
#endif
#endif
// ReactPhysics3D namespace
@ -148,7 +158,6 @@ inline double Contact::getPenetrationDepth() const {
#ifdef VISUAL_DEBUG
// 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);

View File

@ -33,8 +33,8 @@ using namespace std;
// Constructor
ConstraintSolver::ConstraintSolver(PhysicsWorld* world)
:physicsWorld(world), nbConstraints(0), nbIterationsLCP(MAX_LCP_ITERATIONS),
penetrationFactor(10.0) {
:physicsWorld(world), nbConstraints(0), nbIterationsLCP(DEFAULT_LCP_ITERATIONS),
penetrationFactor(DEFAULT_PENETRATION_FACTOR) {
}
@ -120,7 +120,7 @@ void ConstraintSolver::fillInMatrices() {
uint b=0;
for (set<Body*>::iterator it = constraintBodies.begin(); it != constraintBodies.end(); ++it, b++) {
body = *it;
uint bodyNumber = bodyNumberMapping.at(body);
uint bodyNumber = bodyNumberMapping[body];
// TODO : Use polymorphism and remove this downcasting
rigidBody = dynamic_cast<RigidBody*>(body);

View File

@ -26,17 +26,14 @@
#ifndef TIMER_H
#define TIMER_H
// TODO : Test this code on Windows platform
// TODO : Test this code on Linux platform
// Libraries
#include <stdexcept>
#include <iostream>
#include <ctime>
#include <cassert>
#include "../configuration.h"
#if defined(WIN32) || defined(_WIN32) // For Windows platform
#define WINDOWS_TIME
#if defined(WINDOWS_OS) // For Windows platform
#include <windows.h>
#else // For Mac OS or Linux platform
#include <sys/time.h>
@ -109,7 +106,7 @@ inline bool Timer::getIsRunning() const {
inline void Timer::start() {
if (!isRunning) {
#ifdef WINDOWS_TIME
#if defined(WINDOWS_OS)
LARGE_INTEGER ticksPerSecond;
LARGE_INTEGER ticks;
QueryPerformanceFrequency(&ticksPerSecond);
@ -157,7 +154,7 @@ inline double Timer::computeInterpolationFactor() {
inline void Timer::update() {
long double currentTime;
#ifdef WINDOWS_TIME
#if defined(WINDOWS_OS)
LARGE_INTEGER ticksPerSecond;
LARGE_INTEGER ticks;
QueryPerformanceFrequency(&ticksPerSecond);

View File

@ -397,7 +397,6 @@ inline std::vector<reactphysics3d::Vector3> clipPolygonWithRectangleInPlane(cons
reactphysics3d::Vector3 P = inputPolygon[(j+1) % inputPolygon.size()];
// If the point P is inside the clip plane
double test = planeNormal.dot(P-A);
if (planeNormal.dot(P-A) >= 0.0 - epsilon) {
// If the point S is also inside the clip plane
if (planeNormal.dot(S-A) >= 0.0 - epsilon) {

View File

@ -61,8 +61,8 @@ class MemoryPool {
struct Unit* pAllocatedLinkedList; // Pointer to the linked list of allocated memory units
struct Unit* pFreeLinkedList; // Pointer to the linked list of free memory units
size_t memorySize; // Total allocated memory in the pool
const uint maxNbObjects; // Maximum number of objects in the pool
uint currentNbObjects; // Current number of objects in the pool
const uint maxNbObjects; // Maximum number of objects in the pool
public:
MemoryPool(uint nbObjectsToAllocate) throw(std::bad_alloc); // Constructor

View File

@ -26,7 +26,7 @@
/********************************************************************************
* ReactPhysics3D *
* Version 0.01 *
* Version 0.02 *
* http://code.google.com/p/reactphysics3d/ *
* Daniel Chappuis *
********************************************************************************/
@ -35,6 +35,7 @@
#define REACTPHYSICS3D_H
// Libraries
#include "configuration.h"
#include "mathematics/mathematics.h"
#include "body/RigidBody.h"
#include "engine/PhysicsWorld.h"

View File

@ -25,10 +25,20 @@
// Libraries
#include "AABB.h"
#include "../configuration.h"
#include <cassert>
#ifdef VISUAL_DEBUG
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#if defined(VISUAL_DEBUG)
#if defined(APPLE_OS)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#elif defined(WINDOWS_OS)
#include <GL/glut.h>
#include <GL/gl.h>
#elif defined(LINUX_OS)
#include <GL/freeglut.h>
#include <GL/gl.h>
#endif
#endif
using namespace reactphysics3d;

View File

@ -25,12 +25,21 @@
// Libraries
#include "BoxShape.h"
#include "../configuration.h"
#include <vector>
#include <cassert>
#ifdef VISUAL_DEBUG
#include <GLUT/glut.h> // TODO : Remove this in the final version
#include <OpenGL/gl.h> // TODO : Remove this in the final version
#if defined(VISUAL_DEBUG)
#if defined(APPLE_OS)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#elif defined(WINDOWS_OS)
#include <GL/glut.h>
#include <GL/gl.h>
#elif defined(LINUX_OS)
#include <GL/freeglut.h>
#include <GL/gl.h>
#endif
#endif
using namespace reactphysics3d;

View File

@ -25,11 +25,20 @@
// Libraries
#include <complex>
#include "../configuration.h"
#include "ConeShape.h"
#ifdef VISUAL_DEBUG
#include <GLUT/glut.h> // TODO : Remove this in the final version
#include <OpenGL/gl.h> // TODO : Remove this in the final version
#if defined(VISUAL_DEBUG)
#if defined(APPLE_OS)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#elif defined(WINDOWS_OS)
#include <GL/glut.h>
#include <GL/gl.h>
#elif defined(LINUX_OS)
#include <GL/freeglut.h>
#include <GL/gl.h>
#endif
#endif
using namespace reactphysics3d;

View File

@ -25,9 +25,19 @@
// Libraries
#include "CylinderShape.h"
#ifdef VISUAL_DEBUG
#include <GLUT/glut.h> // TODO : Remove this in the final version
#include <OpenGL/gl.h> // TODO : Remove this in the final version
#include "../configuration.h"
#if defined(VISUAL_DEBUG)
#if defined(APPLE_OS)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#elif defined(WINDOWS_OS)
#include <GL/glut.h>
#include <GL/gl.h>
#elif defined(LINUX_OS)
#include <GL/freeglut.h>
#include <GL/gl.h>
#endif
#endif
using namespace reactphysics3d;

View File

@ -60,7 +60,7 @@ class Shape {
// Return the body pointer
inline Body* Shape::getBodyPointer() const {
assert(bodyPointer != NULL);
assert(bodyPointer != 0);
return bodyPointer;
}

View File

@ -25,11 +25,20 @@
// Libraries
#include "SphereShape.h"
#include "../configuration.h"
#include <cassert>
#ifdef VISUAL_DEBUG
#include <GLUT/glut.h> // TODO : Remove this in the final version
#include <OpenGL/gl.h> // TODO : Remove this in the final version
#if defined(VISUAL_DEBUG)
#if defined(APPLE_OS)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#elif defined(WINDOWS_OS)
#include <GL/glut.h>
#include <GL/gl.h>
#elif defined(LINUX_OS)
#include <GL/freeglut.h>
#include <GL/gl.h>
#endif
#endif
using namespace reactphysics3d;