Add Transform and changes in code design

git-svn-id: https://reactphysics3d.googlecode.com/svn/trunk@428 92aac97c-a6ce-11dd-a772-7fcde58d38e6
This commit is contained in:
chappuis.daniel 2011-06-30 20:23:01 +00:00
parent 1e3543752f
commit bf8f9cf482
14 changed files with 228 additions and 668 deletions

View File

@ -26,24 +26,22 @@
#include "AABB.h" #include "AABB.h"
#include <cassert> #include <cassert>
#ifdef VISUAL_DEBUG #ifdef VISUAL_DEBUG
#include <GL/freeglut.h> // TODO : Remove this in the final version #include <GL/freeglut.h>
#include <GL/gl.h> // TODO : Remove this in the final version #include <GL/gl.h>
#endif #endif
using namespace reactphysics3d; using namespace reactphysics3d;
using namespace std; using namespace std;
// Constructor // Constructor
AABB::AABB(const Vector3D& center,double extentX, double extentY, double extentZ) { AABB::AABB(const Body* bodyPointer) : bodyPointer(bodyPointer) {
this->center = center;
this->extent[0] = extentX; }
this->extent[1] = extentY;
this->extent[2] = extentZ;
this->originalAABBExtent[0] = extentX; // Constructor
this->originalAABBExtent[1] = extentY; AABB::AABB(const Body* bodyPointer, const Transform& transform, const Vector3D& extents)
this->originalAABBExtent[2] = extentZ; : bodyPointer(bodyPointer) {
update(transform, extents);
} }
// Destructor // Destructor
@ -55,64 +53,48 @@ AABB::~AABB() {
// Draw the OBB (only for testing purpose) // Draw the OBB (only for testing purpose)
void AABB::draw() const { void AABB::draw() const {
Vector3D s1 = center + Vector3D(extent[0], extent[1], -extent[2]);
Vector3D s2 = center + Vector3D(extent[0], extent[1], extent[2]);
Vector3D s3 = center + Vector3D(-extent[0], extent[1], extent[2]);
Vector3D s4 = center + Vector3D(-extent[0], extent[1], -extent[2]);
Vector3D s5 = center + Vector3D(extent[0], -extent[1], -extent[2]);
Vector3D s6 = center + Vector3D(extent[0], -extent[1], extent[2]);
Vector3D s7 = center + Vector3D(-extent[0], -extent[1], extent[2]);
Vector3D s8 = center + Vector3D(-extent[0], -extent[1], -extent[2]);
// Draw in red // Draw in red
glColor3f(1.0, 0.0, 0.0); glColor3f(1.0, 0.0, 0.0);
// Draw the OBB // Draw the OBB
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex3f(s1.getX(), s1.getY(), s1.getZ()); glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s2.getX(), s2.getY(), s2.getZ()); glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s2.getX(), s2.getY(), s2.getZ()); glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s3.getX(), s3.getY(), s3.getZ()); glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s3.getX(), s3.getY(), s3.getZ()); glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s4.getX(), s4.getY(), s4.getZ()); glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s4.getX(), s4.getY(), s4.getZ()); glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s1.getX(), s1.getY(), s1.getZ()); glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s5.getX(), s5.getY(), s5.getZ()); glVertex3f(minCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s6.getX(), s6.getY(), s6.getZ()); glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s6.getX(), s6.getY(), s6.getZ()); glVertex3f(minCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s7.getX(), s7.getY(), s7.getZ()); glVertex3f(minCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s7.getX(), s7.getY(), s7.getZ()); glVertex3f(minCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s8.getX(), s8.getY(), s8.getZ()); glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s8.getX(), s8.getY(), s8.getZ()); glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s5.getX(), s5.getY(), s5.getZ()); glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s1.getX(), s1.getY(), s1.getZ()); glVertex3f(minCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s5.getX(), s5.getY(), s5.getZ()); glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s4.getX(), s4.getY(), s4.getZ()); glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s8.getX(), s8.getY(), s8.getZ()); glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
glVertex3f(s3.getX(), s3.getY(), s3.getZ()); glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s7.getX(), s7.getY(), s7.getZ()); glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s2.getX(), s2.getY(), s2.getZ()); glVertex3f(minCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
glVertex3f(s6.getX(), s6.getY(), s6.getZ()); glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
glEnd(); glEnd();
} }
#endif #endif
// Static method that computes an AABB from a set of vertices. The "center" argument corresponds to the center of the AABB
// This method allocates a new AABB object and return a pointer to the new allocated AABB object
AABB* AABB::computeFromVertices(const vector<Vector3D>& vertices, const Vector3D& center) {
// TODO : Implement this method;
return NULL;
}

View File

