Collision Shape From FBX SDK Vertices
Posted: Fri Oct 22, 2021 11:36 pm
I am using extracting vertex information from the FBX SDK to construct a btBvhTriangleMeshShape. Firstly I'm not sure if this is the most appropriate type of collision shape to use and secondly the collision shape appears to be deformed. Objects sometimes only collide with one side of some other objects. Objects also sometimes do not collide with some other objects if they are moving too fast. I do not believe this is a Continuous Collision Detection issue, however I will not rule that out as the issue. Let me show you what I'm doing to better understand.
We load in a .fbx file which is split up into multiple child mesh objects. First we must calculate a transform based on the child mesh translation/rotation/scale which will later be applied to offset our vertices from local to global positions:
Then we use 'matrix' to offset the vertices and save them into a buffer for later use:
Before we continue, I would like to mention that once a vertex is stored into its array it is not altered in any way shape or form. The same array of vertices are passed over to bullet to create the collision object and also passed to the renderer for visual display and representation. Visually the meshes are being rendered correctly with no noticeable defects from that which is shown in the 3d modeling software.
After constructing array of vertices we pass this array over to create a collision shape with bullet:
Create our 'btTransform' which, please correct me if I am wrong, does not need an origin or rotation, the commented out lines here were back from before I was using FBX SDK to transform vertex positions into global space, and as such required me to manually translate/rotate/scale the objects into their intended positions (otherwise all the child mesh objects would be bunched up at 0,0,0 with incorrect rotations and scale)
Finally construct our rigid body and store important objects into various locations:
So that's the important bits of the process. Visually everything looks okay, physically there are problems.
I would like to draw your attention to this section of code:
Flipping which lines here are commented out results in absolutely no issues with the collision system. Essentially swapping which lines are commented here will no longer use the global matrix to translate vertex positions and instead directly store positions as they are read from the .fbx file (albeit with incorrect position/rotation/scale). So this leads me to believe the vertex transformation isn't quite right, but then why does everything look okay visually..? I have also inspected the vertex buffer with a break point and nothing stands out as odd..
Any ideas?
We load in a .fbx file which is split up into multiple child mesh objects. First we must calculate a transform based on the child mesh translation/rotation/scale which will later be applied to offset our vertices from local to global positions:
Code: Select all
FbxAMatrix matrixGeo;
matrixGeo.SetIdentity();
if (Node->GetNodeAttribute())
{
const fbxsdk::FbxVector4 lT = Node->GetGeometricTranslation(FbxNode::eSourcePivot);
const fbxsdk::FbxVector4 lR = Node->GetGeometricRotation(FbxNode::eSourcePivot);
const fbxsdk::FbxVector4 lS = Node->GetGeometricScaling(FbxNode::eSourcePivot);
matrixGeo.SetT(lT);
matrixGeo.SetR(lR);
matrixGeo.SetS(lS);
}
FbxAMatrix globalMatrix = Node->EvaluateGlobalTransform();
FbxAMatrix matrix = globalMatrix * matrixGeo;
Code: Select all
const FbxMesh* Mesh = FbxCast<const FbxMesh>(Node->GetNodeAttribute());
fbxsdk::FbxVector4* Vertices = Mesh->GetControlPoints();
uint32_t IndexCount = 0;
for (unsigned int j = 0; j < Mesh->GetPolygonCount(); j++) {
const unsigned int NumVerts = Mesh->GetPolygonSize(j);
if (NumVerts != 3) { continue; }
for (unsigned int k = 0; k < NumVerts; k++) {
Vertex* NewVertex = new Vertex;
const unsigned int Index = Mesh->GetPolygonVertex(j, k);
//NewVertex->pos.x = (float)(Vertices[Index].mData[0]);
//NewVertex->pos.y = (float)(Vertices[Index].mData[1]);
//NewVertex->pos.z = (float)(Vertices[Index].mData[2]);
fbxsdk::FbxVector4 result = matrix.MultT(Vertices[Index]);
NewVertex->pos.x = (float)result.mData[0];
NewVertex->pos.y = (float)result.mData[1];
NewVertex->pos.z = (float)result.mData[2];
NewFBX->Meshes.back()->Indices.push_back(IndexCount++);
NewFBX->Meshes.back()->Vertices.push_back(*NewVertex);
}
}
After constructing array of vertices we pass this array over to create a collision shape with bullet:
Code: Select all
TriangleMesh* Mesh = new TriangleMesh(_Driver, Pipe, FBXMesh, DiffuseTex);
btCollisionShape* ColShape;
btTriangleMesh* trimesh = new btTriangleMesh();
for (unsigned int i = 0; i < FBXMesh->Indices.size() / 3; i++) {
auto V1 = FBXMesh->Vertices[i * 3].pos;
auto V2 = FBXMesh->Vertices[i * 3 + 1].pos;
auto V3 = FBXMesh->Vertices[i * 3 + 2].pos;
trimesh->addTriangle(btVector3(V1.x, V1.y, V1.z), btVector3(V2.x, V2.y, V2.z), btVector3(V3.x, V3.y, V3.z));
}
ColShape = new btBvhTriangleMeshShape(trimesh, true);
Code: Select all
btTransform Transform;
Transform.setIdentity();
//Transform.setOrigin(btVector3(FBXMesh->translation[0], FBXMesh->translation[1], FBXMesh->translation[2]));
//Transform.setRotation(btQuaternion(glm::radians(FBXMesh->rotation[1]), glm::radians(FBXMesh->rotation[0]), glm::radians(FBXMesh->rotation[2])));
Code: Select all
SceneNodeMotionState* MotionState = new SceneNodeMotionState(MeshNode, Transform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(Mass, MotionState, MeshNode->_CollisionShape, localInertia);
MeshNode->_RigidBody = new btRigidBody(rbInfo);
MeshNode->_RigidBody->setUserPointer(MeshNode);
dynamicsWorld->addRigidBody(MeshNode->_RigidBody);
I would like to draw your attention to this section of code:
Code: Select all
//NewVertex->pos.x = (float)(Vertices[Index].mData[0]);
//NewVertex->pos.y = (float)(Vertices[Index].mData[1]);
//NewVertex->pos.z = (float)(Vertices[Index].mData[2]);
fbxsdk::FbxVector4 result = matrix.MultT(Vertices[Index]);
NewVertex->pos.x = (float)result.mData[0];
NewVertex->pos.y = (float)result.mData[1];
NewVertex->pos.z = (float)result.mData[2];
Any ideas?