Inconsistent compute penetration depth results using different Geometries
gabrielecaddeo opened this issue · 2 comments
Hi, I am using the PxGeometryQuery::computePenetration
with two boxes that are compenetrating (pose0
and pose1
), as the image below shows.
Basically I am trying to use this query to compute the penetration between a Triangle mesh and a simple box. However, I see that sometimes the function return very different results if I am using 2 simple boxes or if I am using a simple box and a Triangle mesh. The triangle mesh is loaded using the code in the samples directory.
The green box can be either box0
or trimeshGeom
object. The red box is the box1
.
I attach here the code.
#define NDEBUG
#include "PxPhysicsAPI.h"
#include <iostream>
#include "wavefront.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
int main (int argc, char** argv)
{
// Init the top level PxPhysics object
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
if(!gFoundation)
std::cout<<"PxCreateFoundation failed!"<<std::endl;
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true);
if(!gPhysics)
exit(0);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
WavefrontObj obj;
obj.loadObj("/path/to/the/prism.obj", false);
PxVec3* vertices = new PxVec3[obj.mVertexCount];
PxU32* indices = new PxU32[obj.mTriCount * 3];
for (int i = 0; i < obj.mVertexCount ; i++)
{
PxVec3 v(obj.mVertices[i*3], obj.mVertices[i*3+1], obj.mVertices[i*3+2]);
vertices[i] = v;
}
for (int i = 0; i < obj.mTriCount; i++)
{
for (int j = 0; j<3; j++)
{
indices[i*3 +j] = obj.mIndices[i*3 +j];
}
}
// Create the triangle mesh
PxTriangleMeshDesc meshDesc;
meshDesc.points.count = obj.mVertexCount;
meshDesc.points.data = vertices;
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.count = obj.mTriCount;
meshDesc.triangles.data = indices;
meshDesc.triangles.stride = 3 * sizeof(PxU32);
PxTriangleMesh* triMesh = NULL;
triMesh = gCooking->createTriangleMesh(meshDesc, gPhysics->getPhysicsInsertionCallback());
PxTriangleMeshGeometry trimeshGeom(triMesh);
// Create the simple boxes
PxBoxGeometry box0(0.023, 0.0455, 0.0865);
PxBoxGeometry box1(0.0161, 0.0135, 0.017);
PxVec3 direction;
PxF32 depth;
PxTransform pose0(PxVec3(0.1171, 0.0015, 0.1955));
PxTransform pose1(PxVec3(0.133365, 0.000294747, 0.275435), PxQuat(-0.00200156, 0.000335579, 0.999991, 0.00359089));
bool isPenetrating = PxGeometryQuery::computePenetration(direction, depth, box0, pose0, box1, pose1);
std::cout<<isPenetrating<<std::endl;
if (isPenetrating)
{
std::cout<<depth<<std::endl;
std::cout<< direction.x << " " << direction.y << " " << direction.z << std::endl;
}
isPenetrating = PxGeometryQuery::computePenetration(direction, depth, trimeshGeom, pose0, box1, pose1);
std::cout<<isPenetrating<<std::endl;
if (isPenetrating)
{
std::cout<<depth<<std::endl;
std::cout<< direction.x << " " << direction.y << " " << direction.z << std::endl;
}
gCooking->release();
gPhysics->release();
gFoundation->release();
return 0;
}
This is the output of the code:
1
0.0229577
-0.999992 0 -0.00400068
0
In this example, the function with the trimeshGeom
does not return any compenetration. However, if I slightly change the pose0
for example in this way
PxTransform pose0(PxVec3(0.1, 0.0015, 0.1955));
then the code works perfectly.
Can you give me some advice or explanation?
Here is the code of the prism.obj
file
####
#
# OBJ File Generated by Meshlab
#
####
# Object unit_cube_small.obj
#
# Vertices: 8
# Faces: 12
#
####
vn -0.005774 -0.005774 0.005774
v -0.0230000 -0.04550000 0.08650000
vn -0.005774 0.005774 0.005774
v -0.0230000 0.04550000 0.08650000
vn -0.005774 -0.005774 -0.005774
v -0.0230000 -0.04550000 -0.08650000
vn -0.005774 0.005774 -0.005774
v -0.0230000 0.04550000 -0.08650000
vn 0.005774 -0.005774 0.005774
v 0.0230000 -0.04550000 0.08650000
vn 0.005774 -0.005774 -0.005774
v 0.0230000 -0.04550000 -0.08650000
vn 0.005774 0.005774 0.005774
v 0.0230000 0.04550000 0.08650000
vn 0.005774 0.005774 -0.005774
v 0.0230000 0.04550000 -0.08650000
# 8 vertices, 0 vertices normals
f 1//1 2//2 3//3
f 3//3 2//2 4//4
f 5//5 1//1 6//6
f 6//6 1//1 3//3
f 7//7 5//5 8//8
f 8//8 5//5 6//6
f 2//2 7//7 4//4
f 4//4 7//7 8//8
f 5//5 7//7 1//1
f 1//1 7//7 2//2
f 8//8 6//6 4//4
f 4//4 6//6 3//3
# 12 faces, 0 coords texture
# End of File
Contacts/MTDs are for box-box pairs are generated based on the pair of box geometries that have well-defined volumes, it can generate a valid MTD regardless of the configuration of the intersecting boxes (including one being fully contained by the other).
However, there is no volumetric information associated with a triMesh. It's just a set of triangles that form a shape - this shape could be closed (e.g. a box) or open (e.g. the surface of a ground). As we have no notion of volumetric information, a box made from a triMesh is effectively treated as a hollow shell of a box. As such, PhysX generates MTDs based on triangle-box intersections. These are really only well-defined when the COM of the box is on the positive side of the triangle's plane. If COM is on the negative side but touching the triangle, the triangle is culled. As such, there are many cases where a triangle mesh and box/convex equivalent would not generate the same MTD.
Thanks for your answer!