TriAxis-Games / RealtimeMeshComponent

Unreal Engine 5 plugin component for rendering runtime generated content.
https://rmc.triaxis.games/
Other
1.58k stars 412 forks source link

RemoveSection bug #194

Closed Alex-Folts closed 3 years ago

Alex-Folts commented 4 years ago

When call RemoveSection, geometry do not removed, only material resets to default ue material(checkerboard). Issue reproducible for custom provider with multi-sections mesh.

I dig code a bit and found the reason: in this function: https://github.com/TriAxis-Games/RuntimeMeshComponent/blob/42e2bc4e79984fcdd485f8f664b4d5412d03c4ce/Source/RuntimeMeshComponent/Private/RuntimeMesh.cpp#L695 called RemoveSection_GameThread, but there is check: https://github.com/TriAxis-Games/RuntimeMeshComponent/blob/42e2bc4e79984fcdd485f8f664b4d5412d03c4ce/Source/RuntimeMeshComponent/Private/RuntimeMesh.cpp#L734 and, for the case of removing section, at this point LODs[LODId].Sections[SectionId] already removed, it removed before in call stack, so for the case of removing section this check always fail and RenderProxyRef->RemoveSection_GameThread(LODId, SectionId); never called.

I changed code like so and now sections removing properly:

//  if (LODs[LODId].Sections.Contains(SectionId))//fix remove section bug
//  {
        if (EnumHasAnyFlags(UpdateType, ESectionUpdateType::AllData))
        {
            if (LODs[LODId].Sections.Contains(SectionId))//fix remove section bug
            {
                if (EnumHasAllFlags(UpdateType, ESectionUpdateType::Properties))
                {
                    const auto& Section = LODs[LODId].Sections[SectionId];
                    RenderProxyRef->CreateOrUpdateSection_GameThread(LODId, SectionId, Section, false);
                }

                if (EnumHasAllFlags(UpdateType, ESectionUpdateType::Mesh))
                {
                    SectionsToGetMesh.FindOrAdd(LODId).Add(SectionId);
                }
            }
        }
        else
        {
            if (EnumHasAllFlags(UpdateType, ESectionUpdateType::Remove))
            {
                RenderProxyRef->RemoveSection_GameThread(LODId, SectionId);
            }
            else if (EnumHasAllFlags(UpdateType, ESectionUpdateType::Clear))
            {
                RenderProxyRef->ClearSection_GameThread(LODId, SectionId);
            }
        }
//  }

Basically i moved section check so it doesn't check for when we removing section.