Converting Static Meshes
URealtimeMeshStaticMeshConverter (in the RealtimeMeshExt module — see the
section overview for the Build.cs dependency) copies geometry between a UStaticMesh asset
and RMC. It works in both directions and at two levels of granularity: raw stream sets, or a whole
URealtimeMeshSimple with its LODs and materials.
The canonical demonstration is the example actor
ARealtimeMeshExample_Simple_StaticMeshConvert
(Source/RealtimeMeshExamples/.../Simple/).
Editor vs. runtime. Reading out of a static mesh works at runtime with one caveat (see below). Writing into a static mesh requires the editor — the UE static-mesh build pipeline is editor-only. The converter logs a warning and returns failure if you call the to -static-mesh paths in a cooked/runtime build.
Static Mesh → RealtimeMesh
Section titled “Static Mesh → RealtimeMesh”Into a stream set
Section titled “Into a stream set”#include "RealtimeMeshStaticMeshConverter.h"#include "RealtimeMeshSimple.h"
using namespace RealtimeMesh;
FRealtimeMeshStreamSet StreamSet;
FStreamSetStaticMeshConversionOptions Options;Options.LODIndex = 0;Options.bWantTangents = true;Options.bWantUVs = true;Options.bWantVertexColors = true;Options.bWantPolyGroups = true; // keeps each static-mesh section as its own poly group
if (URealtimeMeshStaticMeshConverter::CopyStreamSetFromStaticMesh(SourceStaticMesh, StreamSet, Options)){ URealtimeMeshSimple* Mesh = GetRealtimeMeshComponent()->InitializeRealtimeMesh<URealtimeMeshSimple>();
const FRealtimeMeshBufferSetKey GroupKey = FRealtimeMeshBufferSetKey::Create(0, FName("FromStaticMesh")); Mesh->CreateBufferSet(GroupKey, MoveTemp(StreamSet));}CopyStreamSetFromStaticMesh has two internal sources and picks the best one available:
- Source data (the editor
MeshDescription) — highest fidelity, but editor-only. Used automatically in-editor when the asset has valid source models. - Render data (the cooked LOD render buffers) — this is what’s available at runtime. It has
been through build-time vertex splitting and optimization, so it’s slightly lower fidelity, and
it only works if the static mesh asset has
Allow CPU Accessenabled. Without that flag the render buffers aren’t readable on the CPU and the copy fails with a warning.
So: to convert a static mesh at runtime, tick Allow CPU Access on the asset. In-editor it works either way.
Into a whole RealtimeMesh
Section titled “Into a whole RealtimeMesh”CopyRealtimeMeshFromStaticMesh (Blueprint-callable) copies a range of LODs, the materials, and
optionally the distance field and Lumen card data straight into a URealtimeMeshSimple:
ERealtimeMeshOutcomePins Outcome;
FRealtimeMeshStaticMeshConversionOptions Options;Options.MinLODIndex = 0;Options.MaxLODIndex = REALTIME_MESH_MAX_LOD_INDEX; // all LODsOptions.bWantsMaterials = true;Options.bWantsDistanceField = true;Options.bWantsLumenCards = true;
URealtimeMeshSimple* Mesh = URealtimeMeshStaticMeshConverter::CopyRealtimeMeshFromStaticMesh( SourceStaticMesh, GetRealtimeMeshComponent()->InitializeRealtimeMesh<URealtimeMeshSimple>(), Options, Outcome);FRealtimeMeshStaticMeshConversionOptions extends the stream-set options with MinLODIndex /
MaxLODIndex (the LOD range to copy), bWantsMaterials, bWantsDistanceField, and
bWantsLumenCards. The distance field and card data are copied from the source asset’s render data
when present. (A Nanite copy option exists in the header but is commented out — Nanite conversion is
an RMC-Pro feature and is not part of this converter.)
Outcome is an ExpandEnumAsExecs pin in Blueprint (Success / Failure branches); in C++ it’s an
out-param you check against ERealtimeMeshOutcomePins::Success.
RealtimeMesh → Static Mesh
Section titled “RealtimeMesh → Static Mesh”This direction builds a real UStaticMesh asset and is editor-only (it drives
UStaticMesh::Build()). Use it to bake authored/generated geometry into an asset — for example, to
save a runtime-generated mesh from an editor utility.
From a stream set
Section titled “From a stream set”#if WITH_EDITORFStreamSetStaticMeshConversionOptions Options;
const bool bOk = URealtimeMeshStaticMeshConverter::CopyStreamSetToStaticMesh(StreamSet, TargetStaticMesh, Options);#endifThe converter builds a MeshDescription, creates one polygon group per distinct poly-group value
(named Material_<n>), lets the build derive the tangent basis, and calls Build(). It keeps your
authored normals unless a stream lacked them.
From a whole RealtimeMesh
Section titled “From a whole RealtimeMesh”CopyRealtimeMeshToStaticMesh (Blueprint-callable) does the same for an entire
URealtimeMeshSimple, spanning all its section groups into one LOD0 mesh description with one
polygon group per material slot:
ERealtimeMeshOutcomePins Outcome;
UStaticMesh* Baked = URealtimeMeshStaticMeshConverter::CopyRealtimeMeshToStaticMesh( SourceRealtimeMesh, TargetStaticMeshAsset, FRealtimeMeshStaticMeshConversionOptions(), Outcome);Blueprint summary
Section titled “Blueprint summary”| Node | Direction | Notes |
|---|---|---|
Copy Stream Set From Static Mesh | SM → stream set | Runtime needs Allow CPU Access |
Copy Stream Set To Static Mesh | stream set → SM | Editor only |
Copy Realtime Mesh From Static Mesh | SM → RealtimeMesh | Copies LODs, materials, DF, cards |
Copy Realtime Mesh To Static Mesh | RealtimeMesh → SM | Editor only |
All four expose a Success/Failure execution pin.
Related
Section titled “Related”- Mesh Optimization — optimize the stream set after converting from a static mesh, before creating the section group.
- Converting Dynamic Meshes — the equivalent for GeometryScript’s
UDynamicMesh.