Log an error when convex mesh is created with duplicated vertices and add in user manual that this is not supported

This commit is contained in:
Daniel Chappuis 2020-09-21 13:59:23 +02:00
parent 30af76dfaf
commit 71f7980fdf
4 changed files with 78 additions and 20 deletions

View File

@ -1236,6 +1236,9 @@ ConvexMeshShape* convexMeshShape = physicsCommon.createConvexMeshShape(polyhedro
that you need to avoid coplanar faces in your convex mesh shape. Coplanar faces have to be merged together. Remember that convex meshes are
not limited to triangular faces, you can create faces with more than three vertices. \\
Also note that meshes with duplicated vertices are not supported. The number of vertices you pass to create the PolygonVertexArray must be exactly
the number of vertices in your convex mesh. \\
When you specify the vertices for each face of your convex mesh, be careful with their order. The vertices of a face must be specified in
counter clockwise order as seen from the outside of your convex mesh. \\

View File

@ -28,6 +28,7 @@
// Libraries
#include <reactphysics3d/mathematics/mathematics.h>
#include <reactphysics3d/containers/Array.h>
#include "HalfEdgeStructure.h"
namespace reactphysics3d {
@ -69,7 +70,7 @@ class PolyhedronMesh {
PolyhedronMesh(PolygonVertexArray* polygonVertexArray, MemoryAllocator& allocator);
/// Create the half-edge structure of the mesh
void createHalfEdgeStructure();
bool createHalfEdgeStructure();
/// Compute the faces normals
void computeFacesNormals();
@ -80,6 +81,9 @@ class PolyhedronMesh {
/// Compute and return the area of a face
decimal getFaceArea(uint faceIndex) const;
/// Static factory method to create a polyhedron mesh
static PolyhedronMesh* create(PolygonVertexArray* polygonVertexArray, MemoryAllocator& polyhedronMeshAllocator, MemoryAllocator& dataAllocator);
public:
// -------------------- Methods -------------------- //

View File

@ -27,6 +27,8 @@
#include <reactphysics3d/collision/PolyhedronMesh.h>
#include <reactphysics3d/memory/MemoryManager.h>
#include <reactphysics3d/collision/PolygonVertexArray.h>
#include <reactphysics3d/utils/DefaultLogger.h>
#include <reactphysics3d/engine/PhysicsCommon.h>
#include <cstdlib>
using namespace reactphysics3d;
@ -37,38 +39,62 @@ using namespace reactphysics3d;
* Create a polyhedron mesh given an array of polygons.
* @param polygonVertexArray Pointer to the array of polygons and their vertices
*/
PolyhedronMesh::PolyhedronMesh(PolygonVertexArray* polygonVertexArray, MemoryAllocator &allocator)
PolyhedronMesh::PolyhedronMesh(PolygonVertexArray* polygonVertexArray, MemoryAllocator& allocator)
: mMemoryAllocator(allocator), mHalfEdgeStructure(allocator, polygonVertexArray->getNbFaces(), polygonVertexArray->getNbVertices(),
(polygonVertexArray->getNbFaces() + polygonVertexArray->getNbVertices() - 2) * 2) {
(polygonVertexArray->getNbFaces() + polygonVertexArray->getNbVertices() - 2) * 2), mFacesNormals(nullptr) {
mPolygonVertexArray = polygonVertexArray;
// Create the half-edge structure of the mesh
createHalfEdgeStructure();
// Create the face normals array
mFacesNormals = new Vector3[mHalfEdgeStructure.getNbFaces()];
// Compute the faces normals
computeFacesNormals();
// Compute the centroid
computeCentroid();
}
// Destructor
PolyhedronMesh::~PolyhedronMesh() {
delete[] mFacesNormals;
if (mFacesNormals != nullptr) {
for (uint f=0; f < mHalfEdgeStructure.getNbFaces(); f++) {
mFacesNormals[f].~Vector3();
}
mMemoryAllocator.release(mFacesNormals, mHalfEdgeStructure.getNbFaces() * sizeof(Vector3));
}
}
/// Static factory method to create a polyhedron mesh. This methods returns null_ptr if the mesh is not valid
PolyhedronMesh* PolyhedronMesh::create(PolygonVertexArray* polygonVertexArray, MemoryAllocator& polyhedronMeshAllocator, MemoryAllocator& dataAllocator) {
PolyhedronMesh* mesh = new (polyhedronMeshAllocator.allocate(sizeof(PolyhedronMesh))) PolyhedronMesh(polygonVertexArray, dataAllocator);
// Create the half-edge structure of the mesh
bool isValid = mesh->createHalfEdgeStructure();
if (isValid) {
// Compute the faces normals
mesh->computeFacesNormals();
// Compute the centroid
mesh->computeCentroid();
}
else {
mesh->~PolyhedronMesh();
polyhedronMeshAllocator.release(mesh, sizeof(PolyhedronMesh));
mesh = nullptr;
}
return mesh;
}
// Create the half-edge structure of the mesh
void PolyhedronMesh::createHalfEdgeStructure() {
/// This method returns true if the mesh is valid or false otherwise
bool PolyhedronMesh::createHalfEdgeStructure() {
// For each vertex of the mesh
for (uint v=0; v < mPolygonVertexArray->getNbVertices(); v++) {
mHalfEdgeStructure.addVertex(v);
}
uint32 nbEdges = 0;
// For each polygon face of the mesh
for (uint f=0; f < mPolygonVertexArray->getNbFaces(); f++) {
@ -82,14 +108,34 @@ void PolyhedronMesh::createHalfEdgeStructure() {
faceVertices.add(mPolygonVertexArray->getVertexIndexInFace(f, v));
}
nbEdges += face->nbVertices;
assert(faceVertices.size() >= 3);
// Addd the face into the half-edge structure
mHalfEdgeStructure.addFace(faceVertices);
}
nbEdges /= 2;
// If the mesh is valid (check Euler formula V + F - E = 2) and does not use duplicated vertices
if (2 + nbEdges - mPolygonVertexArray->getNbFaces() != mPolygonVertexArray->getNbVertices()) {
RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
"Error when creating a PolyhedronMesh: input PolygonVertexArray is not valid. Mesh with duplicated vertices is not supported.", __FILE__, __LINE__);
assert(false);
return false;
}
// Initialize the half-edge structure
mHalfEdgeStructure.init();
// Create the face normals array
mFacesNormals = new (mMemoryAllocator.allocate(mHalfEdgeStructure.getNbFaces() * sizeof(Vector3))) Vector3[mHalfEdgeStructure.getNbFaces()];
return true;
}
/// Return a vertex

View File

@ -488,13 +488,18 @@ void PhysicsCommon::deleteConcaveMeshShape(ConcaveMeshShape* concaveMeshShape) {
// Create a polyhedron mesh
/**
* @param polygonVertexArray A pointer to the polygon vertex array to use to create the polyhedron mesh
* @return A pointer to the created polyhedron mesh
* @return A pointer to the created polyhedron mesh or nullptr if the mesh is not valid
*/
PolyhedronMesh* PhysicsCommon::createPolyhedronMesh(PolygonVertexArray* polygonVertexArray) {
PolyhedronMesh* mesh = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(PolyhedronMesh))) PolyhedronMesh(polygonVertexArray, mMemoryManager.getHeapAllocator());
// Create the polyhedron mesh
PolyhedronMesh* mesh = PolyhedronMesh::create(polygonVertexArray, mMemoryManager.getPoolAllocator(), mMemoryManager.getHeapAllocator());
mPolyhedronMeshes.add(mesh);
// If the mesh is valid
if (mesh != nullptr) {
mPolyhedronMeshes.add(mesh);
}
return mesh;
}