Correction of a bug in collision detection and creation of new collision shapes

git-svn-id: https://reactphysics3d.googlecode.com/svn/trunk@434 92aac97c-a6ce-11dd-a772-7fcde58d38e6
This commit is contained in:
chappuis.daniel 2011-08-05 17:35:01 +00:00
parent 0de337cfe5
commit 00b9fc45dc
15 changed files with 395 additions and 105 deletions

View File

@ -43,7 +43,7 @@ Body::Body(const Transform& transform, Shape* shape, double mass)
oldTransform = transform;
// Create the AABB for broad-phase collision detection
aabb = new AABB(transform, shape->getLocalExtents());
aabb = new AABB(transform, shape->getLocalExtents(OBJECT_MARGIN));
}
// Destructor

View File

@ -151,7 +151,7 @@ inline void Body::updateOldTransform() {
// Update the rigid body in order to reflect a change in the body state
inline void Body::updateAABB() {
// Update the AABB
aabb->update(transform, shape->getLocalExtents());
aabb->update(transform, shape->getLocalExtents(OBJECT_MARGIN));
}

View File

@ -146,18 +146,18 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(Simplex simplex, cons
Vector3D v3 = rotationMat * v2;
// Compute the support point in the direction of v1
suppPointsA[2] = shape1->getSupportPoint(v1, OBJECT_MARGIN);
suppPointsB[2] = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * v1.getOpposite(), OBJECT_MARGIN);
suppPointsA[2] = shape1->getLocalSupportPoint(v1, OBJECT_MARGIN);
suppPointsB[2] = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * v1.getOpposite(), OBJECT_MARGIN);
points[2] = suppPointsA[2] - suppPointsB[2];
// Compute the support point in the direction of v2
suppPointsA[3] = shape1->getSupportPoint(v2, OBJECT_MARGIN);
suppPointsB[3] = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * v2.getOpposite(), OBJECT_MARGIN);
suppPointsA[3] = shape1->getLocalSupportPoint(v2, OBJECT_MARGIN);
suppPointsB[3] = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * v2.getOpposite(), OBJECT_MARGIN);
points[3] = suppPointsA[3] - suppPointsB[3];
// Compute the support point in the direction of v3
suppPointsA[4] = shape1->getSupportPoint(v3, OBJECT_MARGIN);
suppPointsB[4] = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * v3.getOpposite(), OBJECT_MARGIN);
suppPointsA[4] = shape1->getLocalSupportPoint(v3, OBJECT_MARGIN);
suppPointsB[4] = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * v3.getOpposite(), OBJECT_MARGIN);
points[4] = suppPointsA[4] - suppPointsB[4];
// Now we have an hexahedron (two tetrahedron glued together). We can simply keep the
@ -173,9 +173,9 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(Simplex simplex, cons
}
else if (isOriginInTetrahedron(points[1], points[2], points[3], points[4]) == 0) { // If the origin is in the tetrahedron of points 1, 2, 3, 4
// We use the point 4 instead of point 0 for the initial tetrahedron
suppPointsA[0] = suppPointsA[0];
suppPointsB[0] = suppPointsB[0];
points[0] = points[0];
suppPointsA[0] = suppPointsA[4];
suppPointsB[0] = suppPointsB[4];
points[0] = points[4];
}
else {
// The origin is not in the initial polytope
@ -251,11 +251,11 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(Simplex simplex, cons
Vector3D n = v1.cross(v2);
// Compute the two new vertices to obtain a hexahedron
suppPointsA[3] = shape1->getSupportPoint(n, OBJECT_MARGIN);
suppPointsB[3] = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * n.getOpposite(), OBJECT_MARGIN);
suppPointsA[3] = shape1->getLocalSupportPoint(n, OBJECT_MARGIN);
suppPointsB[3] = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * n.getOpposite(), OBJECT_MARGIN);
points[3] = suppPointsA[3] - suppPointsB[3];
suppPointsA[4] = shape1->getSupportPoint(n.getOpposite(), OBJECT_MARGIN);
suppPointsB[4] = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * n, OBJECT_MARGIN);
suppPointsA[4] = shape1->getLocalSupportPoint(n.getOpposite(), OBJECT_MARGIN);
suppPointsB[4] = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * n, OBJECT_MARGIN);
points[4] = suppPointsA[4] - suppPointsB[4];
// Construct the triangle faces
@ -324,8 +324,8 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(Simplex simplex, cons
}
// Compute the support point of the Minkowski difference (A-B) in the closest point direction
suppPointsA[nbVertices] = shape1->getSupportPoint(triangle->getClosestPoint(), OBJECT_MARGIN);
suppPointsB[nbVertices] = shape2ToShape1 *shape2->getSupportPoint(rotateToShape2 * triangle->getClosestPoint().getOpposite(), OBJECT_MARGIN);
suppPointsA[nbVertices] = shape1->getLocalSupportPoint(triangle->getClosestPoint(), OBJECT_MARGIN);
suppPointsB[nbVertices] = shape2ToShape1 *shape2->getLocalSupportPoint(rotateToShape2 * triangle->getClosestPoint().getOpposite(), OBJECT_MARGIN);
points[nbVertices] = suppPointsA[nbVertices] - suppPointsB[nbVertices];
int indexNewVertex = nbVertices;
@ -364,7 +364,6 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(Simplex simplex, cons
i++;
}
}
} while(nbTriangles > 0 && triangleHeap[0]->getDistSquare() <= upperBoundSquarePenDepth);
// Compute the contact info (in world-space)

