Thanks for your detail answer.
I looked at the code a bit more and tried to fix it in the way I think it should manage the sections and polygon group ids in the source data. We are going to try the modded version for some time.
In FStaticMeshBuilder::Build instead of using GetMaterialIndexFromImportedMaterialSlotName path we simply bind the sections to slots by applying to the generated lod sections the same material slot of the source lod sections by matching polygon group id:
int32 LodSectionIndex = 0;
for (const FPolygonGroupID LodPolygonGroupID : MeshDescriptions[LodIndex].PolygonGroups().GetElementIDs())
{
bool bSectionInfoSet = false;
int32 BaseLodSectionIndex = 0;
for (const FPolygonGroupID BaseLodPolygonGroupID : MeshDescriptions[BaseReduceLodIndex].PolygonGroups().GetElementIDs())
{
if (LodPolygonGroupID == BaseLodPolygonGroupID)
{
//Copy the base sectionInfoMap
FMeshSectionInfo SectionInfo = StaticMesh->GetSectionInfoMap().Get(BaseReduceLodIndex, BaseLodSectionIndex);
FMeshSectionInfo OriginalSectionInfo = StaticMesh->GetOriginalSectionInfoMap().Get(BaseReduceLodIndex, BaseLodSectionIndex);
StaticMesh->GetSectionInfoMap().Set(LodIndex, LodSectionIndex, SectionInfo);
StaticMesh->GetOriginalSectionInfoMap().Set(LodIndex, LodSectionIndex, OriginalSectionInfo);
bSectionInfoSet = true;
break;
}
BaseLodSectionIndex++;
}
ensureAlways(bSectionInfoSet);
LodSectionIndex++;
}
So we had to be certain that reduction code does not mess you those.
In QuadricMeshReduction.cpp we changed the “Fill the PolygonGroups from the InMesh” loop to be the only code to manage polygon group ids:
//Fill the PolygonGroups from the InMesh
for (const FPolygonGroupID PolygonGroupID : InMesh.PolygonGroups().GetElementIDs())
{
OutReducedMesh.CreatePolygonGroupWithID(PolygonGroupID);
OutPolygonGroupMaterialNames[PolygonGroupID] = InPolygonGroupMaterialNames[PolygonGroupID];
{
// Copy all attributes from the base polygon group to the new polygon group
InMesh.PolygonGroupAttributes().ForEach(
[&OutReducedMesh, PolygonGroupID](const FName Name, const auto ArrayRef)
{
for (int32 Index = 0; Index < ArrayRef.GetNumChannels(); ++Index)
{
// Only copy shared attribute values, since input mesh description can differ from output mesh description
const auto& Value = ArrayRef.Get(PolygonGroupID, Index);
if (OutReducedMesh.PolygonGroupAttributes().HasAttribute(Name))
{
OutReducedMesh.PolygonGroupAttributes().SetAttribute(PolygonGroupID, Name, Index, Value);
}
}
}
);
}
}
so the following “// material index” if/else block is much simpler:
FPolygonGroupID MaterialPolygonGroupID = FPolygonGroupID(MaterialIndexes[TriangleIndex]); this works because MaterialIndexes are not really indices, but just polygon group ids casted to int (in the previous “MaterialIndexes.Add( PolygonGroupID.GetValue() );”).
This seems to fix all our problems. This works on static meshes without proper impoterted material names too.