From 2b3b1bff0a56524c0dfaaa67acb239c184708432 Mon Sep 17 00:00:00 2001 From: "chappuis.daniel" Date: Thu, 9 Sep 2010 22:27:01 +0000 Subject: [PATCH] Change in the repository structure git-svn-id: https://reactphysics3d.googlecode.com/svn/trunk@398 92aac97c-a6ce-11dd-a772-7fcde58d38e6 --- src/body/AABB.cpp | 114 ++++++++++++++ src/body/AABB.h | 178 +++++++++++++++++++++ src/body/Body.cpp | 65 ++++++++ src/body/Body.h | 112 ++++++++++++++ src/body/BoundingVolume.cpp | 39 +++++ src/body/BoundingVolume.h | 73 +++++++++ src/body/BroadBoundingVolume.cpp | 39 +++++ src/body/BroadBoundingVolume.h | 52 +++++++ src/body/NarrowBoundingVolume.cpp | 39 +++++ src/body/NarrowBoundingVolume.h | 56 +++++++ src/body/OBB.cpp | 210 +++++++++++++++++++++++++ src/body/OBB.h | 228 +++++++++++++++++++++++++++ src/body/RigidBody.cpp | 67 ++++++++ src/body/RigidBody.h | 246 ++++++++++++++++++++++++++++++ 14 files changed, 1518 insertions(+) create mode 100644 src/body/AABB.cpp create mode 100644 src/body/AABB.h create mode 100644 src/body/Body.cpp create mode 100644 src/body/Body.h create mode 100644 src/body/BoundingVolume.cpp create mode 100644 src/body/BoundingVolume.h create mode 100644 src/body/BroadBoundingVolume.cpp create mode 100644 src/body/BroadBoundingVolume.h create mode 100644 src/body/NarrowBoundingVolume.cpp create mode 100644 src/body/NarrowBoundingVolume.h create mode 100644 src/body/OBB.cpp create mode 100644 src/body/OBB.h create mode 100644 src/body/RigidBody.cpp create mode 100644 src/body/RigidBody.h diff --git a/src/body/AABB.cpp b/src/body/AABB.cpp new file mode 100644 index 00000000..03ae3443 --- /dev/null +++ b/src/body/AABB.cpp @@ -0,0 +1,114 @@ +/******************************************************************************** +* 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 "AABB.h" +#include // TODO : Remove this in the final version +#include // TODO : Remove this in the final version +#include + +using namespace reactphysics3d; +using namespace std; + +// Constructor +AABB::AABB(const Vector3D& center,double extentX, double extentY, double extentZ) { + this->center = center; + + this->extent[0] = extentX; + this->extent[1] = extentY; + this->extent[2] = extentZ; + + this->originalAABBExtent[0] = extentX; + this->originalAABBExtent[1] = extentY; + this->originalAABBExtent[2] = extentZ; +} + +// Destructor +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(s2.getX(), s2.getY(), s2.getZ()); + glVertex3f(s3.getX(), s3.getY(), s3.getZ()); + + glVertex3f(s3.getX(), s3.getY(), s3.getZ()); + glVertex3f(s4.getX(), s4.getY(), s4.getZ()); + + glVertex3f(s4.getX(), s4.getY(), s4.getZ()); + glVertex3f(s1.getX(), s1.getY(), s1.getZ()); + + glVertex3f(s5.getX(), s5.getY(), s5.getZ()); + glVertex3f(s6.getX(), s6.getY(), s6.getZ()); + + glVertex3f(s6.getX(), s6.getY(), s6.getZ()); + glVertex3f(s7.getX(), s7.getY(), s7.getZ()); + + glVertex3f(s7.getX(), s7.getY(), s7.getZ()); + glVertex3f(s8.getX(), s8.getY(), s8.getZ()); + + glVertex3f(s8.getX(), s8.getY(), s8.getZ()); + glVertex3f(s5.getX(), s5.getY(), s5.getZ()); + + glVertex3f(s1.getX(), s1.getY(), s1.getZ()); + glVertex3f(s5.getX(), s5.getY(), s5.getZ()); + + glVertex3f(s4.getX(), s4.getY(), s4.getZ()); + glVertex3f(s8.getX(), s8.getY(), s8.getZ()); + + glVertex3f(s3.getX(), s3.getY(), s3.getZ()); + glVertex3f(s7.getX(), s7.getY(), s7.getZ()); + + glVertex3f(s2.getX(), s2.getY(), s2.getZ()); + glVertex3f(s6.getX(), s6.getY(), s6.getZ()); + + glEnd(); +} + +// 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& vertices, const Vector3D& center) { + // TODO : Implement this method; + return 0; +} + diff --git a/src/body/AABB.h b/src/body/AABB.h new file mode 100644 index 00000000..17b10c0a --- /dev/null +++ b/src/body/AABB.h @@ -0,0 +1,178 @@ +/******************************************************************************** +* 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 AABB_H +#define AABB_H + +// Libraries +#include "BroadBoundingVolume.h" +#include "../mathematics/mathematics.h" + +// ReactPhysics3D namespace +namespace reactphysics3d { + +/* ------------------------------------------------------------------- + Class AABB : + This class represents a bounding volume of type "Axis Aligned + Bounding Box". It's a box where all the edges are always aligned + with the world coordinate system. The AABB is defined by a center + 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) + + public : + AABB(const Vector3D& center, double extentX, double extentY, double extentZ); // 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 + virtual void draw() const; // Draw the AABB (only for testing purpose) + static AABB* computeFromVertices(const std::vector& vertices, const Vector3D& center); // Compute an AABB from a set of vertices +}; + +// Return the center point +inline Vector3D AABB::getCenter() const { + return center; +} + +// Set the center point +inline void AABB::setCenter(const Vector3D& center) { + this->center = center; +} + +// 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 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 +inline double AABB::getMinValueOnAxis(uint axis) const throw(std::invalid_argument) { + switch (axis) { + case 0: return center.getX() - extent[0]; + case 1: return center.getY() - extent[1]; + case 2: return center.getZ() - extent[2]; + 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 +inline double AABB::getMaxValueOnAxis(uint axis) const throw(std::invalid_argument) { + switch (axis) { + case 0: return center.getX() + extent[0]; + case 1: return center.getY() + extent[1]; + case 2: return center.getZ() + extent[2]; + 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 is the AABB in argument +// Two AABB overlap if they overlap in the three x, y and z axis at the same time +inline bool AABB::testCollision(const AABB& aabb) const { + Vector3D center2 = aabb.getCenter(); + if (std::abs(center.getX() - center2.getX()) > (extent[0] + aabb.getExtent(0))) return false; + if (std::abs(center.getY() - center2.getY()) > (extent[1] + aabb.getExtent(1))) return false; + if (std::abs(center.getZ() - center2.getZ()) > (extent[2] + aabb.getExtent(2))) 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]; + } + } +} + +}; // End of the ReactPhysics3D namespace + +#endif diff --git a/src/body/Body.cpp b/src/body/Body.cpp new file mode 100644 index 00000000..64079491 --- /dev/null +++ b/src/body/Body.cpp @@ -0,0 +1,65 @@ +/******************************************************************************** +* 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 "Body.h" +#include "BroadBoundingVolume.h" +#include "NarrowBoundingVolume.h" + +// We want to use the ReactPhysics3D namespace +using namespace reactphysics3d; + +// Constructor +Body::Body(double mass) throw(std::invalid_argument) + : mass(mass), broadBoundingVolume(0), narrowBoundingVolume(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"); + } +} + +// Destructor +Body::~Body() { + if (broadBoundingVolume) { + delete broadBoundingVolume; + } + if (narrowBoundingVolume) { + delete narrowBoundingVolume; + } +} + +// 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) { + assert(narrowBoundingVolume); + this->narrowBoundingVolume = narrowBoundingVolume; + narrowBoundingVolume->setBodyPointer(this); +} diff --git a/src/body/Body.h b/src/body/Body.h new file mode 100644 index 00000000..7bc4555a --- /dev/null +++ b/src/body/Body.h @@ -0,0 +1,112 @@ +/******************************************************************************** +* 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 BODY_H +#define BODY_H + +// Libraries +#include +#include + + +// Namespace reactphysics3d +namespace reactphysics3d { + +class BroadBoundingVolume; +class NarrowBoundingVolume; + +/* ------------------------------------------------------------------- + Class Body : + This class is an abstract class to represent body of the physics + engine. + ------------------------------------------------------------------- +*/ +class Body { + protected : + double mass; // Mass of the body + 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 + + 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 + virtual ~Body(); // Destructor + + double getMass() const; // Return the mass of the body + void setMass(double mass); // Set the mass 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 +}; + +// Method that return the mass of the body +inline double Body::getMass() const { + return mass; +}; + +// Return if the rigid body can move +inline bool Body::getIsMotionEnabled() const { + return isMotionEnabled; +} + +// Set the value to true if the body can move +inline void Body::setIsMotionEnabled(bool isMotionEnabled) { + this->isMotionEnabled = isMotionEnabled; +} + +// Method that set the mass of the body +inline void Body::setMass(double mass) { + this->mass = mass; +} + + // Return true if the body can collide with others bodies +inline bool Body::getIsCollisionEnabled() const { + return isCollisionEnabled; +} + +// Set the isCollisionEnabled value +inline void Body::setIsCollisionEnabled(bool isCollisionEnabled) { + this->isCollisionEnabled = isCollisionEnabled; +} + +// 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; +} + +} + + #endif diff --git a/src/body/BoundingVolume.cpp b/src/body/BoundingVolume.cpp new file mode 100644 index 00000000..6d13a672 --- /dev/null +++ b/src/body/BoundingVolume.cpp @@ -0,0 +1,39 @@ +/******************************************************************************** +* 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 "BoundingVolume.h" + +// We want to use the ReactPhysics3D namespace +using namespace reactphysics3d; + +// Constructor +BoundingVolume::BoundingVolume() { + this->body = 0; +} + +// Destructor +BoundingVolume::~BoundingVolume() { + +} diff --git a/src/body/BoundingVolume.h b/src/body/BoundingVolume.h new file mode 100644 index 00000000..163671b6 --- /dev/null +++ b/src/body/BoundingVolume.h @@ -0,0 +1,73 @@ +/******************************************************************************** +* 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 BOUNDING_VOLUME_H +#define BOUNDING_VOLUME_H + +// Libraries +#include "Body.h" +#include "../mathematics/mathematics.h" +#include + + +// ReactPhysics3D namespace +namespace reactphysics3d { + +/* ------------------------------------------------------------------- + Class BoundingVolume : + This class represents the volume that contains a rigid body. + This volume will be used to compute the collisions with others + bodies. + ------------------------------------------------------------------- +*/ +class BoundingVolume { + protected : + Body* body; // Pointer to the body + + public : + BoundingVolume(); // Constructor + virtual ~BoundingVolume(); // Destructor + + 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 + virtual void draw() const=0; // Display the bounding volume (only for testing purpose) +}; + +// Return the body pointer +inline Body* BoundingVolume::getBodyPointer() const { + assert(body != 0); + return body; +} + +// Set the body pointer +inline void BoundingVolume::setBodyPointer(Body* bodyPointer) { + this->body = bodyPointer; +} + + +} // End of the ReactPhysics3D namespace + +#endif diff --git a/src/body/BroadBoundingVolume.cpp b/src/body/BroadBoundingVolume.cpp new file mode 100644 index 00000000..fa7a59ef --- /dev/null +++ b/src/body/BroadBoundingVolume.cpp @@ -0,0 +1,39 @@ +/******************************************************************************** +* 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() { + +} diff --git a/src/body/BroadBoundingVolume.h b/src/body/BroadBoundingVolume.h new file mode 100644 index 00000000..dad2e361 --- /dev/null +++ b/src/body/BroadBoundingVolume.h @@ -0,0 +1,52 @@ +/******************************************************************************** +* 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 \ No newline at end of file diff --git a/src/body/NarrowBoundingVolume.cpp b/src/body/NarrowBoundingVolume.cpp new file mode 100644 index 00000000..848a333c --- /dev/null +++ b/src/body/NarrowBoundingVolume.cpp @@ -0,0 +1,39 @@ +/******************************************************************************** +* 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 "NarrowBoundingVolume.h" + +// We want to use the ReactPhysics3D namespace +using namespace reactphysics3d; + +// Constructor +NarrowBoundingVolume::NarrowBoundingVolume() : BoundingVolume() { + +} + +// Destructor +NarrowBoundingVolume::~NarrowBoundingVolume() { + +} diff --git a/src/body/NarrowBoundingVolume.h b/src/body/NarrowBoundingVolume.h new file mode 100644 index 00000000..64d07a30 --- /dev/null +++ b/src/body/NarrowBoundingVolume.h @@ -0,0 +1,56 @@ +/**************************************************************************** +/******************************************************************************** +* 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 NARROW_BOUNDING_VOLUME_H +#define NARROW_BOUNDING_VOLUME_H + +// Libraries +#include "BoundingVolume.h" +#include "AABB.h" + + +// ReactPhysics3D namespace +namespace reactphysics3d { + +/* ------------------------------------------------------------------- + Class NarrowBoundingVolume : + This class represents the volume that contains a rigid body + This volume will be used to compute the narrow-phase collision + detection. + ------------------------------------------------------------------- +*/ +class NarrowBoundingVolume : public BoundingVolume { + protected : + + public : + NarrowBoundingVolume(); // Constructor + virtual ~NarrowBoundingVolume(); // Destructor + + virtual AABB* computeAABB() const=0; // Return the corresponding AABB +}; + +} + +#endif \ No newline at end of file diff --git a/src/body/OBB.cpp b/src/body/OBB.cpp new file mode 100644 index 00000000..adea91be --- /dev/null +++ b/src/body/OBB.cpp @@ -0,0 +1,210 @@ +/******************************************************************************** +* 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 "OBB.h" +#include +#include // TODO : Remove this in the final version +#include // TODO : Remove this in the final version +#include + +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; + + 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 +OBB::~OBB() { + +} + +// 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); + + // 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(s2.getX(), s2.getY(), s2.getZ()); + glVertex3f(s3.getX(), s3.getY(), s3.getZ()); + + glVertex3f(s3.getX(), s3.getY(), s3.getZ()); + glVertex3f(s4.getX(), s4.getY(), s4.getZ()); + + glVertex3f(s4.getX(), s4.getY(), s4.getZ()); + glVertex3f(s1.getX(), s1.getY(), s1.getZ()); + + glVertex3f(s5.getX(), s5.getY(), s5.getZ()); + glVertex3f(s6.getX(), s6.getY(), s6.getZ()); + + glVertex3f(s6.getX(), s6.getY(), s6.getZ()); + glVertex3f(s7.getX(), s7.getY(), s7.getZ()); + + glVertex3f(s7.getX(), s7.getY(), s7.getZ()); + glVertex3f(s8.getX(), s8.getY(), s8.getZ()); + + glVertex3f(s8.getX(), s8.getY(), s8.getZ()); + glVertex3f(s5.getX(), s5.getY(), s5.getZ()); + + glVertex3f(s1.getX(), s1.getY(), s1.getZ()); + glVertex3f(s5.getX(), s5.getY(), s5.getZ()); + + glVertex3f(s4.getX(), s4.getY(), s4.getZ()); + glVertex3f(s8.getX(), s8.getY(), s8.getZ()); + + glVertex3f(s3.getX(), s3.getY(), s3.getZ()); + glVertex3f(s7.getX(), s7.getY(), s7.getZ()); + + 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()); + + glEnd(); +} + +// 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 OBB::getExtremeVertices(const Vector3D& directionAxis) const { + assert(directionAxis.length() != 0); + + vector extremeVertices; + + // Check if the given axis is parallel to an axis on the OBB + if (axis[0].isParallelWith(directionAxis)) { + if (axis[0].scalarProduct(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].scalarProduct(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].scalarProduct(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.scalarProduct(vertex-center) / directionAxis.length(); + + // If we found a bigger projection length + if (projectionLength > maxProjectionLength + EPSILON) { + 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& vertices, const Vector3D& center) { + // TODO : Implement this method; + return 0; +} + +// 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]); +} diff --git a/src/body/OBB.h b/src/body/OBB.h new file mode 100644 index 00000000..c72a8fff --- /dev/null +++ b/src/body/OBB.h @@ -0,0 +1,228 @@ +/******************************************************************************** +* 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 OBB_H +#define OBB_H + +// Libraries +#include +#include "NarrowBoundingVolume.h" +#include "../mathematics/mathematics.h" + +// ReactPhysics3D namespace +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. + ------------------------------------------------------------------- +*/ +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 + + public : + OBB(const Vector3D& center, const Vector3D& axis1, const Vector3D& axis2, + const Vector3D& axis3, double extent1, double extent2, double extent3); // 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 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 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 void draw() const; // Draw the OBB (only for testing purpose) + static OBB* computeFromVertices(const std::vector& 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; +} + +// Set the center point +inline void OBB::setCenter(const Vector3D& center) { + this->center = center; +} + +// 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 OBB::getFace(unsigned int index) const throw(std::invalid_argument) { + // Check the argument + if (index >=0 && index <6) { + std::vector 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(); +} + +}; // End of the ReactPhysics3D namespace + +#endif diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp new file mode 100644 index 00000000..9e375edb --- /dev/null +++ b/src/body/RigidBody.cpp @@ -0,0 +1,67 @@ +/******************************************************************************** +* 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 "RigidBody.h" +#include "BroadBoundingVolume.h" +#include "NarrowBoundingVolume.h" + + // We want to use the ReactPhysics3D namespace + using namespace reactphysics3d; + + // Constructor + RigidBody::RigidBody(const Vector3D& position, const Quaternion& orientation, 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) { + + restitution = 1.0; + isMotionEnabled = true; + isCollisionEnabled = true; + interpolationFactor = 0.0; + + // 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); +} + +// Destructor +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); +} \ No newline at end of file diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h new file mode 100644 index 00000000..e3ecf788 --- /dev/null +++ b/src/body/RigidBody.h @@ -0,0 +1,246 @@ +/******************************************************************************** +* 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 RIGIDBODY_H +#define RIGIDBODY_H + +// Libraries +#include +#include "Body.h" +#include "../mathematics/mathematics.h" + +// Namespace reactphysics3d +namespace reactphysics3d { + +/* ------------------------------------------------------------------- + Class RigidBody : + This class represents a rigid body of the physics + engine. A rigid body is a non-deformable body that + has a constant mass. + ------------------------------------------------------------------- +*/ +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 + Vector3D linearVelocity; // Linear velocity of the body + Vector3D angularVelocity; // Angular velocity of the body + Vector3D externalForce; // Current external force on the body + Vector3D externalTorque; // Current external torque on the 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, + 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 + void setAngularVelocity(const Vector3D& angularVelocity); // Set the angular velocity + void setMassInverse(double massInverse); // Set the inverse of the mass + Vector3D getExternalForce() const; // Return the current external force of the body + void setExternalForce(const Vector3D& force); // Set the current external force on the body + Vector3D getExternalTorque() const; // Return the current external torque of the body + void setExternalTorque(const Vector3D& torque); // Set the current external torque of the body + double getMassInverse() const; // Return the inverse of the mass of the body + Matrix3x3 getInertiaTensorLocal() const; // Return the local inertia tensor of the body (in body coordinates) + void setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal); // Set the local inertia tensor of the body (in body coordinates) + 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; +} + +// Return the angular velocity of the body +inline Vector3D RigidBody::getAngularVelocity() const { + return angularVelocity; +} + +inline void RigidBody::setAngularVelocity(const Vector3D& angularVelocity) { + this->angularVelocity = angularVelocity; +} + +// Set the inverse of the mass +inline void RigidBody::setMassInverse(double massInverse) { + this->massInverse = massInverse; +} + +// Get the inverse of the inertia tensor +inline Matrix3x3 RigidBody::getInertiaTensorLocalInverse() const { + return inertiaTensorLocalInverse; +} + +// Return the external force on the body +inline Vector3D RigidBody::getExternalForce() const { + return externalForce; +} + +// Set the external force on the body +inline void RigidBody::setExternalForce(const Vector3D& force) { + this->externalForce = force; +} + +// Return the current external torque on the body +inline Vector3D RigidBody::getExternalTorque() const { + return externalTorque; +} + + // Set the current external torque on the body +inline void RigidBody::setExternalTorque(const Vector3D& torque) { + this->externalTorque = torque; +} + +// Return the inverse of the mass of the body +inline double RigidBody::getMassInverse() const { + return massInverse; +} + +// Return the local inertia tensor of the body (in body coordinates) +inline Matrix3x3 RigidBody::getInertiaTensorLocal() const { + return inertiaTensorLocal; +} + +// Set the local inertia tensor of the body (in body coordinates) +inline void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) { + this->inertiaTensorLocal = inertiaTensorLocal; +} + +// Return the inertia tensor in world coordinates +// The inertia tensor I_w in world coordinates in computed with the local inertia tensor I_b in body coordinates +// by I_w = R * I_b * R^T +// 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 the inverse of the inertia tensor in world coordinates +// The inertia tensor I_w in world coordinates in computed with the local inverse inertia tensor I_b^-1 in body coordinates +// by I_w = R * I_b^-1 * R^T +// 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); +} + +// Set the linear velocity of the rigid body +inline void RigidBody::setLinearVelocity(const Vector3D& linearVelocity) { + // If the body is able to move + if (isMotionEnabled) { + // Update the linear velocity of the current body state + this->linearVelocity = linearVelocity; + } +} + +// Get the restitution coeffficient of the rigid body +inline double RigidBody::getRestitution() const { + return restitution; +} + +// Set the restitution coefficient +inline void RigidBody::setRestitution(double restitution) throw(std::invalid_argument) { + // Check if the restitution coefficient is between 0 and 1 + if (restitution >= 0.0 && restitution <= 1.0) { + this->restitution = restitution; + } + else { + throw std::invalid_argument("Error : the restitution coefficent must be between 0 and 1"); + } +} + +// 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 + + #endif