View File

@ -37,8 +37,6 @@
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
// TODO : Check that allocated memory is correctly deleted
// Constructor
GJKAlgorithm::GJKAlgorithm() {
@ -91,15 +89,15 @@ bool GJKAlgorithm::testCollision(const Shape* shape1, const Transform& transform
// Get the last point V (last separating axis)
// TODO : Implement frame coherence. For each pair of body, store
// the last separating axis and use it to initialize the v vector
Vector3D v(0.0, 1.0, 0.0);
Vector3D v(1.0, 1.0, 1.0);
// Initialize the upper bound for the square distance
double distSquare = DBL_MAX;
do {
// Compute the support points for original objects (without margins) A and B
suppA = shape1->getSupportPoint(v.getOpposite());
suppB = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * v);
suppA = shape1->getLocalSupportPoint(v.getOpposite());
suppB = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * v);
// Compute the support point for the Minkowski difference A-B
w = suppA - suppB;
@ -208,10 +206,6 @@ bool GJKAlgorithm::testCollision(const Shape* shape1, const Transform& transform
// There is an intersection, therefore we return true
return true;
}
double test = simplex.getMaxLengthSquareOfAPoint(); // TODO : Remove this
test = 4.5;
} while(!simplex.isFull() && distSquare > MACHINE_EPSILON * simplex.getMaxLengthSquareOfAPoint());
// The objects (without margins) intersect. Therefore, we run the GJK algorithm again but on the
@ -245,8 +239,8 @@ bool GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const Shape* const
do {
// Compute the support points for the enlarged object A and B
suppA = shape1->getSupportPoint(v.getOpposite(), OBJECT_MARGIN);
suppB = shape2ToShape1 * shape2->getSupportPoint(rotateToShape2 * v, OBJECT_MARGIN);
suppA = shape1->getLocalSupportPoint(v.getOpposite(), OBJECT_MARGIN);
suppB = shape2ToShape1 * shape2->getLocalSupportPoint(rotateToShape2 * v, OBJECT_MARGIN);
// Compute the support point for the Minkowski difference A-B
w = suppA - suppB;

View File

@ -63,6 +63,7 @@ class Vector3D {
void setZ(double z); // Set the z component of the vector
void setAllValues(double x, double y, double z); // Set all the values of the vector
double length() const; // Return the lenght of the vector
double lengthSquare() const; // Return the square of the length of the vector
Vector3D getUnit() const throw(MathematicsException); // Return the corresponding unit vector
bool isUnit() const; // Return true if the vector is unit and false otherwise
bool isZero() const; // Return true if the current vector is the zero vector
@ -148,6 +149,11 @@ inline double Vector3D::length() const {
return sqrt(x*x + y*y + z*z);
}
// Return the square of the length of the vector
inline double Vector3D::lengthSquare() const {
return x*x + y*y + z*z;
}
// Return the vector in the opposite direction
inline Vector3D Vector3D::getOpposite() const {
return (Vector3D(0.0, 0.0, 0.0) - *this);

View File

@ -42,6 +42,7 @@
#include "shapes/BoxShape.h"
#include "shapes/SphereShape.h"
#include "shapes/ConeShape.h"
#include "shapes/CylinderShape.h"
#include "shapes/AABB.h"
// Alias to the ReactPhysics3D namespace

View File

@ -60,9 +60,9 @@ class AABB {
void setBodyPointer(Body* bodyPointer); // Set the body pointer
bool testCollision(const AABB& aabb) const; // Return true if the current AABB is overlapping is the AABB in argument
virtual void update(const Transform& newTransform, const Vector3D& extents); // Update the oriented bounding box orientation according to a new orientation of the rigid body
#ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the AABB (only for testing purpose)
#endif
#ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the AABB (only for testing purpose)
#endif
};
// Return the center point of the AABB in world coordinates
@ -93,22 +93,18 @@ inline void AABB::setBodyPointer(Body* bodyPointer) {
// Return true if the current AABB is overlapping with the AABB in argument
// Two AABB overlap if they overlap in the three x, y and z axis at the same time
inline bool AABB::testCollision(const AABB& aabb) const {
if (maxCoordinates.getX() + OBJECT_MARGIN < aabb.minCoordinates.getX() - OBJECT_MARGIN ||
aabb.maxCoordinates.getX() + OBJECT_MARGIN < minCoordinates.getX() - OBJECT_MARGIN) return false;
if (maxCoordinates.getY() + OBJECT_MARGIN < aabb.minCoordinates.getY() - OBJECT_MARGIN ||
aabb.maxCoordinates.getY() + OBJECT_MARGIN < minCoordinates.getY() - OBJECT_MARGIN) return false;
if (maxCoordinates.getZ() + OBJECT_MARGIN < aabb.minCoordinates.getZ() - OBJECT_MARGIN ||
aabb.maxCoordinates.getZ() + OBJECT_MARGIN < minCoordinates.getZ() - OBJECT_MARGIN) return false;
if (maxCoordinates.getX() < aabb.minCoordinates.getX() || aabb.maxCoordinates.getX() < minCoordinates.getX()) return false;
if (maxCoordinates.getY() < aabb.minCoordinates.getY() || aabb.maxCoordinates.getY() < minCoordinates.getY()) return false;
if (maxCoordinates.getZ() < aabb.minCoordinates.getZ() || aabb.maxCoordinates.getZ() < minCoordinates.getZ()) return false;
return true;
}
// Update the world minimum and maximum coordinates of the AABB on the three x,y and z axis
inline void AABB::update(const Transform& newTransform, const Vector3D& extents) {
Vector3D localExtents = extents + Vector3D(OBJECT_MARGIN, OBJECT_MARGIN, OBJECT_MARGIN);
Matrix3x3 worldAxis = newTransform.getOrientation().getAbsoluteMatrix();
Vector3D worldExtents = Vector3D(worldAxis.getColumn(0).dot(localExtents),
worldAxis.getColumn(1).dot(localExtents),
worldAxis.getColumn(2).dot(localExtents));
Vector3D worldExtents = Vector3D(worldAxis.getColumn(0).dot(extents),
worldAxis.getColumn(1).dot(extents),
worldAxis.getColumn(2).dot(extents));
minCoordinates = newTransform.getPosition() - worldExtents;
maxCoordinates = newTransform.getPosition() + worldExtents;
}

View File

@ -30,6 +30,9 @@
#include "Shape.h"
#include "../mathematics/mathematics.h"
// TODO : CHECK THAT THE AABB IS CORRECT
// TODO : TEST THIS SHAPE WITH GJK AND EPA ALGORITHMS
// ReactPhysics3D namespace
namespace reactphysics3d {
@ -38,7 +41,7 @@ namespace reactphysics3d {
This class represents a 3D box. Those axis are unit length.
The three extents are half-widths of the box along the three
axis x, y, z local axis. The "transform" of the corresponding
rigid body given an orientation and a position to the box
rigid body gives an orientation and a position to the box.
-------------------------------------------------------------------
*/
class BoxShape : public Shape {
@ -51,8 +54,8 @@ class BoxShape : public Shape {
const Vector3D& getExtent() const; // Return the extents of the box
void setExtent(const Vector3D& extent); // Set the extents of the box
virtual Vector3D getLocalExtents() const; // Return the local extents in x,y and z direction
virtual Vector3D getSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a support point in a given direction
virtual Vector3D getLocalExtents(double margin=0.0) const; // Return the local extents in x,y and z direction
virtual Vector3D getLocalSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a local support point in a given direction
#ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the Box (only for testing purpose)
@ -71,12 +74,12 @@ inline void BoxShape::setExtent(const Vector3D& extent) {
// Return the local extents of the shape (half-width) in x,y and z local direction
// This method is used to compute the AABB of the box
inline Vector3D BoxShape::getLocalExtents() const {
return extent;
inline Vector3D BoxShape::getLocalExtents(double margin) const {
return extent + Vector3D(margin, margin, margin);
}
// Return a support point in a given direction
inline Vector3D BoxShape::getSupportPoint(const Vector3D& direction, double margin) const {
// Return a local support point in a given direction
inline Vector3D BoxShape::getLocalSupportPoint(const Vector3D& direction, double margin) const {
assert(margin >= 0.0);
return Vector3D(direction.getX() < 0.0 ? -extent.getX()-margin : extent.getX()+margin,

View File

@ -1 +1,94 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2011 Daniel Chappuis *
*********************************************************************************
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
********************************************************************************/
// Libraries
#include <complex>
#include "ConeShape.h"
#ifdef VISUAL_DEBUG
#include <GL/freeglut.h> // TODO : Remove this in the final version
#include <GL/gl.h> // TODO : Remove this in the final version
#endif
using namespace reactphysics3d;
// Constructor
ConeShape::ConeShape(double radius, double height) : radius(radius), halfHeight(height/2.0) {
assert(radius > 0.0);
assert(halfHeight > 0.0);
// Compute the sine of the semi-angle at the apex point
sinTheta = radius / (sqrt(radius * radius + height * height));
}
// Destructor
ConeShape::~ConeShape() {
}
// Return a local support point in a given direction
inline Vector3D ConeShape::getLocalSupportPoint(const Vector3D& direction, double margin) const {
assert(margin >= 0.0);
const Vector3D& v = direction;
double sinThetaTimesLengthV = sinTheta * v.length();
Vector3D supportPoint;
if (v.getY() >= sinThetaTimesLengthV) {
supportPoint = Vector3D(0.0, halfHeight, 0.0);
}
else {
double projectedLength = sqrt(v.getX() * v.getX() + v.getZ() * v.getZ());
if (projectedLength > MACHINE_EPSILON) {
double d = radius / projectedLength;
supportPoint = Vector3D(v.getX() * d, -halfHeight, v.getZ() * d);
}
else {
supportPoint = Vector3D(radius, -halfHeight, 0.0);
}
}
// Add the margin to the support point
if (margin != 0.0) {
Vector3D unitVec(0.0, -1.0, 0.0);
if (v.lengthSquare() > MACHINE_EPSILON * MACHINE_EPSILON) {
unitVec = v.getUnit();
}
supportPoint = supportPoint + unitVec * margin;
}
return supportPoint;
}
#ifdef VISUAL_DEBUG
// Draw the cone (only for debuging purpose)
void ConeShape::draw() const {
// Draw in red
glColor3f(1.0, 0.0, 0.0);
// Draw the sphere
glutWireCone(radius, 2.0 * halfHeight, 50, 50);
}
#endif

View File

@ -29,27 +29,76 @@
#include "Shape.h"
#include "../mathematics/mathematics.h"
// TODO : CHECK THAT THE AABB IS CORRECT
// TODO : TEST THIS SHAPE WITH GJK AND EPA ALGORITHMS
// ReactPhysics3D namespace
namespace reactphysics3d {
/* -------------------------------------------------------------------
Class ConeShape :
This class represents a cone bounding volume.
This class represents a cone collision shape centered at the
origin and alligned with the Y axis. The cone is defined
by its height and by the radius of its base. The center of the
cone is at the half of the height. The "transform" of the
corresponding rigid body gives an orientation and a position
to the cone.
-------------------------------------------------------------------
*/
class ConeShape : public Shape {
private :
double radius; // Radius of the base
double halfHeight; // Half height of the cone
double sinTheta; // sine of the semi angle at the apex point
public :
ConeShape(); // Constructor
virtual ~ConeShape(); // Destructor
ConeShape(double radius, double height); // Constructor
virtual ~ConeShape(); // Destructor
double getRadius() const; // Return the radius
void setRadius(double radius); // Set the radius
double getHeight() const; // Return the height
void setHeight(double height); // Set the height
virtual Vector3D getLocalSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a support point in a given direction
virtual Vector3D getLocalExtents(double margin=0.0) const; // Return the local extents in x,y and z direction
#ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the sphere (only for testing purpose)
virtual void draw() const; // Draw the sphere (only for testing purpose)
#endif
};
// Return the radius
inline double ConeShape::getRadius() const {
return radius;
}
// Set the radius
inline void ConeShape::setRadius(double radius) {
this->radius = radius;
// Update sine of the semi-angle at the apex point
sinTheta = radius / (sqrt(radius * radius + 4 * halfHeight * halfHeight));
}
// Return the height
inline double ConeShape::getHeight() const {
return 2.0 * halfHeight;
}
// Set the height
inline void ConeShape::setHeight(double height) {
this->halfHeight = height / 2.0;
// Update the sine of the semi-angle at the apex point
sinTheta = radius / (sqrt(radius * radius + height * height));
}
// Return the local extents in x,y and z direction
inline Vector3D ConeShape::getLocalExtents(double margin) const {
return Vector3D(radius + margin, halfHeight + margin, radius + margin);
}
}; // End of the ReactPhysics3D namespace
#endif

View File

@ -0,0 +1,85 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2011 Daniel Chappuis *
*********************************************************************************
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
********************************************************************************/
// Libraries
#include "CylinderShape.h"
#ifdef VISUAL_DEBUG
#include <GL/freeglut.h> // TODO : Remove this in the final version
#include <GL/gl.h> // TODO : Remove this in the final version
#endif
using namespace reactphysics3d;
// Constructor
CylinderShape::CylinderShape(double radius, double height) : radius(radius), halfHeight(height/2.0) {
}
// Destructor
CylinderShape::~CylinderShape() {
}
// Return a local support point in a given direction
Vector3D CylinderShape::getLocalSupportPoint(const Vector3D& direction, double margin) const {
assert(margin >= 0.0);
Vector3D supportPoint(0.0, 0.0, 0.0);
double uDotv = direction.getY();
Vector3D w(direction.getX(), 0.0, direction.getZ());
double lengthW = sqrt(direction.getX() * direction.getX() + direction.getZ() * direction.getZ());
if (lengthW != 0.0) {
if (uDotv < 0.0) supportPoint.setY(-halfHeight);
else supportPoint.setY(halfHeight);
supportPoint = supportPoint + (radius / lengthW) * w;
}
else {
if (uDotv < 0.0) supportPoint.setY(-halfHeight);
else supportPoint.setY(halfHeight);
}
// Add the margin to the support point
if (margin != 0.0) {
Vector3D unitVec(0.0, 1.0, 0.0);
if (direction.lengthSquare() > MACHINE_EPSILON * MACHINE_EPSILON) {
unitVec = direction.getUnit();
}
supportPoint = supportPoint + unitVec * margin;
}
return supportPoint;
}
#ifdef VISUAL_DEBUG
// Draw the cone (only for debuging purpose)
void CylinderShape::draw() const {
// Draw in red
glColor3f(1.0, 0.0, 0.0);
// Draw the sphere
glutWireSphere(radius, 50, 50);
}
#endif

View File

@ -0,0 +1,96 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2011 Daniel Chappuis *
*********************************************************************************
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
********************************************************************************/
#ifndef CYLINDER_SHAPE_H
#define CYLINDER_SHAPE_H
// Libraries
#include "Shape.h"
#include "../mathematics/mathematics.h"
// TODO : CHECK THAT THE AABB IS CORRECT
// TODO : TEST THIS SHAPE WITH GJK AND EPA ALGORITHMS
// ReactPhysics3D namespace
namespace reactphysics3d {
/* -------------------------------------------------------------------
Class CylinderShape :
This class represents a cylinder collision shape around the Y axis
and centered at the origin. The cylinder is defined by its height
and the radius of its base. The "transform" of the corresponding
rigid body gives an orientation and a position to the cylinder.
-------------------------------------------------------------------
*/
class CylinderShape : public Shape {
private :
double radius; // Radius of the base
double halfHeight; // Half height of the cone
public :
CylinderShape(double radius, double height); // Constructor
virtual ~CylinderShape(); // Destructor
double getRadius() const; // Return the radius
void setRadius(double radius); // Set the radius
double getHeight() const; // Return the height
void setHeight(double height); // Set the height
virtual Vector3D getLocalSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a support point in a given direction
virtual Vector3D getLocalExtents(double margin=0.0) const; // Return the local extents in x,y and z direction
#ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the sphere (only for testing purpose)
#endif
};
// Return the radius
inline double CylinderShape::getRadius() const {
return radius;
}
// Set the radius
inline void CylinderShape::setRadius(double radius) {
this->radius = radius;
}
// Return the height
inline double CylinderShape::getHeight() const {
return halfHeight * 2.0;
}
// Set the height
inline void CylinderShape::setHeight(double height) {
this->halfHeight = height / 2.0;
}
// Return the local extents in x,y and z direction
inline Vector3D CylinderShape::getLocalExtents(double margin) const {
return Vector3D(radius + margin, halfHeight + margin, radius + margin);
}
}; // End of the ReactPhysics3D namespace
#endif

View File

@ -50,10 +50,10 @@ class Shape {
Shape(); // Constructor
virtual ~Shape(); // Destructor
Body* getBodyPointer() const; // Return the body pointer
void setBodyPointer(Body* bodyPointer); // Set the body pointer
virtual Vector3D getSupportPoint(const Vector3D& direction, double margin=0.0) const=0; // Return a support point in a given direction
virtual Vector3D getLocalExtents() const=0; // Return the local extents in x,y and z direction
Body* getBodyPointer() const; // Return the body pointer
void setBodyPointer(Body* bodyPointer); // Set the body pointer
virtual Vector3D getLocalSupportPoint(const Vector3D& direction, double margin=0.0) const=0; // Return a local support point in a given direction
virtual Vector3D getLocalExtents(double margin=0.0) const=0; // Return the local extents in x,y and z direction
};
// Return the body pointer

View File

@ -36,9 +36,8 @@ using namespace reactphysics3d;
using namespace std;
// Constructor
SphereShape::SphereShape(const Vector3D& center, double radius) {
this->center = center;
this->radius = radius;
SphereShape::SphereShape(double radius) : radius(radius) {
}
// Destructor
@ -53,17 +52,7 @@ void SphereShape::draw() const {
// Draw in red
glColor3f(1.0, 0.0, 0.0);
glTranslatef(center.getX(), center.getY(), center.getZ());
// Draw the sphere
glutWireSphere(radius, 50, 50);
}
#endif
/*TODO: DELETE THIS
// Return the corresponding AABB
AABB* BoundingSphere::computeAABB() const {
// Create and return the AABB
return new AABB(center, radius, radius, radius);
}
*/
#endif

View File

@ -34,43 +34,28 @@ namespace reactphysics3d {
/* -------------------------------------------------------------------
Class SphereShape :
This class represents a sphere bounding volume.
This class represents a sphere collision shape that is centered
at the origin and defined by its radius.
-------------------------------------------------------------------
*/
class SphereShape : public Shape {
private :
Vector3D center; // Center point of the sphere
double radius; // Radius of the sphere
public :
SphereShape(const Vector3D& center, double radius); // Constructor
virtual ~SphereShape(); // Destructor
SphereShape(double radius); // Constructor
virtual ~SphereShape(); // Destructor
Vector3D getCenter() const; // Return the center point of the sphere
void setCenter(const Vector3D& center); // Set the center point of the sphere
double getRadius() const; // Return the radius of the sphere
void setRadius(double radius); // Set the radius of the sphere
virtual void update(const Vector3D& newCenter,
const Quaternion& rotationQuaternion); // Update the sphere orientation according to a new orientation of the rigid body
// TODO : DELETE virtual AABB* computeAABB() const; // Return the corresponding AABB
virtual Vector3D getSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a support point in a given direction
virtual Vector3D getLocalExtents() const; // Return the local extents in x,y and z direction
double getRadius() const; // Return the radius of the sphere
void setRadius(double radius); // Set the radius of the sphere
virtual Vector3D getLocalSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a local support point in a given direction
virtual Vector3D getLocalExtents(double margin=0.0) const; // Return the local extents in x,y and z direction
#ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the sphere (only for testing purpose)
#endif
};
// Return the center point of the sphere
inline Vector3D SphereShape::getCenter() const {
return center;
}
// Set the center point of the sphere
inline void SphereShape::setCenter(const Vector3D& center) {
this->center = center;
}
// Get the radius of the sphere
inline double SphereShape::getRadius() const {
return radius;
@ -81,14 +66,8 @@ inline void SphereShape::setRadius(double radius) {
this->radius = radius;
}
// Update the orientation of the shere according to the orientation of the rigid body
inline void SphereShape::update(const Vector3D& newCenter, const Quaternion& rotationQuaternion) {
// Update the center of the sphere
center = newCenter;
}
// Return a support point in a given direction
inline Vector3D SphereShape::getSupportPoint(const Vector3D& direction, double margin) const {
// Return a local support point in a given direction
inline Vector3D SphereShape::getLocalSupportPoint(const Vector3D& direction, double margin) const {
assert(margin >= 0.0);
double length = direction.length();
@ -105,8 +84,8 @@ inline Vector3D SphereShape::getSupportPoint(const Vector3D& direction, double m
// Return the local extents of the shape (half-width) in x,y and z local direction
// This method is used to compute the AABB of the box
inline Vector3D SphereShape::getLocalExtents() const {
return Vector3D(radius, radius, radius);
inline Vector3D SphereShape::getLocalExtents(double margin) const {
return Vector3D(radius + margin, radius + margin, radius + margin);
}
}; // End of the ReactPhysics3D namespace