# GregOrigin - Instant Organic Caves: Lightweight Procedural Runtime Structure Generator 

**URL:** <https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206>\
**Category:** Product Discussion\
**Tags:** fab\
**Created:** [January 10, 2026, 9:31pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206 "2026-01-10T21:31:46Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [January 10, 2026, 9:31pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/1 "2026-01-10T21:31:46Z")

</div>

[IOC 0.1 in action (Youtube).](https://www.youtube.com/watch?v=xURtHTS8Stk)  
  
[Read the docs.](https://gregorigin.com/InstantOrganicCaves/)  
  
📖 Overview

**Instant Organic Caves (IOC)** is a small plugin designed to generate massive, seamless, and organic cave and/or rock systems procedurally at runtime. Unlike traditional marketplace assets that rely on static meshes or Blueprint construction scripts, IOC utilizes a **"Metal C++"** approach.

It builds geometry directly using Unreal's `FDynamicMesh3` core math libraries, bypassing overhead from the Blueprint VM and intermediate wrapper libraries. The result is a system that can generate infinite, seamless, Nanite-enabled environments suitable for high-fidelity production.

✨ Key Features

\*Pure C++ Architecture:\*\* No dependency on Blueprint logic, PCG Graphs, or external assets. The geometry is calculated mathematically from scratch.

\*Direct Dynamic Mesh Manipulation:\*\* Operates directly on `UE::Geometry::FDynamicMesh3` for maximum performance.

\*Infinite World Generation:\*\* Supports seamless chunk tiling using world-space Perlin Noise.

\*Organic Smoothing:\*\* Implements custom, stable Laplacian Smoothing to convert blocky voxel grids into smooth, eroded cavern walls.

\*Welded Topology:\*\* Custom meshing algorithm ensures watertight geometry with no internal faces, preventing shading artifacts and mesh tearing.

\*Nanite & Lumen Ready:\*\* programmatically enables Nanite support on generated meshes.

🚀 Quick Start

Single Chunk Generation

1. In a **New Scene** , open the **Place Actors** panel.

2. Search for `IOCProceduralActor` in Plugins.

3. Drag it into the viewport.

4. A cave chunk will generate immediately. Use the **Details Panel** to adjust settings like `Seed`, `Roughness`, and `Cave Size`.

1. Use LeftAlt+LMB to duplicate the generated chunk in any direction. Chunks can be seamlessly merged. More sophisticated options to extend the structures will come in the next version.

Infinite World Generation (WIP, coming soon)

1. Search for `IOCWorldGenerator` in the Class list.

2. Drag it into the level.

3. In the Details Panel:

_Set_ \*Chunk Class\*\* to `IOCProceduralActor`.

_Set_ \*Render Distance\*\* (e.g., `2` for a 5x5 grid).

_Set_ \*Update Interval\*\* (e.g., `0.5` seconds).

4. Press **Play**. As the camera moves, new cave chunks will form ahead of you seamlessly.  
  
Please note: the plugin needs the **PCG** and **GeometryScripting** modules enabled.

> **[Instant Organic Caves: Lightweight Procedural Runtime Structure Generator](https://www.fab.com/listings/016b22dc-d04c-41fa-857c-d4f391a96c12)**
>
> IOC 0.1 in action (Youtube).Read the docs.📖 OverviewInstant Organic Caves (IOC) is a small plugin designed to generate massive, seamless, and organic cave and/or rock systems procedurally at runtime. Unlike traditional marketplace assets that rely on...

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [February 16, 2026, 10:59am UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/2 "2026-02-16T10:59:57Z")

</div>

Hi all. I am looking into the possibilities of merging this plugin with another one of mine, [TerraDyne](https://www.fab.com/listings/20f72d71-9737-4ac1-bce5-034eca166529): I think it would make great sense since both are essentially runtime procedural systems to generate or manipulate organic structures in a level.  
However, such a merge would result in a deeply complex unified plugin with a higher margin of error (and a book-length manual really).  
If you have any comments or requests on this, please share it here or in email, thanks.

 ![IOCPromo1](https://d3kjluh73b9h9o.cloudfront.net/original/4X/0/8/d/08de43dca69446f04563d3e3c286edf55643a7e2.jpeg)

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [June 19, 2026, 12:33pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/3 "2026-06-19T12:33:37Z")

</div>

# [0.3.0] - 2026-06-20 update 🏕

## Added ➕ 📰

 🎨 Pure Math Material: Developed M\_IOC\_MathRock , a zero-footprint master material that uses World Position and 3D Simplex Noise to generate organic rock strata without relying on texture memory.

🪨 Hybrid PBR Pipeline: Upgraded the Master Material with a Use PBR Texture switch, instantly swapping between Pure Math and traditional Textures.  
💎 Seamless Biome Textures: Packaged three new 4K tileable rock textures directly into the plugin: Obsidian Flow, Limestone Crawl, and Alien Hive. (More to come later.)  
🗺 Triplanar Projection: Implemented automatic Box Mapping to prevent texture stretching on generated vertical cave walls.  
📚 Vector Documentation: Overhauled the shipped Manual. Replaced static screenshots with clean, responsive SVG vector illustrations and added comprehensive guides for the new Hybrid Texture workflow.

- **Readiness Guard:** Showcase flythrough camera now intelligently defers its start until all asynchronous procedural caves have completed generating (or up to a 30s fallback timeout).
- **Flythrough Looping:** Added `bLoopShowcase` property to `AIOCShowcaseLauncher`, giving users control over whether the showcase flythrough loops continuously or halts after one pass.
- **Dedicated Tools Menu:** Added `Tools > Instant Organic Caves` with one-click access to the setup wizard, validation, documentation, demo spawns, showcase launch, and showcase cleanup.
- **Launcher Quick Actions:** `AIOCShowcaseLauncher` now exposes clearer Call In Editor actions for standard showcase start, capture showcase start, and showcase cleanup, with friendlier property labels and tooltips.
- **Wizard Quick Start UX:** The setup wizard now exposes a welcome-page project snapshot, quick-start actions, clickable step navigation, and preset-to-custom workflow shortcuts.

## Changed 🪸

- **Showcase Robustness:** Refactored the showcase spawn pipeline into resilient conditional blocks. If a specific section's actor fails to spawn, the system gracefully skips it without crashing or desyncing the camera.
- **Concurrency Safety:** Added a strict `bIsActive` lock to `ShowcaseState` with hardened reset logic to prevent overlapping showcases, memory pollution, and hot-reload errors.
- **Python Drift Prevention:** Fully deprecated `IOC_CreateShowcaseMap.py` via runtime warnings and comments, establishing the C++ Setup Wizard as the single source of truth for starter map configuration.
- **Shipping Build Compatibility:** Wrapped editor-only setup wizard capture functionality inside `#if WITH_EDITOR` blocks, completely resolving compilation errors in Game/Runtime/Shipping targets.
- **Typed Showcase/Demo API:** Wizard and launcher flows now call a shared native module API instead of relying on string-built `GEngine->Exec` commands.
- **Validation Feedback:** Installation validation now also shows editor notifications while still writing the full report to the Output Log.
- **Documentation Access:** Wizard and editor menu actions now share a single documentation opener that prefers the local shipped docs and falls back to the website.
- **Wizard Practicality:** Review now links directly to starter assets, preview-side workload visibility is stronger, and safer-first-pass actions surface earlier in the flow.
- **Standalone Packaging:** Fixed Win64 game-target packaging by restoring the runtime material-domain include used by fallback cave materials.
- **Native Setup Flow:** The setup wizard no longer depends on Python execution for starter assets or showcase-map creation; both workflows now use built-in editor APIs with explicit success/failure handling.
- **Validation Messaging:** Installation checks now treat Python automation as optional and correctly describe starter assets as shipped plugin content.

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [June 19, 2026, 12:34pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/4 "2026-06-19T12:34:42Z")

</div>

This really needs at least 2 new videos to showcase new features and instruct on usage. Please bear with me.

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [July 17, 2026, 5:33am UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/5 "2026-07-17T05:33:59Z")

</div>

## 0.3.5 update, 2026-07-18 🌋

### Added

- **Authoritative runtime carving:** Reflected carve records now replicate to late joiners, serialize through `SaveGame`, validate radius/input, and obey a bounded FIFO history.
- **Persistent streamed carving:** `AIOCStreamingManager` owns a saveable carve history, routes excavation to affected chunks, and restores it after unload/reload.
- **Production resource budgets:** Hard voxel, triangle, and scatter caps reject unsafe work while preserving the last valid generated mesh.
- **Multiplayer streaming controls:** Authority tracks all player pawns, unions their desired chunks, caps retention, throttles loads, and releases chunks after the last player leaves.
- **Seam-safe streamed density:** Voxel/LOD-aligned chunk dimensions, a one-voxel neighbor halo, stable global seeding, and locked smoothing boundaries prevent artificial interface caps.
- **World-aligned generated UVs:** World-space chunks now project generated UVs from world coordinates so UV-driven materials do not restart at every chunk origin.
- 🎨 **Pure Math Material (updated):** Developed `M_IOC_MathRock`, a zero-footprint master material that uses World Position and 3D Simplex Noise to generate organic rock strata without relying on texture memory.
- 🪨 **Hybrid PBR Pipeline (updated):** Upgraded the Master Material with a `Use PBR Texture` switch, instantly swapping between Pure Math and traditional Textures.
- 💎 **Seamless Biome Textures (updated):** Packaged three new 4K tileable rock textures directly into the plugin: Obsidian Flow, Limestone Crawl, and Alien Hive.
- 🗺 **Triplanar Projection (updated):** Implemented automatic Box Mapping to prevent texture stretching on generated vertical cave walls.
- **Readiness Guard:** Showcase flythrough camera now intelligently defers its start until all asynchronous procedural caves have completed generating (or up to a 30s fallback timeout).
- **Flythrough Looping:** Added `bLoopShowcase` property to `AIOCShowcaseLauncher`, giving users control over whether the showcase flythrough loops continuously or halts after one pass.
- **Production bake controls:** Stable unique naming, material override, lightmap UV/tangent generation, optional generated LOD, optional Nanite, and selectable collision mode.
- **Runtime status:** Blueprint-visible success, failure reason, timing, voxel, triangle, LOD, and scatter metrics.
- **Regression coverage:** Added runtime-contract, generation-budget, streamed-seam, and streamed-carve-persistence automation tests.

### Changed

- Cave transforms now participate correctly in world-space noise, biome, and carve sampling.
- Generation cancellation is lifecycle-safe and checks cancellation during expensive parallel voxel/carve work.
- LOD distance uses generated mesh bounds and never switches to an invalid LOD.
- Player coupling is opt-in and disabled for network games unless explicitly allowed.
- Demo/showcase commands are non-shipping cheat commands; the showcase launcher is inert in Shipping.

### Fixed

- Removed global debug-line flushing that could erase unrelated project visualization.
- Removed module delegate leakage during shutdown.
- Removed plugin-owned UE 5.7 deprecation warnings for networking and Nanite access.
- Fixed Shipping compilation of the showcase launcher.
- Fixed world-space generation seeds being ignored and per-chunk seeds breaking density continuity.

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [September 8, 2026, 7:01am UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/6 "2026-09-08T07:01:22Z")

</div>

# [0.4.0] update, 2026-09-09 🍄‍🟫 🏕

At a glance:

- Support for UE5.5, 5.6, 5.7, 5.8.x
- An original scatter library
- 10x performance boost
- All content re-authored on UE5.5 to ensure compatibility
- New demo map and offline / online tutorial
- Redesigned Setup Wizard
- Major rehauling of cave materials
- Carving and instrumentation upgrade
- Network update: delta-replicate
- Many fixes

A long overdue major update. Carving, content and onboarding. Every shipped asset was re-authored on the 5.5 floor, the plugin gained its own scatter library, the Setup Wizard was rebuilt, and a demo map and tutorial now give two routes in that need no setup.

A deeply technical changelog follows, aimed mainly at enthusiasts. The [online manual](https://gregorigin.com/Manuals/InstantOrganicCaves/) and [setup tutorial](https://gregorigin.com/Manuals/InstantOrganicCaves_Tutorial/) may be an easier read otherwise. Please remember that the [open-source version](https://github.com/gregorik/InstantOrganicCaves) is also advanced, updated and supported.

**Verified on UE 5.5, 5.6, 5.7 and 5.8**. Automation suite **21/21 green on the 5.5 floor** , up from 14 tests, and every assertion added this cycle was negative-tested: deliberately broken, observed to fail, then restored.

### ⚡ Performance — carve latency 200 ms to 118 ms (1.7x)

Measured on an 80^3 cave (3200 uu bounds, 40 uu voxels, non-tunnel, one sphere carve).  
New per-stage instrumentation, logged when `bLogPresetDebug` is set, drove all of it:

| stage | before | after |
| --- | --- | --- |
| noise fill | 23 ms | 0 ms (replayed) |
| carve | 0.3 ms | 0.3 ms |
| face extract | 10.5 ms | 10 ms |
| **Laplacian smooth** | **73 ms** | **7.2 ms** |
| mesh build | 58 ms | 64 ms |
| overlays | 35 ms | 35 ms |
| **worker total** | **200 ms** | **118 ms** |

- **Laplacian smoothing was allocating a `TSet<int32>` per vertex** to hold adjacency – one  
hash set per mesh vertex, which made allocator traffic the single largest cost in the whole  
generator (36% of generation time). Replaced with compressed-sparse-row adjacency built in  
two linear passes, with per-slice sort-and-unique reproducing `TSet`’s unique-neighbour  
semantics. The per-vertex update has no cross-vertex dependency, so it now also runs through  
`ParallelFor`. **10x faster on that stage.**
- **Added `FIOCVoxelCache`** : the post-noise, pre-carve voxel field is cached and replayed, so  
a carve no longer re-evaluates the noise. Keyed by a signature covering every input to the  
fill (seed, noise parameters, tunnel geometry, biome overrides, spline segments, actor  
transform, bounds) plus voxel size and grid dimensions – change any generation parameter and  
the signature stops matching, so a stale field cannot be served and there is no invalidation  
call to forget. Stored as one bit per voxel (a 2M-voxel streamed chunk costs ~250 KB); only  
caves that actually carry carves populate a cache. Toggleable in Project Settings.
- **The carve pass is restricted to the union bounding box of the carves’ influence.** Outside  
it the field is identical to the filled or replayed result. The remaining ~110 ms is entirely mesh build (64 ms) and attribute overlays (35 ms), both bound  
by single-threaded `FDynamicMesh3` append APIs.

### 💥 Breaking

- **`AIOCProceduralActor::RuntimeCarves` changed type** from `TArray<FIOCCarvingCapture>` to  
`FIOCCarveHistory`. C++ that iterated it should use `RuntimeCarves.Items` or the new  
`GetRuntimeCarves()`; Blueprint should use `GetRuntimeCarves()`. **The SaveGame layout for  
carve history changed** – previously saved carve histories will not load.
- `OnRep_RuntimeCarves` is gone; the FastArray notifies through its own hook.

### 🗿 Content — everything re-authored on the 5.5 floor

- **All shipped assets are now fully compatible with the declared 5.5 floor.**  
Forward compatibility runs one way only — there is no downgrade path and  
no descriptor setting that helps. Every asset was rebuilt natively on 5.5 by dumping its  
_semantic_ content on a newer engine and replaying it through the editor API, then re-dumping  
the rebuild on 5.5 and diffing: 279 values compared, one difference, and that one is an  
engine limitation carrying no data.
- **`Packaging.ContentEngineFloor`** now scans every shipped `.uasset` and `.umap` and fails on  
anything saved above the floor, so this cannot recur silently.

### 🩹 Fixed — cave materials

- Three base materials were one-sided. A cave is a shell – `TunnelRadius` of air inside `WallThickness` of rock – and the player stands inside it, so the bore’s  
surfaces are backfaces and were being culled. All three are now two-sided,  
which also fixes shading, since Unreal flips the vertex normal on  
backfaces for two-sided materials.
- Both flags are set by `Resources/SetMaterialRenderFlags.py` and guarded by the  
`Content.MaterialRenderFlags` automation test.
- 🎨 `M_IOC_SmartCave` ignored vertex colours. `VertexColor` was wired to nothing  
and both `LinearInterpolate` alpha pins sat at `const_alpha = 0.5`, so the material rendered a  
fixed 50/50 blend. The authoring script wired outputs named `"Green"`/`"Blue"`; the outputs  
are `R`/`G`/`B`/`A`.
- 🎨 `M_IOC_MathRock` ran its noise at default world scale. The `Noise` position input was  
unconnected and `WorldPosition → Multiply(x0.002)` dangled — the script targeted a pin named  
`"Position"`, which is actually `"World Position"`.
- 🧩 **`IOC_Fn_ScatterCrystals` computed a density it discarded** — `NormalToDensity_0.Out` went  
nowhere. It now feeds `DensityFilter_0.In`.
- `ConnectMaterialExpressions` returns false on an unknown pin or  
output name and changes nothing. Every authoring  
script now routes through a helper that raises on rejection.

### 🪨 Added — an original scatter library

- **Eight meshes generated with GeometryScripting** and shipped in  
`/InstantOrganicCaves/InstantOrganicCaves/Geometry/`: three rocks from boulder to gravel, two  
crystals, a geode, a stalactite and a stalagmite. Each has two LODs, simple collision, and a  
pivot placed for how it is used — the stalactite hangs from its top, the rest sit on their  
base — so instances neither float nor sink when aligned to a surface.
- **`Content.ScatterMeshLibrary`** checks all eight for material slots, LOD count and reduction,  
triangle budget, collision, real-world scale and pivot placement. All eight gates have now  
been proven able to fail.

### 🧭 Added — two routes in that need no setup

- 🗺 **A demo map ships** : `/InstantOrganicCaves/Maps/IOC_DemoMap`, reachable from  
**Tools → Instant Organic Caves → Open Demo Map**. It holds one launcher and a PlayerStart  
and nothing else — every cave is built at runtime on Play, so there is no baked lighting to  
rebuild, nothing to rot, and no content references beyond a native class.
- 📖 **A tutorial ships** : `Resources/Docs/Tutorial.html`. The manual documents every property  
and teaches nothing, which left no guided path for a new user. The tutorial  
covers demo, wizard, presets, sizing, the six parameters that matter, scatter and  
troubleshooting, with a preset explorer that draws each cave’s cross-section to scale from  
the real preset values and a voxel budget calculator running the wizard’s own arithmetic.
- 🧹 **`IOC.ClearAllDemos`** removes everything any demo command added, including the playtest  
character, so the commands leave no residue in a customer’s level.

### 🪄 Changed — the Setup Wizard

- **Every `SWrapBox` had always been wrapping at 100px.** `SWrapBox` defaults to  
`PreferredSize = 100` with `UseAllottedSize = false`, and all twelve instances set neither —  
so button rows stacked vertically regardless of available width.
- The wizard opens on a first run with a working route forward. `IOC.OpenSetupWizard` opens it without the menu.

### 🌐 Network

- **`RuntimeCarves` now delta-replicates.** It was a plain `TArray<FIOCCarvingCapture>`, so  
every carve resent the whole array – roughly 25 KB to each relevant client against a  
256-entry history. It is now `FIOCCarveHistory`, a `FFastArraySerializer`. The common case  
(append) marks one item and sends one small delta; only FIFO eviction degrades to a full  
array update, because a removal invalidates the replication keys after it.
- Client-side rebuilds are driven by `PostReplicatedReceive`, which fires once per received  
update, rather than by the per-element add/change/remove hooks.

### ✨ Added — carving and instrumentation

- `InstantOrganicCaves.Cave.CarveFieldCacheParity` – proves a replayed field produces geometry  
identical to a recomputed one, that two consecutive cached generations agree, and that  
changing the seed invalidates the cache rather than serving the stale field.
- `Production.RuntimeContract` now asserts the carve history carries  
`STRUCT_NetDeltaSerializeNative`. Omitting the type trait still compiles and still  
replicates, just as a whole array – this is the only check that distinguishes the two.
- Per-stage generation timings behind `bLogPresetDebug`.

### 🧪 Verification

- Suite grown from 14 tests to **21**. Seven are new: `Content.ScatterMeshLibrary`,  
`Content.MaterialRenderFlags`, `Content.WizardStyleAssets`, `Demo.DemoMap`,  
`Demo.ShowcaseLifecycle`, `SetupWizard.ButtonSweep` and `SetupWizard.Layout`. The  
fourteenth, `Packaging.ContentEngineFloor`, existed and was the one failure — it passes now  
that the content is authored on the floor.
- **Every new assertion was negative-tested.** Two proved worth the effort by exposing tests  
that could not have failed: a mesh-breaking helper reported success while doing nothing,  
because the editor library it called is a silent no-op outside a real editor session; and an  
early layout test emitted four confident failures.

### 🧱 Structure

- **Split out an `InstantOrganicCavesEditor` module (Type: Editor).**
- The showcase still runs in PIE and packaged builds, so it stayed in the Runtime module; its level-viewport control is inverted through `FIOCShowcaseViewportHooks`, which the editor module binds on startup. The Runtime module no longer depends on `LevelEditor`, `ToolMenus` or `ApplicationCore` at all.
- `FInstantOrganicCavesModule::ValidateInstallation` / `OpenDocumentation` moved to `FInstantOrganicCavesEditorModule`. **API break** for any C++ that called them.
- Editor logging goes to a separate `LogIOCEditor` category.

### ✨ Also added

- **Project Settings page** (`UIOCSettings`, Project Settings \> Plugins \> Instant Organic Caves): fallback cave material as a `FSoftObjectPath`, max grid cells per axis, max spline samples, and the vertex welding toggle.
- **Blueprint-assignable generation events.** `OnGenerationStartedEvent` and `OnGenerationFinishedEvent` are `BlueprintAssignable`; generation is asynchronous and can take seconds, and Blueprints previously had to poll `bIsGeneratingDisplay` on tick to know when a cave was ready. The native C++ delegates are unchanged and still broadcast.
- `GenerateCave` and `RequestRegeneration` are now `BlueprintCallable`.
- **Vertical chunk streaming.** `AIOCStreamingManager` keys chunks by `FIntVector` and gained `VerticalStreamRadius`. It defaults to 0, which reproduces the previous single-layer behaviour exactly; raising it streams cave systems deeper than one chunk. Note the chunk count scales by `(2 * VerticalStreamRadius + 1)`, so `MaxLoadedChunks` needs raising to match.
- `InstantOrganicCaves.Cave.VertexWelding` regression test: asserts welding preserves every triangle while sharing vertices, and logs the measured saving.

### 🔧 Additional changes

- **Generated meshes weld their vertices.** The generator emitted four unshared vertices per quad because `FDynamicMesh3` rejects triangles that would create a non-manifold edge – something diagonal-touching voxels produce constantly. It now shares a vertex per grid corner and falls back to duplicated vertices for only the individual triangles that actually fail, so the manifold guarantee holds and no triangle is lost. Measured **2.93x fewer vertices** (5504 → 1881 for 2752 triangles) on the test cave, with the same reduction carried into cooked collision. Revertible via the project setting.
- **The PCG node has a version-gated output path.** `UPCGBasePointData` (structure-of-arrays) does not exist on 5.5, so 5.5 keeps `UPCGPointData` + `TArray<FPCGPoint>` while 5.6+ uses `FPCGContext::NewPointData_AnyThread` with the SoA value ranges – which also picks up `UPCGPointArrayData` where a project has enabled it. The solid-voxel scan was restructured into a count-then-fill pass so both back-ends write output in parallel with no per-point reallocation.
- `TObjectPtr` for all `UPROPERTY` object references on the cave actor, streaming manager and character.
- Editor UI strings converted from `INVTEXT` to `LOCTEXT` in the menus and validation notifications.

### 🩹 Additional fixes

- **PCG element allocated UObjects off the game thread.** `FIOCVoxelCoreElement::ExecuteInternal` called `NewObject<UPCGPointData>()` directly; PCG elements run on worker threads (`IPCGElement::CanExecuteOnlyOnMainThread` defaults to false), so this raced the garbage collector. Now uses `FPCGContext::NewObject_AnyThread`.
- **Cellular Automata seeding produced a lattice, not noise.** The initial fill used a single LCG step, which leaves consecutive cells a fixed stride apart and yields regular banding. Replaced with a MurmurHash3-finalised, coordinate-keyed hash that is also stable across grid resizes.
- **Streaming manager held raw `UObject*` chunk pointers** in a non-`UPROPERTY` map, invisible to the GC and left dangling when a chunk was destroyed outside `UnloadChunk`. Now `TWeakObjectPtr`, with an explicit prune pass.
- **Clients overwrote replicated generation settings.** `BeginPlay` re-expanded the cave preset on every peer, clobbering the replicated recipe and producing client geometry (and collision) the server did not have. Preset expansion is now authority-only.
- **The legacy preset migration could hijack runtime actors.** `ShouldAutoPreset()` is a value-match heuristic over user-editable fields; it no longer runs at `BeginPlay`, only in a genuine editor world, so a streamed chunk whose settings coincide with the defaults is not silently converted into a tunnel.
- **Generation bounds were silently truncated.** The working grid is capped per axis; exceeding it shrank the cave with no diagnostic. The cap is raised to 2048 cells per axis and clamping now logs a warning.
- **Splines were chorded, not followed.** Tunnel generation read only `GetLocationAtSplinePoint`, so a two-point spline with tangents produced a straight tunnel and curves were clipped by bounds derived from the same chords. Splines are now sampled by arc length, backed by a new uniform segment grid so the extra segments do not turn the nearest-segment query into an O(voxels x segments) scan.
- **World-space noise tiled.** `FMath::PerlinNoise3D` masks its lattice with `& 255`, repeating roughly every 512 m at the default frequency and folding large seed offsets back onto the same lattice. Replaced with a hash-lattice gradient noise of matching range and distribution, so existing thresholds still apply. Regenerating an existing cave will change its shape.
- **Collision was re-cooked on every mesh edit.** Complex-as-simple collision updates are now deferred and cooked once per completed generation.
- **The demo and showcase commands changed the user’s level.** They took the first DirectionalLight / SkyLight / Fog / PostProcessVolume found in the level, overwrote its settings and renamed it. Environment dressing is now plugin-owned, tagged, transient in editor worlds, and removed by `IOC.ClearShowcase`.
- **`IOC.CaptureWizardPreset`** — an authoring screenshot tool that spawns actors into the open level, moves the viewport and can quit the editor — is now registered only when the editor is launched with `-IOCDevTools`, and its retry ticker is removed on module shutdown.
- **Setup wizard rollback snapshot** held bare `UObject*` references on a Slate widget. `SIOCSetupWizard` is now an `FGCObject` and reports them; the referenced fields use `TObjectPtr`.
- **Authoring Python scripts shipped with absolute paths from the author’s machine** (including a user-profile path). Paths are now relative or environment-driven, logging goes to the Output Log.
- `AIOCCharacter` no longer teleports to an arbitrary cave on `BeginPlay`: the snap is an exposed, documented option, picks the nearest cave, honours spline mode, and runs on the authority only. Input modifiers use `CreateDefaultSubobject` instead of `NewObject` during construction.
- Property edits that cannot affect geometry (bake options, debug toggles, LOD switch distance, runtime-carve limits) no longer trigger a full regeneration.
- Runtime carves within a frame are coalesced into a single rebuild instead of one full revoxelisation each.
- `bShowDebugViz` gizmos persist while the box is ticked. They were issued once from `OnConstruction` into the transient line batcher, which expires them after about a second.
- `UIOCVoxelCoreSettings` exposes `MaxVoxelCount` instead of a hard-coded 15M ceiling.

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [September 22, 2026, 6:15pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/7 "2026-09-22T18:15:48Z")

</div>

## [0.4.1] update, 2026-09-23 🌋

### 🌟 At a glance

- 🔄 **Cave meshes face into the cave.** Collision, scatter and lighting now match the surface you see.
- 🗺 **Interactive tour** : six feature zones on one walkable route, then a portal to an endless  
streamed tunnel. Ships as a map.
- ⛏ **Player carving** : `AIOCCharacter` can carve the cave under its crosshair (opt-in).
- 🌫 **Biome blending** : `AIOCBiomeVolume::BlendDistance` eases a volume’s overrides in rather  
than switching them at its face.
- 🐛 **Fixes** : capsule carves, spline bends, carve falloff, runtime biome volumes,  
biome ledges, streaming placement and stalactites.
- 📘 **Illustrated demo guide** : `Resources/Docs/DemoGuide.html`, with a frame from every zone.
- 🧪 **35 automation tests** , up from 22.

**✅ Verified** : automation suite **35/35 green on UE 5.8 and on the 5.5 floor** , 0 ensures; every  
new test negative-tested. `BuildPlugin` unity and strict passes succeed with zero warnings on 5.5,  
5.6, 5.7 and 5.8, and all packages pass the isolated-build validator. The shipped tour map (262 m in 53 s) starts cleanly in a standalone `-game` run.

### 💥 Upgrading from 0.4.0 — behaviour changes

- 🔄 **Every cave looks and behaves differently.** Surfaces face into the cave, so lighting,  
collision from inside a cave and scatter placement all change.
- 🦷 **Stalactites now grow along +Z from their base.** Scatter layers that place `SM_IOC_Stalactite`  
need **Align To Normal** on; with it off, stalactites now point up.
- 💊 **Capsule carving components carve a capsule.** They used to carve everything within the  
capsule’s length inside the carve pass’s bounds: a box on their own, and the whole region when  
beside a larger carve. Caves that use capsule carves change shape.
- ⛏ **A carve never puts rock back.** Where carve falloffs overlap, the strongest carve now wins,  
so caves with overlapping falloffs come out slightly more open.
- 🧵 **Spline tunnels are sealed on the outside of every bend.** Tunnels whose bends showed slits  
to the outside are now closed.
- 📍 **`AIOCStreamingManager` builds where it is placed.** It always used the world origin; a  
manager placed elsewhere now builds its caves around its own location.

### 🔄 Fixed

- **Vertex normals now agree with the winding.** They pointed at the air while the winding did not,  
and two-sided shading flips the normal on back faces, so surfaces were lit from behind.
- **The smart-material ceiling mask was inverted.** `SmoothStep(-0.6, -0.85, Up)` has its bounds  
reversed and returned 1 for every surface above -0.6, so `M_IOC_SmartCave` painted the ceiling  
colour on floors and walls. It now mirrors the floor test.

### 🗺 Added — the interactive tour

- **Six zones, one route, ~264 m.** _The Mouth_ (a drop-in cave actor on a preset), _The Winding Run_  
(a spline tunnel that a biome volume flares open), _Crystal Gallery_ (a carved hall dressed by  
scatter layers), _Alien Hive_ (domain warp), _Strata Canyon_ (terraces switched on by a second  
biome volume) and _The Forge_ (a hall shaped by sphere, box and capsule carving components, and the  
one cave the player may carve). A glowing crystal by the Forge’s far wall leads to _Infinite  
Depths_, where an `AIOCStreamingManager` builds cave around the walking player.
- **Built from four cave actors** : two tunnels and two solid-block chambers whose rooms are carved,  
joined tunnel to chamber through carved passages sized from the tunnel mouths measured after they  
generate. Walkable about a second after spawning; no window to the outside anywhere along the  
route except the entrance.
- **A caption per zone** on first entry (what the feature is, how to use it, live generation  
numbers), and a “Generating caves…” caption while it builds.
- **Carve the Forge yourself** : left mouse / right trigger with the crosshair on the rock.
- **Ships as a map** : `/InstantOrganicCaves/Maps/IOC_InteractiveDemo` (authored on UE 5.5; a launcher  
in Interactive mode and a PlayerStart), opened from **Tools \> Instant Organic Caves \> Open  
Interactive Demo **or the Setup Wizard’s** Open Interactive Demo** button. Also  
`FInstantOrganicCavesModule::SpawnInteractiveTour`, the console command `IOC.SpawnInteractiveTour`  
and a **Spawn Interactive Tour** menu entry.
- **`AIOCShowcaseLauncher` Interactive Demo mode** (`bInteractiveMode`, **Start Interactive Demo** )  
runs the tour at the launcher’s location instead of the flythrough.
- **`IOC.TourAutopilot`** walks the tour on its own – the route, a carve in the Forge, the portal and  
the depths – for recording and kiosks (`-IOCTourAutopilot`, `-IOCTourAutopilotQuit`,  
`-IOCTourNoCaptions`). Zone entries log their engine frame, for timing titles on a frame dump.
- **The caption overlay is shared** by the showcase and the tour, and no longer takes mouse input.

### 🐛 Fixed

- **Biome volumes left a ledge.** Overrides switched at the volume’s face, leaving a step in a tunnel  
floor wherever the radius changed – 186 cm in the test case. `BlendDistance` eases them in; 45 cm  
with a 10 m blend. The default, 0, keeps the old switch.
- **Capsule carves cut a slab.** The capsule distance took the closest axis point as  
`(x, y, clamped z)`, dropping the radial term, so everything within the capsule’s length read as  
inside. The carve pass visits the union of all carves’ bounds, so a capsule beside any larger carve  
hollowed out that whole region – the showcase’s Carved Chamber included, which now has its proper  
shape.
- **Spline tunnels had slits on the outside of every bend.** A voxel beyond the end of one spline  
segment and before the start of the next counted as “past the tunnel’s open end” and was dropped,  
cutting a wedge through the wall wherever the spline turned. Only a spline’s true first and last  
segments are open now. Measured on the tour’s tunnel: 228 rays escaped around one bend before, 0 after.
- **Adding a carve could add rock.** In a falloff band the carve probability came from the nearest  
carve rather than the strongest, so a new carve’s weak outer band could undo a stronger carve’s  
work. A click in the Forge grew a wall 1.7 m in front of where the player aimed. The pass now takes  
the strongest carve, so carving only ever removes rock.
- **Scattered stalactites grew into the ceiling.** See Content below.
- **The walking lane is checked, not assumed.** The demo traces the floor every metre (highest rock  
under each 1 m x 2.1 m footprint), sweeps the character’s capsule along the lane, carves a corridor  
with `CarveAtLocation` wherever rock intrudes, removes scatter props reaching into it (they have no  
collision), then lays one-metre slabs that follow the floor. The same lane runs through every cave  
of the tour and through `IOC.SpawnSpectacular`.
- **The freeze while the cave generates now holds.** `Possess()` runs `Restart()`, which reset the  
movement mode and undid the freeze. Possession now happens first.
- **`IOC.SpawnSpectacular` got a lighting pass** : staged warm-key / cool-fill / violet-rim lighting  
in physical units, a SkyAtmosphere for the real-time SkyLight, and limestone / alien-rock surfaces.
- `AIOCCharacter` forces an Enhanced Input component, so it works in host projects still configured  
for the legacy input component.

### ✨ Added — API

- ⛏ **`AIOCCharacter` carving, opt-in** : `bEnableCaveCarving` (off by default),  
`SetCaveCarvingEnabled`, `CarveAtAim`, `CarveRadius`, `CarveReach`, and `PlayerCarvableTag`  
(`IOC_PlayerCarvable`). Only caves with that tag accept the player’s carves. The carve keys live in  
their own mapping context, installed only while carving is on, so a project’s own use of the left  
mouse button is untouched.
- 🌫 **`AIOCBiomeVolume`** : `BlendDistance`, `bUseBoxExtent`, `BoxExtent`.
- 🗺 **`FInstantOrganicCavesModule`** : `SpawnInteractiveTour(World, Origin)`, and  
`GetShownCaptionTitle` for tests and tools.
- ⌨ **Console** : `IOC.SpawnInteractiveTour`, `IOC.TourAutopilot`.

### 🪨 Content

- **`SM_IOC_Stalactite` re-authored to grow from its base along +Z** , like `SM_IOC_Stalagmite`.  
Scatter aligns +Z to the surface normal, which points into the cave – down, on a ceiling – so the  
normal is what hangs it. Authored tip-down with its pivot on top, it only suited the inside-out  
mesh; with correct normals every stalactite on a ceiling pointed up into the rock and vanished.  
Regenerated on UE 5.5 from its seed; the other seven meshes are unchanged.
- **New map `IOC_InteractiveDemo`** , authored on UE 5.5.
- **Poisson spacing packs a surface.** Worth knowing when tuning scatter: with  
`PoissonMinSeparation` set, the scatter throws 30x the candidates and keeps every one far enough  
apart, so the result approaches the spacing limit whatever `Density` says. The tour uses density  
alone.

### 📚 Documentation

- 📘 **New `Resources/Docs/DemoGuide.html`** , replacing `IOC_DEMO_GUIDE.md`: the tour zone by zone,  
illustrated with frames from the game, plus its controls, console commands, how to record it and a  
presenter’s script. Its images are inlined, so it works opened from disk.
- 🎓 **Tutorial** : the two demo levels, the tour’s zones and controls, `IOC.SpawnInteractiveTour`,  
biome blending, player carving, stalactite pivots and Poisson spacing, and two new  
troubleshooting entries.
- 📖 **Manual** : supported engines 5.5-5.8, the Tools menu, the wizard’s and launcher’s interactive  
entries, streaming placement, the new biome properties, carve falloff, a Player Carving section,  
decoration pivots and spacing, the new console commands and API.
- All three pages link to each other.

### 🧪 Tests — 35, up from 22

- **Mesh orientation** : `Cave.NormalOrientation` – from inside a tunnel, the floor faces up, the  
ceiling faces down, physics hits the floor the mesh shows, vertex normals agree with the winding,  
and floors and ceilings carry the right smart-colour masks. Against the inside-out mesh all three  
facing checks fail.
- **Generator defects** : `Carving.CapsuleShape`, `Carving.NeverAddsRock`, `Cave.SplineBendSealed`,  
`Cave.BiomeBlend`, `Cave.BiomeVolumeBox`, `Content.ScatterFacesIntoCave`, and a placement check in  
`Production.StreamingCarvePersistence`.
- **The tour** : `Demo.InteractiveLaneInBore` (the walkway on the cave floor at 12 stations across  
all six zones, a route of at least 200 m, nothing left behind by `IOC.ClearAllDemos`),  
`Demo.InteractiveRouteSealed` (from head height over the walkway, no ray sideways or upward reaches  
the void except out of the entrance), `Demo.InteractiveCarving` (a click at a Forge wall carves the  
Forge only and digs into the wall; a click in Tunnel B carves nothing), `Demo.InteractiveStreaming`  
(the portal puts the player on a streamed floor, inside the tunnel, able to walk) and  
`Demo.InteractiveBudget` (walkable within 4 s; measured 0.7 s).
- **Real input** : `Demo.InteractiveInput` sends a real key event through Slate into the focused game  
viewport in PIE (one layer down under `-NullRHI`, where the viewport has no size and drops keys),  
walks the whole tour and requires every zone caption in route order.
- **Coverage** : `Demo.DemoMap` covers both shipped maps; `SetupWizard.SafetyAndValidation` and  
`ButtonSweep` cover the new command, map and button. `Demo.ShowcaseLifecycle` no longer fails inside  
a level with its own `IOC_`-labelled actors.
- Every new test was negative-tested: broken on purpose, observed to fail, then restored.

### ⚠ Known

- `AIOCCharacter` has no mesh: the third-person camera follows an invisible capsule. For now, this is intentional.
- Runtime carving still re-meshes the whole actor per carve (unchanged from 0.4.0).
- `SetupWizard.Layout` still checks how the wrap boxes are built, not their laid-out width (see 0.4.0).

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [September 22, 2026, 6:18pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/8 "2026-09-22T18:18:54Z")

</div>

Basic procedural walkthrough of the 0.4.1 interactive demo:

[![](https://d3kjluh73b9h9o.cloudfront.net/original/4X/5/a/e/5aea24a530394640b0bb9470a254f00000b3f209.jpeg "Instant Organic Caves: Procedural Cavern & Rock Structure Generation for Unreal (UE5.5 - 5.8, 2026)") ](https://www.youtube.com/watch?v=lla2aHqhH6U)

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [September 23, 2026, 9:30am UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/9 "2026-09-23T09:30:10Z")

</div>

Another interactive 0.4.1 demo:

[![](https://d3kjluh73b9h9o.cloudfront.net/original/4X/0/3/9/0399bf3970c5165eec40087437bd5840ba80d10c.jpeg "Instant Organic Caves: Procedural Cavern & Rock Structure Generation for Unreal (UE5.5 - 5.8, 2026)") ](https://www.youtube.com/watch?v=zgr4bcv4Qys)

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [September 29, 2026, 5:50pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/10 "2026-09-29T17:50:05Z")

</div>

A comprehensive tutorial video is now available:

https://www.youtube.com/embed/-f1CXbGEsJc?feature=oembed&wmode=opaque

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [September 29, 2026, 6:46pm UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/11 "2026-09-29T18:46:46Z")

</div>

## [0.4.5] update, 2026-10-01 🗻

**🕯 A dark level, in its own rock — and every surface rebuilt at 2K.** _The Warren_ is a second  
playable demo: 346 m of tight, organic burrow walked by flashlight, with scripted moments, a rock plug  
you carve through, and a hollow beyond it open to the daylight. Each of its six beats wears its own  
rock, drawn by a new world-aligned material you can put on any cave. Around it, every texture and prop  
in the plugin was rebuilt: ten 2048² rock sets drawn world-aligned, and thirteen props modelled and  
baked in Blender with real UVs. The setup wizard lost seven rough edges on the way. The release after  
0.4.1 is numbered 0.4.5; there was no public 0.4.2 to 0.4.4.

### 🌟 At a glance

- 🕯 **The Warren** — six beats, ~346 m, lit only by the character’s flashlight. Ships as  
`/InstantOrganicCaves/Maps/IOC_DarkDemo`.
- 🪨 **Six rock sets, one per beat** — flesh-rock, mycelium, rusted shale, calcified bone,  
weeping stone and fractured basalt.
- 🧱 **`M_IOC_WarrenRock`** — a world-aligned rock material: no UV streaks, real surface relief  
under a torch, usable on any cave.
- 🕳 **Organic Warren preset** — a tight, heavily warped bore: a burrow rather than a bore hole.
- 🦴 **Five new props** — roots, a fungal shelf, an egg sac, a bone pile and a membrane, plus a wet  
organic material and a glowing fungus one.
- ⛏ **Carve to continue** — the level dead-ends in rock; carve through it and walk on into the  
Hollow.
- 🎬 **`IOC.WarrenAutopilot`** — walks the whole level by itself, for recording and kiosks.
- 🖼 **2K rock, world-aligned** — obsidian, limestone, alien, cave floor and the six Warren sets are  
2048², and the default cave skin (`MI_IOC_CaveWalls`) now draws them world-aligned too: no UV  
streaks, real relief in the normal map, glowing veins on the alien set.
- 🪨 **Thirteen props, rebuilt in Blender** — sculpted, UV-unwrapped, baked onto three 2048² atlases  
(rock, crystal, organic), two LODs and convex collision each.
- 🧙 **A better-mannered setup wizard** — it keeps the lights already in your level, stays in front  
of the editor, says “Setup Complete” without contradicting itself, shows every preset name in  
full, and keeps its banner’s title at any window size.
- 📱 **Platforms: Win64, Linux and Android.** The modules’ `PlatformAllowList` is now  
`[Win64, Linux, Android]` (it was `[Win64, Mac, Linux]`), and all three are compiled for every  
supported engine before release.
- 🧪 **49 automation tests** , up from 35.

**✅ Verified** : automation suite **49/49 green on UE 5.5, 5.6, 5.7 and 5.8** , each built from a clean  
copy of the plugin in a content-free host (PluginTestMatrix), and 0 ensures in the 5.8 and 5.5-floor  
runs of the dev project. The  
Warren’s tests and the four new wizard tests were negative-tested, as was the budget-message check;  
`SetupWizard.OwnedByEditor` and `SetupWizard.LiveLayout` were run in a rendering editor, where a  
headless suite skips them. The  
Warren’s own autopilot walks it end to end — through the carved plug and across the Hollow — in a  
standalone `-game` run. All new and rebuilt content is authored on UE 5.5.

### 💥 Upgrading from 0.4.1

- 🎨 **Caves using the default material look different.** `MI_IOC_CaveWalls` (parent  
`M_IOC_MathRock`) is now world-aligned, so the cave’s UVs and `TextureTiling` no longer place its  
texture: use the material’s **`TileSize`** (world cm per repeat) instead. `CaveStyleTexture` and the  
**Use PBR Texture** switch keep their names; set **`CaveStyleNormal`** to the style’s `_N` map when you  
change styles.
- 🎨 **`M_IOC_SmartCave` is textured.** `Color_Wall`, `Color_Floor` and `Color_Ceiling` are now tints  
over the wall and floor textures (neutral by default) rather than flat colours, `Roughness` multiplies  
the maps, and it blends by world normal, so it no longer needs `bGenerateSmartColors`. Instances that  
set strong colours will tint the rock rather than replace it.
- 🪨 **The thirteen props were replaced in place** — same names and paths, so scatter layers, PCG graphs  
and placed actors keep working, but the geometry is new and each mesh has one material slot. If you  
overrode a prop’s material, check it still lands where you want.
- 🧙 **The wizard’s _Set up lighting_ no longer duplicates your lights.** It adds only the directional  
light, sky light, height fog and unbound post-process volume the level lacks.
- 🖥 **Mac is no longer listed.** The modules’ `PlatformAllowList` is `[Win64, Linux, Android]`, so the  
plugin does not load in a Mac editor or build for Mac.
- 📦 **The package is larger** : plugin content grows from about 27 MB to about 209 MB, almost all of it  
the 2048² textures (normal maps are stored uncompressed-quality BC5 at 9–13 MB each).

### 🕯 Added — the Warren, the dark demo level

- 🧭 **Six beats, one descent, ~346 m.** _The Gullet_ (a tight warped crawl with membranes strung  
across it), _The Nest_ (five overlapping sphere carves — pods, not a room — with egg sacs, roots  
and a glowing fungus cluster), _The Throat_ (tighter and steeper; the roof comes down behind you),  
_The Bone Garden_ (a low hall of columns and bone piles, with a light that dies as you approach),  
_The Weep_ (the narrowest run, where an alcove opens behind you) and _The Hollow_ (reached only by  
carving through a rock plug, ending at a crack of daylight).
- 🏗 **Built from six cave actors** : three tight spline tunnels and three solid blocks whose rooms  
are carve components, joined tunnel to block through passages sized from the tunnels’ measured  
mouths — the same join recipe as the interactive tour.
- 🔦 **Lit by the flashlight.** The level places four lights in 346 m: the fungus, the dying lamp,  
a rim on the Hollow’s far wall and the daylight crack. Sun and sky are turned down to almost  
nothing.
- 🎭 **Scripted moments, no creature.** A collapse that drops rubble behind you with a stutter of  
the flashlight, a light that goes out as you close on it, and a side alcove that opens in rock  
you have already walked past. Each is a carve or a prop, placed against its own trigger point, so  
nothing can land in front of you.
- ⛏ **Carve to continue.** The level ends in solid rock, and only that cave accepts your carves.  
Carve through the plug and a walkway is laid beyond it, joined to the one you arrived on, into the  
Hollow and on towards the daylight.
- 🗺 **Ships as a map** : `/InstantOrganicCaves/Maps/IOC_DarkDemo` (authored on UE 5.5), opened  
from **Tools ▸ Instant Organic Caves ▸ Open Dark Demo** or the Setup Wizard’s **Open Dark Demo**  
button. Also `FInstantOrganicCavesModule::SpawnDarkWarren`, the console command  
`IOC.SpawnDarkWarren`, a **Spawn Dark Warren** menu entry, and `AIOCShowcaseLauncher`’s new  
**Dark Warren** mode.
- 🎬 **`IOC.WarrenAutopilot`** walks the level on its own — the route, the scripted moments,  
carving the plug and out across the Hollow (`-IOCWarrenAutopilot`, `-IOCWarrenAutopilotQuit`,  
`-IOCWarrenNoCaptions`). Beats and events log their engine frame, for timing a recording.

### 🪨 Added — the Warren’s own rock

Each beat wears a rock of its own, so every stretch of the descent looks like a different place:

- 🫀 **Gullet** — wet, folded, flesh-toned rock, glossy in the creases.
- 🍄 **Nest** — dark stone laced with pale fungal threads and flecked with spores.
- 🟤 **Throat** — cracked shale with rust weeping from the cracks.
- 🦴 **Bone Garden** — pale, pitted, calcified stone the colour of old bone.
- 💧 **Weep** — dark wet stone with teal and white mineral seeps that glisten under the torch.
- 🌋 **Hollow** — fractured basalt, with lichen where the daylight reaches.
- 🎨 Each set is a colour map with roughness in its alpha plus a normal map, 2048², in  
`Textures/Warren/` (`T_Warren_<Beat>_D` / `_N`). They are generated from fixed seeds, so they tile  
without seams.
- 🧱 **`M_IOC_WarrenRock`** draws them **world-aligned** (triplanar): colour, roughness and normals  
are projected in world space, ignoring the cave’s UVs, so nothing smears where the UV projection  
changes and the torch finds real relief in the rock. Parameters: `RockColour`, `RockNormal`,  
`TileSize` (world cm per repeat), `RoughnessScale`, `FloorWetness` (below 1, up-facing surfaces  
read wetter) and `NormalStrength`.
- 🔁 **Use it on your own caves** : set `CaveMaterial` to an instance of it with any of the six sets  
(see the Manual’s _Warren Rock_). The Warren falls back to the shared rock textures if the set is  
missing, so it never renders untextured.

### ✨ Added — preset and API

- 🕳 **`EIOCCavePreset::Warren` (“Organic Warren”)**: `TunnelRadius` 350, `WallThickness` 70,  
`NoiseFrequency` 0.009, `VoxelSize` 25, `DomainWarpIntensity` 260. Like Tight Crawlspace it is a  
shape, not a promise a character fits; the demo opens its own tunnels up for walking.
- 🔌 **`FInstantOrganicCavesModule::SpawnDarkWarren(World, Origin)`**, and `GetDarkWarrenPlug` for  
tests and tools.
- 🚀 **`AIOCShowcaseLauncher::bDarkWarrenMode` / `StartDarkWarren()`**.

### 📦 Content

- 🦴 **Five new generated props** , seeded and reproducible like the other eight:  
`SM_IOC_Root_A`, `SM_IOC_FungalShelf`, `SM_IOC_EggSac`, `SM_IOC_BonePile`, `SM_IOC_Membrane`.  
Thirteen props ship now.
- 🟢 **`M_IOC_Organic`** with `BaseColor`, `Roughness` and `EmissiveColor` parameters — the first  
shipped material to expose emissive — plus `MI_IOC_Organic` (wet) and `MI_IOC_Fungus` (glowing).
- 🪨 **Twelve rock textures and `M_IOC_WarrenRock`** (above).
- 🧊 Both new base materials are two-sided and flagged for instanced static meshes, like every  
other shipped material.
- ✅ All new and rebuilt assets, the map included, were authored on the UE 5.5 floor. 61 content  
assets ship (46 in 0.4.1’s count plus the 2K rework below).

### 🖼 Changed — every texture and prop, rebuilt at 2K

- 🪨 **Four shared rock sets at 2048²** : `T_RockObsidian`, `T_RockLimestone`, `T_RockAlien` and  
`T_CaveFloor`, each a colour map with roughness in alpha plus a `_N` normal map. Obsidian is glassy  
scalloped fracture with knife-edge ridges, limestone pale water-worn stone, alien dark bioporous  
stone with veins, and the floor packed grit and pebbles. The six Warren sets are 2048² as well.
- 🧱 **`M_IOC_MathRock` is world-aligned.** The default cave skin (`MI_IOC_CaveWalls`) projects its  
texture in world space like `M_IOC_WarrenRock`, so it never streaks where the generator’s UV  
projection changes axis, and it finally has a normal map. New parameters: `CaveStyleNormal`,  
`TileSize`, `ProjectionContrast`, `NormalStrength`, `RoughnessScale`, `Tint`, `VeinGlow` and  
`VeinGlowColour` (the alien set’s veins glow). With **Use PBR Texture** off it is still the  
zero-texture rock, now with a gentler bump that no longer tips whole patches away from the light.
- 🧩 **`M_IOC_SmartCave` is textured** : a wall set and a floor set blended by world normal, tinted by  
its three colours (see _Upgrading_).
- 🪨 **Thirteen props, modelled in Blender.** Each prop is a fixed-seed sculpt, decimated to a game  
mesh with real UVs, with a lighter LOD1 and convex collision. The props bake onto three shared  
2048² atlases — rock, crystal, organic — with colour, roughness, normal and emissive, drawn by one  
new master, `Materials/M_IOC_Prop` (`Tint`, `RoughnessScale`, `EmissiveColour`,  
`EmissiveStrength`, `RimGlow`). `MI_IOC_PropRock` is new; `MI_IOC_Crystal`, `MI_IOC_Organic` and  
`MI_IOC_Fungus` now derive from it. Crystals glow at their rims and the fungus shelves glow.
- 🔁 **Regenerable from source** : the textures come from `Resources/GenerateRockTextures.py` and the  
props from `Resources/Blender/GenerateScatterProps.py` (Blender 5.2) plus  
`Resources/ImportScatterProps.py`. None of these scripts ship.

### 🧙 Fixed — the setup wizard

- 💡 **It no longer puts a second sun in a lit level.** _Set up lighting_ always spawned a  
directional light, sky light, height fog and post-process volume, and the UE Basic template already  
has the first three. The first Generate in a new level left two suns fighting over the sky (UE  
prints a warning over the viewport) and doubled the fog. It now adds only what the level lacks and  
logs what it kept.
- 🪟 **It stays in front of the editor.** It was an unowned window, so the moment the editor took  
focus it drew over the wizard, and Generate Cave focuses the editor by selecting the new cave. The  
Finish page, with **Undo Added Actors** , vanished behind the level editor exactly when it was  
needed. The wizard is now owned by the editor’s main window.
- ✅ **The Finish page says what happened.** A successful setup read “Setup Complete” over “No cave was  
generated yet”, above the new cave’s statistics.
- 🏷 **Preset names are no longer cut off.** At the wizard’s default size every style card clipped  
its name (“[A] Larg”), its description and its spec line: an empty spacer took half of each title  
row, and the description wrapped at a fixed 250 px on a card about 170 px wide. Everything on a  
card now wraps to the card.
- 🖼 **The banner keeps its title when the wizard is widened.** Its art was cropped into a fixed  
196 px box, so a wider window scaled the art up and cropped the title away. The banner’s height now  
follows its width, showing the same slice of the art at any size.
- 🏁 **After Undo Added Actors, the Finish page stops describing the undone setup.** Its “Spawned new  
cave actor” and “LOD generated” badges stayed under “Setup Not Run”; they now show only while a  
setup is running or done.
- 🐍 **The validation report no longer mentions Python helpers that don’t ship.** It said Python was  
“enabled for optional Resources/\*.py automation helpers”; those are authoring scripts excluded from  
the package, and the plugin needs no Python.
- 🧹 **“Reconfigure an existing cave actor” is no longer restored from an earlier session.** It names  
an entry in that session’s cave list, so restored it made Generate fail with “the selected cave  
actor is no longer available”. And the automation tests no longer save their own wizard settings  
over yours.

### 🐛 Fixed — generation errors

- 💬 **`LastGenerationError` names the budget that stopped a cave.** A generation refused by  
`MaxVoxelCount` or `MaxGeneratedTriangles` reported the generic “Generation produced no surface…”;  
it now carries the same message the log does (“Voxel grid budget exceeded (…)”).

### 🐛 Fixed

- 🎯 **A scripted event could fire where the player stands rather than where it belongs.** The  
collapse placed its rubble relative to the player’s position at the moment it triggered, so a  
player who covered ground in one step — a teleport, a hitch — could have it land in front of  
them, or on them. Events now place themselves against their own trigger point.
- 🪜 **Carves that sank below a chamber’s floor left steps nobody could climb.** Sphere and capsule  
carves centred less than their own radius above the floor scoop pits through it; the walkway  
followed them down and back up, leaving a 96 cm step — a character climbs 45 cm. Every round  
carve in the level now sits tangent to its floor, and `Demo.WarrenLaneInBore` measures the  
tallest step on the walkway.

### 🔧 Changed

- 🔗 The interactive tour and the Warren now share their cave-building helpers  
(`IOCDemo::MakeRockMaterial`, `AddScatterLayer`, `AddCarveComponent`, `SplinePointAt`,  
`MeasureFloorBelow`) rather than keeping two copies.

### 📚 Documentation

- 📘 **The demo guide covers both levels** : a new _The Warren, beat by beat_ section with a frame  
from each beat, and the new commands in its command table.
- 🎓 **Tutorial** : a third demo card, the Organic Warren preset in the preset explorer with its real  
values, and `IOC.SpawnDarkWarren` in the console list.
- 📖 **Manual** : the preset table, the new console commands, the wizard’s new button, and a  
_Warren Rock (world-aligned)_ section on using the new material. The material pipeline is rewritten  
for the world-aligned `M_IOC_MathRock` and the textured `M_IOC_SmartCave`, the scatter section lists  
all thirteen props and their atlases, and the wizard’s Environment step says it keeps your lights.
- 🎓 **Tutorial** : the scatter section lists the organic props as well as the mineral ones.

### 🧪 Tests — 49, up from 35

- 🛤 `Demo.WarrenLaneInBore` — six beats tile a route of at least 280 m, the walkway lies on the  
cave floor at twelve stations, no step along it is taller than a character can climb, and  
`IOC.ClearAllDemos` leaves nothing behind.
- 🔒 `Demo.WarrenRouteSealed` — from head height over the walkway, no ray reaches the void except  
out of the entrance.
- 🎭 `Demo.WarrenBeats` — each scripted moment fires once, in route order; the way forward is as  
clear after the collapse as before it; the dying light ends at zero; the alcove opens behind its  
trigger.
- ⛏ `Demo.WarrenPlug` (PIE) — a click at the plug carves the Hollow, carving through opens a  
character-sized way on, no other cave in the level accepts a carve, and a character **walks**  
from the end of the walkway through the carved plug and 5 m beyond, with real movement input.
- 🌑 `Demo.WarrenDarkness` — at most four placed lights, none of them a key light, sun and sky  
turned down, and the character’s flashlight lit.
- 🪨 `Demo.WarrenRock` — each of the six caves renders its own rock set through `M_IOC_WarrenRock`;  
colour maps are sRGB with roughness in alpha, normal maps are linear normal maps.
- ⏱ `Demo.WarrenBudget` — walkable within 3 s (measured 0.6 s).
- 🕳 `Cave.PresetWarren` — the preset is tighter and more warped than the wide default, with a  
voxel fine enough to resolve it.
- 🪨 `Content.RockStyles` — every shared rock style is a 2048² pair (sRGB colour that keeps its  
roughness alpha, and a normal map that is not sRGB); both cave materials take world-space normals  
and expose their style parameters; `MI_IOC_CaveWalls` wears obsidian with its normal map; and a  
style swap moves the normal map with the colour.
- 🗺 `Content.PropAtlases` — the three prop atlases are 2048² with the same colour/normal rules, and  
every prop is UV-mapped into its atlas and wears an `M_IOC_Prop` instance sampling its family’s maps.
- 💡 `SetupWizard.KeepsLevelLighting` — in a lit level, _Set up lighting_ adds no second directional  
light, sky light or fog, and a test run leaves your saved wizard settings untouched.
- 🪟 `SetupWizard.OwnedByEditor` — the wizard window is a child of the editor’s main window (needs a  
rendering editor; skipped in a headless run).
- ✅ `SetupWizard.FinishMessage` — after setup the Finish page does not also say no cave was generated,  
and with no setup done (never run, or undone) no badge describes one.
- 📐 `SetupWizard.LiveLayout` — opens the real wizard window and measures what the editor drew: at the  
default size no text on a style card is narrower than it needs, and widened, the banner keeps its  
height-to-width ratio (needs a rendering editor; skipped in a headless run).
- ➕ Extended: `Production.GenerationBudget` checks that the refusal names the voxel budget;  
`Demo.DemoMap` covers three shipped maps, `Content.ScatterMeshLibrary` thirteen  
props, `Content.MaterialRenderFlags` both new materials, `Content.ShippedDocumentation` the  
guide’s new section, and the wizard’s sweeps the new command, map and button.

---

<div class="post-metadata">

**Author:** ![andgregori](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/andgregori/32/1148407_2.png) [@andgregori](https://forums.unrealengine.com/u/andgregori)\
**Post date:** [October 23, 2026, 8:51am UTC](https://forums.unrealengine.com/t/gregorigin-instant-organic-caves-lightweight-procedural-runtime-structure-generator/2691206/12 "2026-10-23T08:51:47Z")

</div>

## [0.5.0] update, 2026-10-25

**🦶 Floors you can walk at any frame rate, and dressing that stays where it is.** A cave’s floor is  
now smoothed harder than its walls, which fixes the one open defect from 0.4.5: at 120 frames a second  
and above, a Character stuck on the first floor step it met. Scatter props are now placed per  
triangle, so a runtime carve re-dresses only the rock it changed instead of reshuffling the whole cave,  
and a path you keep clear of props stays clear through every rebuild. The IOC Voxel Core PCG node now  
does what the Manual always said it did — points on the rock’s surface, facing the air. The setup  
wizard offers the sixth preset, the props lost their wet look, streamed tunnels lost a crack at every  
chunk seam, and tunnel generation takes about 40% less time.

### 🌟 At a glance

- 🦶 **Walkable floors at any frame rate** — `WalkableFloorSmoothing` (default 8) gives up-facing  
surface extra smoothing passes. Floor area too steep to walk on drops from about 30% to about 1%.
- 🪨 **A carve re-dresses only the rock it changed** — every other prop in the cave stays exactly  
where it was.
- 🚧 **Paths stay clear** — `ScatterExclusions`, `AddScatterExclusionPath()` and  
`bScatterOnRuntimeCarves` keep props out of a corridor, or out of a fresh hole, through every rebuild.
- 🌱 **PCG node on the surface** — Surface Only points, turned to face the air, with an optional  
surface offset, exposure as density, per-point seeds, and noise that no longer repeats.
- 🧙 **Organic Warren in the setup wizard** , with its own dressing, dark lighting and cost estimate;  
four layout fixes; two presets’ cost estimates corrected.
- ⚡ **Faster tunnels** — mesh building, attribute overlays and hole filling reworked or run in  
parallel: about 40% off a tunnel’s generation at 25 cm voxels.
- 🎨 **Props without the wet look** — rock props bake the roughness they were meant to have, and no  
longer darken where a neighbouring prop sat during the bake.
- 🛡 **A cave too big for collision says so** , instead of letting the player fall through it.
- 🧩 **No crack at streamed tunnel seams** — a slot up to 2.5 m deep across the floor at every  
chunk seam is closed.
- 🕳 **Demo fixes** — the Warren’s walkway is clear of rock, the tour’s portal is entered by walking  
off the end of the walkway, and pruned props no longer come back after a carve.
- 🧪 **56 automation tests** , up from 49.

**✅ Verified** : automation suite **56/56 green on UE 5.5, 5.6, 5.7 and 5.8** , each built from a clean  
copy of the plugin in a content-free host (PluginTestMatrix; the 5.8 leg was built by hand with  
`-NoHotReloadFromIDE` because a 5.8 editor was open), 0 ensures on every engine. The plugin also builds  
for Linux and Android, Development and Shipping, on 5.5 and 5.8. Every new test and check was  
negative-tested; `SetupWizard.OwnedByEditor` and `SetupWizard.LiveLayout` were run in a rendering  
editor. The re-imported props and the renamed PCG instance were saved on UE 5.5.

### 💥 Upgrading from 0.4.5

- 🦶 **Floors are smoother.** Caves regenerate with `WalkableFloorSmoothing` = 8: floors keep their  
shape but lose the one-voxel steps. Set it to `0` (actor, or `AIOCStreamingManager`) for the old  
floors. Generation costs about 2–3 ms more on a mid-size tunnel.
- 🪨 **Every cave’s dressing is laid out afresh** — same layers, same density, different (and now  
stable) positions. Per-layer counts can differ by a few props from 0.4.5, since fractional counts  
now round per triangle.
- 🌱 **IOC Voxel Core outputs Surface Only, rotated to the surface.** Existing graphs pick this up.  
Set `PointMode` to **All Solid** and turn off `bAlignPointsToSurface` for the old output. Its  
Perlin Tunnel and Infinite modes now sample the cave actor’s noise, so their fields change.
- 🔀 **`NewPCGGraphInstance` is now `IOC_GraphInstance_Master`** (no redirector is shipped; nothing in  
the plugin referenced it). Re-point anything of yours that used it.
- 🌐 **New replicated properties** on `AIOCProceduralActor`: `WalkableFloorSmoothing`,  
`ScatterExclusions`, `bScatterOnRuntimeCarves`. Server and clients must run the same plugin version.
- 🧙 **Wizard settings migrate themselves.** Custom moved from index 5 to 6 to make room for Organic  
Warren; a saved Custom selection is carried across.

### 🦶 Fixed — Characters sticking on cave floors at high frame rates

- 🐌 **At 120 ticks a second and above, the player stuck on the first floor step.** After 2–3  
smoothing passes, a one-voxel step in the floor is still a 45–62° ramp: steeper than a Character’s  
walkable angle, so only a step-up crosses it. The step-up probe is one tick of movement — under  
2 cm at 240 Hz — so it landed back on the ramp, the step was undone, and the character stood still  
with W held. 30 and 60 ticks/s walked through. Found in 0.4.5’s Infinite Depths, 0.4 m from the  
portal; any IOC floor could do it.
- 🔧 **`WalkableFloorSmoothing`** (IOC|Shape, default 8; on the streaming manager too): floors get at  
least that many passes, walls and ceilings keep `SmoothIterations`, and vertices on the grid’s outer  
faces stay put so chunk seams don’t move. On the depths recipe, floor area steeper than 44.8° goes  
from 32% to under 1%.
- 🧪 `Demo.InteractiveStreamingHighTickRate` walks the depths for 5 s of game time at a fixed  
1/240 s step: 24 m, never stalled more than 0.14 s. With the fix removed it reproduces the defect  
exactly — 47 cm, stuck for 4.6 s. `Cave.WalkableFloor` compares a cave with the setting on and off.

### 🪨 Fixed — scatter that moved, and paths that filled back up

- 🎲 **One carve moved nearly every prop in the cave.** Scatter drew every prop from one random  
stream and carried fractional counts from triangle to triangle, so any change to the mesh shifted  
every prop after it. Each triangle now draws from its own stream, keyed by where it is; Poisson-spaced  
layers are dart-thrown in a per-prop order. Props away from a carve stay put (`Cave.ScatterStableAcrossCarves`:  
every one of 123 plain and 328 Poisson-spaced props kept).
- 🚧 **Props pruned from a walkway came back after a carve.** The demos removed scatter from their  
walkways once; the next rebuild scattered the cave again, and a stalagmite stood up through the  
Forge’s walkway. Exclusions now live on the cave (`ScatterExclusions`, actor-local capsules) and every  
scatter pass applies them — first generation, carve rebuilds and replicated rebuilds alike.  
`AddScatterExclusionPath(WorldPoints, Radius)` adds a corridor and removes what is already in it.
- 🕳 **A fresh hole grew props.** With `bScatterOnRuntimeCarves` off, nothing is scattered inside a  
runtime carve’s reach, so a pocket dug half way up a wall no longer sprouts a floating stalagmite.  
The tour’s Forge and the Warren’s Throat, Weep and Hollow use it.

### 🧩 Fixed — a slot across the floor at every streamed tunnel seam

- 🕳 **Streamed tunnels had a crack at every chunk seam.** Density chunks get a one-voxel halo and  
their seam vertices are pinned; tunnel chunks had neither, so smoothing pulled each chunk’s floor  
back from its neighbour’s. On the Infinite Depths recipe, rays cast down at a seam fell 1.0–2.5 m  
below the floor either side — every ~24 m. Seam vertices of streamed tunnel chunks are now pinned to  
the shared voxel lattice like the density chunks’, so both sides meet; what remains is a shallow  
groove (worst 31 cm on that recipe) where a pinned vertex sits below its smoothed neighbours  
(`Production.StreamingTunnelSeam`).

### 🌱 Changed — the IOC Voxel Core PCG node

- 📍 **`PointMode`: Surface Only** (new default) emits one point per solid voxel that touches air; All  
Solid keeps the old every-voxel output, most of it buried rock.
- 🧭 **`bAlignPointsToSurface`** turns each point so +Z faces the air — meshes stand on floors, lean  
out of walls, hang from ceilings. **`SurfaceOffset`** moves points towards the air.
- 🌫 **`bExposureAsDensity`** : density is the share of a voxel’s 26 neighbours that are air, for a  
Density Filter that keeps exposed ridges.
- 🌱 **Every point gets a seed from its position** , so spawners vary per point and stay stable.
- 🔁 **No more repeating noise.** The node used `FMath::PerlinNoise3D`, which tiles every 256 noise  
units — every ~51 m in Infinite mode at the default frequency. It now uses the cave actor’s  
gradient noise, which has no period. In Infinite mode the surface test reads the neighbouring  
chunk’s rock from the halo, so a chunk border is not mistaken for surface.

### 🧙 Changed — the setup wizard

- 🕳 **Organic Warren is offered** as the sixth style: a card, a row in the comparison table, its own  
dressing (roots on the ceiling, fungal shelves on the walls, egg sacs on the floor), texture tiling,  
render rig, cost estimate and Convert-to-Custom values, and dark, flashlight-ready lighting.
- 🔢 **The cost estimate counted the wrong number of scatter layers** for Large Tunnel and Open  
Cavern (3 where the preset builds 5); every preset now agrees with what it builds.
- 📐 **Two labels were cut off at 150 % display scaling** : “Reconfigure an existing cave actor instead of  
spawning a new one” (it needed 457 px and got 412) and the “Done” step badges. Both fit now, 29  
fixed-width text wraps follow their container instead, and the window’s minimum size is 960×720.
- 🎛 Smaller fixes: Alien Hive’s and Strata Canyon’s radii in the comparison table match the presets  
(400 and 1000 cm); the Preset Workflow buttons sit under their description; the “Selected” badge  
moved to the card’s footer; risk and validation colours update live instead of keeping the colour  
they had when the page was built.

### ⚡ Performance

On a 28 m tunnel with a 7 m bore at 25 cm voxels (1.3 M voxels), the generator’s worker time went from  
87–90 ms to 52–57 ms: hole fill 33 → 14 ms, mesh build 15.4 → 9.7 ms, overlays 10.4 → 3.1 ms. The new  
floor smoothing adds about 2 ms of that back.

- 🧱 Mesh attributes are enabled after the vertices and triangles are appended, not before.
- 🎨 Normal, colour and UV overlays are computed in parallel and filled one overlay per task, one  
element per vertex. This also fixes UV elements that were shared between a welded vertex and the  
copy the welder split off for a non-manifold triangle, which broke the overlay’s invariant.
- 🕳 The tunnel hole-fill pass runs in parallel over Z slices, with an identical result; it was the  
largest single-threaded stage.

### 🎨 Fixed — the props’ look

- 💧 **Rock props rendered wet.** The bake script passed output ranges to a helper that expects input  
ranges, so rock roughness came out near 0 (atlas average 0.17 where 0.72–0.9 was asked for). Rock  
roughness now averages 0.68; crystal and organic roughness are corrected the same way.
- 🌑 **Props were darkened by their neighbours.** All thirteen props sit at the origin in the bake  
scene, and the ambient-occlusion bake counted the others as occluders. Each prop now bakes alone.
- 📦 The thirteen meshes, three atlases and four material instances were re-imported on UE 5.5 and  
replaced in place.

### 🛡 Added — the collision cap warning

- 🕳 **Unreal builds no collision for a dynamic mesh over 250,000 triangles**  
(`geometry.DynamicMesh.MaxComplexCollisionTriCount`) and says so once per session, at Display level —  
while IOC allows 2,000,000. A big cave rendered and the player fell through it. Such a cave now logs a  
warning by name every time, sets `bLastCollisionSkipped`, and `GetPerformanceSummary()` ends with  
“NO COLLISION” (`Production.CollisionCapWarning`).

### 🕳 Fixed — the demos

- ⛏ **The Warren’s walkway was blocked in two places in the Nest.** The lane re-ran the same carve  
three times, and an identical carve changes nothing, so 2 of 615 clearance checks stayed in rock  
every run. Lane carves are now sized by the cave’s voxel — a sphere on each end of the character’s  
clearance capsule, reaching a voxel past it — and each later round reaches half a voxel deeper.  
With 0.4.5’s floors it clears the Nest in one round (`Demo.WarrenPlug` now checks the count).
- 🌀 **The tour’s portal was up the Forge’s end wall.** Its trigger started 2 m past the walkway, on a  
slope steeper than a character can walk, and its crystal stood in the rock. The trigger now starts  
just past the walkway’s end and the crystal and its light stand on the generated floor  
(`Demo.InteractiveLaneInBore`).
- 🚧 Walkways in both demos keep their corridor through every rebuild (above);  
`Demo.InteractiveLaneInBore` and `Demo.WarrenLaneInBore` check it independently of the cave.

### 📚 Docs

- Manual: `WalkableFloorSmoothing`, scatter stability and exclusions, the PCG node’s output settings,  
the collision cap, two new troubleshooting entries; the tutorial and demo guide say six presets,  
thirteen props and three demo maps.

### 🧪 Tests

- 🆕 **Seven new tests** : `Cave.WalkableFloor`, `Cave.ScatterStableAcrossCarves`,  
`Cave.ScatterExclusionSurvivesRebuild`, `Demo.InteractiveStreamingHighTickRate`,  
`Production.StreamingTunnelSeam`, `Production.CollisionCapWarning` and `PCG.VoxelCoreSurface` (the  
node’s work now sits in `IOCVoxelCore::BuildPoints`, so it can be tested without a PCG context).
- ➕ **Extended** : `SetupWizard.Workflow` checks every preset’s dressing against its cost estimate and the  
Organic Warren’s values; `SetupWizard.Layout` counts the style cards; `SetupWizard.LiveLayout` sweeps  
every page and scroll position for cut or spilling text; `Demo.InteractiveLaneInBore` and  
`Demo.WarrenLaneInBore` check the walking corridor for props (with their own geometry, not the cave’s)  
and the portal; `Demo.WarrenPlug` checks the walkway is clear of rock.
- 🔨 **Every new test and check was negative-tested** : each failed against a build with its fix removed  
(the 240 Hz walk reproduced the original stall exactly), and the live layout sweep caught both cut  
labels in the 0.4.5 wizard.
