Mesh Optimizer — Sibling Duplicate Remover

Editor-only Unreal Engine plugin that finds geometrically identical StaticMesh assets used across a level, rebases every placement onto a single canonical mesh with a corrected transform, and optionally collapses the group into a Hierarchical Instanced Static Mesh (HISM).

UE 5.7 · Editor module OptimizerEditor · native Slate tool panel.


The problem it solves

Bought kits and Kitbash3D-style packs import the same geometry as many separate assets: SM_Fence_01, SM_Fence_02, … are literal twins — identical vertices, sometimes with a different baked pivot or rotation. That defeats instancing: the engine sees N different meshes, so it can't batch them, and you can't make one HISM out of them.

Mesh Optimizer detects those "sibling" meshes, picks one to keep, and re-points every actor that used a sibling to the survivor — fixing each actor's transform so nothing moves on screen — leaving a set that is ready to become a single HISM.


What it does

  1. Scan (dry run — mutates nothing): walk the level's StaticMesh placements, fingerprint every unique mesh, group the geometric siblings, and report each group with a confidence figure (maxDeviation).
  2. Unify: reassign every sibling placement to its group's canonical mesh and apply the corrected world transform. Undoable (Ctrl+Z).
  3. Build HISM: create one HierarchicalInstancedStaticMeshComponent per group from the corrected transforms, optionally destroying the originals. Undoable.

Every mutation runs inside a single editor transaction.


How it works

extract geometry (LOD0 FMeshDescription)
   → fingerprint  (welded vertex/tri counts, surface area, |volume|,
                   covariance eigenvalues, radial histogram — all rotation-invariant)
   → bucket by (welded vertex count, triangle count)
   → recover the rigid delta between candidates
      (identity fast-path, then the 24/48 signed-permutation axis rotations)
   → verify by order-independent nearest-neighbour vertex match (spatial hash)
   → union-find into groups, pick a canonical
   → plan the corrected transform per placement

The corrective transform. With D = the recovered canonical-local → sibling-local delta and W = the sibling placement's current world transform, the canonical mesh must be placed at

W' = D * W        (UE FTransform multiply order; matrix W'_mat = D_mat * W_mat)

built via FMatrix and reconstructed into an FTransform. Because a non-uniform actor scale combined with a rotational D can produce shear (which FTransform cannot represent), each result is checked at the bounding-box corners and any placement that would shear is skipped and reported rather than silently corrupted.

Every candidate match is confirmed by an exact vertex-set verification before it is ever applied, so a bad transform is rejected, not shipped.


Installation

  1. Copy this folder into your project's Plugins/ directory (so it lives at Plugins/Optimizer/).
  2. Add it to your .uproject (editor-only):
    { "Name": "Optimizer", "Enabled": true, "TargetAllowList": [ "Editor" ] }
    
  3. Regenerate project files and build the editor target (a new module needs a full build — Live Coding cannot register a brand-new module).

Requires Unreal Engine 5.7 and an editor build (<Project>Editor Win64 Development).


Usage

Open the panel from Tools → Optimizer → Mesh Optimizer.

Control Effect
Scan Dry-run analysis of the current level; fills the report. Changes nothing.
Unify Reassign sibling placements to the canonical mesh + corrected transform.
Build HISM Collapse each group into one HISM actor.
☐ Mirrored Also treat negative-scale (mirrored) variants as siblings.
☐ Scaled Also treat uniformly-scaled copies as siblings.
☐ Merge materials Group siblings even if their material sets differ (the canonical's materials win).
☐ Destroy originals When building HISM, delete the original actors/components.

Recommended flow: Scan → review the report (check maxDev and the flags) → Unify (or Build HISM). Everything is undoable with Ctrl+Z.


Detection modes

  • Exact + rigid (default): identical geometry up to a rigid transform (rotation and/or a baked pivot offset). Covers almost all Kitbash cases.
  • + Mirrored: negative-scale reflections (kept as a separate canonical group, since HISM winding differs).
  • + Scaled: uniform-scale copies (the instance carries the scale).

Advanced tolerances (weld epsilon, accept tolerance, scalar relative tolerance, degenerate-eigenvalue epsilon) are exposed on the scan settings for tuning against specific content.


Safety & limitations

  • World Partition: only loaded cells are visible to the scan — coverage is partial and the report says so.
  • Shear: non-uniform actor scale combined with a rotational delta is unrepresentable by FTransform; those placements are skipped and counted, never corrupted.
  • ISM/HISM sources: existing instanced components are out of scope in this version (only plain StaticMeshActors / components are processed).
  • Materials: by default siblings with different material sets are kept in separate groups so each HISM keeps one material set.

Architecture

Source/OptimizerEditor/
  OptimizerEditor.Build.cs
  Public/
    OptimizerEditorModule.h     module + Tools menu / nomad tab
    OptimizerSubsystem.h        UEditorSubsystem: ScanLevel / ApplyUnify / BuildHISM
    OptimizerTypes.h            settings + result structs/enums
  Private/
    OptimizerEditorModule.cpp
    OptimizerGeometry.{h,cpp}   geometry extraction + fingerprint + 3x3 Jacobi eigensolver
    OptimizerMatcher.{h,cpp}    bucketing, transform recovery, spatial-hash verification
    OptimizerReconciler.{h,cpp} W' = D * W + shear detection
    OptimizerSubsystem.cpp      enumeration, planning, transacted mutation, HISM build
    SOptimizerPanel.{h,cpp}     native Slate tool panel

The heavy logic is UI-agnostic C++ in UOptimizerSubsystem (BlueprintCallable); the Slate panel is a thin driver.


License

Internal tool. © IHY / ExbyteLabs.

Description
No description provided
Readme 54 KiB
Languages
C++ 87.2%
C 10.1%
C# 2.7%