I'm having trouble figuring what to use to get indices from a FBX file. Recovering data is perfectly fine (at least for positions anyway), but I can't seem to find how to get indices.
Disclaimer: sorry about the long pieces of code, feel free to edit if you think some parts are really unnecessary.
I'm currently getting data like this:
// Recovering geometry
for (int meshIndex = 0; meshIndex < scene->GetGeometryCount(); ++meshIndex)
{
const auto mesh = static_cast<FbxMesh*>(scene->GetGeometry(meshIndex));
// Recovering positions
int currentVertIndex = points_coords.size();
points_coords.resize(currentVertIndex + mesh->GetControlPointsCount(), std::vector<coord_type>(3));
for (int vertIndex = 0; vertIndex < mesh->GetControlPointsCount(); ++vertIndex, ++currentVertIndex)
{
const auto& vertPos = mesh->GetControlPointAt(vertIndex);
points_coords[currentVertIndex][0] = vertPos[0]; // X position
points_coords[currentVertIndex][1] = vertPos[1]; // Y position
points_coords[currentVertIndex][2] = vertPos[2]; // Z position
}
// Iterate over normals with mesh->GetElementNormal()->GetDirectArray().GetCount()
// Iterate over texcoords with mesh->GetElementUV()->GetDirectArray().GetCount()
As for indices, I'm iterating over faces (polygons) and getting their vertices' indices as such:
// Fetching positions' indices
int currentPosPolyIndex = face_indices.size();
face_indices.resize(currentPosPolyIndex + mesh->GetPolygonCount());
for (int polyIndex = 0; polyIndex < mesh->GetPolygonCount(); ++polyIndex, ++currentPosPolyIndex)
{
const auto polySize = mesh->GetPolygonSize(polyIndex);
face_indices[currentPosPolyIndex].resize(polySize);
for (int polyVertIndex = 0; polyVertIndex < polySize; ++polyVertIndex)
face_indices[currentPosPolyIndex][polyVertIndex] = mesh->GetPolygonVertex(polyIndex, polyVertIndex);
}
Doing this works fine for FBXs containing only one mesh, but when there are several it seems it can't seam the faces. I will thoroughly investigate further if this comes from the data structures I'm using, but if anyone finds a problem in this, please let me know.
The problem lies within normals & texcoords' indices, which I can't figure how to fetch. Currently I'm checking the mapping mode for both, and trying to fill data accordingly:
const auto texMapping = mesh->GetElementUV()->GetMappingMode();
if (texMapping == FbxLayerElement::EMappingMode::eByControlPoint)
{
std::cout << "[FbxFileReader] Mapping mesh's texture coordinates by vertex." << std::endl;
texture_face_indices.resize(texture_face_indices.size() + mesh->GetPolygonCount());
std::copy(face_indices.cend() - mesh->GetPolygonCount(), face_indices.cend(), texture_face_indices.end() - mesh->GetPolygonCount());
}
else if (texMapping == FbxLayerElement::EMappingMode::eByEdge)
{
std::cout << "[FbxFileReader] Mapping mesh's texture coordinates by halfedge." << std::endl;
}
else if (texMapping == FbxLayerElement::EMappingMode::eByPolygon || texMapping == FbxLayerElement::EMappingMode::eByPolygonVertex)
{
std::cout << "[FbxFileReader] Mapping mesh's texture coordinates by face" << (texMapping == FbxLayerElement::EMappingMode::eByPolygonVertex ? " vertices" : "") << '.' << std::endl;
int currentTexPolyIndex = texture_face_indices.size();
texture_face_indices.resize(currentTexPolyIndex + mesh->GetPolygonCount());
for (int polyIndex = 0; polyIndex < mesh->GetPolygonCount(); ++polyIndex, ++currentTexPolyIndex)
{
if (texMapping == FbxLayerElement::EMappingMode::eByPolygonVertex)
{
const auto polySize = mesh->GetPolygonSize(polyIndex);
texture_face_indices[currentTexPolyIndex].resize(polySize);
for (int polyVertIndex = 0; polyVertIndex < polySize; ++polyVertIndex)
texture_face_indices[currentTexPolyIndex][polyVertIndex] = mesh->GetTextureUVIndex(polyIndex, polyVertIndex);
}
else
{
// Fetch face's texcoords & add it
//texture_face_indices[currentTexPolyIndex].emplace_back(...);
}
}
}
else if (texMapping == FbxLayerElement::EMappingMode::eAllSame)
{
std::cout << "[FbxFileReader] Mapping mesh's texture coordinates by mesh." << std::endl;
}
else
{
std::cerr << "[FbxFileReader] Couldn't handle mesh's texture coordinates' mapping mode." << std::endl;
}
I'm only handling face [vertices] cases for now, and I think it is correct for texcoords (I'm not getting materials at the moment so I can't check). But for normals, I can't find anything about getting their indices; this is why I'm only copying the same indices as positions', which I assume is plain wrong:
// Same checks for normals
else if (normMapping == FbxLayerElement::EMappingMode::eByPolygon || normMapping == FbxLayerElement::EMappingMode::eByPolygonVertex)
{
std::cout << "[FbxFileReader] Mapping mesh's normals by face" << (normMapping == FbxLayerElement::EMappingMode::eByPolygonVertex ? " vertices" : "") << "." << std::endl;
int currentNormPolyIndex = normal_face_indices.size();
normal_face_indices.resize(currentNormPolyIndex + mesh->GetPolygonCount());
for (int polyIndex = 0; polyIndex < mesh->GetPolygonCount(); ++polyIndex, ++currentNormPolyIndex)
{
if (normMapping == FbxLayerElement::EMappingMode::eByPolygonVertex)
{
const auto polySize = mesh->GetPolygonSize(polyIndex);
normal_face_indices[currentNormPolyIndex].resize(polySize);
for (int polyVertIndex = 0; polyVertIndex < polySize; ++polyVertIndex)
normal_face_indices[currentNormPolyIndex][polyVertIndex] = face_indices[currentNormPolyIndex][polyVertIndex];
}
else { /*...*/ }
}
}
Is this the proper way to recover the indices? Did I miss something?