Introduction

TerraDyne is a next-generation native plugin for Unreal Engine 5.7. It decouples landscape physics from visual representation, enabling infinite runtime deformation — digging, raising, and painting — with fully persistent state, distance-based scalability, and smart procedural visuals.

The Scaling Problem

Legacy voxel systems are CPU heavy. Standard landscapes are static. Runtime mesh manipulation often leads to collision desyncs and visual seams.

TerraDyne solves this via Synchronous Physics / Asynchronous Visuals. We use a CPU-side float cache to drive throttled collision updates (Geometry Script) while simultaneously pushing R16f textures to the GPU for Virtual Heightfield Mesh displacement.

CPU CACHE GPU HEIGHT_RT MANAGER

Technical Pillars

Built strictly for UE 5.7, TerraDyne leverages modern modules like Geometry Scripting and Virtual Texturing to achieve AAA performance.

Direct Memory Write

Bypasses slow material draws using low-level memory locking (`LOCK_READ_WRITE`) to push float arrays directly to R16f textures.

Smart Procedurality

Includes a "Smart Material" pipeline that automatically textures terrain based on Slope (Rock/Grass) and Height (Snow/Sand) without manual painting.

Adaptive Scalability

Chunks utilize distance-based LOD to disable physics >500m away, and edits are debounced (0.2s) to prevent frame spikes during rapid sculpting.

Quick Start Guide (Developers)

1. Include the Module

TerraDyne relies on core geometry modules. Ensure your Build.cs includes:

PublicDependencyModuleNames.AddRange(new string[] { 
    "TerraDyne", "GeometryScripting", "VirtualHeightfieldMesh" 
});

2. Access the Manager

The ATerraDyneManager is a singleton-style actor registered to the world subsystem. You do not need to scan for it.

// Get the Subsystem first
if (UTerraDyneSubsystem* Sys = GetWorld()->GetSubsystem())
{
    // Retrieve the active Manager
    if (ATerraDyneManager* Manager = Sys->GetTerrainManager())
    {
        // 3. Dig a hole (Radius 500, Strength -100)
        Manager->ApplyGlobalBrush(HitLocation, 500.0f, -100.0f, false);
        
        // 4. Save Changes
        Manager->SaveWorld("MySaveSlot");
    }
}

3. Configure a Projectile

For fast-moving objects (meteors, grenades) to interact with dynamic terrain, enable CCD and bind to the Hit event.

MeshComp->BodyInstance.bUseCCD = true; // Prevents Tunneling
MeshComp->OnComponentHit.AddDynamic(this, &ATerraDyneProjectile::OnHit);

Configuration

TerraDyne exposes global settings via the Unreal Editor's Project Settings window. This allows you to configure default materials, asset paths, and performance thresholds without recompiling C++.

Configuration Data Flow

Project Settings
UTerraDyneSettings
DefaultGame.ini
Runtime Manager

Asset Paths

  • Master Material Path Defines the default material applied to new chunks.
    Default: /Game/TerraDyne/Materials/VHFM/M_TerraDyne_Smart
  • Height Brush Material The "Stamp" texture used for sculpting.
  • HUD Widget Class The UI widget spawned by the Showcase Orchestrator.

Performance Tuning

  • LOD Distance Threshold float
    Distance (in cm) at which chunks disable complex collision. Default is 50,000 (500m).
  • Collision Debounce Time seconds
    Wait time after a brush stroke before triggering a physics cook. Increase for smoother sculpting, decrease for responsiveness.

Using TerraDyne

This guide covers the operational workflows for TerraDyne: setting up the Manager, importing worlds via Lidar, and utilizing the runtime brush API for gameplay mechanics.

1 Manager Configuration

The BP_TerraDyneManager is the central orchestrator. It must be placed in the level (usually at 0,0,0) to manage chunk streaming and tool distribution.

Required Property Assignments

  • Chunk Class: BP_TerraDyneChunk (The tile actor)
  • Master Material: M_TerraDyne_Smart (Procedural)
  • Height Brush Material: M_HeightBrush (Additive Shape)
  • Weight Brush Material: M_WeightBrush (Layer Masking)
MANAGER BP MATERIALS CHUNK BP

2 Runtime Brush API

Use ApplyGlobalBrush to deform terrain or paint layers. The system automatically debounces collision updates (0.2s delay) to ensure smooth frame rates during continuous painting.

// 1. Sculpting (Physics)

Deforms geometry. Physics updates automatically via Async Cook.

