in libraries/hvvr/samples_shared/model_import_fbx.cpp [202:301]
bool importMesh(ImportState& state, FbxNode* pNode) {
auto pMesh = pNode->GetMesh();
if (!pMesh->IsTriangleMesh()) {
printf("error: We only support triangle meshes.\n");
return false;
}
model_import::Mesh mesh;
mesh.transform = AsTransform(pNode->EvaluateGlobalTransform()) * GetGeometryTransform(pNode);
// Import the materials.
int materialCount = pNode->GetMaterialCount();
for (int n = 0; n < materialCount; n++) {
FbxSurfaceMaterial* material = pNode->GetMaterial(n);
if (!importMaterial(state, mesh, material)) {
return false;
}
}
const FbxGeometryElementNormal* pNormals = pMesh->GetElementNormal(0);
if (!pNormals) {
// Generate normals if we don't have any
pMesh->GenerateNormals();
pNormals = pMesh->GetElementNormal(0);
}
const FbxGeometryElementUV* pUVs = pMesh->GetElementUV(0);
const FbxLayerElementMaterial* pPolygonMaterials = pMesh->GetElementMaterial();
assert(pPolygonMaterials != nullptr);
assert(pPolygonMaterials->GetReferenceMode() == FbxGeometryElement::eIndex ||
pPolygonMaterials->GetReferenceMode() == FbxGeometryElement::eIndexToDirect);
FbxGeometryElement::EMappingMode mappingMode = pPolygonMaterials->GetMappingMode();
auto getMaterialIndex = [pPolygonMaterials, mappingMode, materialCount](uint32_t triangleIndex) {
int lookupIndex = 0;
switch (mappingMode) {
case FbxGeometryElement::eByPolygon:
lookupIndex = triangleIndex;
break;
case FbxGeometryElement::eAllSame:
lookupIndex = 0;
break;
default:
assert(false);
break;
}
int materialIndex = pPolygonMaterials->mIndexArray->GetAt(lookupIndex);
assert(materialIndex >= 0 && materialIndex < materialCount);
return uint32_t(materialIndex);
};
// vertex deduplication
UnorderedMapGenerator<hvvr::ShadingVertex, uint32_t>::Type hashMap;
uint32_t numTriangles = uint32_t(pMesh->GetPolygonCount());
mesh.data.verts.reserve(numTriangles * 3);
mesh.data.triShade.resize(numTriangles);
for (uint32_t t = 0; t < numTriangles; t++) {
uint32_t triIndices[3];
for (uint32_t v = 0; v < 3; v++) {
int iPoint = pMesh->GetPolygonVertex(t, v);
FbxVector4 point = pMesh->GetControlPointAt(iPoint);
FbxVector4 normal = GetVertexElement(pNormals, iPoint, t, v, FbxVector4(0, 0, 0, 0));
FbxVector2 uv = GetVertexElement(pUVs, iPoint, t, v, FbxVector2(0, 1));
hvvr::ShadingVertex vertex = {};
vertex.pos = hvvr::vector3(float(point[0]), float(point[1]), float(point[2]));
vertex.normal = hvvr::vector4h(hvvr::vector4(float(normal[0]), float(normal[1]), float(normal[2]), 0));
vertex.uv = hvvr::vector2(float(uv[0]), 1.0f - float(uv[1]));
auto it = hashMap.find(vertex);
if (it != hashMap.end()) {
// it's a duplicate vertex
triIndices[v] = it->second;
} else {
// we haven't run into this vertex yet
uint32_t index = uint32_t(mesh.data.verts.size());
mesh.data.verts.emplace_back(vertex);
hashMap[vertex] = index;
triIndices[v] = index;
}
}
uint32_t materialIndex = getMaterialIndex(t);
hvvr::PrecomputedTriangleShade& triShade = mesh.data.triShade[t];
triShade.indices[0] = triIndices[0];
triShade.indices[1] = triIndices[1];
triShade.indices[2] = triIndices[2];
triShade.material = materialIndex;
}
hvvr::GenerateTopology(mesh.data);
state.model.meshes.emplace_back(std::move(mesh));
return true;
}