Modifications before release
git-svn-id: https://reactphysics3d.googlecode.com/svn/trunk@454 92aac97c-a6ce-11dd-a772-7fcde58d38e6
This commit is contained in:
parent
55c1168b5d
commit
b82228d3ed
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
*/
|
|
@ -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
38
src/configuration.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -60,7 +60,7 @@ class Shape {
|
|||
|
||||
// Return the body pointer
|
||||
inline Body* Shape::getBodyPointer() const {
|
||||
assert(bodyPointer != NULL);
|
||||
assert(bodyPointer != 0);
|
||||
return bodyPointer;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user