DanielChappuis / reactphysics3d

Open source C++ physics engine library in 3D

Home Page:http://www.reactphysics3d.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug with pyramid custom mesh

patrikpatrik opened this issue · comments

Can you verify this? Ive checked and rechecked but for some reason, when a 4-sided pyramid custom shape is created, it tips over as if the bottom has only 1 face. Yet it has 2 faces (2 triangles) for bottom base. (5 vertices and 6 faces total)

This was kind of confusing to figure out but I've made sure my vertices windings are counter clockwise, as well as the indices. It compiles successfully and enabling debugging lines + triangles I always see it tipping over as if the bottom is only supported by 3 vertices. Could this be a bug?

// 4 sided pyramid
float quadTriVertices[15];
	quadTriVertices[0]  = -1;  quadTriVertices[1]  = -1;  quadTriVertices[2]  =  1; // front left
	quadTriVertices[3]  =  1;  quadTriVertices[4]  = -1;  quadTriVertices[5]  =  1; // front right
	quadTriVertices[6]  =  1;  quadTriVertices[7]  = -1;  quadTriVertices[8]  = -1; // back right
	quadTriVertices[9]  = -1;  quadTriVertices[10] = -1;  quadTriVertices[11] = -1; // back left
	quadTriVertices[12] =  0;  quadTriVertices[13] =  1;  quadTriVertices[14] =  0; // top
int quadTriIndices[18];
	quadTriIndices[0] = 0; quadTriIndices[1] = 2;  quadTriIndices[2] = 1;       // bottom right lower tri
	quadTriIndices[3] = 0; quadTriIndices[4] = 3;  quadTriIndices[5] = 2;       // bottom left upper tri
	quadTriIndices[6] = 0; quadTriIndices[7] = 4;  quadTriIndices[8] = 3;       // left
	quadTriIndices[9] = 0; quadTriIndices[10] = 1;  quadTriIndices[11] = 4;   // front
	quadTriIndices[12] = 1; quadTriIndices[13] = 2;  quadTriIndices[14] = 4;  // right
	quadTriIndices[15] = 4; quadTriIndices[16] = 2;  quadTriIndices[17] = 3;  // back
rp3d::PolygonVertexArray::PolygonFace* quadTriFaces = new rp3d::PolygonVertexArray::PolygonFace[6];
	rp3d::PolygonVertexArray::PolygonFace* quadTriFace = quadTriFaces;

	for (int i = 0; i < 6; i++) {

		// First vertex of the face in the indices array 
		quadTriFace->indexBase = i * 3;
		// Number of vertices in the face 
		quadTriFace->nbVertices = 3;

		quadTriFace++;
	}
	// positions for custom quad 4 sided pyramid shape!
	rp3d::Vector3 positionFour(0.0f, 2.0f, 0.0f);
	rp3d::Quaternion orientationFour = rp3d::Quaternion::identity();
	rp3d::Transform transformFour(positionFour, orientationFour);
	rp3d::RigidBody* bodyFour = world->createRigidBody(transformFour);

	// Create the quad 4 sided pyramid vertex array
	rp3d::PolygonVertexArray* quadTriVertexArray = new rp3d::PolygonVertexArray(5, quadTriVertices, 3 * sizeof(float),
		quadTriIndices, sizeof(int), 6, quadTriFaces,
		rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
		rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);

	// Create the polyhedron 4 sided quad pyramid mesh 
	rp3d::PolyhedronMesh* quadPyramidPolyhedronMesh = physicsCommon.createPolyhedronMesh(quadTriVertexArray);

	// Create the custom 4 sided quad pyramid convex mesh collision shape
	rp3d::ConvexMeshShape* quadPyramidMeshShape = physicsCommon.createConvexMeshShape(quadPyramidPolyhedronMesh);

Hello,

Your pyramid mesh seems to be fine. However, as you can read in the documentation here:

You need to make sure that the mesh you provide is indeed convex. Secondly, you should provide the simplest possible convex mesh. It means 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.

Therefore, you should really not use two coplanar triangular faces for the bottom face. You need to use a quad face instead, the collision detection will be more stable this way.

Therefore, you should really not use two coplanar triangular faces for the bottom face. You need to use a quad face instead, the collision detection will be more stable this way.

Is there a way to slightly tweak the code to make it so that the bottom base uses 4 vertices and the sides just 3 without crashing? I can't seem to make that happen without making it all 3 vertices all around.

For instance, then the indices would change to 16 instead of 18 correct? 3 * 4 (sides) + 4 (bottom base) ?

int quadTriIndices[16];
	// ccw for 1st
	quadTriIndices[0] = 0; quadTriIndices[1] = 1;  quadTriIndices[2] = 4;  // front
	quadTriIndices[3] = 0; quadTriIndices[4] = 4;  quadTriIndices[5] = 3;  // left
	quadTriIndices[6] = 1; quadTriIndices[7] = 2;  quadTriIndices[8] = 4;  // right
	quadTriIndices[9] = 3; quadTriIndices[10] = 4;  quadTriIndices[11] = 2;  // back
	quadTriIndices[12] = 1; quadTriIndices[13] = 0;  quadTriIndices[14] = 3;  quadTriIndices[15] = 2; // bottom base

Then the polygonFace is now 5 instead of 6 faces.

rp3d::PolygonVertexArray::PolygonFace* quadTriFaces = new rp3d::PolygonVertexArray::PolygonFace[5];
rp3d::PolygonVertexArray::PolygonFace* quadTriFace = quadTriFaces ;

And then I've tried two different variations of this loop but crash

for (int i = 0; i < 5; i++) {
		if (i == 4) { // for bottom base
			quadTriFace->indexBase = i * 4;
			quadTriFace->nbVertices = 4;
		}
		else
		{
			// First vertex of the face in the indices array 
			quadTriFace->indexBase = i * 3;
			// Number of vertices in the face 
			quadTriFace->nbVertices = 3;
		}
		quadTriFace++;
	}

And then here is a version of a loop without incrementing quadTriFace and doing it manually outside the loop

rp3d::PolygonVertexArray::PolygonFace* quadTriFaces = new rp3d::PolygonVertexArray::PolygonFace[5];
//rp3d::PolygonVertexArray::PolygonFace* quadTriFace = quadTriFaces;
	for (int i = 0; i < 4; i++) {

		// First vertex of the face in the indices array 
		quadTriFaces[i].indexBase = i * 3;
		// Number of vertices in the face 
		quadTriFaces[i].nbVertices = 3;
	}
	// for bottom base
	quadTriFaces[4].indexBase = 4 * 4; 
	quadTriFaces[4].nbVertices = 4;

Am I doing something wrong in the loop?

Am I doing something wrong in the loop?

Yes you are. The indexBase needed to be (i - 1) * 4 and NOT i * 4
I couldn't understand out why, until I needed to write this this down paper and pen. So the indices are laid out like so:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Then the starting index for each face would occur at:
0, 3, 6, 9, 12 which equals 5 faces. The first 4 faces are 3 vertices of triangles, and the last face is 1 quad of 4 vertices. However,
quadTriFaces[4].indexBase = 4 * 4; would equal 16, which is out of bounds and throws an error.
So to start on the 12th index, quadTriFaces[4].indexBase = (i - 1) * 4; = 12. Which is the bottom quad face, therefore quadTriFaces[4].nbVertices = 4;

Now I generate a stable pyramid! My god... thank you Daniel for the helpful tip!

Perfect. Glad that you find the issue.