Refactor convex mesh shape (create PolyhedronMesh, ConvexPolyhedron classes)

This commit is contained in:
Daniel Chappuis 2017-03-22 19:07:31 +01:00
parent 0ecd554f50
commit 050e8b36dc
22 changed files with 751 additions and 421 deletions

View File

@ -90,6 +90,8 @@ SET (REACTPHYSICS3D_SOURCES
"src/collision/shapes/AABB.cpp"
"src/collision/shapes/ConvexShape.h"
"src/collision/shapes/ConvexShape.cpp"
"src/collision/shapes/ConvexPolyhedron.h"
"src/collision/shapes/ConvexPolyhedron.cpp"
"src/collision/shapes/ConcaveShape.h"
"src/collision/shapes/ConcaveShape.cpp"
"src/collision/shapes/BoxShape.h"
@ -114,6 +116,8 @@ SET (REACTPHYSICS3D_SOURCES
"src/collision/ProxyShape.cpp"
"src/collision/TriangleVertexArray.h"
"src/collision/TriangleVertexArray.cpp"
"src/collision/PolygonVertexArray.h"
"src/collision/PolygonVertexArray.cpp"
"src/collision/TriangleMesh.h"
"src/collision/TriangleMesh.cpp"
"src/collision/PolyhedronMesh.h"

View File

@ -29,8 +29,8 @@
using namespace reactphysics3d;
// Initialize the structure
void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vector<uint>> faces) {
// Initialize the structure (when all vertices and faces have been added)
void HalfEdgeStructure::init() {
using edgeKey = std::pair<uint, uint>;
@ -41,30 +41,19 @@ void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vec
std::map<uint, edgeKey> mapEdgeIndexToKey;
std::map<uint, edgeKey> mapFaceIndexToEdgeKey;
// For each vertices
for (uint v=0; v<vertices.size(); v++) {
Vertex vertex(vertices[v]);
mVertices.push_back(vertex);
}
// For each face
for (uint f=0; f<faces.size(); f++) {
for (uint f=0; f<mFaces.size(); f++) {
// Create a new face
Face face;
mFaces.push_back(face);
// Vertices of the current face
std::vector<uint>& faceVertices = faces[f];
Face face = mFaces[f];
std::vector<edgeKey> currentFaceEdges;
edgeKey firstEdgeKey;
// For each vertex of the face
for (uint v=0; v < faceVertices.size(); v++) {
uint v1Index = faceVertices[v];
uint v2Index = faceVertices[v == (faceVertices.size() - 1) ? 0 : v + 1];
for (uint v=0; v < face.faceVertices.size(); v++) {
uint v1Index = face.faceVertices[v];
uint v2Index = face.faceVertices[v == (face.faceVertices.size() - 1) ? 0 : v + 1];
const edgeKey pairV1V2 = std::make_pair(v1Index, v2Index);
@ -78,7 +67,7 @@ void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vec
else if (v >= 1) {
nextEdges.insert(std::make_pair(currentFaceEdges[currentFaceEdges.size() - 1], pairV1V2));
}
if (v == (faceVertices.size() - 1)) {
if (v == (face.faceVertices.size() - 1)) {
nextEdges.insert(std::make_pair(pairV1V2, firstEdgeKey));
}
edges.insert(std::make_pair(pairV1V2, edge));
@ -121,7 +110,7 @@ void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vec
}
// Set face edge
for (uint f=0; f < faces.size(); f++) {
for (uint f=0; f < mFaces.size(); f++) {
mFaces[f].edgeIndex = mapEdgeToIndex[mapFaceIndexToEdgeKey[f]];
}
}

View File

@ -51,14 +51,18 @@ class HalfEdgeStructure {
struct Face {
uint edgeIndex; // Index of an half-edge of the face
std::vector<uint> faceVertices; // Index of the vertices of the face
/// Constructor
Face(std::vector<uint> vertices) : faceVertices(vertices) {}
};
struct Vertex {
Vector3 point; // Coordinates of the vertex
uint vertexPointIndex; // Index of the vertex point in the origin vertex array
uint edgeIndex; // Index of one edge emanting from this vertex
/// Constructor
Vertex(Vector3& p) { point = p;}
Vertex(uint vertexCoordsIndex) : vertexPointIndex(vertexCoordsIndex) { }
};
private:
@ -80,8 +84,14 @@ class HalfEdgeStructure {
/// Destructor
~HalfEdgeStructure() = default;
/// Initialize the structure
void init(std::vector<Vector3> vertices, std::vector<std::vector<uint>> faces);
/// Initialize the structure (when all vertices and faces have been added)
void init();
/// Add a vertex
uint addVertex(uint vertexPointIndex);
/// Add a face
void addFace(std::vector<uint> faceVertices);
/// Return the number of faces
uint getNbFaces() const;
@ -98,11 +108,26 @@ class HalfEdgeStructure {
/// Return a given edge
Edge getHalfEdge(uint index) const;
/// Retunr a given vertex
/// Return a given vertex
Vertex getVertex(uint index) const;
};
// Add a vertex
inline uint HalfEdgeStructure::addVertex(uint vertexPointIndex) {
Vertex vertex(vertexPointIndex);
mVertices.push_back(vertex);
return mVertices.size() - 1;
}
// Add a face
inline void HalfEdgeStructure::addFace(std::vector<uint> faceVertices) {
// Create a new face
Face face(faceVertices);
mFaces.push_back(face);
}
// Return the number of faces
inline uint HalfEdgeStructure::getNbFaces() const {
return mFaces.size();

View File

@ -0,0 +1,75 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "PolygonVertexArray.h"
using namespace reactphysics3d;
// Constructor
/// Note that your data will not be copied into the PolygonVertexArray and
/// therefore, you need to make sure that those data are always valid during
/// the lifetime of the PolygonVertexArray.
/**
*/
PolygonVertexArray::PolygonVertexArray(uint nbVertices, void* verticesStart, int verticesStride,
void* indexesStart, int indexesStride,
uint nbFaces, PolygonFace* facesStart,
VertexDataType vertexDataType, IndexDataType indexDataType) {
mNbVertices = nbVertices;
mVerticesStart = reinterpret_cast<unsigned char*>(verticesStart);
mVerticesStride = verticesStride;
mIndicesStart = reinterpret_cast<unsigned char*>(indexesStart);
mIndicesStride = indexesStride;
mNbFaces = nbFaces;
mPolygonFacesStart = facesStart;
mVertexDataType = vertexDataType;
mIndexDataType = indexDataType;
}
// Return the vertex index of a given vertex in a face
uint PolygonVertexArray::getVertexIndexInFace(uint faceIndex, uint noVertexInFace) const {
assert(faceIndex < mNbFaces);
// Get the face
PolygonFace* face = getPolygonFace(faceIndex);
assert(noVertexInFace < face->nbVertices);
void* vertexIndexPointer = mIndicesStart + (face->indexBase + noVertexInFace) * mIndicesStride;
if (mIndexDataType == PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE) {
return *((uint*)vertexIndexPointer);
}
else if (mIndexDataType == PolygonVertexArray::IndexDataType::INDEX_SHORT_TYPE) {
return *((unsigned short*)vertexIndexPointer);
}
else {
assert(false);
}
return 0;
}

View File

@ -0,0 +1,188 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_POLYGON_VERTEX_ARRAY_H
#define REACTPHYSICS3D_POLYGON_VERTEX_ARRAY_H
// Libraries
#include "configuration.h"
#include <cassert>
namespace reactphysics3d {
// Class PolygonVertexArray
/**
* This class is used to describe the vertices and faces of a polyhedron mesh.
* A PolygonVertexArray represents an array of vertices and polygon faces
* of a polyhedron mesh. When you create a PolygonVertexArray, no data is copied
* into the array. It only stores pointer to the data. The purpose is to allow
* the user to share vertices data between the physics engine and the rendering
* part. Therefore, make sure that the data pointed by a PolygonVertexArray
* remains valid during the PolygonVertexArray life.
*/
class PolygonVertexArray {
public:
/// Data type for the vertices in the array
enum class VertexDataType {VERTEX_FLOAT_TYPE, VERTEX_DOUBLE_TYPE};
/// Data type for the indices in the array
enum class IndexDataType {INDEX_INTEGER_TYPE, INDEX_SHORT_TYPE};
/// Represent a polygon face of the polyhedron
struct PolygonFace {
/// Number of vertices in the polygon face
uint nbVertices;
/// Index of the first vertex of the polygon face
/// inside the array with all vertex indices
uint indexBase;
};
protected:
/// Number of vertices in the array
uint mNbVertices;
/// Pointer to the first vertex value in the array
unsigned char* mVerticesStart;
/// Stride (number of bytes) between the beginning of two vertices
/// values in the array
int mVerticesStride;
/// Pointer to the first vertex index of the array
unsigned char* mIndicesStart;
/// Stride (number of bytes) between the beginning of two indices in
/// the array
int mIndicesStride;
/// Number of polygon faces in the array
uint mNbFaces;
/// Pointer to the first polygon face in the polyhedron
PolygonFace* mPolygonFacesStart;
/// Data type of the vertices in the array
VertexDataType mVertexDataType;
/// Data type of the indices in the array
IndexDataType mIndexDataType;
public:
/// Constructor
PolygonVertexArray(uint nbVertices, void* verticesStart, int verticesStride,
void* indexesStart, int indexesStride,
uint nbFaces, PolygonFace* facesStart,
VertexDataType vertexDataType, IndexDataType indexDataType);
/// Destructor
~PolygonVertexArray() = default;
/// Return the vertex data type
VertexDataType getVertexDataType() const;
/// Return the index data type
IndexDataType getIndexDataType() const;
/// Return the number of vertices
uint getNbVertices() const;
/// Return the number of faces
uint getNbFaces() const;
/// Return the vertices stride (number of bytes)
int getVerticesStride() const;
/// Return the indices stride (number of bytes)
int getIndicesStride() const;
/// Return the vertex index of a given vertex in a face
uint getVertexIndexInFace(uint faceIndex, uint noVertexInFace) const;
/// Return a polygon face of the polyhedron
PolygonFace* getPolygonFace(uint faceIndex) const;
/// Return the pointer to the start of the vertices array
unsigned char* getVerticesStart() const;
/// Return the pointer to the start of the indices array
unsigned char* getIndicesStart() const;
};
// Return the vertex data type
inline PolygonVertexArray::VertexDataType PolygonVertexArray::getVertexDataType() const {
return mVertexDataType;
}
// Return the index data type
inline PolygonVertexArray::IndexDataType PolygonVertexArray::getIndexDataType() const {
return mIndexDataType;
}
// Return the number of vertices
inline uint PolygonVertexArray::getNbVertices() const {
return mNbVertices;
}
// Return the number of faces
inline uint PolygonVertexArray::getNbFaces() const {
return mNbFaces;
}
// Return the vertices stride (number of bytes)
inline int PolygonVertexArray::getVerticesStride() const {
return mVerticesStride;
}
// Return the indices stride (number of bytes)
inline int PolygonVertexArray::getIndicesStride() const {
return mIndicesStride;
}
// Return a polygon face of the polyhedron
inline PolygonVertexArray::PolygonFace* PolygonVertexArray::getPolygonFace(uint faceIndex) const {
assert(faceIndex < mNbFaces);
return &mPolygonFacesStart[faceIndex];
}
// Return the pointer to the start of the vertices array
inline unsigned char* PolygonVertexArray::getVerticesStart() const {
return mVerticesStart;
}
// Return the pointer to the start of the indices array
inline unsigned char* PolygonVertexArray::getIndicesStart() const {
return mIndicesStart;
}
}
#endif

View File

@ -30,33 +30,70 @@ using namespace reactphysics3d;
// Constructor
PolyhedronMesh::PolyhedronMesh() : mIsFinalized(false) {
PolyhedronMesh::PolyhedronMesh(PolygonVertexArray* polygonVertexArray) {
mPolygonVertexArray = polygonVertexArray;
// Create the half-edge structure of the mesh
createHalfEdgeStructure();
}
// Add a vertex into the polyhedron.
// This method returns the index of the vertex that you need to use
// to add faces.
uint PolyhedronMesh::addVertex(const Vector3& vertex) {
mVertices.push_back(vertex);
return mVertices.size() - 1;
// Create the half-edge structure of the mesh
void PolyhedronMesh::createHalfEdgeStructure() {
// For each vertex of the mesh
for (uint v=0; v < mPolygonVertexArray->getNbVertices(); v++) {
mHalfEdgeStructure.addVertex(v);
}
// Add a face into the polyhedron.
// A face is a list of vertices indices (returned by addVertex() method).
// The order of the indices are important. You need to specify the vertices of
// of the face sorted counter-clockwise as seen from the outside of the polyhedron.
void PolyhedronMesh::addFace(std::vector<uint> faceVertices) {
mFaces.push_back(faceVertices);
// For each polygon face of the mesh
for (uint f=0; f < mPolygonVertexArray->getNbFaces(); f++) {
// Get the polygon face
PolygonVertexArray::PolygonFace* face = mPolygonVertexArray->getPolygonFace(f);
std::vector<uint> faceVertices;
// For each vertex of the face
for (uint v=0; v < face->nbVertices; v++) {
faceVertices.push_back(mPolygonVertexArray->getVertexIndexInFace(f, v));
}
// Call this method when you are done adding vertices and faces
void PolyhedronMesh::finalize() {
if (mIsFinalized) return;
// Addd the face into the half-edge structure
mHalfEdgeStructure.addFace(faceVertices);
}
// Initialize the half-edge structure
mHalfEdgeStructure.init(mVertices, mFaces);
mIsFinalized = true;
mHalfEdgeStructure.init();
}
/// Return a vertex
Vector3 PolyhedronMesh::getVertex(uint index) const {
assert(index < getNbVertices());
// Get the vertex index in the array with all vertices
uint vertexIndex = mHalfEdgeStructure.getVertex(index).vertexPointIndex;
PolygonVertexArray::VertexDataType vertexType = mPolygonVertexArray->getVertexDataType();
unsigned char* verticesStart = mPolygonVertexArray->getVerticesStart();
int vertexStride = mPolygonVertexArray->getVerticesStride();
Vector3 vertex;
if (vertexType == PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE) {
const float* vertices = (float*)(verticesStart + vertexIndex * vertexStride);
vertex.x = decimal(vertices[0]);
vertex.y = decimal(vertices[1]);
vertex.z = decimal(vertices[2]);
}
else if (vertexType == PolygonVertexArray::VertexDataType::VERTEX_DOUBLE_TYPE) {
const double* vertices = (double*)(verticesStart + vertexIndex * vertexStride);
vertex.x = decimal(vertices[0]);
vertex.y = decimal(vertices[1]);
vertex.z = decimal(vertices[2]);
}
else {
assert(false);
}
return vertex;
}

View File

@ -29,6 +29,7 @@
// Libraries
#include "mathematics/mathematics.h"
#include "HalfEdgeStructure.h"
#include "collision/PolygonVertexArray.h"
#include <vector>
namespace reactphysics3d {
@ -36,45 +37,51 @@ namespace reactphysics3d {
// Class PolyhedronMesh
/**
* This class describes a polyhedron mesh made of faces and vertices.
* The faces do not have to be triangle
* The faces do not have to be triangles.
*/
class PolyhedronMesh {
private:
// -------------------- Attributes -------------------- //
/// Pointer the the polygon vertex array with vertices and faces
/// of the mesh
PolygonVertexArray* mPolygonVertexArray;
/// Half-edge structure of the mesh
HalfEdgeStructure mHalfEdgeStructure;
/// True if the half-edge structure has been generated
bool mIsFinalized;
// -------------------- Methods -------------------- //
/// All the vertices
std::vector<Vector3> mVertices;
/// All the indexes of the face vertices
std::vector<std::vector<uint>> mFaces;
/// Create the half-edge structure of the mesh
void createHalfEdgeStructure();
public:
// -------------------- Methods -------------------- //
/// Constructor
PolyhedronMesh();
PolyhedronMesh(PolygonVertexArray* polygonVertexArray);
/// Destructor
~PolyhedronMesh() = default;
/// Add a vertex into the polyhedron
uint addVertex(const Vector3& vertex);
/// Return the number of vertices
uint getNbVertices() const;
/// Add a face into the polyhedron
void addFace(std::vector<uint> faceVertices);
/// Call this method when you are done adding vertices and faces
void finalize();
/// Return a vertex
Vector3 getVertex(uint index) const;
/// Return the half-edge structure of the mesh
const HalfEdgeStructure& getHalfEdgeStructure() const;
};
// Return the number of vertices
inline uint PolyhedronMesh::getNbVertices() const {
return mHalfEdgeStructure.getNbVertices();
}
// Return the half-edge structure of the mesh
inline const HalfEdgeStructure& PolyhedronMesh::getHalfEdgeStructure() const {
return mHalfEdgeStructure;

View File

@ -26,6 +26,7 @@
// Libraries
#include "SATAlgorithm.h"
#include "constraint/ContactPoint.h"
#include "collision/PolyhedronMesh.h"
#include "configuration.h"
#include "engine/Profiler.h"
#include <algorithm>
@ -36,8 +37,60 @@
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
bool SATAlgorithm::testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactManifoldInfo& contactManifoldInfo) {
bool SATAlgorithm::testCollision(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) {
assert(narrowPhaseInfo->collisionShape2->getType() == CollisionShapeType::CONVEX_POLYHEDRON);
switch (narrowPhaseInfo->collisionShape1->getType()) {
case CollisionShapeType::CONVEX_POLYHEDRON:
return testCollisionConvexMeshVsConvexMesh(narrowPhaseInfo, contactManifoldInfo);
case CollisionShapeType::SPHERE:
return testCollisionSphereVsConvexMesh(narrowPhaseInfo, contactManifoldInfo);
case CollisionShapeType::CAPSULE:
return testCollisionCapsuleVsConvexMesh(narrowPhaseInfo, contactManifoldInfo);
case CollisionShapeType::TRIANGLE:
return testCollisionTriangleVsConvexMesh(narrowPhaseInfo, contactManifoldInfo);
default: assert(false);
}
return false;
}
// Test collision between a sphere and a convex mesh
bool SATAlgorithm::testCollisionSphereVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const {
}
// Test collision between a capsule and a convex mesh
bool SATAlgorithm::testCollisionCapsuleVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const {
}
// Test collision between a triangle and a convex mesh
bool SATAlgorithm::testCollisionTriangleVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const {
}
// Test collision between two convex meshes
bool SATAlgorithm::testCollisionConvexMeshVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const {
}
// Return true if the arcs AB and CD on the Gauss Map (unit sphere) intersect
/// This is used to know if the edge between faces with normal A and B on first polyhedron
/// and edge between faces with normal C and D on second polygon create a face on the Minkowski
/// sum of both polygons. If this is the case, it means that the cross product of both edges
/// might be a separating axis.
bool SATAlgorithm::testGaussMapArcsIntersect(const Vector3& a, const Vector3& b,
const Vector3& c, const Vector3& d) const {
const Vector3 bCrossA = b.cross(a);
const Vector3 dCrossC = d.cross(c);
const decimal cba = c.dot(bCrossA);
const decimal dba = d.dot(bCrossA);
const decimal adc = a.dot(dCrossC);
const decimal bdc = b.dot(dCrossC);
return cba * dba < decimal(0.0) && adc * bdc < decimal(0.0) && cba * bdc > decimal(0.0);
}

View File

@ -42,6 +42,22 @@ class SATAlgorithm {
// -------------------- Methods -------------------- //
/// Return true if the arcs AB and CD on the Gauss Map intersect
bool testGaussMapArcsIntersect(const Vector3& a, const Vector3& b,
const Vector3& c, const Vector3& d) const;
/// Test collision between a sphere and a convex mesh
bool testCollisionSphereVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const;
/// Test collision between a capsule and a convex mesh
bool testCollisionCapsuleVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const;
/// Test collision between a triangle and a convex mesh
bool testCollisionTriangleVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const;
/// Test collision between two convex meshes
bool testCollisionConvexMeshVsConvexMesh(const NarrowPhaseInfo* narrowPhaseInfo, ContactManifoldInfo& contactManifoldInfo) const;
public :
// -------------------- Methods -------------------- //

View File

@ -38,7 +38,7 @@ using namespace reactphysics3d;
* @param margin The collision margin (in meters) around the collision shape
*/
BoxShape::BoxShape(const Vector3& extent, decimal margin)
: ConvexShape(CollisionShapeType::BOX, margin), mExtent(extent - Vector3(margin, margin, margin)) {
: ConvexPolyhedron(margin), mExtent(extent - Vector3(margin, margin, margin)) {
assert(extent.x > decimal(0.0) && extent.x > margin);
assert(extent.y > decimal(0.0) && extent.y > margin);
assert(extent.z > decimal(0.0) && extent.z > margin);

View File

@ -28,7 +28,7 @@
// Libraries
#include <cfloat>
#include "ConvexShape.h"
#include "ConvexPolyhedron.h"
#include "body/CollisionBody.h"
#include "mathematics/mathematics.h"
@ -50,7 +50,7 @@ namespace reactphysics3d {
* constructor of the box shape. Otherwise, it is recommended to use the
* default margin distance by not using the "margin" parameter in the constructor.
*/
class BoxShape : public ConvexShape {
class BoxShape : public ConvexPolyhedron {
protected :

View File

@ -40,7 +40,7 @@
namespace reactphysics3d {
/// Type of the collision shape
enum class CollisionShapeType {TRIANGLE, SPHERE, CAPSULE, BOX, CONVEX_MESH, CONCAVE_MESH, HEIGHTFIELD};
enum class CollisionShapeType {TRIANGLE, SPHERE, CAPSULE, CONVEX_POLYHEDRON, CONCAVE_MESH, HEIGHTFIELD};
const int NB_COLLISION_SHAPE_TYPES = 9;
// Declarations

View File

@ -30,6 +30,9 @@
using namespace reactphysics3d;
// TODO : Check in every collision shape that localScalling is used correctly and even with SAT
// algorithm (not only in getLocalSupportPoint***() methods)
// Constructor to initialize with an array of 3D vertices.
/// This method creates an internal copy of the input vertices.
/**
@ -38,108 +41,13 @@ using namespace reactphysics3d;
* @param stride Stride between the beginning of two elements in the vertices array
* @param margin Collision margin (in meters) around the collision shape
*/
ConvexMeshShape::ConvexMeshShape(const decimal* arrayVertices, uint nbVertices, int stride, decimal margin)
: ConvexShape(CollisionShapeType::CONVEX_MESH, margin), mNbVertices(nbVertices), mMinBounds(0, 0, 0),
mMaxBounds(0, 0, 0), mIsEdgesInformationUsed(false) {
assert(nbVertices > 0);
assert(stride > 0);
const unsigned char* vertexPointer = (const unsigned char*) arrayVertices;
// Copy all the vertices into the internal array
for (uint i=0; i<mNbVertices; i++) {
const decimal* newPoint = (const decimal*) vertexPointer;
mVertices.push_back(Vector3(newPoint[0], newPoint[1], newPoint[2]));
vertexPointer += stride;
}
ConvexMeshShape::ConvexMeshShape(PolyhedronMesh* polyhedronMesh, decimal margin)
: ConvexPolyhedron(margin), mPolyhedronMesh(polyhedronMesh), mMinBounds(0, 0, 0), mMaxBounds(0, 0, 0) {
// Recalculate the bounds of the mesh
recalculateBounds();
}
// Constructor to initialize with a triangle mesh
/// This method creates an internal copy of the input vertices.
/**
* @param triangleVertexArray Array with the vertices and indices of the vertices and triangles of the mesh
* @param isEdgesInformationUsed True if you want to use edges information for collision detection (faster but requires more memory)
* @param margin Collision margin (in meters) around the collision shape
*/
ConvexMeshShape::ConvexMeshShape(TriangleVertexArray* triangleVertexArray, bool isEdgesInformationUsed, decimal margin)
: ConvexShape(CollisionShapeType::CONVEX_MESH, margin), mMinBounds(0, 0, 0),
mMaxBounds(0, 0, 0), mIsEdgesInformationUsed(isEdgesInformationUsed) {
TriangleVertexArray::VertexDataType vertexType = triangleVertexArray->getVertexDataType();
TriangleVertexArray::IndexDataType indexType = triangleVertexArray->getIndexDataType();
unsigned char* verticesStart = triangleVertexArray->getVerticesStart();
unsigned char* indicesStart = triangleVertexArray->getIndicesStart();
int vertexStride = triangleVertexArray->getVerticesStride();
int indexStride = triangleVertexArray->getIndicesStride();
// For each vertex of the mesh
for (uint v = 0; v < triangleVertexArray->getNbVertices(); v++) {
// Get the vertices components of the triangle
if (vertexType == TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE) {
const float* vertices = (float*)(verticesStart + v * vertexStride);
Vector3 vertex(vertices[0], vertices[1], vertices[2] );
vertex = vertex * mScaling;
mVertices.push_back(vertex);
}
else if (vertexType == TriangleVertexArray::VertexDataType::VERTEX_DOUBLE_TYPE) {
const double* vertices = (double*)(verticesStart + v * vertexStride);
Vector3 vertex(vertices[0], vertices[1], vertices[2] );
vertex = vertex * mScaling;
mVertices.push_back(vertex);
}
}
// If we need to use the edges information of the mesh
if (mIsEdgesInformationUsed) {
// For each triangle of the mesh
for (uint triangleIndex=0; triangleIndex<triangleVertexArray->getNbTriangles(); triangleIndex++) {
void* vertexIndexPointer = (indicesStart + triangleIndex * 3 * indexStride);
uint vertexIndex[3] = {0, 0, 0};
// For each vertex of the triangle
for (int k=0; k < 3; k++) {
// Get the index of the current vertex in the triangle
if (indexType == TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE) {
vertexIndex[k] = ((uint*)vertexIndexPointer)[k];
}
else if (indexType == TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE) {
vertexIndex[k] = ((unsigned short*)vertexIndexPointer)[k];
}
else {
assert(false);
}
}
// Add information about the edges
addEdge(vertexIndex[0], vertexIndex[1]);
addEdge(vertexIndex[0], vertexIndex[2]);
addEdge(vertexIndex[1], vertexIndex[2]);
}
}
mNbVertices = mVertices.size();
recalculateBounds();
}
// Constructor.
/// If you use this constructor, you will need to set the vertices manually one by one using
/// the addVertex() method.
ConvexMeshShape::ConvexMeshShape(decimal margin)
: ConvexShape(CollisionShapeType::CONVEX_MESH, margin), mNbVertices(0), mMinBounds(0, 0, 0),
mMaxBounds(0, 0, 0), mIsEdgesInformationUsed(false) {
}
// Return a local support point in a given direction without the object margin.
/// If the edges information is not used for collision detection, this method will go through
/// the whole vertices list and pick up the vertex with the largest dot product in the support
@ -151,65 +59,16 @@ ConvexMeshShape::ConvexMeshShape(decimal margin)
Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
void** cachedCollisionData) const {
assert(mNbVertices == mVertices.size());
assert(cachedCollisionData != nullptr);
// Allocate memory for the cached collision data if not allocated yet
if ((*cachedCollisionData) == nullptr) {
*cachedCollisionData = (int*) malloc(sizeof(int));
*((int*)(*cachedCollisionData)) = 0;
}
// If the edges information is used to speed up the collision detection
if (mIsEdgesInformationUsed) {
assert(mEdgesAdjacencyList.size() == mNbVertices);
uint maxVertex = *((int*)(*cachedCollisionData));
decimal maxDotProduct = direction.dot(mVertices[maxVertex]);
bool isOptimal;
// Perform hill-climbing (local search)
do {
isOptimal = true;
assert(mEdgesAdjacencyList.at(maxVertex).size() > 0);
// For all neighbors of the current vertex
std::set<uint>::const_iterator it;
std::set<uint>::const_iterator itBegin = mEdgesAdjacencyList.at(maxVertex).begin();
std::set<uint>::const_iterator itEnd = mEdgesAdjacencyList.at(maxVertex).end();
for (it = itBegin; it != itEnd; ++it) {
// Compute the dot product
decimal dotProduct = direction.dot(mVertices[*it]);
// If the current vertex is a better vertex (larger dot product)
if (dotProduct > maxDotProduct) {
maxVertex = *it;
maxDotProduct = dotProduct;
isOptimal = false;
}
}
} while(!isOptimal);
// Cache the support vertex
*((int*)(*cachedCollisionData)) = maxVertex;
// Return the support vertex
return mVertices[maxVertex] * mScaling;
}
else { // If the edges information is not used
// TODO : Do we still need to have cachedCollisionData or we can remove it from everywhere ?
double maxDotProduct = DECIMAL_SMALLEST;
uint indexMaxDotProduct = 0;
// For each vertex of the mesh
for (uint i=0; i<mNbVertices; i++) {
for (uint i=0; i<mPolyhedronMesh->getNbVertices(); i++) {
// Compute the dot product of the current vertex
double dotProduct = direction.dot(mVertices[i]);
double dotProduct = direction.dot(mPolyhedronMesh->getVertex(i));
// If the current dot product is larger than the maximum one
if (dotProduct > maxDotProduct) {
@ -221,8 +80,7 @@ Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direct
assert(maxDotProduct >= decimal(0.0));
// Return the vertex with the largest dot product in the support direction
return mVertices[indexMaxDotProduct] * mScaling;
}
return mPolyhedronMesh->getVertex(indexMaxDotProduct) * mScaling;
}
// Recompute the bounds of the mesh
@ -235,16 +93,16 @@ void ConvexMeshShape::recalculateBounds() {
mMaxBounds.setToZero();
// For each vertex of the mesh
for (uint i=0; i<mNbVertices; i++) {
for (uint i=0; i<mPolyhedronMesh->getNbVertices(); i++) {
if (mVertices[i].x > mMaxBounds.x) mMaxBounds.x = mVertices[i].x;
if (mVertices[i].x < mMinBounds.x) mMinBounds.x = mVertices[i].x;
if (mPolyhedronMesh->getVertex(i).x > mMaxBounds.x) mMaxBounds.x = mPolyhedronMesh->getVertex(i).x;
if (mPolyhedronMesh->getVertex(i).x < mMinBounds.x) mMinBounds.x = mPolyhedronMesh->getVertex(i).x;
if (mVertices[i].y > mMaxBounds.y) mMaxBounds.y = mVertices[i].y;
if (mVertices[i].y < mMinBounds.y) mMinBounds.y = mVertices[i].y;
if (mPolyhedronMesh->getVertex(i).y > mMaxBounds.y) mMaxBounds.y = mPolyhedronMesh->getVertex(i).y;
if (mPolyhedronMesh->getVertex(i).y < mMinBounds.y) mMinBounds.y = mPolyhedronMesh->getVertex(i).y;
if (mVertices[i].z > mMaxBounds.z) mMaxBounds.z = mVertices[i].z;
if (mVertices[i].z < mMinBounds.z) mMinBounds.z = mVertices[i].z;
if (mPolyhedronMesh->getVertex(i).z > mMaxBounds.z) mMaxBounds.z = mPolyhedronMesh->getVertex(i).z;
if (mPolyhedronMesh->getVertex(i).z < mMinBounds.z) mMinBounds.z = mPolyhedronMesh->getVertex(i).z;
}
// Apply the local scaling factor

View File

@ -27,10 +27,11 @@
#define REACTPHYSICS3D_CONVEX_MESH_SHAPE_H
// Libraries
#include "ConvexShape.h"
#include "ConvexPolyhedron.h"
#include "engine/CollisionWorld.h"
#include "mathematics/mathematics.h"
#include "collision/TriangleMesh.h"
#include "collision/PolyhedronMesh.h"
#include "collision/narrowphase/GJK/GJKAlgorithm.h"
#include <vector>
#include <set>
@ -58,17 +59,14 @@ class CollisionWorld;
* with the addEdge() method. Then, you must use the setIsEdgesInformationUsed(true) method
* in order to use the edges information for collision detection.
*/
class ConvexMeshShape : public ConvexShape {
class ConvexMeshShape : public ConvexPolyhedron {
protected :
// -------------------- Attributes -------------------- //
/// Array with the vertices of the mesh
std::vector<Vector3> mVertices;
/// Number of vertices in the mesh
uint mNbVertices;
/// Polyhedron structure of the mesh
PolyhedronMesh* mPolyhedronMesh;
/// Mesh minimum bounds in the three local x, y and z directions
Vector3 mMinBounds;
@ -76,13 +74,6 @@ class ConvexMeshShape : public ConvexShape {
/// Mesh maximum bounds in the three local x, y and z directions
Vector3 mMaxBounds;
/// True if the shape contains the edges of the convex mesh in order to
/// make the collision detection faster
bool mIsEdgesInformationUsed;
/// Adjacency list representing the edges of the mesh
std::map<uint, std::set<uint> > mEdgesAdjacencyList;
// -------------------- Methods -------------------- //
/// Recompute the bounds of the mesh
@ -108,16 +99,10 @@ class ConvexMeshShape : public ConvexShape {
// -------------------- Methods -------------------- //
/// Constructor to initialize with an array of 3D vertices.
ConvexMeshShape(const decimal* arrayVertices, uint nbVertices, int stride,
decimal margin = OBJECT_MARGIN);
/// Constructor to initialize with a triangle vertex array
ConvexMeshShape(TriangleVertexArray* triangleVertexArray, bool isEdgesInformationUsed = true,
decimal margin = OBJECT_MARGIN);
/// Constructor.
ConvexMeshShape(decimal margin = OBJECT_MARGIN);
/// Constructor
// TODO : Do we really need to use the margin anymore ? Maybe for raycasting ? If not, remove all the
// comments documentation about margin
ConvexMeshShape(PolyhedronMesh* polyhedronMesh, decimal margin = OBJECT_MARGIN);
/// Destructor
virtual ~ConvexMeshShape() override = default;
@ -134,21 +119,8 @@ class ConvexMeshShape : public ConvexShape {
/// Return the local inertia tensor of the collision shape.
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override;
/// Add a vertex into the convex mesh
void addVertex(const Vector3& vertex);
/// Add an edge into the convex mesh by specifying the two vertex indices of the edge.
void addEdge(uint v1, uint v2);
/// Return true if the collision shape is a polyhedron
virtual bool isPolyhedron() const override;
/// Return true if the edges information is used to speed up the collision detection
bool isEdgesInformationUsed() const;
/// Set the variable to know if the edges information is used to speed up the
/// collision detection
void setIsEdgesInformationUsed(bool isEdgesUsed);
};
/// Set the scaling vector of the collision shape
@ -197,68 +169,6 @@ inline void ConvexMeshShape::computeLocalInertiaTensor(Matrix3x3& tensor, decima
0.0, 0.0, factor * (xSquare + ySquare));
}
// Add a vertex into the convex mesh
/**
* @param vertex Vertex to be added
*/
inline void ConvexMeshShape::addVertex(const Vector3& vertex) {
// Add the vertex in to vertices array
mVertices.push_back(vertex);
mNbVertices++;
// Update the bounds of the mesh
if (vertex.x * mScaling.x > mMaxBounds.x) mMaxBounds.x = vertex.x * mScaling.x;
if (vertex.x * mScaling.x < mMinBounds.x) mMinBounds.x = vertex.x * mScaling.x;
if (vertex.y * mScaling.y > mMaxBounds.y) mMaxBounds.y = vertex.y * mScaling.y;
if (vertex.y * mScaling.y < mMinBounds.y) mMinBounds.y = vertex.y * mScaling.y;
if (vertex.z * mScaling.z > mMaxBounds.z) mMaxBounds.z = vertex.z * mScaling.z;
if (vertex.z * mScaling.z < mMinBounds.z) mMinBounds.z = vertex.z * mScaling.z;
}
// Add an edge into the convex mesh by specifying the two vertex indices of the edge.
/// Note that the vertex indices start at zero and need to correspond to the order of
/// the vertices in the vertices array in the constructor or the order of the calls
/// of the addVertex() methods that you use to add vertices into the convex mesh.
/**
* @param v1 Index of the first vertex of the edge to add
* @param v2 Index of the second vertex of the edge to add
*/
inline void ConvexMeshShape::addEdge(uint v1, uint v2) {
// If the entry for vertex v1 does not exist in the adjacency list
if (mEdgesAdjacencyList.count(v1) == 0) {
mEdgesAdjacencyList.insert(std::make_pair(v1, std::set<uint>()));
}
// If the entry for vertex v2 does not exist in the adjacency list
if (mEdgesAdjacencyList.count(v2) == 0) {
mEdgesAdjacencyList.insert(std::make_pair(v2, std::set<uint>()));
}
// Add the edge in the adjacency list
mEdgesAdjacencyList[v1].insert(v2);
mEdgesAdjacencyList[v2].insert(v1);
}
// Return true if the edges information is used to speed up the collision detection
/**
* @return True if the edges information is used and false otherwise
*/
inline bool ConvexMeshShape::isEdgesInformationUsed() const {
return mIsEdgesInformationUsed;
}
// Set the variable to know if the edges information is used to speed up the
// collision detection
/**
* @param isEdgesUsed True if you want to use the edges information to speed up
* the collision detection with the convex mesh shape
*/
inline void ConvexMeshShape::setIsEdgesInformationUsed(bool isEdgesUsed) {
mIsEdgesInformationUsed = isEdgesUsed;
}
// Return true if a point is inside the collision shape
inline bool ConvexMeshShape::testPointInside(const Vector3& localPoint,
ProxyShape* proxyShape) const {

View File

@ -0,0 +1,37 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "ConvexPolyhedron.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Constructor
ConvexPolyhedron::ConvexPolyhedron(decimal margin)
: ConvexShape(CollisionShapeType::CONVEX_POLYHEDRON, margin) {
}

View File

@ -0,0 +1,68 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_CONVEX_POLYHEDRON_H
#define REACTPHYSICS3D_CONVEX_POLYHEDRON_H
// Libraries
#include "ConvexShape.h"
/// ReactPhysics3D namespace
namespace reactphysics3d {
// Class ConvexPolyhedron
/**
* This abstract class represents a convex polyhedron collision shape associated with a
* body that is used during the narrow-phase collision detection.
*/
class ConvexPolyhedron : public ConvexShape {
protected :
// -------------------- Attributes -------------------- //
// -------------------- Methods -------------------- //
public :
// -------------------- Methods -------------------- //
/// Constructor
ConvexPolyhedron(decimal margin);
/// Destructor
virtual ~ConvexPolyhedron() override = default;
/// Deleted copy-constructor
ConvexPolyhedron(const ConvexPolyhedron& shape) = delete;
/// Deleted assignment operator
ConvexPolyhedron& operator=(const ConvexPolyhedron& shape) = delete;
};
}
#endif

View File

@ -55,7 +55,9 @@
#include "collision/ProxyShape.h"
#include "collision/RaycastInfo.h"
#include "collision/TriangleMesh.h"
#include "collision/PolyhedronMesh.h"
#include "collision/TriangleVertexArray.h"
#include "collision/PolygonVertexArray.h"
#include "constraint/BallAndSocketJoint.h"
#include "constraint/SliderJoint.h"
#include "constraint/HingeJoint.h"

View File

@ -43,19 +43,28 @@ class TestHalfEdgeStructure : public Test {
void testCube() {
// Create the half-edge structure for a cube
std::vector<rp3d::Vector3> vertices;
std::vector<std::vector<uint>> faces;
rp3d::HalfEdgeStructure cubeStructure;
rp3d::Vector3 vertices[8] = {
rp3d::Vector3(-0.5, -0.5, 0.5),
rp3d::Vector3(0.5, -0.5, 0.5),
rp3d::Vector3(0.5, 0.5, 0.5),
rp3d::Vector3(-0.5, 0.5, 0.5),
rp3d::Vector3(-0.5, -0.5, -0.5),
rp3d::Vector3(0.5, -0.5, -0.5),
rp3d::Vector3(0.5, 0.5, -0.5),
rp3d::Vector3(-0.5, 0.5, -0.5)
};
// Vertices
vertices.push_back(rp3d::Vector3(-0.5, -0.5, 0.5));
vertices.push_back(rp3d::Vector3(0.5, -0.5, 0.5));
vertices.push_back(rp3d::Vector3(0.5, 0.5, 0.5));
vertices.push_back(rp3d::Vector3(-0.5, 0.5, 0.5));
vertices.push_back(rp3d::Vector3(-0.5, -0.5, -0.5));
vertices.push_back(rp3d::Vector3(0.5, -0.5, -0.5));
vertices.push_back(rp3d::Vector3(0.5, 0.5, -0.5));
vertices.push_back(rp3d::Vector3(-0.5, 0.5, -0.5));
cubeStructure.addVertex(0);
cubeStructure.addVertex(1);
cubeStructure.addVertex(2);
cubeStructure.addVertex(3);
cubeStructure.addVertex(4);
cubeStructure.addVertex(5);
cubeStructure.addVertex(6);
cubeStructure.addVertex(7);
// Faces
std::vector<uint> face0;
@ -71,14 +80,14 @@ class TestHalfEdgeStructure : public Test {
std::vector<uint> face5;
face5.push_back(2); face5.push_back(6); face5.push_back(7); face5.push_back(3);
faces.push_back(face0);
faces.push_back(face1);
faces.push_back(face2);
faces.push_back(face3);
faces.push_back(face4);
faces.push_back(face5);
cubeStructure.addFace(face0);
cubeStructure.addFace(face1);
cubeStructure.addFace(face2);
cubeStructure.addFace(face3);
cubeStructure.addFace(face4);
cubeStructure.addFace(face5);
cubeStructure.init(vertices, faces);
cubeStructure.init();
// --- Test that the half-edge structure of the cube is valid --- //
@ -87,44 +96,44 @@ class TestHalfEdgeStructure : public Test {
test(cubeStructure.getNbHalfEdges() == 24);
// Test vertices
test(cubeStructure.getVertex(0).point.x == -0.5);
test(cubeStructure.getVertex(0).point.y == -0.5);
test(cubeStructure.getVertex(0).point.z == 0.5);
test(vertices[cubeStructure.getVertex(0).vertexPointIndex].x == -0.5);
test(vertices[cubeStructure.getVertex(0).vertexPointIndex].y == -0.5);
test(vertices[cubeStructure.getVertex(0).vertexPointIndex].z == 0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(0).edgeIndex).vertexIndex == 0);
test(cubeStructure.getVertex(1).point.x == 0.5);
test(cubeStructure.getVertex(1).point.y == -0.5);
test(cubeStructure.getVertex(1).point.z == 0.5);
test(vertices[cubeStructure.getVertex(1).vertexPointIndex].x == 0.5);
test(vertices[cubeStructure.getVertex(1).vertexPointIndex].y == -0.5);
test(vertices[cubeStructure.getVertex(1).vertexPointIndex].z == 0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(1).edgeIndex).vertexIndex == 1);
test(cubeStructure.getVertex(2).point.x == 0.5);
test(cubeStructure.getVertex(2).point.y == 0.5);
test(cubeStructure.getVertex(2).point.z == 0.5);
test(vertices[cubeStructure.getVertex(2).vertexPointIndex].x == 0.5);
test(vertices[cubeStructure.getVertex(2).vertexPointIndex].y == 0.5);
test(vertices[cubeStructure.getVertex(2).vertexPointIndex].z == 0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(2).edgeIndex).vertexIndex == 2);
test(cubeStructure.getVertex(3).point.x == -0.5);
test(cubeStructure.getVertex(3).point.y == 0.5);
test(cubeStructure.getVertex(3).point.z == 0.5);
test(vertices[cubeStructure.getVertex(3).vertexPointIndex].x == -0.5);
test(vertices[cubeStructure.getVertex(3).vertexPointIndex].y == 0.5);
test(vertices[cubeStructure.getVertex(3).vertexPointIndex].z == 0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(3).edgeIndex).vertexIndex == 3);
test(cubeStructure.getVertex(4).point.x == -0.5);
test(cubeStructure.getVertex(4).point.y == -0.5);
test(cubeStructure.getVertex(4).point.z == -0.5);
test(vertices[cubeStructure.getVertex(4).vertexPointIndex].x == -0.5);
test(vertices[cubeStructure.getVertex(4).vertexPointIndex].y == -0.5);
test(vertices[cubeStructure.getVertex(4).vertexPointIndex].z == -0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(4).edgeIndex).vertexIndex == 4);
test(cubeStructure.getVertex(5).point.x == 0.5);
test(cubeStructure.getVertex(5).point.y == -0.5);
test(cubeStructure.getVertex(5).point.z == -0.5);
test(vertices[cubeStructure.getVertex(5).vertexPointIndex].x == 0.5);
test(vertices[cubeStructure.getVertex(5).vertexPointIndex].y == -0.5);
test(vertices[cubeStructure.getVertex(5).vertexPointIndex].z == -0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(5).edgeIndex).vertexIndex == 5);
test(cubeStructure.getVertex(6).point.x == 0.5);
test(cubeStructure.getVertex(6).point.y == 0.5);
test(cubeStructure.getVertex(6).point.z == -0.5);
test(vertices[cubeStructure.getVertex(6).vertexPointIndex].x == 0.5);
test(vertices[cubeStructure.getVertex(6).vertexPointIndex].y == 0.5);
test(vertices[cubeStructure.getVertex(6).vertexPointIndex].z == -0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(6).edgeIndex).vertexIndex == 6);
test(cubeStructure.getVertex(7).point.x == -0.5);
test(cubeStructure.getVertex(7).point.y == 0.5);
test(cubeStructure.getVertex(7).point.z == -0.5);
test(vertices[cubeStructure.getVertex(7).vertexPointIndex].x == -0.5);
test(vertices[cubeStructure.getVertex(7).vertexPointIndex].y == 0.5);
test(vertices[cubeStructure.getVertex(7).vertexPointIndex].z == -0.5);
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(7).edgeIndex).vertexIndex == 7);
// Test faces
@ -158,15 +167,21 @@ class TestHalfEdgeStructure : public Test {
void testTetrahedron() {
// Create the half-edge structure for a tetrahedron
std::vector<rp3d::Vector3> vertices;
std::vector<std::vector<uint>> faces;
rp3d::HalfEdgeStructure tetrahedron;
// Vertices
vertices.push_back(rp3d::Vector3(1, -1, -1));
vertices.push_back(rp3d::Vector3(-1, -1, -1));
vertices.push_back(rp3d::Vector3(0, -1, 1));
vertices.push_back(rp3d::Vector3(0, 1, 0));
rp3d::Vector3 vertices[4] = {
rp3d::Vector3(1, -1, -1),
rp3d::Vector3(-1, -1, -1),
rp3d::Vector3(0, -1, 1),
rp3d::Vector3(0, 1, 0)
};
tetrahedron.addVertex(0);
tetrahedron.addVertex(1);
tetrahedron.addVertex(2);
tetrahedron.addVertex(3);
// Faces
std::vector<uint> face0;
@ -178,12 +193,12 @@ class TestHalfEdgeStructure : public Test {
std::vector<uint> face3;
face3.push_back(0); face3.push_back(2); face3.push_back(3);
faces.push_back(face0);
faces.push_back(face1);
faces.push_back(face2);
faces.push_back(face3);
tetrahedron.addFace(face0);
tetrahedron.addFace(face1);
tetrahedron.addFace(face2);
tetrahedron.addFace(face3);
tetrahedron.init(vertices, faces);
tetrahedron.init();
// --- Test that the half-edge structure of the tetrahedron is valid --- //
@ -192,24 +207,24 @@ class TestHalfEdgeStructure : public Test {
test(tetrahedron.getNbHalfEdges() == 12);
// Test vertices
test(tetrahedron.getVertex(0).point.x == 1);
test(tetrahedron.getVertex(0).point.y == -1);
test(tetrahedron.getVertex(0).point.z == -1);
test(vertices[tetrahedron.getVertex(0).vertexPointIndex].x == 1);
test(vertices[tetrahedron.getVertex(0).vertexPointIndex].y == -1);
test(vertices[tetrahedron.getVertex(0).vertexPointIndex].z == -1);
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(0).edgeIndex).vertexIndex == 0);
test(tetrahedron.getVertex(1).point.x == -1);
test(tetrahedron.getVertex(1).point.y == -1);
test(tetrahedron.getVertex(1).point.z == -1);
test(vertices[tetrahedron.getVertex(1).vertexPointIndex].x == -1);
test(vertices[tetrahedron.getVertex(1).vertexPointIndex].y == -1);
test(vertices[tetrahedron.getVertex(1).vertexPointIndex].z == -1);
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(1).edgeIndex).vertexIndex == 1);
test(tetrahedron.getVertex(2).point.x == 0);
test(tetrahedron.getVertex(2).point.y == -1);
test(tetrahedron.getVertex(2).point.z == 1);
test(vertices[tetrahedron.getVertex(2).vertexPointIndex].x == 0);
test(vertices[tetrahedron.getVertex(2).vertexPointIndex].y == -1);
test(vertices[tetrahedron.getVertex(2).vertexPointIndex].z == 1);
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(2).edgeIndex).vertexIndex == 2);
test(tetrahedron.getVertex(3).point.x == 0);
test(tetrahedron.getVertex(3).point.y == 1);
test(tetrahedron.getVertex(3).point.z == 0);
test(vertices[tetrahedron.getVertex(3).vertexPointIndex].x == 0);
test(vertices[tetrahedron.getVertex(3).vertexPointIndex].y == 1);
test(vertices[tetrahedron.getVertex(3).vertexPointIndex].z == 0);
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(3).edgeIndex).vertexIndex == 3);
// Test faces

View File

@ -124,7 +124,8 @@ class TestPointInside : public Test {
mCapsuleShape = new CapsuleShape(2, 10);
mCapsuleProxyShape = mCapsuleBody->addCollisionShape(mCapsuleShape, mShapeTransform);
mConvexMeshShape = new ConvexMeshShape(0.0); // Box of dimension (2, 3, 4)
// TODO : Create convex mesh shape with new way (polyhedron mesh) to add test again
/*mConvexMeshShape = new ConvexMeshShape(0.0); // Box of dimension (2, 3, 4)
mConvexMeshShape->addVertex(Vector3(-2, -3, -4));
mConvexMeshShape->addVertex(Vector3(2, -3, -4));
mConvexMeshShape->addVertex(Vector3(2, -3, 4));
@ -160,6 +161,7 @@ class TestPointInside : public Test {
mConvexMeshProxyShapeEdgesInfo = mConvexMeshBodyEdgesInfo->addCollisionShape(
mConvexMeshShapeBodyEdgesInfo,
mShapeTransform);
*/
// Compound shape is a capsule and a sphere
Vector3 positionShape2(Vector3(4, 2, -3));
@ -175,8 +177,8 @@ class TestPointInside : public Test {
delete mBoxShape;
delete mSphereShape;
delete mCapsuleShape;
delete mConvexMeshShape;
delete mConvexMeshShapeBodyEdgesInfo;
//delete mConvexMeshShape;
//delete mConvexMeshShapeBodyEdgesInfo;
}
/// Run the tests
@ -399,6 +401,7 @@ class TestPointInside : public Test {
// ----- Tests without using edges information ----- //
/*
// Tests with CollisionBody
test(mConvexMeshBody->testPointInside(mLocalShapeToWorld * Vector3(0, 0, 0)));
test(mConvexMeshBody->testPointInside(mLocalShapeToWorld * Vector3(-1.9, 0, 0)));
@ -504,6 +507,7 @@ class TestPointInside : public Test {
test(!mConvexMeshProxyShapeEdgesInfo->testPointInside(mLocalShapeToWorld * Vector3(-10, -2, -1.5)));
test(!mConvexMeshProxyShapeEdgesInfo->testPointInside(mLocalShapeToWorld * Vector3(-1, 4, -2.5)));
test(!mConvexMeshProxyShapeEdgesInfo->testPointInside(mLocalShapeToWorld * Vector3(1, -2, 4.5)));
*/
}
/// Test the CollisionBody::testPointInside() method

View File

@ -206,8 +206,9 @@ class TestRaycast : public Test {
mCapsuleShape = new CapsuleShape(2, 5);
mCapsuleProxyShape = mCapsuleBody->addCollisionShape(mCapsuleShape, mShapeTransform);
// TODO : Create convex mesh shape with new way (polyhedron mesh) to add test again
// Box of dimension (2, 3, 4)
mConvexMeshShape = new ConvexMeshShape(0.0);
/*mConvexMeshShape = new ConvexMeshShape(0.0);
mConvexMeshShape->addVertex(Vector3(-2, -3, -4));
mConvexMeshShape->addVertex(Vector3(2, -3, -4));
mConvexMeshShape->addVertex(Vector3(2, -3, 4));
@ -243,6 +244,7 @@ class TestRaycast : public Test {
mConvexMeshProxyShapeEdgesInfo = mConvexMeshBodyEdgesInfo->addCollisionShape(
mConvexMeshShapeEdgesInfo,
mShapeTransform);
*/
// Compound shape is a cylinder and a sphere
Vector3 positionShape2(Vector3(4, 2, -3));
@ -312,8 +314,8 @@ class TestRaycast : public Test {
delete mBoxShape;
delete mSphereShape;
delete mCapsuleShape;
delete mConvexMeshShape;
delete mConvexMeshShapeEdgesInfo;
//delete mConvexMeshShape;
//delete mConvexMeshShapeEdgesInfo;
delete mTriangleShape;
delete mConcaveMeshShape;
delete mHeightFieldShape;
@ -1297,6 +1299,7 @@ class TestRaycast : public Test {
/// CollisionWorld::raycast() methods.
void testConvexMesh() {
/*
// ----- Test feedback data ----- //
Vector3 point1 = mLocalShapeToWorld * Vector3(1 , 2, 6);
Vector3 point2 = mLocalShapeToWorld * Vector3(1, 2, -4);
@ -1555,6 +1558,7 @@ class TestRaycast : public Test {
mCallback.reset();
mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), &mCallback);
test(mCallback.isHit);
*/
}
/// Test the CollisionBody::raycast() and

View File

@ -40,17 +40,36 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4::identity();
// Vertex and Indices array for the triangle mesh (data in shared and not copied)
mPhysicsTriangleVertexArray =
/*mPolygonVertexArray =
new rp3d::TriangleVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3),
getNbFaces(0), &(mIndices[0][0]), sizeof(int),
rp3d::TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);*/
// Polygon faces descriptions for the polyhedron
mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)];
rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces;
for (int f=0; f < getNbFaces(0); f++) {
face->indexBase = f * 3;
face->nbVertices = 3;
face++;
}
// Create the polygon vertex array
mPolygonVertexArray =
new rp3d::PolygonVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3),
&(mIndices[0][0]), sizeof(int),
getNbFaces(0), mPolygonFaces,
rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
// Create the polyhedron mesh
mPolyhedronMesh = new rp3d::PolyhedronMesh(mPolygonVertexArray);
// Create the collision shape for the rigid body (convex mesh shape) and
// do not forget to delete it at the end
mConvexShape = new rp3d::ConvexMeshShape(mPhysicsTriangleVertexArray);
mConvexShape = new rp3d::ConvexMeshShape(mPolyhedronMesh);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
@ -85,16 +104,29 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4::identity();
// Vertex and Indices array for the triangle mesh (data in shared and not copied)
mPhysicsTriangleVertexArray =
new rp3d::TriangleVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3),
getNbFaces(0), &(mIndices[0][0]), sizeof(int),
rp3d::TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
// Polygon faces descriptions for the polyhedron
mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)];
rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces;
for (int f=0; f < getNbFaces(0); f++) {
face->indexBase = f * 3;
face->nbVertices = 3;
face++;
}
// Create the polygon vertex array
mPolygonVertexArray =
new rp3d::PolygonVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3),
&(mIndices[0][0]), sizeof(int),
getNbFaces(0), mPolygonFaces,
rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
// Create the polyhedron mesh
mPolyhedronMesh = new rp3d::PolyhedronMesh(mPolygonVertexArray);
// Create the collision shape for the rigid body (convex mesh shape) and do
// not forget to delete it at the end
mConvexShape = new rp3d::ConvexMeshShape(mPhysicsTriangleVertexArray);
mConvexShape = new rp3d::ConvexMeshShape(mPolyhedronMesh);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
@ -128,7 +160,9 @@ ConvexMesh::~ConvexMesh() {
mVBOTextureCoords.destroy();
mVAO.destroy();
delete mPhysicsTriangleVertexArray;
delete mPolyhedronMesh;
delete mPolygonVertexArray;
delete[] mPolygonFaces;
delete mConvexShape;
}

View File

@ -41,7 +41,11 @@ class ConvexMesh : public PhysicsObject {
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
rp3d::TriangleVertexArray* mPhysicsTriangleVertexArray;
rp3d::PolygonVertexArray::PolygonFace* mPolygonFaces;
rp3d::PolygonVertexArray* mPolygonVertexArray;
rp3d::PolyhedronMesh* mPolyhedronMesh;
/// Collision shape
rp3d::ConvexMeshShape* mConvexShape;