@ -26,12 +26,14 @@
#define AABB_H #define AABB_H
// Libraries // Libraries
#include "BroadBoundingVolume.h"
#include "../mathematics/mathematics.h" #include "../mathematics/mathematics.h"
// ReactPhysics3D namespace // ReactPhysics3D namespace
namespace reactphysics3d { namespace reactphysics3d {
// Declaration
class Body;
/* ------------------------------------------------------------------- /* -------------------------------------------------------------------
Class AABB : Class AABB :
This class represents a bounding volume of type "Axis Aligned This class represents a bounding volume of type "Axis Aligned
@ -40,109 +42,46 @@ namespace reactphysics3d {
point and three extent size in the x,y and z directions. point and three extent size in the x,y and z directions.
------------------------------------------------------------------- -------------------------------------------------------------------
*/ */
class AABB : public BroadBoundingVolume { class AABB {
protected : private :
Vector3D center; // Center point of the AABB Vector3D minCoordinates; // Minimum world coordinates of the AABB on the x,y and z axis
double extent[3]; // Three extents size in the x, y and z directions Vector3D maxCoordinates; // Maximum world coordinates of the AABB on the x,y and z axis
double originalAABBExtent[3]; // Extents of the original AABB (this is used to update the AABB) const Body* bodyPointer; // Pointer to the owner body
public : public :
AABB(const Vector3D& center, double extentX, double extentY, double extentZ); // Constructor AABB(const Body* body); // Constructor
AABB(const Body* bodyPointer, const Transform& transform, const Vector3D& extents); // Constructor
virtual ~AABB(); // Destructor virtual ~AABB(); // Destructor
Vector3D getCenter() const; // Return the center point Vector3D getCenter() const; // Return the center point
void setCenter(const Vector3D& center); // Set the center point const Vector3D& getMinCoordinates() const; // Return the minimum coordinates of the AABB
Vector3D getVertex(uint index) const throw (std::invalid_argument); // Return a vertex of the AABB const Vector3D& getMaxCoordinates() const; // Return the maximum coordinates of the AABB
double getExtent(uint index) const throw(std::invalid_argument); // Return an extent value const Body* getBodyPointer() const; // Return a pointer to the owner body
void setExtent(uint index, double extent) throw(std::invalid_argument); // Set an extent value
double getMinValueOnAxis(uint axis) const throw(std::invalid_argument); // Return the minimum position value on the given axis
double getMaxValueOnAxis(uint axis) const throw(std::invalid_argument); // Return the maximum position value on the given axis
bool testCollision(const AABB& aabb) const; // Return true if the current AABB is overlapping is the AABB in argument bool testCollision(const AABB& aabb) const; // Return true if the current AABB is overlapping is the AABB in argument
virtual void update(const Vector3D& newCenter, const Quaternion& rotationQuaternion); // Update the oriented bounding box orientation according to a new orientation of the rigid body 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 #ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the AABB (only for testing purpose) virtual void draw() const; // Draw the AABB (only for testing purpose)
#endif #endif
static AABB* computeFromVertices(const std::vector<Vector3D>& vertices, const Vector3D& center); // Compute an AABB from a set of vertices
}; };
// Return the center point // Return the center point of the AABB in world coordinates
inline Vector3D AABB::getCenter() const { inline Vector3D AABB::getCenter() const {
return center; return (minCoordinates + maxCoordinates) * 0.5;
} }
// Set the center point // Return the minimum coordinates of the AABB
inline void AABB::setCenter(const Vector3D& center) { inline const Vector3D& AABB::getMinCoordinates() const {
this->center = center; return minCoordinates;
} }
// Return one of the 8 vertices of the AABB // Return the maximum coordinates of the AABB
inline Vector3D AABB::getVertex(unsigned int index) const throw (std::invalid_argument) { inline const Vector3D& AABB::getMaxCoordinates() const {
// Check if the index value is valid return maxCoordinates;
if (index >= 0 && index <8) {
switch(index) {
case 0 : return center + Vector3D(extent[0], extent[1], -extent[2]);
case 1 : return center + Vector3D(extent[0], extent[1], extent[2]);
case 2 : return center + Vector3D(-extent[0], extent[1], extent[2]);
case 3 : return center + Vector3D(-extent[0], extent[1], -extent[2]);
case 4 : return center + Vector3D(extent[0], -extent[1], -extent[2]);
case 5 : return center + Vector3D(extent[0], -extent[1], extent[2]);
case 6 : return center + Vector3D(-extent[0], -extent[1], extent[2]);
case 7 : return center + Vector3D(-extent[0], -extent[1], -extent[2]);
}
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 8");
}
} }
// Return a pointer to the owner body
// Return an extent value inline const Body* AABB::getBodyPointer() const {
inline double AABB::getExtent(unsigned int index) const throw(std::invalid_argument) { return bodyPointer;
// Check if the index value is valid
if (index >= 0 && index <3) {
return extent[index];
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Set an extent value
inline void AABB::setExtent(unsigned int index, double extent) throw(std::invalid_argument) {
// Check if the index value is valid
if (index >= 0 && index <3) {
this->extent[index] = extent;
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Return the minimum position value on the given axis
// We consider the object margin here
inline double AABB::getMinValueOnAxis(uint axis) const throw(std::invalid_argument) {
switch (axis) {
case 0: return center.getX() - extent[0] - OBJECT_MARGIN;
case 1: return center.getY() - extent[1] - OBJECT_MARGIN;
case 2: return center.getZ() - extent[2] - OBJECT_MARGIN;
default: // The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Return the maximum position value on the given axis
// We consider the object margin here
inline double AABB::getMaxValueOnAxis(uint axis) const throw(std::invalid_argument) {
switch (axis) {
case 0: return center.getX() + extent[0] + OBJECT_MARGIN;
case 1: return center.getY() + extent[1] + OBJECT_MARGIN;
case 2: return center.getZ() + extent[2] + OBJECT_MARGIN;
default: // The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
} }
// Return true if the current AABB is overlapping with the AABB in argument // Return true if the current AABB is overlapping with the AABB in argument
@ -150,32 +89,24 @@ inline double AABB::getMaxValueOnAxis(uint axis) const throw(std::invalid_argume
inline bool AABB::testCollision(const AABB& aabb) const { inline bool AABB::testCollision(const AABB& aabb) const {
Vector3D center2 = aabb.getCenter(); Vector3D center2 = aabb.getCenter();
double margin = 2 * OBJECT_MARGIN; double margin = 2 * OBJECT_MARGIN;
if (std::abs(center.getX() - center2.getX()) > (extent[0] + aabb.getExtent(0) + margin)) return false; if (maxCoordinates.getX() + OBJECT_MARGIN < aabb.minCoordinates.getX() - OBJECT_MARGIN ||
if (std::abs(center.getY() - center2.getY()) > (extent[1] + aabb.getExtent(1) + margin)) return false; aabb.maxCoordinates.getX() + OBJECT_MARGIN < minCoordinates.getX() - OBJECT_MARGIN) return false;
if (std::abs(center.getZ() - center2.getZ()) > (extent[2] + aabb.getExtent(2) + 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;
return true; return true;
} }
// Update the orientation of the AABB according to the orientation of the rigid body // Update the world minimum and maximum coordinates of the AABB on the three x,y and z axis
// In order to compute the new AABB we use the original AABB (represented by the originalAABBExtent inline void AABB::update(const Transform& newTransform, const Vector3D& extents) {
// values). The goal is to rotate the original AABB according to the current rotation (rotationQuaternion) Vector3D localExtents = extents + Vector3D(OBJECT_MARGIN, OBJECT_MARGIN, OBJECT_MARGIN);
// and then compute the new extent values from the rotated axis of the original AABB. The three columns of Matrix3x3 worldAxis = newTransform.getOrientation().getAbsoluteMatrix();
// the rotation matrix correspond to the rotated axis of the rotated original AABB. The we have to compute Vector3D worldExtents = Vector3D(worldAxis.getColumn(0).dot(localExtents),
// the projections of the three rotated axis onto the x, y and z axis. The projections are easy to compute worldAxis.getColumn(1).dot(localExtents),
// because for instance if the size of the projection of the vector (4, 5, 6) onto the x axis is simply 4. worldAxis.getColumn(2).dot(localExtents));
inline void AABB::update(const Vector3D& newCenter, const Quaternion& rotationQuaternion) { minCoordinates = newTransform.getPosition() - worldExtents;
// Update the center of the AABB maxCoordinates = newTransform.getPosition() + worldExtents;
center = newCenter;
// Recompute the new extents size from the rotated AABB
Matrix rotationMatrix = rotationQuaternion.getMatrix(); // Rotation matrix
for (int i=0; i<3; i++) { // For each x, y and z axis
extent[i] = 0.0;
for (int j=0; j<3; j++) { // For each rotated axis of the rotated original AABB
// Add the size of the projection of the current rotated axis to the extent of the current (x, y, or z) axis
extent[i] += std::abs(rotationMatrix.getValue(i, j)) * originalAABBExtent[j];
}
}
} }
}; // End of the ReactPhysics3D namespace }; // End of the ReactPhysics3D namespace

View File

@ -31,31 +31,45 @@
using namespace reactphysics3d; using namespace reactphysics3d;
// Constructor // Constructor
Body::Body(double mass) throw(std::invalid_argument) Body::Body(const Transform& transform, double mass) throw(std::invalid_argument)
: mass(mass), broadBoundingVolume(0), narrowBoundingVolume(0) { : transform(transform), mass(mass), narrowBoundingVolume(0), aabb(0) {
// Check if the mass is not larger than zero // Check if the mass is not larger than zero
if (mass <= 0.0) { if (mass <= 0.0) {
// We throw an exception // We throw an exception
throw std::invalid_argument("Exception in Body constructor : the mass has to be different larger than zero"); throw std::invalid_argument("Exception in Body constructor : the mass has to be different larger than zero");
} }
// Initialize the old transform
oldTransform = transform;
// Create the AABB for Broad-Phase collision detection
aabb = new AABB(this);
} }
// Destructor // Destructor
Body::~Body() { Body::~Body() {
/* TODO : DELETE THIS
if (broadBoundingVolume) { if (broadBoundingVolume) {
delete broadBoundingVolume; delete broadBoundingVolume;
} }
*/
if (narrowBoundingVolume) { if (narrowBoundingVolume) {
delete narrowBoundingVolume; delete narrowBoundingVolume;
} }
// Delete the AABB
delete aabb;
} }
/* TODO : DELETE THIS
// Set the broad-phase bounding volume // Set the broad-phase bounding volume
void Body::setBroadBoundingVolume(BroadBoundingVolume* broadBoundingVolume) { void Body::setBroadBoundingVolume(BroadBoundingVolume* broadBoundingVolume) {
assert(broadBoundingVolume); assert(broadBoundingVolume);
this->broadBoundingVolume = broadBoundingVolume; this->broadBoundingVolume = broadBoundingVolume;
broadBoundingVolume->setBodyPointer(this); broadBoundingVolume->setBodyPointer(this);
} }
*/
// Set the narrow-phase bounding volume // Set the narrow-phase bounding volume
void Body::setNarrowBoundingVolume(NarrowBoundingVolume* narrowBoundingVolume) { void Body::setNarrowBoundingVolume(NarrowBoundingVolume* narrowBoundingVolume) {

View File

@ -28,12 +28,12 @@
// Libraries // Libraries
#include <stdexcept> #include <stdexcept>
#include <cassert> #include <cassert>
#include "../mathematics/Transform.h"
#include "../body/AABB.h"
// Namespace reactphysics3d // Namespace reactphysics3d
namespace reactphysics3d { namespace reactphysics3d {
class BroadBoundingVolume;
class NarrowBoundingVolume; class NarrowBoundingVolume;
/* ------------------------------------------------------------------- /* -------------------------------------------------------------------
@ -45,26 +45,34 @@ class NarrowBoundingVolume;
class Body { class Body {
protected : protected :
double mass; // Mass of the body double mass; // Mass of the body
BroadBoundingVolume* broadBoundingVolume; // Bounding volume used for the broad-phase collision detection Transform transform; // Position and orientation of the body
Transform oldTransform; // Last position and orientation of the body
double interpolationFactor; // Interpolation factor used for the state interpolation
// TODO : DELETE BroadBoundingVolume* broadBoundingVolume; // Bounding volume used for the broad-phase collision detection
NarrowBoundingVolume* narrowBoundingVolume; // Bounding volume used for the narrow-phase collision detection NarrowBoundingVolume* narrowBoundingVolume; // Bounding volume used for the narrow-phase collision detection
bool isMotionEnabled; // True if the body is able to move bool isMotionEnabled; // True if the body is able to move
bool isCollisionEnabled; // True if the body can collide with others bodies bool isCollisionEnabled; // True if the body can collide with others bodies
AABB* aabb; // Axis-Aligned Bounding Box for Broad-Phase collision detection
void setBroadBoundingVolume(BroadBoundingVolume* broadBoundingVolume); // Set the broad-phase bounding volume
void setNarrowBoundingVolume(NarrowBoundingVolume* narrowBoundingVolume); // Set the narrow-phase bounding volume void setNarrowBoundingVolume(NarrowBoundingVolume* narrowBoundingVolume); // Set the narrow-phase bounding volume
public : public :
Body(double mass) throw(std::invalid_argument); // Constructor Body(const Transform& transform, double mass) throw(std::invalid_argument); // Constructor
virtual ~Body(); // Destructor virtual ~Body(); // Destructor
double getMass() const; // Return the mass of the body double getMass() const; // Return the mass of the body
void setMass(double mass); // Set the mass of the body void setMass(double mass); // Set the mass of the body
const Transform& getTransform() const; // Return the current position and orientation
void setTransform(const Transform& transform); // Set the current position and orientation
const AABB* getAABB() const; // Return the AAABB of the body
Transform getInterpolatedTransform() const; // Return the interpolated transform for rendering
void setInterpolationFactor(double factor); // Set the interpolation factor of the body
bool getIsMotionEnabled() const; // Return if the rigid body can move bool getIsMotionEnabled() const; // Return if the rigid body can move
void setIsMotionEnabled(bool isMotionEnabled); // Set the value to true if the body can move void setIsMotionEnabled(bool isMotionEnabled); // Set the value to true if the body can move
bool getIsCollisionEnabled() const; // Return true if the body can collide with others bodies bool getIsCollisionEnabled() const; // Return true if the body can collide with others bodies
void setIsCollisionEnabled(bool isCollisionEnabled); // Set the isCollisionEnabled value void setIsCollisionEnabled(bool isCollisionEnabled); // Set the isCollisionEnabled value
const BroadBoundingVolume* getBroadBoundingVolume() const; // Return the broad-phase bounding volume
const NarrowBoundingVolume* getNarrowBoundingVolume() const; // Return the narrow-phase bounding volume of the body const NarrowBoundingVolume* getNarrowBoundingVolume() const; // Return the narrow-phase bounding volume of the body
void updateOldTransform(); // Update the old transform with the current one
}; };
// Method that return the mass of the body // Method that return the mass of the body
@ -72,6 +80,17 @@ inline double Body::getMass() const {
return mass; return mass;
}; };
// Return the interpolated transform for rendering
inline Transform Body::getInterpolatedTransform() const {
return Transform::interpolateTransforms(oldTransform, transform, interpolationFactor);
}
// Set the interpolation factor of the body
inline void Body::setInterpolationFactor(double factor) {
// Set the factor
interpolationFactor = factor;
}
// Return if the rigid body can move // Return if the rigid body can move
inline bool Body::getIsMotionEnabled() const { inline bool Body::getIsMotionEnabled() const {
return isMotionEnabled; return isMotionEnabled;
@ -87,6 +106,21 @@ inline void Body::setMass(double mass) {
this->mass = mass; this->mass = mass;
} }
// Return the current position and orientation
inline const Transform& Body::getTransform() const {
return transform;
}
// Set the current position and orientation
inline void Body::setTransform(const Transform& transform) {
this->transform = transform;
}
// Return the AAABB of the body
inline const AABB* Body::getAABB() const {
return aabb;
}
// Return true if the body can collide with others bodies // Return true if the body can collide with others bodies
inline bool Body::getIsCollisionEnabled() const { inline bool Body::getIsCollisionEnabled() const {
return isCollisionEnabled; return isCollisionEnabled;
@ -97,16 +131,25 @@ inline void Body::setIsCollisionEnabled(bool isCollisionEnabled) {
this->isCollisionEnabled = isCollisionEnabled; this->isCollisionEnabled = isCollisionEnabled;
} }
/* TODO : DELETE
// Return the broad-phase bounding volume // Return the broad-phase bounding volume
inline const BroadBoundingVolume* Body::getBroadBoundingVolume() const { inline const BroadBoundingVolume* Body::getBroadBoundingVolume() const {
return broadBoundingVolume; return broadBoundingVolume;
} }
*/
// Return the oriented bounding box of the rigid body // Return the oriented bounding box of the rigid body
inline const NarrowBoundingVolume* Body::getNarrowBoundingVolume() const { inline const NarrowBoundingVolume* Body::getNarrowBoundingVolume() const {
return narrowBoundingVolume; return narrowBoundingVolume;
} }
// Update the old transform with the current one
// This is used to compute the interpolated position and orientation of the body
inline void Body::updateOldTransform() {
oldTransform = transform;
}
} }
#endif #endif

View File

@ -60,9 +60,10 @@ void BoundingSphere::draw() const {
} }
#endif #endif
/*TODO: DELETE THIS
// Return the corresponding AABB // Return the corresponding AABB
AABB* BoundingSphere::computeAABB() const { AABB* BoundingSphere::computeAABB() const {
// Create and return the AABB // Create and return the AABB
return new AABB(center, radius, radius, radius); return new AABB(center, radius, radius, radius);
} }
*/

View File

@ -52,8 +52,9 @@ class BoundingSphere : public NarrowBoundingVolume {
void setRadius(double radius); // Set the radius of the sphere void setRadius(double radius); // Set the radius of the sphere
virtual void update(const Vector3D& newCenter, virtual void update(const Vector3D& newCenter,
const Quaternion& rotationQuaternion); // Update the sphere orientation according to a new orientation of the rigid body const Quaternion& rotationQuaternion); // Update the sphere orientation according to a new orientation of the rigid body
virtual AABB* computeAABB() const; // Return the corresponding AABB // 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 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
#ifdef VISUAL_DEBUG #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)
@ -94,12 +95,18 @@ inline Vector3D BoundingSphere::getSupportPoint(const Vector3D& direction, doubl
// If the direction vector is not the zero vector // If the direction vector is not the zero vector
if (length > 0.0) { if (length > 0.0) {
// Return the support point of the sphere in the given direction // Return the support point of the sphere in the given direction
return center + (radius + margin) * direction.getUnit(); return (radius + margin) * direction.getUnit();
} }
// If the direction vector is the zero vector we return a point on the // If the direction vector is the zero vector we return a point on the
// boundary of the sphere // boundary of the sphere
return center + Vector3D(0, radius + margin, 0); return Vector3D(0, radius + margin, 0);
}
// 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 BoundingSphere::getLocalExtents() const {
return Vector3D(radius, radius, radius);
} }
}; // End of the ReactPhysics3D namespace }; // End of the ReactPhysics3D namespace

View File

@ -52,7 +52,7 @@ class BoundingVolume {
Body* getBodyPointer() const; // Return the body pointer Body* getBodyPointer() const; // Return the body pointer
void setBodyPointer(Body* body); // Set the body pointer void setBodyPointer(Body* body); // Set the body pointer
virtual void update(const Vector3D& newCenter, const Quaternion& rotationQuaternion)=0; // Update the orientation of the bounding volume according to the new orientation of the body
#ifdef VISUAL_DEBUG #ifdef VISUAL_DEBUG
virtual void draw() const=0; // Display the bounding volume (only for testing purpose) virtual void draw() const=0; // Display the bounding volume (only for testing purpose)
#endif #endif

View File

@ -1,39 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010 Daniel Chappuis *
*********************************************************************************
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
********************************************************************************/
// Libraries
#include "BroadBoundingVolume.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Constructor
BroadBoundingVolume::BroadBoundingVolume() : BoundingVolume() {
}
// Destructor
BroadBoundingVolume::~BroadBoundingVolume() {
}

View File

@ -1,52 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010 Daniel Chappuis *
*********************************************************************************
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
********************************************************************************/
#ifndef BROAD_BOUNDING_VOLUME_H
#define BROAD_BOUNDING_VOLUME_H
// Libraries
#include "BoundingVolume.h"
// ReactPhysics3D namespace
namespace reactphysics3d {
/* -------------------------------------------------------------------
Class BroadBoundingVolume :
This class represents the volume that contains a rigid body
This volume will be used to compute the broad-phase collision
detection.
-------------------------------------------------------------------
*/
class BroadBoundingVolume : public BoundingVolume {
protected :
public :
BroadBoundingVolume(); // Constructor
virtual ~BroadBoundingVolume(); // Destructor
};
}
#endif

View File

@ -48,8 +48,9 @@ class NarrowBoundingVolume : public BoundingVolume {
NarrowBoundingVolume(); // Constructor NarrowBoundingVolume(); // Constructor
virtual ~NarrowBoundingVolume(); // Destructor virtual ~NarrowBoundingVolume(); // Destructor
virtual AABB* computeAABB() const=0; // Return the corresponding AABB // TODO : DELETE virtual AABB* computeAABB() const=0; // Return the corresponding AABB
virtual Vector3D getSupportPoint(const Vector3D& direction, double margin=0.0) const=0; // Return a support point in a given direction 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
}; };
} }

View File

@ -36,21 +36,8 @@ using namespace reactphysics3d;
using namespace std; using namespace std;
// Constructor // Constructor
OBB::OBB(const Vector3D& center, const Vector3D& axis1, const Vector3D& axis2, OBB::OBB(const Vector3D& extent) : extent(extent) {
const Vector3D& axis3, double extent1, double extent2, double extent3) {
this->center = center;
oldAxis[0] = axis1.getUnit();
oldAxis[1] = axis2.getUnit();
oldAxis[2] = axis3.getUnit();
this->axis[0] = oldAxis[0];
this->axis[1] = oldAxis[1];
this->axis[2] = oldAxis[2];
this->extent[0] = extent1;
this->extent[1] = extent2;
this->extent[2] = extent3;
} }
// Destructor // Destructor
@ -61,155 +48,51 @@ OBB::~OBB() {
#ifdef VISUAL_DEBUG #ifdef VISUAL_DEBUG
// Draw the OBB (only for testing purpose) // Draw the OBB (only for testing purpose)
void OBB::draw() const { void OBB::draw() const {
double e0 = extent[0]; double e1 = extent.getX();
double e1 = extent[1]; double e2 = extent.getY();
double e2 = extent[2]; double e3 = extent.getZ();
Vector3D s1 = center + (axis[0]*e0) + (axis[1]*e1) - (axis[2]*e2);
Vector3D s2 = center + (axis[0]*e0) + (axis[1]*e1) + (axis[2]*e2);
Vector3D s3 = center - (axis[0]*e0) + (axis[1]*e1) + (axis[2]*e2);
Vector3D s4 = center - (axis[0]*e0) + (axis[1]*e1) - (axis[2]*e2);
Vector3D s5 = center + (axis[0]*e0) - (axis[1]*e1) - (axis[2]*e2);
Vector3D s6 = center + (axis[0]*e0) - (axis[1]*e1) + (axis[2]*e2);
Vector3D s7 = center - (axis[0]*e0) - (axis[1]*e1) + (axis[2]*e2);
Vector3D s8 = center - (axis[0]*e0) - (axis[1]*e1) - (axis[2]*e2);
// Draw in red // Draw in red
glColor3f(1.0, 0.0, 0.0); glColor3f(1.0, 0.0, 0.0);
// Draw the OBB // Draw the OBB
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex3f(s1.getX(), s1.getY(), s1.getZ()); glVertex3f(e1, -e2, -e3);
glVertex3f(s2.getX(), s2.getY(), s2.getZ()); glVertex3f(e1, e2, -e3);
glVertex3f(s2.getX(), s2.getY(), s2.getZ()); glVertex3f(e1, -e2, -e3);
glVertex3f(s3.getX(), s3.getY(), s3.getZ()); glVertex3f(e1, -e2, e3);
glVertex3f(s3.getX(), s3.getY(), s3.getZ()); glVertex3f(e1, -e2, e3);
glVertex3f(s4.getX(), s4.getY(), s4.getZ()); glVertex3f(e1, e2, e3);
glVertex3f(s4.getX(), s4.getY(), s4.getZ()); glVertex3f(e1, e2, e3);
glVertex3f(s1.getX(), s1.getY(), s1.getZ()); glVertex3f(e1, e2, -e3);
glVertex3f(s5.getX(), s5.getY(), s5.getZ()); glVertex3f(-e1, -e2, -e3);
glVertex3f(s6.getX(), s6.getY(), s6.getZ()); glVertex3f(-e1, e2, -e3);
glVertex3f(s6.getX(), s6.getY(), s6.getZ()); glVertex3f(-e1, -e2, -e3);
glVertex3f(s7.getX(), s7.getY(), s7.getZ()); glVertex3f(-e1, -e2, e3);
glVertex3f(s7.getX(), s7.getY(), s7.getZ()); glVertex3f(-e1, -e2, e3);
glVertex3f(s8.getX(), s8.getY(), s8.getZ()); glVertex3f(-e1, e2, e3);
glVertex3f(s8.getX(), s8.getY(), s8.getZ()); glVertex3f(-e1, e2, e3);
glVertex3f(s5.getX(), s5.getY(), s5.getZ()); glVertex3f(-e1, e2, -e3);
glVertex3f(s1.getX(), s1.getY(), s1.getZ()); glVertex3f(e1, -e2, -e3);
glVertex3f(s5.getX(), s5.getY(), s5.getZ()); glVertex3f(-e1, -e2, -e3);
glVertex3f(s4.getX(), s4.getY(), s4.getZ()); glVertex3f(e1, -e2, -e3);
glVertex3f(s8.getX(), s8.getY(), s8.getZ()); glVertex3f(-e1, -e2, -e3);
glVertex3f(s3.getX(), s3.getY(), s3.getZ()); glVertex3f(e1, -e2, e3);
glVertex3f(s7.getX(), s7.getY(), s7.getZ()); glVertex3f(-e1, -e2, e3);
glVertex3f(s2.getX(), s2.getY(), s2.getZ()); glVertex3f(e1, e2, e3);
glVertex3f(s6.getX(), s6.getY(), s6.getZ()); glVertex3f(-e1, e2, e3);
glVertex3f(center.getX(), center.getY(), center.getZ());
glVertex3f(center.getX() + 8.0 * axis[1].getX(), center.getY() + 8.0 * axis[1].getY(), center.getZ() + 8.0 * axis[1].getZ());
glEnd(); glEnd();
} }
#endif #endif
// Return all the vertices that are projected at the extreme of the projection of the bouding volume on the axis.
// If the extreme vertices are part of a face of the OBB, the returned vertices will be ordered according to the face.
vector<Vector3D> OBB::getExtremeVertices(const Vector3D& directionAxis) const {
assert(directionAxis.length() != 0);
vector<Vector3D> extremeVertices;
// Check if the given axis is parallel to an axis on the OBB
if (axis[0].isParallelWith(directionAxis)) {
if (axis[0].dot(directionAxis) >= 0) { // If both axis are in the same direction
extremeVertices = getFace(0); // The extreme is the face 0
}
else {
extremeVertices = getFace(1); // The extreme is the face 1
}
}
else if(axis[1].isParallelWith(directionAxis)) {
if (axis[1].dot(directionAxis) >= 0) { // If both axis are in the same direction
extremeVertices = getFace(2); // The extreme is the face 2
}
else {
extremeVertices = getFace(3); // The extreme is the face 3
}
}
else if(axis[2].isParallelWith(directionAxis)) {
if (axis[2].dot(directionAxis) >= 0) { // If both axis are in the same direction
extremeVertices = getFace(4); // The extreme is the face 4
}
else {
extremeVertices = getFace(5); // The extreme is the face 5
}
}
else { // The extreme is made of an unique vertex or an edge
double maxProjectionLength = 0.0; // Longest projection length of a vertex onto the projection axis
// For each vertex of the OBB
for (unsigned int i=0; i<8; ++i) {
Vector3D vertex = getVertex(i);
// Compute the projection length of the current vertex onto the projection axis
double projectionLength = directionAxis.dot(vertex-center) / directionAxis.length();
// If we found a bigger projection length
if (projectionLength > maxProjectionLength + EPSILON_TEST) {
maxProjectionLength = projectionLength;
extremeVertices.clear();
extremeVertices.push_back(vertex);
}
else if (approxEqual(projectionLength, maxProjectionLength)) {
extremeVertices.push_back(vertex);
}
}
assert(extremeVertices.size() == 1 || extremeVertices.size() == 2);
}
// An extreme should be a unique vertex, an edge or a face
assert(extremeVertices.size() == 1 || extremeVertices.size() == 2 || extremeVertices.size() == 4);
// Return the extreme vertices
return extremeVertices;
}
// Static method that computes an OBB from a set of vertices. The "center" argument corresponds to the center of the OBB
// This method allocates a new OBB object and return a pointer to the new allocated OBB object
OBB* OBB::computeFromVertices(const vector<Vector3D>& vertices, const Vector3D& center) {
// TODO : Implement this method;
return NULL;
}
// Return the corresponding AABB
AABB* OBB::computeAABB() const {
double maxLength[] = {0.0, 0.0, 0.0}; // Maximum length for each of the three x,y and z axis
Vector3D vertex;
double length;
// For each vertex of the OBB
for (int i = 0; i<8; i++) {
vertex = getVertex(i) - center;
for (int j=0; j<3; j++) {
length = std::abs(vertex.getValue(j));
if (length > maxLength[j]) {
maxLength[j] = length;
}
}
}
// Create and return the AABB
return new AABB(center, maxLength[0], maxLength[1], maxLength[2]);
}

View File

@ -35,206 +35,53 @@ namespace reactphysics3d {
/* ------------------------------------------------------------------- /* -------------------------------------------------------------------
Class OBB : Class OBB :
This class represents a bounding volume of type "Oriented Bounding This class represents a 3D box. Those axis are unit length.
Box". It's a box that has a given orientation is space. The three The three extents are half-widths of the box along the three
axis of the OBB are three axis that give the orientation of the axis x, y, z local axis. The "transform" of the corresponding
OBB. The three axis are normal vectors to the faces of the OBB. rigid body given an orientation and a position to the box
Those axis are unit length. The three extents are half-widths
of the box along the three axis of the OBB.
------------------------------------------------------------------- -------------------------------------------------------------------
*/ */
class OBB : public NarrowBoundingVolume { class OBB : public NarrowBoundingVolume {
protected : private :
Vector3D center; // Center point of the OBB Vector3D extent; // Extent sizes of the box
Vector3D oldAxis[3]; // Array that contains the three unit length axis at the beginning
Vector3D axis[3]; // Array that contains the three unit length axis of the OBB
double extent[3]; // Array that contains the three extents size of the OBB
public : public :
OBB(const Vector3D& center, const Vector3D& axis1, const Vector3D& axis2, OBB(const Vector3D& extent); // Constructor
const Vector3D& axis3, double extent1, double extent2, double extent3); // Constructor
virtual ~OBB(); // Destructor virtual ~OBB(); // Destructor
Vector3D getCenter() const; // Return the center point of the OBB const Vector3D& getExtent() const; // Return the extents of the box
void setCenter(const Vector3D& center); // Set the center point void setExtent(const Vector3D& extent); // Set the extents of the box
Vector3D getAxis(unsigned int index) const throw(std::invalid_argument); // Return an axis of the OBB virtual Vector3D getLocalExtents() const; // Return the local extents in x,y and z direction
void setAxis(unsigned int index, const Vector3D& axis) throw(std::invalid_argument); // Set an axis
Vector3D getVertex(unsigned int index) const throw (std::invalid_argument); // Return a vertex of the OBB
std::vector<Vector3D> getFace(unsigned int index) const throw(std::invalid_argument); // Return the 4 vertices the OBB's face in the direction of a given axis
double getExtent(unsigned int index) const throw(std::invalid_argument); // Return an extent value
void setExtent(unsigned int index, double extent) throw(std::invalid_argument); // Set an extent value
virtual std::vector<Vector3D> getExtremeVertices(const Vector3D& axis) const; // Return all the vertices that are projected at the extreme of the projection of the bouding volume on the axis
virtual void update(const Vector3D& newCenter, const Quaternion& rotationQuaternion); // Update the oriented bounding box orientation according to a new orientation of the rigid body
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 getSupportPoint(const Vector3D& direction, double margin=0.0) const; // Return a support point in a given direction
#ifdef VISUAL_DEBUG #ifdef VISUAL_DEBUG
virtual void draw() const; // Draw the OBB (only for testing purpose) virtual void draw() const; // Draw the OBB (only for testing purpose)
#endif #endif
static OBB* computeFromVertices(const std::vector<Vector3D>& vertices, const Vector3D& center); // Compute an OBB from a set of vertices
}; };
// Return the center point of the OBB // Return the extents of the box
inline Vector3D OBB::getCenter() const { inline const Vector3D& OBB::getExtent() const {
return center; return extent;
} }
// Set the center point // Set the extents of the box
inline void OBB::setCenter(const Vector3D& center) { inline void OBB::setExtent(const Vector3D& extent) {
this->center = center; this->extent = extent;
} }
// Return an axis of the OBB // Return the local extents of the shape (half-width) in x,y and z local direction
inline Vector3D OBB::getAxis(unsigned int index) const throw(std::invalid_argument) { // This method is used to compute the AABB of the box
// Check if the index value is valid inline Vector3D OBB::getLocalExtents() const {
if (index >= 0 && index <3) { return extent;
return axis[index];
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Set an axis
inline void OBB::setAxis(unsigned int index, const Vector3D& axis) throw(std::invalid_argument) {
// Check if the index value is valid
if (index >= 0 && index <3) {
this->axis[index] = axis;
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Return a vertex of the OBB
inline Vector3D OBB::getVertex(unsigned int index) const throw (std::invalid_argument) {
// Check if the index value is valid
if (index >= 0 && index <8) {
Vector3D vertex;
switch(index) {
case 0 : vertex = center + (axis[0]*extent[0]) + (axis[1]*extent[1]) - (axis[2]*extent[2]);
break;
case 1 : vertex = center + (axis[0]*extent[0]) + (axis[1]*extent[1]) + (axis[2]*extent[2]);
break;
case 2 : vertex = center - (axis[0]*extent[0]) + (axis[1]*extent[1]) + (axis[2]*extent[2]);
break;
case 3 : vertex = center - (axis[0]*extent[0]) + (axis[1]*extent[1]) - (axis[2]*extent[2]);
break;
case 4 : vertex = center + (axis[0]*extent[0]) - (axis[1]*extent[1]) - (axis[2]*extent[2]);
break;
case 5 : vertex = center + (axis[0]*extent[0]) - (axis[1]*extent[1]) + (axis[2]*extent[2]);
break;
case 6 : vertex = center - (axis[0]*extent[0]) - (axis[1]*extent[1]) + (axis[2]*extent[2]);
break;
case 7 : vertex = center - (axis[0]*extent[0]) - (axis[1]*extent[1]) - (axis[2]*extent[2]);
break;
}
// Return the vertex
return vertex;
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 8");
}
}
// Return the 4 vertices of a face of the OBB. The 4 vertices will be ordered. The convention is that the index 0 corresponds to
// the face in the direction of the axis[0], 1 corresponds to the face in the opposite direction of the axis[0], 2 corresponds to
// the face in the direction of the axis[1], etc.
inline std::vector<Vector3D> OBB::getFace(unsigned int index) const throw(std::invalid_argument) {
// Check the argument
if (index >=0 && index <6) {
std::vector<Vector3D> vertices;
switch(index) {
case 0: vertices.push_back(center + (axis[0]*extent[0]) + (axis[1]*extent[1]) - (axis[2]*extent[2]));
vertices.push_back(center + (axis[0]*extent[0]) + (axis[1]*extent[1]) + (axis[2]*extent[2]));
vertices.push_back(center + (axis[0]*extent[0]) - (axis[1]*extent[1]) + (axis[2]*extent[2]));
vertices.push_back(center + (axis[0]*extent[0]) - (axis[1]*extent[1]) - (axis[2]*extent[2]));
break;
case 1: vertices.push_back(center - (axis[0]*extent[0]) + (axis[1]*extent[1]) - (axis[2]*extent[2]));
vertices.push_back(center - (axis[0]*extent[0]) + (axis[1]*extent[1]) + (axis[2]*extent[2]));
vertices.push_back(center - (axis[0]*extent[0]) - (axis[1]*extent[1]) + (axis[2]*extent[2]));
vertices.push_back(center - (axis[0]*extent[0]) - (axis[1]*extent[1]) - (axis[2]*extent[2]));
break;
case 2: vertices.push_back(center + (axis[1]*extent[1]) + (axis[0]*extent[0]) - (axis[2]*extent[2]));
vertices.push_back(center + (axis[1]*extent[1]) + (axis[0]*extent[0]) + (axis[2]*extent[2]));
vertices.push_back(center + (axis[1]*extent[1]) - (axis[0]*extent[0]) + (axis[2]*extent[2]));
vertices.push_back(center + (axis[1]*extent[1]) - (axis[0]*extent[0]) - (axis[2]*extent[2]));
break;
case 3: vertices.push_back(center - (axis[1]*extent[1]) + (axis[0]*extent[0]) - (axis[2]*extent[2]));
vertices.push_back(center - (axis[1]*extent[1]) + (axis[0]*extent[0]) + (axis[2]*extent[2]));
vertices.push_back(center - (axis[1]*extent[1]) - (axis[0]*extent[0]) + (axis[2]*extent[2]));
vertices.push_back(center - (axis[1]*extent[1]) - (axis[0]*extent[0]) - (axis[2]*extent[2]));
break;
case 4: vertices.push_back(center + (axis[2]*extent[2]) + (axis[0]*extent[0]) - (axis[1]*extent[1]));
vertices.push_back(center + (axis[2]*extent[2]) + (axis[0]*extent[0]) + (axis[1]*extent[1]));
vertices.push_back(center + (axis[2]*extent[2]) - (axis[0]*extent[0]) + (axis[1]*extent[1]));
vertices.push_back(center + (axis[2]*extent[2]) - (axis[0]*extent[0]) - (axis[1]*extent[1]));
break;
case 5: vertices.push_back(center - (axis[2]*extent[2]) + (axis[0]*extent[0]) - (axis[1]*extent[1]));
vertices.push_back(center - (axis[2]*extent[2]) + (axis[0]*extent[0]) + (axis[1]*extent[1]));
vertices.push_back(center - (axis[2]*extent[2]) - (axis[0]*extent[0]) + (axis[1]*extent[1]));
vertices.push_back(center - (axis[2]*extent[2]) - (axis[0]*extent[0]) - (axis[1]*extent[1]));
break;
}
// Return the vertices
assert(vertices.size() == 4);
return vertices;
}
else {
// Throw an exception
throw std::invalid_argument("Exception: The argument must be between 0 and 5");
}
}
// Return an extent value
inline double OBB::getExtent(unsigned int index) const throw(std::invalid_argument) {
// Check if the index value is valid
if (index >= 0 && index <3) {
return extent[index];
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Set an extent value
inline void OBB::setExtent(unsigned int index, double extent) throw(std::invalid_argument) {
// Check if the index value is valid
if (index >= 0 && index <3) {
this->extent[index] = extent;
}
else {
// The index value is not valid, we throw an exception
throw std::invalid_argument("Exception : The index value has to be between 0 and 2");
}
}
// Update the orientation of the OBB according to the orientation of the rigid body
inline void OBB::update(const Vector3D& newCenter, const Quaternion& rotationQuaternion) {
// Update the center of the OBB
center = newCenter;
// Update the three axis of the OBB by rotating and normalize then
axis[0] = rotateVectorWithQuaternion(oldAxis[0], rotationQuaternion).getUnit();
axis[1] = rotateVectorWithQuaternion(oldAxis[1], rotationQuaternion).getUnit();
axis[2] = rotateVectorWithQuaternion(oldAxis[2], rotationQuaternion).getUnit();
} }
// Return a support point in a given direction // Return a support point in a given direction
inline Vector3D OBB::getSupportPoint(const Vector3D& direction, double margin) const { inline Vector3D OBB::getSupportPoint(const Vector3D& direction, double margin) const {
assert(direction.length() > 0.0);
assert(margin >= 0.0); assert(margin >= 0.0);
// TODO : Implement this method return Vector3D(direction.getX() < 0.0 ? -extent.getX()-margin : extent.getX()+margin,
assert(false); direction.getY() < 0.0 ? -extent.getY()-margin : extent.getY()+margin,
return Vector3D(); direction.getZ() < 0.0 ? -extent.getZ()-margin : extent.getZ()+margin);
} }
}; // End of the ReactPhysics3D namespace }; // End of the ReactPhysics3D namespace

View File

@ -31,10 +31,11 @@
using namespace reactphysics3d; using namespace reactphysics3d;
// Constructor // Constructor
RigidBody::RigidBody(const Vector3D& position, const Quaternion& orientation, double mass, const Matrix3x3& inertiaTensorLocal, // TODO : Use a Transform in the constructor instead of "position" and "orientation"
RigidBody::RigidBody(const Transform& transform, double mass, const Matrix3x3& inertiaTensorLocal,
NarrowBoundingVolume* narrowBoundingVolume) NarrowBoundingVolume* narrowBoundingVolume)
: Body(mass), position(position), orientation(orientation.getUnit()), inertiaTensorLocal(inertiaTensorLocal), : Body(transform, mass), inertiaTensorLocal(inertiaTensorLocal),
inertiaTensorLocalInverse(inertiaTensorLocal.getInverse()), massInverse(1.0/mass), oldPosition(position), oldOrientation(orientation) { inertiaTensorLocalInverse(inertiaTensorLocal.getInverse()), massInverse(1.0/mass) {
restitution = 1.0; restitution = 1.0;
isMotionEnabled = true; isMotionEnabled = true;
@ -44,13 +45,9 @@
// Set the bounding volume for the narrow-phase collision detection // Set the bounding volume for the narrow-phase collision detection
setNarrowBoundingVolume(narrowBoundingVolume); setNarrowBoundingVolume(narrowBoundingVolume);
// Compute the broad-phase bounding volume (an AABB)
setBroadBoundingVolume(narrowBoundingVolume->computeAABB());
// Update the orientation of the OBB according to the orientation of the rigid body // Update the orientation of the OBB according to the orientation of the rigid body
update(); update();
assert(broadBoundingVolume);
assert(narrowBoundingVolume); assert(narrowBoundingVolume);
} }
@ -61,7 +58,8 @@ RigidBody::~RigidBody() {
// Update the rigid body in order to reflect a change in the body state // Update the rigid body in order to reflect a change in the body state
void RigidBody::update() { void RigidBody::update() {
// Update the orientation of the corresponding bounding volumes of the rigid body // TODO : Remove the following code when using a Transform
broadBoundingVolume->update(position, orientation);
narrowBoundingVolume->update(position, orientation); // Update the AABB
aabb->update(transform, narrowBoundingVolume->getLocalExtents());
} }

View File

@ -42,10 +42,11 @@ namespace reactphysics3d {
*/ */
class RigidBody : public Body { class RigidBody : public Body {
protected : protected :
Vector3D position; // Position of the center of mass of the body // TODO : Remove some of the following variables
Vector3D oldPosition; // Old position used to compute the interpolated position //Vector3D position; // Position of the center of mass of the body
Quaternion orientation; // Orientation quaternion of the body //Vector3D oldPosition; // Old position used to compute the interpolated position
Quaternion oldOrientation; // Old orientation used to compute the interpolated orientation //Quaternion orientation; // Orientation quaternion of the body
//Quaternion oldOrientation; // Old orientation used to compute the interpolated orientation
Vector3D linearVelocity; // Linear velocity of the body Vector3D linearVelocity; // Linear velocity of the body
Vector3D angularVelocity; // Angular velocity of the body Vector3D angularVelocity; // Angular velocity of the body
Vector3D externalForce; // Current external force on the body Vector3D externalForce; // Current external force on the body
@ -53,18 +54,13 @@ class RigidBody : public Body {
Matrix3x3 inertiaTensorLocal; // Local inertia tensor of the body (in body coordinates) Matrix3x3 inertiaTensorLocal; // Local inertia tensor of the body (in body coordinates)
Matrix3x3 inertiaTensorLocalInverse; // Inverse of the inertia tensor of the body (in body coordinates) Matrix3x3 inertiaTensorLocalInverse; // Inverse of the inertia tensor of the body (in body coordinates)
double massInverse; // Inverse of the mass of the body double massInverse; // Inverse of the mass of the body
double interpolationFactor; // Interpolation factor used for the state interpolation
double restitution; // Coefficient of restitution (between 0 and 1), 1 for a very boucing body double restitution; // Coefficient of restitution (between 0 and 1), 1 for a very boucing body
public : public :
RigidBody(const Vector3D& position, const Quaternion& orientation, double mass, RigidBody(const Transform& transform, double mass,
const Matrix3x3& inertiaTensorLocal, NarrowBoundingVolume* narrowBoundingVolume); // Constructor // Copy-constructor const Matrix3x3& inertiaTensorLocal, NarrowBoundingVolume* narrowBoundingVolume); // Constructor // Copy-constructor
virtual ~RigidBody(); // Destructor virtual ~RigidBody(); // Destructor
Vector3D getPosition() const; // Return the position of the body
void setPosition(const Vector3D& position); // Set the position of the body
Quaternion getOrientation() const; // Return the orientation quaternion
void setOrientation(const Quaternion& orientation); // Set the orientation quaternion
Vector3D getLinearVelocity() const; // Return the linear velocity Vector3D getLinearVelocity() const; // Return the linear velocity
void setLinearVelocity(const Vector3D& linearVelocity); // Set the linear velocity of the body void setLinearVelocity(const Vector3D& linearVelocity); // Set the linear velocity of the body
Vector3D getAngularVelocity() const; // Return the angular velocity Vector3D getAngularVelocity() const; // Return the angular velocity
@ -80,40 +76,12 @@ class RigidBody : public Body {
Matrix3x3 getInertiaTensorLocalInverse() const; // Get the inverse of the inertia tensor Matrix3x3 getInertiaTensorLocalInverse() const; // Get the inverse of the inertia tensor
Matrix3x3 getInertiaTensorWorld() const; // Return the inertia tensor in world coordinates Matrix3x3 getInertiaTensorWorld() const; // Return the inertia tensor in world coordinates
Matrix3x3 getInertiaTensorInverseWorld() const; // Return the inverse of the inertia tensor in world coordinates Matrix3x3 getInertiaTensorInverseWorld() const; // Return the inverse of the inertia tensor in world coordinates
void setInterpolationFactor(double factor); // Set the interpolation factor of the body
Vector3D getInterpolatedPosition() const; // Return the interpolated position
Quaternion getInterpolatedOrientation() const; // Return the interpolated orientation
double getRestitution() const; // Get the restitution coefficient double getRestitution() const; // Get the restitution coefficient
void setRestitution(double restitution) throw(std::invalid_argument); // Set the restitution coefficient void setRestitution(double restitution) throw(std::invalid_argument); // Set the restitution coefficient
void updateOldPositionAndOrientation(); // Update the previous position and orientation of the body
void update(); // Update the rigid body in order to reflect a change in the body state void update(); // Update the rigid body in order to reflect a change in the body state
}; };
// --- Inline functions --- //
// Return the position of the body
inline Vector3D RigidBody::getPosition() const {
return position;
}
// Set the position of the body
inline void RigidBody::setPosition(const Vector3D& position) {
this->position = position;
}
// Return the orientation quaternion of the body
inline Quaternion RigidBody::getOrientation() const {
return orientation;
}
// Set the orientation quaternion
inline void RigidBody::setOrientation(const Quaternion& orientation) {
this->orientation = orientation;
// Normalize the orientation quaternion
orientation.getUnit();
}
// Return the linear velocity // Return the linear velocity
inline Vector3D RigidBody::getLinearVelocity() const { inline Vector3D RigidBody::getLinearVelocity() const {
return linearVelocity; return linearVelocity;
@ -179,7 +147,7 @@ inline void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal
// where R is the rotation matrix (and R^T its transpose) of the current orientation quaternion of the body // where R is the rotation matrix (and R^T its transpose) of the current orientation quaternion of the body
inline Matrix3x3 RigidBody::getInertiaTensorWorld() const { inline Matrix3x3 RigidBody::getInertiaTensorWorld() const {
// Compute and return the inertia tensor in world coordinates // Compute and return the inertia tensor in world coordinates
return orientation.getMatrix() * inertiaTensorLocal * orientation.getMatrix().getTranspose(); return transform.getOrientation() * inertiaTensorLocal * transform.getOrientation().getTranspose();
} }
// Return the inverse of the inertia tensor in world coordinates // Return the inverse of the inertia tensor in world coordinates
@ -188,25 +156,7 @@ inline Matrix3x3 RigidBody::getInertiaTensorWorld() const {
// where R is the rotation matrix (and R^T its transpose) of the current orientation quaternion of the body // where R is the rotation matrix (and R^T its transpose) of the current orientation quaternion of the body
inline Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const { inline Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const {
// Compute and return the inertia tensor in world coordinates // Compute and return the inertia tensor in world coordinates
return orientation.getMatrix() * inertiaTensorLocalInverse * orientation.getMatrix().getTranspose(); return transform.getOrientation() * inertiaTensorLocalInverse * transform.getOrientation().getTranspose();
}
// Set the interpolation factor of the body
inline void RigidBody::setInterpolationFactor(double factor) {
// Set the factor
interpolationFactor = factor;
}
// Return the interpolated position
inline Vector3D RigidBody::getInterpolatedPosition() const {
// Compute the interpolated position
return oldPosition * (1-interpolationFactor) + position * interpolationFactor;
}
// Return the interpolated orientation
inline Quaternion RigidBody::getInterpolatedOrientation() const {
// Compute the interpolated orientation
return Quaternion::slerp(oldOrientation, orientation, interpolationFactor);
} }
// Set the linear velocity of the rigid body // Set the linear velocity of the rigid body
@ -234,12 +184,6 @@ inline void RigidBody::setRestitution(double restitution) throw(std::invalid_arg
} }
} }
// Update the previous body state of the body
// This is used to compute the interpolated position and orientation of the body
inline void RigidBody::updateOldPositionAndOrientation() {
oldPosition = position;
oldOrientation = orientation;
}
} // End of the ReactPhyscis3D namespace } // End of the ReactPhyscis3D namespace