Make possible to create a ConvexMeshShape using a TriangleVertexArray

This commit is contained in:
Daniel Chappuis 2016-01-07 23:04:39 +01:00
parent 8be408ccec
commit a12703b86d
10 changed files with 120 additions and 72 deletions

View File

@ -100,10 +100,6 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
} }
}; };
// TODO : Implement raycasting with this collision shape
// TODO : Make possible for the user to have a scaling factor on the mesh
// Class ConcaveMeshShape // Class ConcaveMeshShape
/** /**
* This class represents a concave mesh shape. Note that collision detection * This class represents a concave mesh shape. Note that collision detection

View File

@ -30,7 +30,7 @@
using namespace reactphysics3d; using namespace reactphysics3d;
// Constructor to initialize with a array of 3D vertices. // Constructor to initialize with an array of 3D vertices.
/// This method creates an internal copy of the input vertices. /// This method creates an internal copy of the input vertices.
/** /**
* @param arrayVertices Array with the vertices of the convex mesh * @param arrayVertices Array with the vertices of the convex mesh
@ -58,6 +58,77 @@ ConvexMeshShape::ConvexMeshShape(const decimal* arrayVertices, uint nbVertices,
recalculateBounds(); 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(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 (int v = 0; v < triangleVertexArray->getNbVertices(); v++) {
// Get the vertices components of the triangle
if (vertexType == TriangleVertexArray::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::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 (int triangleIndex=0; triangleIndex<triangleVertexArray->getNbTriangles(); triangleIndex++) {
void* vertexIndexPointer = (indicesStart + triangleIndex * 3 * indexStride);
uint vertexIndex[3];
// 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::INDEX_INTEGER_TYPE) {
vertexIndex[k] = ((uint*)vertexIndexPointer)[k];
}
else if (indexType == TriangleVertexArray::INDEX_SHORT_TYPE) {
vertexIndex[k] = ((unsigned short*)vertexIndexPointer)[k];
}
}
// 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. // Constructor.
/// If you use this constructor, you will need to set the vertices manually one by one using /// If you use this constructor, you will need to set the vertices manually one by one using
/// the addVertex() method. /// the addVertex() method.

View File

@ -30,6 +30,7 @@
#include "ConvexShape.h" #include "ConvexShape.h"
#include "engine/CollisionWorld.h" #include "engine/CollisionWorld.h"
#include "mathematics/mathematics.h" #include "mathematics/mathematics.h"
#include "collision/TriangleMesh.h"
#include "collision/narrowphase/GJK/GJKAlgorithm.h" #include "collision/narrowphase/GJK/GJKAlgorithm.h"
#include <vector> #include <vector>
#include <set> #include <set>
@ -64,8 +65,6 @@ class CollisionWorld;
*/ */
class ConvexMeshShape : public ConvexShape { class ConvexMeshShape : public ConvexShape {
// TODO : Implement method setLocalScaling() here
protected : protected :
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
@ -121,10 +120,14 @@ class ConvexMeshShape : public ConvexShape {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Constructor to initialize with a array of 3D vertices. /// Constructor to initialize with an array of 3D vertices.
ConvexMeshShape(const decimal* arrayVertices, uint nbVertices, int stride, ConvexMeshShape(const decimal* arrayVertices, uint nbVertices, int stride,
decimal margin = OBJECT_MARGIN); decimal margin = OBJECT_MARGIN);
/// Constructor to initialize with a triangle vertex array
ConvexMeshShape(TriangleVertexArray* triangleVertexArray, bool isEdgesInformationUsed = true,
decimal margin = OBJECT_MARGIN);
/// Constructor. /// Constructor.
ConvexMeshShape(decimal margin = OBJECT_MARGIN); ConvexMeshShape(decimal margin = OBJECT_MARGIN);
@ -215,9 +218,6 @@ inline void ConvexMeshShape::addVertex(const Vector3& vertex) {
*/ */
inline void ConvexMeshShape::addEdge(uint v1, uint v2) { inline void ConvexMeshShape::addEdge(uint v1, uint v2) {
assert(v1 >= 0);
assert(v2 >= 0);
// If the entry for vertex v1 does not exist in the adjacency list // If the entry for vertex v1 does not exist in the adjacency list
if (mEdgesAdjacencyList.count(v1) == 0) { if (mEdgesAdjacencyList.count(v1) == 0) {
mEdgesAdjacencyList.insert(std::make_pair(v1, std::set<uint>())); mEdgesAdjacencyList.insert(std::make_pair(v1, std::set<uint>()));

View File

@ -132,6 +132,9 @@ struct Vector2 {
/// Overloaded operator /// Overloaded operator
Vector2& operator=(const Vector2& vector); Vector2& operator=(const Vector2& vector);
/// Overloaded less than operator for ordering to be used inside std::set for instance
bool operator<(const Vector2& vector) const;
/// Return a vector taking the minimum components of two vectors /// Return a vector taking the minimum components of two vectors
static Vector2 min(const Vector2& vector1, const Vector2& vector2); static Vector2 min(const Vector2& vector1, const Vector2& vector2);
@ -313,6 +316,11 @@ inline Vector2& Vector2::operator=(const Vector2& vector) {
return *this; return *this;
} }
// Overloaded less than operator for ordering to be used inside std::set for instance
inline bool Vector2::operator<(const Vector2& vector) const {
return (x == vector.x ? y < vector.y : x < vector.x);
}
// Return a vector taking the minimum components of two vectors // Return a vector taking the minimum components of two vectors
inline Vector2 Vector2::min(const Vector2& vector1, const Vector2& vector2) { inline Vector2 Vector2::min(const Vector2& vector1, const Vector2& vector2) {
return Vector2(std::min(vector1.x, vector2.x), return Vector2(std::min(vector1.x, vector2.x),

View File

@ -144,6 +144,9 @@ struct Vector3 {
/// Overloaded operator /// Overloaded operator
Vector3& operator=(const Vector3& vector); Vector3& operator=(const Vector3& vector);
/// Overloaded less than operator for ordering to be used inside std::set for instance
bool operator<(const Vector3& vector) const;
/// Return a vector taking the minimum components of two vectors /// Return a vector taking the minimum components of two vectors
static Vector3 min(const Vector3& vector1, const Vector3& vector2); static Vector3 min(const Vector3& vector1, const Vector3& vector2);
@ -341,6 +344,11 @@ inline Vector3& Vector3::operator=(const Vector3& vector) {
return *this; return *this;
} }
// Overloaded less than operator for ordering to be used inside std::set for instance
inline bool Vector3::operator<(const Vector3& vector) const {
return (x == vector.x ? (y == vector.y ? z < vector.z : y < vector.y) : x < vector.x);
}
// Return a vector taking the minimum components of two vectors // Return a vector taking the minimum components of two vectors
inline Vector3 Vector3::min(const Vector3& vector1, const Vector3& vector2) { inline Vector3 Vector3::min(const Vector3& vector1, const Vector3& vector2) {
return Vector3(std::min(vector1.x, vector2.x), return Vector3(std::min(vector1.x, vector2.x),

View File

@ -131,7 +131,7 @@ class TestPointInside : public Test {
mConeShape = new ConeShape(2, 6, 0); mConeShape = new ConeShape(2, 6, 0);
mConeProxyShape = mConeBody->addCollisionShape(mConeShape, mShapeTransform); mConeProxyShape = mConeBody->addCollisionShape(mConeShape, mShapeTransform);
mConvexMeshShape = new ConvexMeshShape(0); // Box of dimension (2, 3, 4) 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)); mConvexMeshShape->addVertex(Vector3(2, -3, -4));
mConvexMeshShape->addVertex(Vector3(2, -3, 4)); mConvexMeshShape->addVertex(Vector3(2, -3, 4));
@ -142,7 +142,7 @@ class TestPointInside : public Test {
mConvexMeshShape->addVertex(Vector3(-2, 3, 4)); mConvexMeshShape->addVertex(Vector3(-2, 3, 4));
mConvexMeshProxyShape = mConvexMeshBody->addCollisionShape(mConvexMeshShape, mShapeTransform); mConvexMeshProxyShape = mConvexMeshBody->addCollisionShape(mConvexMeshShape, mShapeTransform);
mConvexMeshShapeBodyEdgesInfo = new ConvexMeshShape(0); mConvexMeshShapeBodyEdgesInfo = new ConvexMeshShape(0.0);
mConvexMeshShapeBodyEdgesInfo->addVertex(Vector3(-2, -3, -4)); mConvexMeshShapeBodyEdgesInfo->addVertex(Vector3(-2, -3, -4));
mConvexMeshShapeBodyEdgesInfo->addVertex(Vector3(2, -3, -4)); mConvexMeshShapeBodyEdgesInfo->addVertex(Vector3(2, -3, -4));
mConvexMeshShapeBodyEdgesInfo->addVertex(Vector3(2, -3, 4)); mConvexMeshShapeBodyEdgesInfo->addVertex(Vector3(2, -3, 4));

View File

@ -207,7 +207,7 @@ class TestRaycast : public Test {
mConeShape = new ConeShape(2, 6, 0); mConeShape = new ConeShape(2, 6, 0);
mConeProxyShape = mConeBody->addCollisionShape(mConeShape, mShapeTransform); mConeProxyShape = mConeBody->addCollisionShape(mConeShape, mShapeTransform);
mConvexMeshShape = new ConvexMeshShape(0); // Box of dimension (2, 3, 4) 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)); mConvexMeshShape->addVertex(Vector3(2, -3, -4));
mConvexMeshShape->addVertex(Vector3(2, -3, 4)); mConvexMeshShape->addVertex(Vector3(2, -3, 4));
@ -218,7 +218,7 @@ class TestRaycast : public Test {
mConvexMeshShape->addVertex(Vector3(-2, 3, 4)); mConvexMeshShape->addVertex(Vector3(-2, 3, 4));
mConvexMeshProxyShape = mConvexMeshBody->addCollisionShape(mConvexMeshShape, mShapeTransform); mConvexMeshProxyShape = mConvexMeshBody->addCollisionShape(mConvexMeshShape, mShapeTransform);
mConvexMeshShapeEdgesInfo = new ConvexMeshShape(0); mConvexMeshShapeEdgesInfo = new ConvexMeshShape(0.0);
mConvexMeshShapeEdgesInfo->addVertex(Vector3(-2, -3, -4)); mConvexMeshShapeEdgesInfo->addVertex(Vector3(-2, -3, -4));
mConvexMeshShapeEdgesInfo->addVertex(Vector3(2, -3, -4)); mConvexMeshShapeEdgesInfo->addVertex(Vector3(2, -3, -4));
mConvexMeshShapeEdgesInfo->addVertex(Vector3(2, -3, 4)); mConvexMeshShapeEdgesInfo->addVertex(Vector3(2, -3, 4));

View File

@ -22,9 +22,6 @@ FILE(COPY "meshes/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/meshes/")
# Copy the fonts used for the GUI into the build directory # Copy the fonts used for the GUI into the build directory
FILE(COPY "imgui/DroidSans.ttf" DESTINATION "${EXECUTABLE_OUTPUT_PATH}") FILE(COPY "imgui/DroidSans.ttf" DESTINATION "${EXECUTABLE_OUTPUT_PATH}")
# Enable C++11 features
SET(CMAKE_CXX_FLAGS "-Wall -std=c++0x")
# Headers # Headers
INCLUDE_DIRECTORIES("src/" ${GLEW_INCLUDE_PATH} "opengl-framework/src/" "glfw/include/" "common/" "scenes/" "imgui/") INCLUDE_DIRECTORIES("src/" ${GLEW_INCLUDE_PATH} "opengl-framework/src/" "glfw/include/" "common/" "scenes/" "imgui/")
@ -95,5 +92,9 @@ SET(SCENES_SOURCES
# Create the executable # Create the executable
ADD_EXECUTABLE(testbed ${TESTBED_SOURCES} ${SCENES_SOURCES} ${COMMON_SOURCES} ${IMGUI_SOURCES}) ADD_EXECUTABLE(testbed ${TESTBED_SOURCES} ${SCENES_SOURCES} ${COMMON_SOURCES} ${IMGUI_SOURCES})
# Enable C++11 features
set_property(TARGET testbed PROPERTY CXX_STANDARD 11)
set_property(TARGET testbed PROPERTY CXX_STANDARD_REQUIRED ON)
# Link with libraries # Link with libraries
TARGET_LINK_LIBRARIES(testbed reactphysics3d openglframework glfw ${GLFW_LIBRARIES}) TARGET_LINK_LIBRARIES(testbed reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -46,36 +46,17 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
// Compute the scaling matrix // Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4::identity(); mScalingMatrix = openglframework::Matrix4::identity();
// Convert the vertices array to the rp3d::decimal type
rp3d::decimal* vertices = new rp3d::decimal[3 * mVertices.size()]; // Vertex and Indices array for the triangle mesh (data in shared and not copied)
for (int i=0; i < mVertices.size(); i++) { mPhysicsTriangleVertexArray =
vertices[3 * i] = static_cast<rp3d::decimal>(mVertices[i].x); new rp3d::TriangleVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3),
vertices[3 * i + 1] = static_cast<rp3d::decimal>(mVertices[i].y); getNbFaces(0), &(mIndices[0][0]), sizeof(int),
vertices[3 * i + 2] = static_cast<rp3d::decimal>(mVertices[i].z); rp3d::TriangleVertexArray::VERTEX_FLOAT_TYPE,
} rp3d::TriangleVertexArray::INDEX_INTEGER_TYPE);
// Create the collision shape for the rigid body (convex mesh shape) and // Create the collision shape for the rigid body (convex mesh shape) and
// do not forget to delete it at the end // do not forget to delete it at the end
mConvexShape = new rp3d::ConvexMeshShape(vertices, mVertices.size(), 3 * sizeof(rp3d::decimal)); mConvexShape = new rp3d::ConvexMeshShape(mPhysicsTriangleVertexArray);
delete[] vertices;
// Add the edges information of the mesh into the convex mesh collision shape.
// This is optional but it really speed up the convex mesh collision detection at the
// cost of some additional memory to store the edges inside the collision shape.
for (unsigned int i=0; i<getNbFaces(); i++) { // For each triangle face of the mesh
// Get the three vertex IDs of the vertices of the face
unsigned int v1 = getVertexIndexInFace(i, 0);
unsigned int v2 = getVertexIndexInFace(i, 1);
unsigned int v3 = getVertexIndexInFace(i, 2);
// Add the three edges into the collision shape
mConvexShape->addEdge(v1, v2);
mConvexShape->addEdge(v1, v3);
mConvexShape->addEdge(v2, v3);
}
mConvexShape->setIsEdgesInformationUsed(true);// Enable the fast collision detection with edges
// Initial position and orientation of the rigid body // Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z); rp3d::Vector3 initPosition(position.x, position.y, position.z);
@ -116,36 +97,16 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
// Compute the scaling matrix // Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4::identity(); mScalingMatrix = openglframework::Matrix4::identity();
// Convert the vertices array to the rp3d::decimal type // Vertex and Indices array for the triangle mesh (data in shared and not copied)
rp3d::decimal* vertices = new rp3d::decimal[3 * mVertices.size()]; mPhysicsTriangleVertexArray =
for (int i=0; i < mVertices.size(); i++) { new rp3d::TriangleVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3),
vertices[3 * i] = static_cast<rp3d::decimal>(mVertices[i].x); getNbFaces(0), &(mIndices[0][0]), sizeof(int),
vertices[3 * i + 1] = static_cast<rp3d::decimal>(mVertices[i].y); rp3d::TriangleVertexArray::VERTEX_FLOAT_TYPE,
vertices[3 * i + 2] = static_cast<rp3d::decimal>(mVertices[i].z); rp3d::TriangleVertexArray::INDEX_INTEGER_TYPE);
}
// Create the collision shape for the rigid body (convex mesh shape) and do // Create the collision shape for the rigid body (convex mesh shape) and do
// not forget to delete it at the end // not forget to delete it at the end
mConvexShape = new rp3d::ConvexMeshShape(vertices, mVertices.size(), 3 * sizeof(rp3d::decimal)); mConvexShape = new rp3d::ConvexMeshShape(mPhysicsTriangleVertexArray);
delete[] vertices;
// Add the edges information of the mesh into the convex mesh collision shape.
// This is optional but it really speed up the convex mesh collision detection at the
// cost of some additional memory to store the edges inside the collision shape.
for (unsigned int i=0; i<getNbFaces(); i++) { // For each triangle face of the mesh
// Get the three vertex IDs of the vertices of the face
unsigned int v1 = getVertexIndexInFace(i, 0);
unsigned int v2 = getVertexIndexInFace(i, 1);
unsigned int v3 = getVertexIndexInFace(i, 2);
// Add the three edges into the collision shape
mConvexShape->addEdge(v1, v2);
mConvexShape->addEdge(v1, v3);
mConvexShape->addEdge(v2, v3);
}
mConvexShape->setIsEdgesInformationUsed(true);// Enable the fast collision detection with edges
// Initial position and orientation of the rigid body // Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z); rp3d::Vector3 initPosition(position.x, position.y, position.z);
@ -179,6 +140,7 @@ ConvexMesh::~ConvexMesh() {
mVBOTextureCoords.destroy(); mVBOTextureCoords.destroy();
mVAO.destroy(); mVAO.destroy();
delete mPhysicsTriangleVertexArray;
delete mConvexShape; delete mConvexShape;
} }

View File

@ -41,6 +41,8 @@ class ConvexMesh : public openglframework::Mesh, public PhysicsObject {
/// Previous transform (for interpolation) /// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform; rp3d::Transform mPreviousTransform;
rp3d::TriangleVertexArray* mPhysicsTriangleVertexArray;
/// Collision shape /// Collision shape
rp3d::ConvexMeshShape* mConvexShape; rp3d::ConvexMeshShape* mConvexShape;
rp3d::ProxyShape* mProxyShape; rp3d::ProxyShape* mProxyShape;