# C++ DirectX FBX SDK Importer Weird Mesh Problem

I'm having a problem understanding how to render the vertex data in fbx model into directx. This is my two functions and I've already triangulated all the mesh nodes.

bool FBXLoader::CopyVertexData(Mesh* mesh)
{
FbxVector4 pos, nor;
FbxNode* rootNode = mScene->GetRootNode();
if (rootNode)
{
int iChildNodeCount = rootNode->GetChildCount();

for (int i = 0; i < iChildNodeCount; i++)
{
// Child Node -> Object
FbxNode* fbxChildNode = rootNode->GetChild(i);
FbxMesh* fbxMesh = fbxChildNode->GetMesh();
if (!fbxMesh)
continue;
int iVertexCount = fbxMesh->GetControlPointsCount();
if (iVertexCount > 0)
{
SubMesh subMesh;
int iPolyCount = fbxMesh->GetPolygonCount();
for (int j = 0; j < iPolyCount; j++)
{
// The poly size should be 3 since it's a triangle
int iPolySize = fbxMesh->GetPolygonSize(j);
// Get 3 vertices for the triangle
for (int k = 0; k < iPolySize; k++)
{
// Get index
int index = fbxMesh->GetPolygonVertex(j, k);
subMesh.indices.push_back(index);

// Get position
pos = fbxMesh->GetControlPointAt(index);
// Get normal
fbxMesh->GetPolygonVertexNormal(j, k, nor);

// Insert pos and nor data
Vertex vertex;
vertex.fPos = DirectX::XMFLOAT3((float)pos.mData[0], (float)pos.mData[1], (float)pos.mData[2]);
vertex.fNor = DirectX::XMFLOAT3((float)nor.mData[0], (float)nor.mData[1], (float)nor.mData[2]);
vertex.fTex = DirectX::XMFLOAT2(0.5f, 1.0f);
subMesh.vertices.push_back(vertex);
}
}
mesh->subMeshes.push_back(subMesh);
}
}
}
else
{
MessageBox(NULL, "Unable to create FBX Root Node object", "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
return false;
}

return true;
}

{
FbxNode* rootNode = mScene->GetRootNode();
if (rootNode)
{
int iChildNodeCount = rootNode->GetChildCount();

for (int i = 0; i < iChildNodeCount; i++)
{
// Child Node -> Object
FbxNode* fbxChildNode = rootNode->GetChild(i);
FbxMesh* fbxMesh = fbxChildNode->GetMesh();
if (!fbxMesh)
continue;
int iVertexCount = fbxMesh->GetControlPointsCount();
if (iVertexCount > 0)
{
SubMesh subMesh;
FbxVector4* pVertices = fbxMesh->GetControlPoints();
for (int j = 0; j < iVertexCount; j++)
{
Vertex vertex;
vertex.fPos = DirectX::XMFLOAT3((float)pVertices[j].mData[0], (float)pVertices[j].mData[1], (float)pVertices[j].mData[2]);
vertex.fNor = DirectX::XMFLOAT3(0.3f, 0.6f, 0.9f);
vertex.fTex = DirectX::XMFLOAT2(0.5f, 1.0f);
subMesh.vertices.push_back(vertex);
}
int iIndexCount = fbxMesh->GetPolygonVertexCount();
//int* indices = new int[iIndexCount];
int* indices = fbxMesh->GetPolygonVertices();
for (int j = 0; j < iIndexCount; j++)
{
subMesh.indices.push_back(indices[j]);
}
mesh->subMeshes.push_back(subMesh);
}
}
}
else
{
MessageBox(NULL, "Unable to create FBX Root Node object", "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
return false;
}

return true;
}


Here's the result using between those 2 functions. All images are the output of shader

CopyVertexData

CopyVertexDataTest

I exported the same model into .obj format for data checking between fbxMesh->GetControlPointAt(index) and fbxMesh->GetControlPoints(). So... my first question is why is it that GetControlPoints() gave me the same exact vertices data as the .obj data while GetControlPointsAt(...) gave different values?

Here's my second question. Let's use a cube model as an example case. A cube have 6 faces and each face have 6 vertices(2 triangles) which means a cube will have 12 triangles and 36 vertices. Assume that the cube have 6 polygon faces.

I load the cube fbx model and then I triangulate the mesh. I assumed that when I use GetPolygonCount(), I will get 12 triangulated polygons and each polygons will give 3 vertices. Is it wrong?

My solution

bool FBXLoader::CopyVertexData(Mesh* mesh)
{
FbxVector4 pos, nor;
FbxNode* rootNode = mScene->GetRootNode();
if (rootNode)
{
int iChildNodeCount = rootNode->GetChildCount();

for (int i = 0; i < iChildNodeCount; i++)
{
// Child Node -> Object
FbxNode* fbxChildNode = rootNode->GetChild(i);
FbxMesh* fbxMesh = fbxChildNode->GetMesh();
if (!fbxMesh)
continue;
int iVertexCount = fbxMesh->GetControlPointsCount();
if (iVertexCount > 0)
{
int indicesIndex = 0;
SubMesh subMesh;
// Get all positions
FbxVector4* pVertices = fbxMesh->GetControlPoints();
int iPolyCount = fbxMesh->GetPolygonCount();
for (int j = 0; j < iPolyCount; j++)
{
// The poly size should be 3 since it's a triangle
int iPolySize = fbxMesh->GetPolygonSize(j);
// Get 3 vertices of the triangle
for (int k = 0; k < iPolySize; k++)
{
// Get index
int index = fbxMesh->GetPolygonVertex(j, k);
subMesh.indices.push_back(indicesIndex++);

// Get normal
fbxMesh->GetPolygonVertexNormal(j, k, nor);

// Insert pos and nor data
Vertex vertex = Vertex();
vertex.fPos = DirectX::XMFLOAT3(static_cast<float>(pVertices[index].mData[0]), static_cast<float>(pVertices[index].mData[1]), static_cast<float>(pVertices[index].mData[2]));
vertex.fNor = DirectX::XMFLOAT3(static_cast<float>(nor.mData[0]), static_cast<float>(nor.mData[1]), static_cast<float>(nor.mData[2]));
vertex.fTex = DirectX::XMFLOAT2(0.0f, 0.0f);
subMesh.vertices.push_back(vertex);
}
}
mesh->subMeshes.push_back(subMesh);
}
}
}
else
{
MessageBox(NULL, "Unable to create FBX Root Node object", "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
return false;
}

return true;
}


Result

• Could you describe what we see above in the first image? Is it the depth map or the output of a shader? – Robert Feb 22 '15 at 12:41
• It's an output of a shader – D13 Feb 24 '15 at 8:40
• Okay. If it still does not work check your input layout. The layout described at Device->CreateInputLayout must match the strides provided at DeviceContext->IASetVertexBuffers. – Robert Feb 24 '15 at 15:13
• It's already matched the layout. My actual problem were caused by how I get the position data. Thanks for trying to help me :) – D13 Feb 25 '15 at 7:58

I had the same issues. Check if you are using LH or RH coordinate system. To use RH (what I would suggest since most tools do) create your projection matrix with :

XMMATRIX perspMatrix = XMMatrixPerspectiveFovRH(angle, aspect, 0.1f, 100.0f);
XMStoreFloat4x4(m_pProjMatrix, XMMatrixTranspose(perspMatrix));


and when setting up your rasterizer use :

D3D11_RASTERIZER_DESC desc;
desc.CullMode = D3D11_CULL_BACK;
desc.FrontCounterClockwise = true;


Otherwise you have to convert from RH to LH i.e. if you are importing .fbx from Maya

I think it would be more clever to copy all control points in advance (before traversing the mesh) by :

    auto axisSystem = fbxScene->GetGlobalSettings().GetAxisSystem();
auto controlPoints = mesh->GetControlPoints();
auto controlPointsCount = mesh->GetControlPointsCount();

// Copy all control points
for (auto cp = 0; cp < controlPointsCount; cp++)
{
auto point = controlPoints[cp];
auto newVertex = new Vertex();
newVertex->Position = ConvertFbxVector4ToXMFLOAT3(&point, axisSystem, 1.0f);
vertices->push_back(*newVertex);
}


whrere ConvertFbxVector4ToXMFLOAT3 is your on function to invert or change axis depending on the actual axis system. For normal RH coordinate systems (+Y-Up, + Z-Front), nothing has to be converted. Then you work on your copied verices like this :

    for (auto v = 0; v < polygonSize; v++)
{
auto vertexIndex = mesh->GetPolygonVertex(p, v);
auto newVertex = new Vertex(vertices->at(vertexIndex));

// Create the normal
FbxVector4 normal;
mesh->GetPolygonVertexNormal(p, v, normal);
newVertex->Normal = XMFLOAT3
{
static_cast<float>(normal.mData[0]),
static_cast<float>(normal.mData[1]),
static_cast<float>(normal.mData[2])
};

// Use a standard color for all vertices
newVertex->Color = XMFLOAT4
{
0.7f, 0.2f, 0.7f, 0.6f
};

// Dont set that now
newVertex->UV = XMFLOAT2
{
0.0f, 0.0f
};
vertices->at(vertexIndex) = *newVertex;
indices->push_back(vertexIndex);
}


I will get 12 triangulated polygons and each polygons will give 3 vertices. Is it wrong?

No, you are right but I know what you mean. I've tried the same with Blender (creating cube and importing it as FBX) and what I got is 4 indices per polygon (4 * 6 = 24) instead of 3 (2 * 3 * 6 = 36) which afaik Direct3D does not accept.

• I managed to fix the problem by following the way you copied the vertices. After checking through my .obj loader codes, I think I'm making a big mistake on how I construct my vertex data since there is only very few data to create the vertex buffer. Will post my new solution once I have the time to check my codes thoroughly and code a new one. – D13 Feb 24 '15 at 10:41
• You might want to take a look at the Samples Content Exporter from the DirectX SDK, and DirectXMesh as well. – Chuck Walbourn Jun 24 '15 at 6:15