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:
parent
1e3543752f
commit
bf8f9cf482
|
@ -26,24 +26,22 @@
|
|||
#include "AABB.h"
|
||||
#include <cassert>
|
||||
#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
|
||||
#include <GL/freeglut.h>
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
using namespace reactphysics3d;
|
||||
using namespace std;
|
||||
|
||||
// Constructor
|
||||
AABB::AABB(const Vector3D& center,double extentX, double extentY, double extentZ) {
|
||||
this->center = center;
|
||||
AABB::AABB(const Body* bodyPointer) : bodyPointer(bodyPointer) {
|
||||
|
||||
}
|
||||
|
||||
this->extent[0] = extentX;
|
||||
this->extent[1] = extentY;
|
||||
this->extent[2] = extentZ;
|
||||
|
||||
this->originalAABBExtent[0] = extentX;
|
||||
this->originalAABBExtent[1] = extentY;
|
||||
this->originalAABBExtent[2] = extentZ;
|
||||
// Constructor
|
||||
AABB::AABB(const Body* bodyPointer, const Transform& transform, const Vector3D& extents)
|
||||
: bodyPointer(bodyPointer) {
|
||||
update(transform, extents);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
@ -55,64 +53,48 @@ AABB::~AABB() {
|
|||
// Draw the OBB (only for testing purpose)
|
||||
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
|
||||
glColor3f(1.0, 0.0, 0.0);
|
||||
|
||||
// Draw the OBB
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(s1.getX(), s1.getY(), s1.getZ());
|
||||
glVertex3f(s2.getX(), s2.getY(), s2.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
|
||||
|
||||
glVertex3f(s2.getX(), s2.getY(), s2.getZ());
|
||||
glVertex3f(s3.getX(), s3.getY(), s3.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s3.getX(), s3.getY(), s3.getZ());
|
||||
glVertex3f(s4.getX(), s4.getY(), s4.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s4.getX(), s4.getY(), s4.getZ());
|
||||
glVertex3f(s1.getX(), s1.getY(), s1.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s5.getX(), s5.getY(), s5.getZ());
|
||||
glVertex3f(s6.getX(), s6.getY(), s6.getZ());
|
||||
glVertex3f(minCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
|
||||
|
||||
glVertex3f(s6.getX(), s6.getY(), s6.getZ());
|
||||
glVertex3f(s7.getX(), s7.getY(), s7.getZ());
|
||||
glVertex3f(minCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(minCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s7.getX(), s7.getY(), s7.getZ());
|
||||
glVertex3f(s8.getX(), s8.getY(), s8.getZ());
|
||||
glVertex3f(minCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
|
||||
glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s8.getX(), s8.getY(), s8.getZ());
|
||||
glVertex3f(s5.getX(), s5.getY(), s5.getZ());
|
||||
glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s1.getX(), s1.getY(), s1.getZ());
|
||||
glVertex3f(s5.getX(), s5.getY(), s5.getZ());
|
||||
glVertex3f(minCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), minCoordinates.getZ());
|
||||
|
||||
glVertex3f(s4.getX(), s4.getY(), s4.getZ());
|
||||
glVertex3f(s8.getX(), s8.getY(), s8.getZ());
|
||||
glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), minCoordinates.getZ());
|
||||
|
||||
glVertex3f(s3.getX(), s3.getY(), s3.getZ());
|
||||
glVertex3f(s7.getX(), s7.getY(), s7.getZ());
|
||||
glVertex3f(minCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), maxCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glVertex3f(s2.getX(), s2.getY(), s2.getZ());
|
||||
glVertex3f(s6.getX(), s6.getY(), s6.getZ());
|
||||
glVertex3f(minCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
|
||||
glVertex3f(maxCoordinates.getX(), minCoordinates.getY(), maxCoordinates.getZ());
|
||||
|
||||
glEnd();
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
157
src/body/AABB.h
157
src/body/AABB.h
|
@ -26,11 +26,13 @@
|
|||
#define AABB_H
|
||||
|
||||
// Libraries
|
||||
#include "BroadBoundingVolume.h"
|
||||
#include "../mathematics/mathematics.h"
|
||||
|
||||
// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Declaration
|
||||
class Body;
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
Class AABB :
|
||||
|
@ -40,109 +42,46 @@ namespace reactphysics3d {
|
|||
point and three extent size in the x,y and z directions.
|
||||
-------------------------------------------------------------------
|
||||
*/
|
||||
class AABB : public BroadBoundingVolume {
|
||||
protected :
|
||||
Vector3D center; // Center point of the AABB
|
||||
double extent[3]; // Three extents size in the x, y and z directions
|
||||
double originalAABBExtent[3]; // Extents of the original AABB (this is used to update the AABB)
|
||||
class AABB {
|
||||
private :
|
||||
Vector3D minCoordinates; // Minimum world coordinates of the AABB on the x,y and z axis
|
||||
Vector3D maxCoordinates; // Maximum world coordinates of the AABB on the x,y and z axis
|
||||
const Body* bodyPointer; // Pointer to the owner body
|
||||
|
||||
public :
|
||||
AABB(const Vector3D& center, double extentX, double extentY, double extentZ); // Constructor
|
||||
virtual ~AABB(); // Destructor
|
||||
AABB(const Body* body); // Constructor
|
||||
AABB(const Body* bodyPointer, const Transform& transform, const Vector3D& extents); // Constructor
|
||||
virtual ~AABB(); // Destructor
|
||||
|
||||
Vector3D getCenter() const; // Return the center point
|
||||
void setCenter(const Vector3D& center); // Set the center point
|
||||
Vector3D getVertex(uint index) const throw (std::invalid_argument); // Return a vertex of the AABB
|
||||
double getExtent(uint index) const throw(std::invalid_argument); // Return an extent value
|
||||
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
|
||||
virtual void update(const Vector3D& newCenter, const Quaternion& rotationQuaternion); // Update the oriented bounding box orientation according to a new orientation of the rigid body
|
||||
Vector3D getCenter() const; // Return the center point
|
||||
const Vector3D& getMinCoordinates() const; // Return the minimum coordinates of the AABB
|
||||
const Vector3D& getMaxCoordinates() const; // Return the maximum coordinates of the AABB
|
||||
const Body* getBodyPointer() const; // Return a pointer to the owner body
|
||||
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)
|
||||
virtual void draw() const; // Draw the AABB (only for testing purpose)
|
||||
#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 {
|
||||
return center;
|
||||
return (minCoordinates + maxCoordinates) * 0.5;
|
||||
}
|
||||
|
||||
// Set the center point
|
||||
inline void AABB::setCenter(const Vector3D& center) {
|
||||
this->center = center;
|
||||
// Return the minimum coordinates of the AABB
|
||||
inline const Vector3D& AABB::getMinCoordinates() const {
|
||||
return minCoordinates;
|
||||
}
|
||||
|
||||
// Return one of the 8 vertices of the AABB
|
||||
inline Vector3D AABB::getVertex(unsigned int index) const throw (std::invalid_argument) {
|
||||
// Check if the index value is valid
|
||||
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 the maximum coordinates of the AABB
|
||||
inline const Vector3D& AABB::getMaxCoordinates() const {
|
||||
return maxCoordinates;
|
||||
}
|
||||
|
||||
|
||||
// Return an extent value
|
||||
inline double AABB::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 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 a pointer to the owner body
|
||||
inline const Body* AABB::getBodyPointer() const {
|
||||
return bodyPointer;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Vector3D center2 = aabb.getCenter();
|
||||
double margin = 2 * OBJECT_MARGIN;
|
||||
if (std::abs(center.getX() - center2.getX()) > (extent[0] + aabb.getExtent(0) + margin)) return false;
|
||||
if (std::abs(center.getY() - center2.getY()) > (extent[1] + aabb.getExtent(1) + margin)) return false;
|
||||
if (std::abs(center.getZ() - center2.getZ()) > (extent[2] + aabb.getExtent(2) + margin)) return false;
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update the orientation of the AABB according to the orientation of the rigid body
|
||||
// In order to compute the new AABB we use the original AABB (represented by the originalAABBExtent
|
||||
// values). The goal is to rotate the original AABB according to the current rotation (rotationQuaternion)
|
||||
// and then compute the new extent values from the rotated axis of the original AABB. The three columns of
|
||||
// the rotation matrix correspond to the rotated axis of the rotated original AABB. The we have to compute
|
||||
// the projections of the three rotated axis onto the x, y and z axis. The projections are easy to compute
|
||||
// because for instance if the size of the projection of the vector (4, 5, 6) onto the x axis is simply 4.
|
||||
inline void AABB::update(const Vector3D& newCenter, const Quaternion& rotationQuaternion) {
|
||||
// Update the center of the AABB
|
||||
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];
|
||||
}
|
||||
}
|
||||
// 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));
|
||||
minCoordinates = newTransform.getPosition() - worldExtents;
|
||||
maxCoordinates = newTransform.getPosition() + worldExtents;
|
||||
}
|
||||
|
||||
}; // End of the ReactPhysics3D namespace
|
||||
|
|
|
@ -31,31 +31,45 @@
|
|||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Body::Body(double mass) throw(std::invalid_argument)
|
||||
: mass(mass), broadBoundingVolume(0), narrowBoundingVolume(0) {
|
||||
Body::Body(const Transform& transform, double mass) throw(std::invalid_argument)
|
||||
: transform(transform), mass(mass), narrowBoundingVolume(0), aabb(0) {
|
||||
// Check if the mass is not larger than zero
|
||||
if (mass <= 0.0) {
|
||||
// We throw an exception
|
||||
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
|
||||
Body::~Body() {
|
||||
/* TODO : DELETE THIS
|
||||
if (broadBoundingVolume) {
|
||||
delete broadBoundingVolume;
|
||||
}
|
||||
*/
|
||||
|
||||
if (narrowBoundingVolume) {
|
||||
delete narrowBoundingVolume;
|
||||
}
|
||||
|
||||
// Delete the AABB
|
||||
delete aabb;
|
||||
}
|
||||
|
||||
/* TODO : DELETE THIS
|
||||
// Set the broad-phase bounding volume
|
||||
void Body::setBroadBoundingVolume(BroadBoundingVolume* broadBoundingVolume) {
|
||||
assert(broadBoundingVolume);
|
||||
this->broadBoundingVolume = broadBoundingVolume;
|
||||
broadBoundingVolume->setBodyPointer(this);
|
||||
}
|
||||
*/
|
||||
|
||||
// Set the narrow-phase bounding volume
|
||||
void Body::setNarrowBoundingVolume(NarrowBoundingVolume* narrowBoundingVolume) {
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
// Libraries
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#include "../mathematics/Transform.h"
|
||||
#include "../body/AABB.h"
|
||||
|
||||
// Namespace reactphysics3d
|
||||
namespace reactphysics3d {
|
||||
|
||||
class BroadBoundingVolume;
|
||||
class NarrowBoundingVolume;
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
|
@ -44,27 +44,35 @@ class NarrowBoundingVolume;
|
|||
*/
|
||||
class Body {
|
||||
protected :
|
||||
double mass; // Mass of the body
|
||||
BroadBoundingVolume* broadBoundingVolume; // Bounding volume used for the broad-phase collision detection
|
||||
double mass; // Mass of the body
|
||||
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
|
||||
bool isMotionEnabled; // True if the body is able to move
|
||||
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
|
||||
|
||||
public :
|
||||
Body(double mass) throw(std::invalid_argument); // Constructor
|
||||
Body(const Transform& transform, double mass) throw(std::invalid_argument); // Constructor
|
||||
virtual ~Body(); // Destructor
|
||||
|
||||
double getMass() const; // Return 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
|
||||
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
|
||||
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
|
||||
void updateOldTransform(); // Update the old transform with the current one
|
||||
};
|
||||
|
||||
// Method that return the mass of the body
|
||||
|
@ -72,6 +80,17 @@ inline double Body::getMass() const {
|
|||
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
|
||||
inline bool Body::getIsMotionEnabled() const {
|
||||
return isMotionEnabled;
|
||||
|
@ -87,6 +106,21 @@ inline void Body::setMass(double 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
|
||||
inline bool Body::getIsCollisionEnabled() const {
|
||||
return isCollisionEnabled;
|
||||
|
@ -97,16 +131,25 @@ inline void Body::setIsCollisionEnabled(bool isCollisionEnabled) {
|
|||
this->isCollisionEnabled = isCollisionEnabled;
|
||||
}
|
||||
|
||||
/* TODO : DELETE
|
||||
// Return the broad-phase bounding volume
|
||||
inline const BroadBoundingVolume* Body::getBroadBoundingVolume() const {
|
||||
return broadBoundingVolume;
|
||||
}
|
||||
*/
|
||||
|
||||
// Return the oriented bounding box of the rigid body
|
||||
inline const NarrowBoundingVolume* Body::getNarrowBoundingVolume() const {
|
||||
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
|
||||
|
|
|
@ -60,9 +60,10 @@ void BoundingSphere::draw() const {
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*TODO: DELETE THIS
|
||||
// Return the corresponding AABB
|
||||
AABB* BoundingSphere::computeAABB() const {
|
||||
// Create and return the AABB
|
||||
return new AABB(center, radius, radius, radius);
|
||||
}
|
||||
*/
|
|
@ -52,8 +52,9 @@ class BoundingSphere : public NarrowBoundingVolume {
|
|||
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
|
||||
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 getLocalExtents() 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)
|
||||
|
@ -94,12 +95,18 @@ inline Vector3D BoundingSphere::getSupportPoint(const Vector3D& direction, doubl
|
|||
// If the direction vector is not the zero vector
|
||||
if (length > 0.0) {
|
||||
// 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
|
||||
// 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
|
||||
|
|
|
@ -52,7 +52,7 @@ class BoundingVolume {
|
|||
Body* getBodyPointer() const; // Return 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
|
||||
virtual void draw() const=0; // Display the bounding volume (only for testing purpose)
|
||||
#endif
|
||||
|
|
|
@ -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() {
|
||||
|
||||
}
|
|
@ -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
|
|
@ -48,8 +48,9 @@ class NarrowBoundingVolume : public BoundingVolume {
|
|||
NarrowBoundingVolume(); // Constructor
|
||||
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 getLocalExtents() const=0; // Return the local extents in x,y and z direction
|
||||
};
|
||||
|
||||
}
|
||||
|
|
173
src/body/OBB.cpp
173
src/body/OBB.cpp
|
@ -36,21 +36,8 @@ using namespace reactphysics3d;
|
|||
using namespace std;
|
||||
|
||||
// Constructor
|
||||
OBB::OBB(const Vector3D& center, const Vector3D& axis1, const Vector3D& axis2,
|
||||
const Vector3D& axis3, double extent1, double extent2, double extent3) {
|
||||
this->center = center;
|
||||
OBB::OBB(const Vector3D& extent) : extent(extent) {
|
||||
|
||||
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
|
||||
|
@ -61,155 +48,51 @@ OBB::~OBB() {
|
|||
#ifdef VISUAL_DEBUG
|
||||
// Draw the OBB (only for testing purpose)
|
||||
void OBB::draw() const {
|
||||
double e0 = extent[0];
|
||||
double e1 = extent[1];
|
||||
double e2 = extent[2];
|
||||
|
||||
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);
|
||||
double e1 = extent.getX();
|
||||
double e2 = extent.getY();
|
||||
double e3 = extent.getZ();
|
||||
|
||||
// Draw in red
|
||||
glColor3f(1.0, 0.0, 0.0);
|
||||
|
||||
// Draw the OBB
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(s1.getX(), s1.getY(), s1.getZ());
|
||||
glVertex3f(s2.getX(), s2.getY(), s2.getZ());
|
||||
glVertex3f(e1, -e2, -e3);
|
||||
glVertex3f(e1, e2, -e3);
|
||||
|
||||
glVertex3f(s2.getX(), s2.getY(), s2.getZ());
|
||||
glVertex3f(s3.getX(), s3.getY(), s3.getZ());
|
||||
glVertex3f(e1, -e2, -e3);
|
||||
glVertex3f(e1, -e2, e3);
|
||||
|
||||
glVertex3f(s3.getX(), s3.getY(), s3.getZ());
|
||||
glVertex3f(s4.getX(), s4.getY(), s4.getZ());
|
||||
glVertex3f(e1, -e2, e3);
|
||||
glVertex3f(e1, e2, e3);
|
||||
|
||||
glVertex3f(s4.getX(), s4.getY(), s4.getZ());
|
||||
glVertex3f(s1.getX(), s1.getY(), s1.getZ());
|
||||
glVertex3f(e1, e2, e3);
|
||||
glVertex3f(e1, e2, -e3);
|
||||
|
||||
glVertex3f(s5.getX(), s5.getY(), s5.getZ());
|
||||
glVertex3f(s6.getX(), s6.getY(), s6.getZ());
|
||||
glVertex3f(-e1, -e2, -e3);
|
||||
glVertex3f(-e1, e2, -e3);
|
||||
|
||||
glVertex3f(s6.getX(), s6.getY(), s6.getZ());
|
||||
glVertex3f(s7.getX(), s7.getY(), s7.getZ());
|
||||
glVertex3f(-e1, -e2, -e3);
|
||||
glVertex3f(-e1, -e2, e3);
|
||||
|
||||
glVertex3f(s7.getX(), s7.getY(), s7.getZ());
|
||||
glVertex3f(s8.getX(), s8.getY(), s8.getZ());
|
||||
glVertex3f(-e1, -e2, e3);
|
||||
glVertex3f(-e1, e2, e3);
|
||||
|
||||
glVertex3f(s8.getX(), s8.getY(), s8.getZ());
|
||||
glVertex3f(s5.getX(), s5.getY(), s5.getZ());
|
||||
glVertex3f(-e1, e2, e3);
|
||||
glVertex3f(-e1, e2, -e3);
|
||||
|
||||
glVertex3f(s1.getX(), s1.getY(), s1.getZ());
|
||||
glVertex3f(s5.getX(), s5.getY(), s5.getZ());
|
||||
glVertex3f(e1, -e2, -e3);
|
||||
glVertex3f(-e1, -e2, -e3);
|
||||
|
||||
glVertex3f(s4.getX(), s4.getY(), s4.getZ());
|
||||
glVertex3f(s8.getX(), s8.getY(), s8.getZ());
|
||||
glVertex3f(e1, -e2, -e3);
|
||||
glVertex3f(-e1, -e2, -e3);
|
||||
|
||||
glVertex3f(s3.getX(), s3.getY(), s3.getZ());
|
||||
glVertex3f(s7.getX(), s7.getY(), s7.getZ());
|
||||
glVertex3f(e1, -e2, e3);
|
||||
glVertex3f(-e1, -e2, e3);
|
||||
|
||||
glVertex3f(s2.getX(), s2.getY(), s2.getZ());
|
||||
glVertex3f(s6.getX(), s6.getY(), s6.getZ());
|
||||
|
||||
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());
|
||||
glVertex3f(e1, e2, e3);
|
||||
glVertex3f(-e1, e2, e3);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
#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]);
|
||||
}
|
||||
|
|
203
src/body/OBB.h
203
src/body/OBB.h
|
@ -35,206 +35,53 @@ namespace reactphysics3d {
|
|||
|
||||
/* -------------------------------------------------------------------
|
||||
Class OBB :
|
||||
This class represents a bounding volume of type "Oriented Bounding
|
||||
Box". It's a box that has a given orientation is space. The three
|
||||
axis of the OBB are three axis that give the orientation of the
|
||||
OBB. The three axis are normal vectors to the faces of the OBB.
|
||||
Those axis are unit length. The three extents are half-widths
|
||||
of the box along the three axis of the OBB.
|
||||
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
|
||||
-------------------------------------------------------------------
|
||||
*/
|
||||
class OBB : public NarrowBoundingVolume {
|
||||
protected :
|
||||
Vector3D center; // Center point of the OBB
|
||||
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
|
||||
private :
|
||||
Vector3D extent; // Extent sizes of the box
|
||||
|
||||
public :
|
||||
OBB(const Vector3D& center, const Vector3D& axis1, const Vector3D& axis2,
|
||||
const Vector3D& axis3, double extent1, double extent2, double extent3); // Constructor
|
||||
virtual ~OBB(); // Destructor
|
||||
OBB(const Vector3D& extent); // Constructor
|
||||
virtual ~OBB(); // Destructor
|
||||
|
||||
Vector3D getCenter() const; // Return the center point of the OBB
|
||||
void setCenter(const Vector3D& center); // Set the center point
|
||||
Vector3D getAxis(unsigned int index) const throw(std::invalid_argument); // Return an axis of the OBB
|
||||
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
|
||||
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
|
||||
|
||||
#ifdef VISUAL_DEBUG
|
||||
virtual void draw() const; // Draw the OBB (only for testing purpose)
|
||||
#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
|
||||
inline Vector3D OBB::getCenter() const {
|
||||
return center;
|
||||
// Return the extents of the box
|
||||
inline const Vector3D& OBB::getExtent() const {
|
||||
return extent;
|
||||
}
|
||||
|
||||
// Set the center point
|
||||
inline void OBB::setCenter(const Vector3D& center) {
|
||||
this->center = center;
|
||||
// Set the extents of the box
|
||||
inline void OBB::setExtent(const Vector3D& extent) {
|
||||
this->extent = extent;
|
||||
}
|
||||
|
||||
// Return an axis of the OBB
|
||||
inline Vector3D OBB::getAxis(unsigned int index) const throw(std::invalid_argument) {
|
||||
// Check if the index value is valid
|
||||
if (index >= 0 && index <3) {
|
||||
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 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 OBB::getLocalExtents() const {
|
||||
return extent;
|
||||
}
|
||||
|
||||
// Return a support point in a given direction
|
||||
inline Vector3D OBB::getSupportPoint(const Vector3D& direction, double margin) const {
|
||||
assert(direction.length() > 0.0);
|
||||
assert(margin >= 0.0);
|
||||
|
||||
// TODO : Implement this method
|
||||
assert(false);
|
||||
return Vector3D();
|
||||
return Vector3D(direction.getX() < 0.0 ? -extent.getX()-margin : extent.getX()+margin,
|
||||
direction.getY() < 0.0 ? -extent.getY()-margin : extent.getY()+margin,
|
||||
direction.getZ() < 0.0 ? -extent.getZ()-margin : extent.getZ()+margin);
|
||||
}
|
||||
|
||||
}; // End of the ReactPhysics3D namespace
|
||||
|
|
|
@ -31,10 +31,11 @@
|
|||
using namespace reactphysics3d;
|
||||
|
||||
// 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)
|
||||
: Body(mass), position(position), orientation(orientation.getUnit()), inertiaTensorLocal(inertiaTensorLocal),
|
||||
inertiaTensorLocalInverse(inertiaTensorLocal.getInverse()), massInverse(1.0/mass), oldPosition(position), oldOrientation(orientation) {
|
||||
: Body(transform, mass), inertiaTensorLocal(inertiaTensorLocal),
|
||||
inertiaTensorLocalInverse(inertiaTensorLocal.getInverse()), massInverse(1.0/mass) {
|
||||
|
||||
restitution = 1.0;
|
||||
isMotionEnabled = true;
|
||||
|
@ -44,13 +45,9 @@
|
|||
// Set the bounding volume for the narrow-phase collision detection
|
||||
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();
|
||||
|
||||
assert(broadBoundingVolume);
|
||||
assert(narrowBoundingVolume);
|
||||
}
|
||||
|
||||
|
@ -61,7 +58,8 @@ RigidBody::~RigidBody() {
|
|||
|
||||
// Update the rigid body in order to reflect a change in the body state
|
||||
void RigidBody::update() {
|
||||
// Update the orientation of the corresponding bounding volumes of the rigid body
|
||||
broadBoundingVolume->update(position, orientation);
|
||||
narrowBoundingVolume->update(position, orientation);
|
||||
// TODO : Remove the following code when using a Transform
|
||||
|
||||
// Update the AABB
|
||||
aabb->update(transform, narrowBoundingVolume->getLocalExtents());
|
||||
}
|
|
@ -42,10 +42,11 @@ namespace reactphysics3d {
|
|||
*/
|
||||
class RigidBody : public Body {
|
||||
protected :
|
||||
Vector3D position; // Position of the center of mass of the body
|
||||
Vector3D oldPosition; // Old position used to compute the interpolated position
|
||||
Quaternion orientation; // Orientation quaternion of the body
|
||||
Quaternion oldOrientation; // Old orientation used to compute the interpolated orientation
|
||||
// TODO : Remove some of the following variables
|
||||
//Vector3D position; // Position of the center of mass of the body
|
||||
//Vector3D oldPosition; // Old position used to compute the interpolated position
|
||||
//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 angularVelocity; // Angular velocity of 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 inertiaTensorLocalInverse; // Inverse of the inertia tensor of the body (in body coordinates)
|
||||
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
|
||||
|
||||
public :
|
||||
RigidBody(const Vector3D& position, const Quaternion& orientation, double mass,
|
||||
RigidBody(const Transform& transform, double mass,
|
||||
const Matrix3x3& inertiaTensorLocal, NarrowBoundingVolume* narrowBoundingVolume); // Constructor // Copy-constructor
|
||||
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
|
||||
void setLinearVelocity(const Vector3D& linearVelocity); // Set the linear velocity of the body
|
||||
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 getInertiaTensorWorld() const; // Return 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
|
||||
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
|
||||
};
|
||||
|
||||
// --- 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
|
||||
inline Vector3D RigidBody::getLinearVelocity() const {
|
||||
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
|
||||
inline Matrix3x3 RigidBody::getInertiaTensorWorld() const {
|
||||
// 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
|
||||
|
@ -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
|
||||
inline Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const {
|
||||
// Compute and return the inertia tensor in world coordinates
|
||||
return orientation.getMatrix() * inertiaTensorLocalInverse * orientation.getMatrix().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);
|
||||
return transform.getOrientation() * inertiaTensorLocalInverse * transform.getOrientation().getTranspose();
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user