@threenative/terrain API
Every public function and class in @threenative/terrain. Headless terrain authoring — noise, erosion, sculpting, roads, rivers, material splats and scatter — evaluated into ordinary typed arrays and indexed Three.js geometry.
On this page
Generated from the engine's capability manifest: 40 functions and 4 classes. Each entry is the exported signature, what it is for, and a working example. Start with the package overview.
applyPlacementOverrides
Attach manual transforms to raw evaluated candidates and report orphan keys.
function applyPlacementOverrides(state: ITerrainState, value: unknown): ITerrainStateNeeds
- npm i -D @threenative/terrain
Use it to
- retain manual prop transforms across terrain scatter re-evaluation
Example
const state = applyPlacementOverrides(terrain.evaluate(), document.placementOverrides ?? {});Good to know
- headless authoring; game applies transforms against its model bounds and actual terrain surface
Options
- transform.grounding=false preserves requested Y while the game still measures clearance
bakeMesh
Bakes the recovered indexed top surface and optional vertical skirts into caller-owned arrays.
function bakeMesh( state: ITerrainState,Needs
- npm i @threenative/terrain
Use it to
- bake an authored terrain into portable indexed mesh arrays
Example
const mesh = bakeMesh(new Terrain({ resolution: 17 }).evaluate());Good to know
- no material is chosen; vertex colours exist only with a caller-supplied palette
Options
- step, chunk bounds, skirtDepth and palette belong to the caller
bakeTerrain
Bakes finite LOD chunks, the same collision samples and resolved placements.
function bakeTerrain( state: ITerrainState,Needs
- npm i @threenative/terrain
Use it to
- prepare terrain arrays and collision before a game starts
Example
const baked = bakeTerrain(new Terrain({ resolution: 129 }).evaluate(), { chunkCells: 64 });Good to know
- collision origin is the southwest corner; engine Heightfield origin is its centre
Options
- chunkCells, lodSteps, skirtDepth and palette are explicit authoring choices
bakeWorldPackage
Bake an evaluated terrain into the engine's world package: a world.json manifest, a uint16 heightmap, a splat mask array, a placement buffer of eight float32 per instance, and the square cells that stream them. The encodings and row orders are the ones the Blender recipe export_world.py writes, so one runtime streams both without a second reader.
function bakeWorldPackage( state: ITerrainState, options: IBakeWorldPackageOptions, ): IBakedWorldPackageNeeds
- npm i -D @threenative/terrain
Use it to
- hand an evaluated Strata terrain to a game without a Blender round trip
Example
const { manifest, files } = bakeWorldPackage(state, { assets });Good to know
- headless authoring; no three, no DOM, and nothing here decides how the world looks
Options
- every asset path, bound, LOD distance and cell size comes from the caller's options
createSegmentIndex
Build the index once per world; ask nearby per scatter candidate or heightfield vertex.
function createSegmentIndex<T>( segments: readonly IWaterSegment<T>[], cellSize: number, ): ISegmentIndex<T>Needs
- npm i @threenative/terrain
Use it to
- test scatter candidates or terrain vertices against rivers and lakes without scanning every segment
- find which river stations can reach a heightfield vertex when baking a wet margin
Example
const rivers = createSegmentIndex(segments, 32); const wet = rivers.nearby(x, z).some(isWet);Good to know
- returns candidates only; the caller applies its own exact distance and level test
decodeHeightPNG
CRC-checked bounded non-interlaced grayscale PNG height decoder.
async function decodeHeightPNG( input: Uint8Array | ArrayBuffer, options: IDecodeHeightPngOptions =Needs
- npm i @threenative/terrain
Use it to
- import numerical PNG8 or PNG16 terrain elevations
Example
const png = await encodeHeightPNG(new Terrain({ resolution: 17 }).evaluate()); const heights = await decodeHeightPNG(png);Good to know
- authoring data only; the game owns appearance, physics and rendering
decodeRAW16
Validates dimensions and range before decoding numerical height samples.
function decodeRAW16( input: Uint8Array | ArrayBuffer,Needs
- npm i @threenative/terrain
Use it to
- import a RAW16 terrain height buffer with explicit dimensions
Example
const decoded = decodeRAW16(new Uint8Array(8), { width: 2, height: 2, min: 0, max: 1 });Good to know
- authoring data only; the game owns appearance, physics and rendering
encodeGLB
Legacy terrain-only GLB encoding with embedded mesh arrays and no chosen material.
function encodeGLB(input: IBakedMesh | readonly IBakedMesh[])Needs
- npm i @threenative/terrain
Use it to
- export baked terrain geometry without engine extensions
Example
const glb = encodeGLB(bakeMesh(new Terrain({ resolution: 17 }).evaluate()));Good to know
- authoring data only; the game owns appearance, physics and rendering
encodeHeightPNG
Encodes numerical grayscale PNG16 with embedded elevation range.
async function encodeHeightPNG(state: ITerrainState, options: Partial<IHeightRange> =Needs
- npm i @threenative/terrain
Use it to
- export a terrain heightmap without an eight-bit colour conversion
Example
const png = await encodeHeightPNG(new Terrain({ resolution: 17 }).evaluate());Good to know
- authoring data only; the game owns appearance, physics and rendering
encodeRAW16
Encodes finite metre elevations as an explicit-range RAW16 buffer.
function encodeRAW16( values: ArrayLike<number> & Iterable<number>, options: IRaw16Options =Needs
- npm i @threenative/terrain
Use it to
- export terrain heights with a numerical range sidecar
Example
const raw = encodeRAW16(new Float32Array([0, 1]), { min: 0, max: 1 });Good to know
- authoring data only; the game owns appearance, physics and rendering
encodeSplatPNGs
Encodes the eight linear material-weight channels as two RGBA images.
async function encodeSplatPNGs(state: ITerrainState)Needs
- npm i @threenative/terrain
Use it to
- export terrain splat weights as linear data
Example
const maps = await encodeSplatPNGs(new Terrain({ resolution: 17 }).evaluate());Good to know
- authoring data only; the game owns appearance, physics and rendering
encodeZIP
Deterministic store-method ZIP with safe unique relative filenames.
function encodeZIP(files: readonly IExportFile[])Needs
- npm i @threenative/terrain
Use it to
- archive derived terrain files without another dependency
Example
const archive = encodeZIP([{ name: "height.raw", bytes: new Uint8Array(8) }]);Good to know
- authoring data only; the game owns appearance, physics and rendering
gradientAt
World-space height gradient from the canonical samples.
function gradientAt(grid: ISampledGrid, x: number, z: number): [number, number]Needs
- npm i @threenative/terrain
Use it to
- measure an authored terrain gradient in metres
Example
const gradient = gradientAt(new Terrain({ resolution: 17 }).evaluate(), 0, 0);Good to know
- authoring data only; the game owns appearance, physics and rendering
makeExport
Recovered numerical/project exports; GLB/runtime outputs contain terrain only.
async function makeExport( state: ITerrainState, recipe: ITerrainDocument, kind: ExportKind, ): Promise<IExportArchive>Needs
- npm i @threenative/terrain
Use it to
- export a terrain recipe and its numerical runtime data
Example
const terrain = new Terrain({ resolution: 17 }); const file = await makeExport(terrain.evaluate(), terrain.toJSON(), "project");Good to know
- authoring data only; the game owns appearance, physics and rendering
sampleHeight
Bilinear query of canonical height samples; triangle sampling is a separate contract.
sampleHeight = (grid: ISampledGrid, x: number, z: number): number => sampleGrid( grid.height, grid.resolution, grid.resolution, x / grid.size + 0.5, z / grid.size + 0.5, )Needs
- npm i @threenative/terrain
Use it to
- query an authored heightfield at world coordinates
Example
const height = sampleHeight(new Terrain({ resolution: 17 }).evaluate(), 0, 0);Good to know
- authoring data only; the game owns appearance, physics and rendering
slopeAtIndex
Slope in degrees at a heightfield sample.
function slopeAtIndex(grid: ISampledGrid, i: number): numberNeeds
- npm i @threenative/terrain
Use it to
- measure terrain slope for authoring diagnostics
Example
const slope = slopeAtIndex(new Terrain({ resolution: 17 }).evaluate(), 0);Good to know
- authoring data only; the game owns appearance, physics and rendering
slopeQuantile
A slope, in degrees, that the given share of this terrain's interior vertices lie at or below. Placement rules keyed to fixed degrees break when a world is rebaked smoother or rougher: an outcrop rule of "over 30 degrees" placed nothing on a forest whose 98th percentile is 22. Asking the terrain for its own steepest share keeps the rule meaning the same thing on every world.
function slopeQuantile(grid: ISampledGrid, quantile: number): numberNeeds
- npm i @threenative/terrain
Use it to
- place rocks or cliffs on a terrain's own steepest ground instead of a fixed slope in degrees
Example
const steep = slopeQuantile(grid, 0.98); if (slopeAt(x, z) > Math.min(30, steep)) placeRock(x, z);Good to know
- interior vertices only (edges have one-sided differences); quantile must be in [0, 1]
splinePoints
Recovered horizontal Catmull–Rom and vertically linear profile sampler.
function splinePoints( points: readonly (readonly [number, number, number])[], step = 3, smooth = true, ): [number, number, number][]Needs
- npm i @threenative/terrain
Use it to
- sample a road or river profile without vertical overshoot
Example
const points = splinePoints([[0, 4, 0], [10, 2, 10]], 3, false);Good to know
- authoring data only; the game owns appearance, physics and rendering
Terrain
Ordered, stable-ID terrain authoring with synchronous atomic transactions.
class TerrainNeeds
- npm i @threenative/terrain
Use it to
- author seeded terrain with noise, sculpting, erosion, roads, rivers and scatter
- generate a procedural heightmap landscape or island for a game
Example
const terrain = new Terrain({ size: 512, resolution: 257, seed: 73 }).noise({ id: "hills", amplitude: 35 });Good to know
- authoring stays outside the game's steady-play graph; no renderer or physics is created
- units are metres with Y up;
sizeis the world edge in metres (1 to 100000), centred on the origin resolutioncounts vertices per edge and must be one of 17, 33, 65, 129, 257, 513 or 1025seedis an integer from 0 to 4294967295; one document and seed evaluate to the same arraysevaluate()is synchronous on the calling thread: run it in a build script, never per frame- no art is chosen or shipped: materials, models and texture paths belong to the game
Options
- size, resolution, seed and all layer parameters are caller choices
TerrainEvaluator
Recovered prefix-caching authoring evaluator. Returned buffers belong to the caller.
class TerrainEvaluatorNeeds
- npm i @threenative/terrain
Use it to
- reuse terrain evaluation prefixes while authoring a finite heightfield
Example
const terrain = new Terrain({ resolution: 17 }); const evaluator = new TerrainEvaluator(); const state = evaluator.evaluate(terrain.toJSON());Good to know
- evaluates authoring documents only; games consume pre-baked arrays
Options
- cacheMB bounds retained prefix data
validateDocument
Validates the recovered recipe schema, operation allow-lists and numeric bounds.
function validateDocument(doc: ITerrainDocument): voidNeeds
- npm i @threenative/terrain
Use it to
- validate a terrain document before accepting an authoring write
Example
validateDocument(new Terrain({ resolution: 17 }).toJSON());Good to know
- authoring data only; the game owns appearance, physics and rendering
validatePlacementOverrides
Validate and clone stable-key placement transforms before saving or previewing them.
function validatePlacementOverrides( value: unknown =Needs
- npm i -D @threenative/terrain
Use it to
- validate finite positive manual prop transforms before a terrain authoring transaction
Example
const transforms = validatePlacementOverrides(document.placementOverrides);Good to know
- grounding defaults on only when omitted; position and scale have three components and quaternion is unit length
Options
- grounding=false preserves authored Y and keeps clearance observable
checkEnvironmentAssets
Check that the images an environment names are registered environment or image assets. @summary Validate the assets a preview environment refers to
function checkEnvironmentAssets( environment: IEnvironment, assets: readonlyNeeds
- npm i -D @threenative/terrain
Use it to
- refuse a saved environment whose sky or lighting image is not a registered file
Example
checkEnvironmentAssets({ sky: { image: "dusk" } }, document.assets ?? []);Good to know
- throws by name; HDR/EXR environment files and ordinary images are accepted, models are not
Options
- the project owns which images it registers
focusCamera
Frame a point, prop, landmark or region for the live viewport and projection. @summary Frame a focus target with an editor observation camera
function focusCamera( camera: ISavedCamera, request: IFocusRequest, resolve: IFocusResolver, ): IFocusOutcomeNeeds
- npm i -D @threenative/terrain
Use it to
- frame one selected prop, a registered landmark, a terrain region or a local point
Example
const outcome = focusCamera(camera, { target: { kind: "prop", id: "pine-3" }, aspect: 16 / 9 }, resolve);Good to know
- framing only; an unknown target returns a named diagnostic and no camera
Options
- the view supplies target bounds, the live aspect and the camera to keep
inspectImage
Validate a PNG, JPEG, WebP, Radiance HDR or OpenEXR container and read its pixel size. @summary Inspect an image file's container and pixel size without decoding it
function inspectImage( bytes: Uint8Array, format: string, limits:Needs
- npm i -D @threenative/terrain
Use it to
- check an imported surface or environment image for damage and for the project's size limit
Example
const report = inspectImage(bytes, "png", { maxDimension: 8192 });Good to know
- headers and checksums only; throws by name for a damaged, truncated or oversize file
Options
- the project sets the dimension limit
inspectSpatial
Read-only spatial inspection of one evaluated terrain revision.
function inspectSpatial( state: ITerrainState, revision: string, query: ISpatialQuery, ): ISpatialObservationNeeds
- npm i -D @threenative/terrain
Use it to
- measure a point, profile a transect or score a saved reference against the world
Example
const observation = inspectSpatial(state, revision, { kind: "point", at: [0, 0] });Good to know
- authoring data only; queries outside the extent or without observations throw
Options
- the caller owns the revision identity and the evaluated state being inspected
mountTerrainEditor
Mount recovered terrain controls around the project-owned ThreeNative view.
async function mountTerrainEditor(options:Needs
- npm i -D @threenative/terrain
Use it to
- open the terrain brush and layer GUI around game-owned rendering
Example
await mountTerrainEditor({ createView: createEditorView, materialColours: terrainPalette });Good to know
- browser authoring only; createView and materialColours are required game choices
Options
- createView owns the renderer scene, materials, lighting and camera
probeTerrain
Probe the evaluated surface at one world point, separating bilinear from triangle values.
function probeTerrain( state: ITerrainState, revision: string, at: readonly number[], ): IPointObservationNeeds
- npm i -D @threenative/terrain
Use it to
- measure an authored terrain point with provenance and a revision identity
Example
const probe = probeTerrain(state, revision, [12, -4]);Good to know
- authoring data only; non-finite, malformed and out-of-extent queries throw
Options
- the caller owns the revision identity and the evaluated state being inspected
runCameraOperation
Run one create / get / list / update / delete / activate operation over saved cameras. @summary Apply an editor camera operation to a saved camera set
function runCameraOperation(set: ICameraSet, operation: unknown): ICameraResultNeeds
- npm i -D @threenative/terrain
Use it to
- drive the terrain editor camera list from an agent or the GUI through one shared dispatch
Example
const next = runCameraOperation(set, { op: "activate", id: "survey" });Good to know
- pure: the input set is never mutated, an unknown id throws, and deleting the live camera falls back
Options
- the caller persists the returned set against its own revision
runEnvironmentOperation
Apply one get / patch / reset against the saved environment overrides; the caller commits it. @summary Run one preview-environment operation
function runEnvironmentOperation( current: IEnvironment, operation: unknown, ): IEnvironmentResultNeeds
- npm i -D @threenative/terrain
Use it to
- patch sun, haze, exposure or sea overrides from a controller or the editor GUI
Example
const result = runEnvironmentOperation({}, { op: "patch", values: { sun: { elevation: 25 } } });Good to know
- authoring metadata only; a null field returns to the project's own value
Options
- the project's render source decides what each value does
sniff
The kind and format a file's own bytes declare, whatever its name says. @summary Identify a GLB, PNG, JPEG, WebP, HDR or EXR file by its header
function sniff( bytes: Uint8Array, ):Needs
- npm i -D @threenative/terrain
Use it to
- decide whether a dropped or downloaded file is a model, surface image or environment image
Example
const kind = sniff(new Uint8Array(await file.arrayBuffer()))?.kind;Good to know
- reads only the first bytes; a file it cannot name returns undefined and must be refused
Options
- the caller decides what to do with an unknown file
surfaceSpace
The colour space an input's pixels are read in, from the channel its name ends with. @summary Resolve a surface input name to sRGB or linear
function surfaceSpace(input: string): "srgb" | "linear"Needs
- npm i -D @threenative/terrain
Use it to
- decide how an imported image bound to a named surface input must be sampled
Example
const space = surfaceSpace("bark.normal");Good to know
- throws by name for an input that is not <surface>.<channel> with a known channel
Options
- the project owns which surface inputs exist
TerrainEditorController
HTTP controller for the project-local terrain editor.
class TerrainEditorControllerNeeds
- npm i -D @threenative/terrain
Use it to
- inspect and atomically edit the terrain editor from an agent
Example
const controller = new TerrainEditorController(editorUrl); const snapshot = await controller.snapshot();Good to know
- optional tooling; only subscribe/mount touches DOM; stale revisions fail explicitly
Options
- editorUrl is the activation-returned project URL
validateAsset
Validate one saved asset registration exactly as a document commit stores it. @summary Validate a registered terrain-editor asset entry
function validateAsset(input: unknown): IProjectAssetNeeds
- npm i -D @threenative/terrain
Use it to
- check a model, image or environment asset entry before saving it in the authoring document
Example
const asset = validateAsset({ id: "oak", kind: "model", name: "oak.glb", path: "models/0123456789ab-oak.glb", sha256: "0123456789ab".padEnd(64, "0"), bytes: 2180, status: "ready" });Good to know
- authoring metadata only; ids, content-hashed paths, bounds and unit adjustments are checked, files are not read
Options
- the project owns its asset directory and which entries it keeps
validateAssets
Validate the whole asset list of an authoring document. @summary Validate the registered terrain-editor assets
function validateAssets(input: unknown): IProjectAsset[]Needs
- npm i -D @threenative/terrain
Use it to
- check every registered model, image and environment entry together, with unique ids
Example
const assets = validateAssets(document.assets ?? []);Good to know
- at most 64 entries; unique ids; each entry as validateAsset
Options
- the project owns its asset directory and which entries it keeps
validateCamera
Normalise and validate one saved camera, exactly as a document commit would store it. @summary Validate an editor observation camera bookmark
function validateCamera( input: unknown, existing: readonly ISavedCamera[] = [], ): ISavedCameraNeeds
- npm i -D @threenative/terrain
Use it to
- create or update a named terrain-editor camera in the shared authoring document
Example
const camera = validateCamera({ id: "survey", name: "Survey", position: [40, 60, 40], target: [0, 12, 0], up: [0, 1, 0], projection: "perspective", fov: 50, near: 0.5, far: 900 });Good to know
- authoring metadata only; finite noncoincident poses, usable up, valid projection, ordered planes
Options
- the caller owns the document revision and the live viewport aspect
validateCameras
Validate a document's saved camera list, keeping ids unique across it. @summary Validate the saved editor camera list of an authoring document
function validateCameras(input: unknown): ISavedCamera[]Needs
- npm i -D @threenative/terrain
Use it to
- reject a disk document whose saved cameras are malformed or duplicated
Example
const cameras = validateCameras(JSON.parse(saved).cameras ?? []);Good to know
- authoring metadata only; the same validation the camera operations apply
Options
- the document owns how many cameras it keeps; the list bound is the editor's own
validateEnvironment
Validate a complete overrides object exactly as a document commit stores it. @summary Validate preview environment overrides
function validateEnvironment(input: unknown): IEnvironmentNeeds
- npm i -D @threenative/terrain
Use it to
- save sun, sky, haze, exposure or ocean overrides in the shared authoring document
Example
const environment = validateEnvironment({ sun: { elevation: 25, intensity: 3 } });Good to know
- authoring metadata only; unknown fields and unsupported fog modes are refused by name
Options
- the project's render source defines what each value does; absent fields keep its own
validateSpatialReference
Normalise and validate one saved reference, exactly as a document commit would store it.
function validateSpatialReference(input: unknown): ISavedSpatialReferenceNeeds
- npm i -D @threenative/terrain
Use it to
- accept a bounded local reference image registration into the shared document
Example
const reference = validateSpatialReference(JSON.parse(saved));Good to know
- authoring metadata only; rejects unknown fields, malformed points and unknown scale
Options
- a project owns the image file; only its hash and provenance travel in the document
validateSurfaces
Validate surface mappings against the registered images they name. @summary Validate terrain-editor surface image mappings
function validateSurfaces( input: unknown, assets: readonly IProjectAsset[], ): ISurfaceMappingsNeeds
- npm i -D @threenative/terrain
Use it to
- save which imported PBR image replaces which named surface input of the project's render source
Example
const surfaces = validateSurfaces({ "bark.normal": { asset: "my-normal" } }, document.assets ?? []);Good to know
- authoring metadata only; each input is <surface>.<channel>; every asset must be a registered image
Options
- the project's render source defines which surface inputs exist and what they draw
terrainEditor
Mount the optional terrain document API on an existing loopback Vite server.
function terrainEditor(options:Needs
- npm i -D @threenative/terrain vite
Use it to
- share terrain recipe edits between an agent and the live terrain editor
Example
const editor = terrainEditor({ documentPath: resolve("terrain/world.json") });Good to know
- dev tooling only; serve a project-owned /terrain-editor/index.html; no runtime import
Options
- documentPath and optional configured viewerUrl belong to the project
TerrainEditorDocument
Project-local terrain document authority; no renderer or game dependency.
class TerrainEditorDocumentNeeds
- npm i -D @threenative/terrain
Use it to
- validate atomic revision-based project-local terrain document edits
Example
const document = new TerrainEditorDocument("/project/terrain/world.json"); const snapshot = document.snapshot();Good to know
- Node authoring only; documentPath is a configured absolute regular file; input is bounded to 64 MiB
Options
- the project chooses its document path; revisions come from validated content
exportWorldGLB
Export a committed evaluated world using ordinary glTF 2.0 nodes and embedded PBR images.
async function exportWorldGLB(input: IWorldGLBInput): Promise<IWorldGLBExport>Needs
- npm i -D @threenative/terrain
Use it to
- export terrain, resolved models and final manual placement transforms as a portable GLB
- export the whole terrain world as one glb for another three.js project
Example
const output = await exportWorldGLB({ revision, snapshotTime: 0, state, terrain, assets, transforms });Good to know
- browser authoring (FileReader/canvas); caller supplies all appearance and coherent baked water; root and /three remain headless
Options
- actual static models, final matrices and baked PBR maps are supplied by the game
toGeometry
Converts baked arrays to ordinary geometry using the consumer's installed Three.js.
function toGeometry(mesh: IBakedMesh): BufferGeometryNeeds
- npm i @threenative/terrain
Use it to
- put an authored terrain mesh in a game-owned Three.js scene
Example
const geometry = toGeometry(bakeMesh(new Terrain({ resolution: 17 }).evaluate()));Good to know
- creates only geometry; the caller owns its material, scene and disposal
Options
- every surface choice remains in game source