bool importMesh()

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;
}