Mesh Builder Local
TRealtimeMeshBuilderLocal is a helper that makes building the most common vertex format simple. Rather than juggling a separate stream builder per stream and a linkage to keep them in sync, the local builder wires all of that up for you: it owns the position, tangents, tex coord, color, triangle, and poly group builders, keeps the vertex streams size-locked through internal linkages, and gives you a single AddVertex / AddTriangle interface. It’s specialized towards the needs of Unreal’s local vertex factory — the format used by ordinary rendered meshes.
You customize the exact stored types through template parameters, and — just like a stream builder — it converts between those stored types and the friendly access types you use in code.
template < typename IndexType = uint32, // per-index type, e.g. uint16 or uint32 typename TangentElementType = FPackedNormal, // per-tangent storage, e.g. FPackedNormal or FPackedRGBA16N typename TexCoordElementType = FVector2DHalf, // per-channel tex coord storage, e.g. FVector2f or FVector2DHalf int32 NumTexCoords = 1, // number of tex coord channels, 1-8 typename PolyGroupIndexType = uint16> // poly group index storagestruct TRealtimeMeshBuilderLocal;Creating a local mesh builder
Section titled “Creating a local mesh builder”using namespace RealtimeMesh;
// The builder operates on a stream set. It creates the required Position and Triangles streams// immediately; the optional streams are added when you enable them below.FRealtimeMeshStreamSet StreamSet;
// Configure the stored data types through the template parameters. Here: 16-bit indices,// FPackedNormal tangents, FVector2DHalf tex coords with one channel.TRealtimeMeshBuilderLocal<uint16, FPackedNormal, FVector2DHalf, 1> Builder(StreamSet);
// Choose which optional vertex elements are enabled.Builder.EnableTangents();Builder.EnableTexCoords();Builder.EnableColors();
// Poly groups let you pack multiple sections into one set of buffers by tagging each triangle.Builder.EnablePolyGroups();
// Add a vertex, then set its attributes with a fluent chain. AddVertex returns a vertex builder that// converts to the new vertex index, so you can capture the index directly.const int32 V0 = Builder.AddVertex(FVector3f(-50.0f, 0.0f, 0.0f)) .SetNormalAndTangent(FVector3f(0.0f, -1.0f, 0.0f), FVector3f(1.0f, 0.0f, 0.0f)) .SetColor(FColor::Red) .SetTexCoord(FVector2f(0.0f, 0.0f));
const int32 V1 = Builder.AddVertex(FVector3f(0.0f, 0.0f, 100.0f)) .SetNormalAndTangent(FVector3f(0.0f, -1.0f, 0.0f), FVector3f(1.0f, 0.0f, 0.0f)) .SetColor(FColor::Green) .SetTexCoord(FVector2f(0.5f, 1.0f));
const int32 V2 = Builder.AddVertex(FVector3f(50.0f, 0.0f, 0.0f)) .SetNormalAndTangent(FVector3f(0.0f, -1.0f, 0.0f), FVector3f(1.0f, 0.0f, 0.0f)) .SetColor(FColor::Blue) .SetTexCoord(FVector2f(1.0f, 0.0f));
// Add a triangle from the three vertex indices, optionally tagging it with a poly group.Builder.AddTriangle(V0, V1, V2, 0);This is the exact pattern used by the ARealtimeMeshExample_Simple_HelloTriangle example
(Source/RealtimeMeshExamples/Private/Simple/RealtimeMeshExample_Simple_HelloTriangle.cpp), which is the shortest path to a working mesh.
What else it can do
Section titled “What else it can do”Beyond AddVertex / AddTriangle, the builder exposes the operations you’d expect:
- Query state with
HasTangents,HasTexCoords,HasVertexColors,HasPolyGroups,HasDepthOnlyTriangles, andNumTexCoordChannels. - Reserve or resize with
ReserveNumVertices/ReserveAdditionalVertices,SetNumVertices, and the matching triangle variants. - Edit an existing vertex with
EditVertex(Index), or set individual attributes by index withSetPosition,SetNormalAndTangent,SetColor,SetTexCoord, and so on. - Enable a simplified shadow/depth index list with
EnableDepthOnlyTriangles()and add to it withAddDepthOnlyTriangle.
If your mesh layout isn’t known until runtime, use FRealtimeMeshDynamicBuilder instead — see Stream Builder.
Motion vectors with PositionPrev
Section titled “Motion vectors with PositionPrev”For a deforming mesh (for example one driven by a compute shader), adding a PositionPrev stream alongside Position turns on per-vertex motion-vector output, which keeps the surface clean under TSR/TAA. The PositionPrev stream isn’t part of the local vertex format the builder manages, so you add it directly to the stream set as a copy of Position — the RMC and the compute driver maintain it from there:
using namespace RealtimeMesh;
// After building your vertices into StreamSet, mirror Position into a PositionPrev stream.if (const FRealtimeMeshStream* PositionStream = StreamSet.Find(FRealtimeMeshStreams::Position)){ FRealtimeMeshStream PrevStream(FRealtimeMeshStreams::PositionPrev, PositionStream->GetLayout()); PrevStream.Append(*PositionStream); StreamSet.AddStream(MoveTemp(PrevStream));}You can see this in the ARealtimeMeshExample_Simple_ComputeWave example
(Source/RealtimeMeshExamples/Private/Simple/RealtimeMeshExample_Simple_ComputeWave.cpp), where toggling the PositionPrev stream on and off A/B-tests the ghosting that occurs without per-vertex velocity.