TV3: Terrain Scatter and Population
Epic TV3 is implemented as a terrain-native scatter workflow layered on top of the existing instanced-mesh renderer.
What shipped
New Python module:
forge3d.terrain_scatterDeterministic placement generators:
seeded_random_transforms(...)grid_jitter_transforms(...)mask_density_transforms(...)
Terrain-aware sampling through
TerrainScatterSource, including:terrain-width contract coordinates
scaled-height placement
slope sampling
normalized elevation helpers
Placement filters through
TerrainScatterFiltersfor slope and elevation bands.Shared batch contract for both offscreen terrain rendering and the interactive viewer.
Renderer/viewer hooks:
apply_to_renderer(renderer, batches)apply_to_viewer(viewer, batches)
Runtime observability:
TerrainRenderer.get_scatter_stats()TerrainRenderer.get_scatter_memory_report()
Public API
import forge3d as f3d
from forge3d import terrain_scatter as ts
source = ts.TerrainScatterSource(heightmap, z_scale=1.4)
transforms = ts.grid_jitter_transforms(
source,
spacing=18.0,
seed=13,
jitter=0.6,
scale_range=(8.0, 14.0),
filters=ts.TerrainScatterFilters(
max_slope_deg=35.0,
min_elevation=source.min_height,
max_elevation=source.min_height + 120.0,
),
)
batch = ts.TerrainScatterBatch(
name="trees",
color=(0.20, 0.42, 0.18, 1.0),
max_draw_distance=2200.0,
transforms=transforms,
levels=[
ts.TerrainScatterLevel(
mesh=f3d.geometry.primitive_mesh("cone", radial_segments=12),
max_distance=900.0,
),
ts.TerrainScatterLevel(
mesh=f3d.geometry.primitive_mesh("box"),
max_distance=1600.0,
),
],
)
ts.apply_to_renderer(renderer, [batch])
stats = renderer.get_scatter_stats()
memory = renderer.get_scatter_memory_report()
Workflow notes
Placement is deterministic for a fixed source, seed, and filter set.
LOD thresholds must be strictly increasing, and only the final LOD may omit
max_distance.viewer_orbit_radius(...)returns a terrain-width-scaled orbit radius that matches the scatter coordinate contract.The viewer IPC path uses the same logical batch/LOD structure as the offscreen renderer.
Example and tests
Example:
python examples/terrain_tv3_scatter_demo.pyUnit and integration tests:
tests/test_terrain_scatter.pyViewer IPC tests:
tests/test_viewer_ipc.py
The bundled TV3 demo renders the same scatter batches both ways:
offscreen through
TerrainRendererinteractive through
open_viewer_async(...)