reactphysics3d/sources/body/OBB.cpp
chappuis.daniel 852b923c21 Change in the repository structure
git-svn-id: https://reactphysics3d.googlecode.com/svn/trunk@391 92aac97c-a6ce-11dd-a772-7fcde58d38e6
2010-09-09 21:00:14 +00:00

211 lines
8.6 KiB
C++

/********************************************************************************
* 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 <vector>
#include <GL/freeglut.h> // TODO : Remove this in the final version
#include <GL/gl.h> // TODO : Remove this in the final version
#include <cassert>
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<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].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<Vector3D>& 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]);
}