Manager->ApplyGlobalBrush( HitLocation, // Center 500.0f, // Radius -50.0f, // Strength (Neg=Dig) false, // bIsHole -1 // Layer (-1 = Sculpt) );

// 2. Painting (Visuals)

Updates RGBA Weightmap. Does not affect collision.

Manager->ApplyGlobalBrush( HitLocation, 500.0f, // Radius 1.0f, // Opacity false, 1 // Layer ID (0=R, 1=G...) );

3 Persistence (Save/Load)

TerraDyne 1.1 introduces a full serialization pipeline. You can capture the state of every chunk (Height & Layers) and save it to disk using the standard USaveGame framework.

Saving the World

Manager->SaveWorld("Level1_State");

Serializes all ActiveChunkMap entries into compressed float arrays. The file is stored in Saved/SaveGames/.

Loading the World

Manager->LoadWorld("Level1_State");

Restores terrain state. Missing chunks are automatically spawned. Existing chunks are updated in-place.

Technical Reference (C++)

This section details the internal architecture, class hierarchy, and low-level data flow of the TerraDyne Runtime module.

ATerraDyneManager

Singleton-like actor responsible for routing "Brush" events to the correct world grid cells.

Function Signature Description
ApplyGlobalBrush(...) Calculates which grid cells overlap the brush radius and forwards the call.
Params: Location, Radius, Strength, bIsHole, PaintLayer
SaveWorld(SlotName) Serializes the entire world state to disk using UTerraDyneSaveGame.
LoadWorld(SlotName) Deserializes and restores world state. Spawns chunks if they don't exist.
RebuildChunkMap() Scans the world for ATerraDyneChunk actors and rebuilds the spatial hash.

ATerraDyneChunk

The atomic unit of terrain. Handles the sync between CPU float arrays, GPU textures, and Physics collision.

Variable / Function Description
TArray<float> HeightBuffer The "Source of Truth". A simple 1D float array representing the Z-height of every vertex in the grid.
UpdateLOD(ViewerPos) Checks distance to viewer. If > 500m, sets collision to NoCollision to save CPU.
GetSerializedData() Packs the chunk's coordinates, ZScale, and HeightBuffer into a struct for saving.

Threading & Performance Model

Physics (Async Cook)

TerraDyne sets PhysicsMesh->UpdateCollision(true). This pushes the PhysX/Chaos geometry cooking to a background thread.

Non-Blocking (Debounced 0.2s)

Visuals (RHI Command)

Texture updates use ENQUEUE_RENDER_COMMAND (implicit via UpdateResource) to upload float data. This avoids Game Thread stalls during frame rendering.

Render Thread

Chunk System & LOD

TerraDyne employs an intelligent Level of Detail (LOD) system to maintain high performance even in massive worlds.

Distance-Based Activation

PLAYER
PHYSICS ACTIVE
PHYSICS DISABLED (Visuals Only)
500m

Near Field (< 500m)

Chunks have Complex Collision enabled. Projectiles bounce, characters can walk, and edits trigger immediate physics recooks (debounced).

Far Field (> 500m)

Chunks automatically switch to NoCollision. They remain visible via VHFM but consume zero physics time. This allows for essentially infinite visual horizons.

Troubleshooting Guide

SYMPTOM: Projectiles fall through distant terrain Error: Aggressive LOD

The Cure

This is intended behavior (optimization). If you need physics further out (e.g., for sniping), adjust the threshold in ATerraDyneChunk::UpdateLOD or TerraDyneManager.cpp.

SYMPTOM: Collision lags behind visual brush Error: Debounce Latency

The Cure

Physics updates are delayed by 0.2s to prevent frame drops. This is a trade-off for performance. For "instant" feedback, you would need to accept significant FPS loss on complex meshes.

SYMPTOM: Terrain is unresponsive to sculpting Error: Material Loading / RT Format

The Cure

1. Material Check: Ensure M_TerraDyne_Smart is assigned in Project Settings. If assets were missing on boot, restart the Editor.
2. Render Target: The GPU readback requires RTF_RGBA16f (FloatRGBA). Check your log for "Invalid Format" warnings.
3. Flush: Ensure FlushRenderingCommands() is called before readback (handled automatically in v1.2+).

SYMPTOM: Character floats above crater (Visual mismatch) Error: Z-Scale Parity

The Cure

The Virtual Heightfield Mesh (Visuals) and Dynamic Mesh (Physics) must have identical Z-Scaling. In v1.2+, this is enforced to 1.0. If you see this, check if your Chunk BP has a manual Z-Scale override.

Budapest, HU

GregOrigin

Created by Andras Gregori @ Gregorigin, a single dad currently based outside Budapest, HU.

"Building tools that empower creators to shape worlds."