@threenative/terrain 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_GUIDE.md +194 -0
- package/LICENSE +21 -0
- package/README.md +71 -2
- package/THIRD_PARTY_NOTICES.md +38 -0
- package/dist/editor/index.d.ts +231 -0
- package/dist/editor/index.js +5624 -0
- package/dist/editor/server.d.ts +3 -0
- package/dist/editor/server.js +3688 -0
- package/dist/editor/worker.d.ts +2 -0
- package/dist/editor/worker.js +2212 -0
- package/dist/export.d.ts +54 -0
- package/dist/export.js +297 -0
- package/dist/index.d.ts +335 -0
- package/dist/index.js +2927 -0
- package/dist/server-ByM2hmYJ.d.ts +630 -0
- package/dist/terrain-gPnkCU6S.d.ts +141 -0
- package/dist/three.d.ts +14 -0
- package/dist/three.js +40 -0
- package/dist/types-Ant8-Axc.d.ts +486 -0
- package/package.json +86 -3
- package/starter/alpine/README.md +29 -0
- package/starter/alpine/assets.json +12 -0
- package/starter/alpine/bake.mjs +118 -0
- package/starter/alpine/recipe.json +66167 -0
- package/starter/alpine/sky.ts +23 -0
- package/starter/alpine/surface.json +53 -0
- package/starter/alpine/world.ts +335 -0
- package/starter/coastal/README.md +37 -0
- package/starter/coastal/assets.json +10 -0
- package/starter/coastal/bake.mjs +118 -0
- package/starter/coastal/recipe.json +66161 -0
- package/starter/coastal/sea.ts +327 -0
- package/starter/coastal/sky.ts +24 -0
- package/starter/coastal/surface.json +41 -0
- package/starter/coastal/world.ts +386 -0
- package/starter/desert/README.md +35 -0
- package/starter/desert/assets.json +12 -0
- package/starter/desert/bake.mjs +118 -0
- package/starter/desert/recipe.json +66156 -0
- package/starter/desert/sky.ts +23 -0
- package/starter/desert/surface.json +54 -0
- package/starter/desert/world.ts +335 -0
- package/starter/forest/README.md +46 -0
- package/starter/forest/assets.json +32 -0
- package/starter/forest/bake.mjs +118 -0
- package/starter/forest/recipe.json +4586 -0
- package/starter/forest/sky.ts +27 -0
- package/starter/forest/surface.json +79 -0
- package/starter/forest/water.ts +266 -0
- package/starter/forest/world.ts +413 -0
- package/starter/tundra/README.md +29 -0
- package/starter/tundra/assets.json +12 -0
- package/starter/tundra/bake.mjs +118 -0
- package/starter/tundra/recipe.json +66325 -0
- package/starter/tundra/sky.ts +27 -0
- package/starter/tundra/surface.json +54 -0
- package/starter/tundra/water.ts +313 -0
- package/starter/tundra/world.ts +366 -0
- package/starter-assets/bark_brown_02/bark_brown_02_diff_1k.jpg +0 -0
- package/starter-assets/bark_brown_02/bark_brown_02_nor_gl_1k.jpg +0 -0
- package/starter-assets/bark_brown_02/bark_brown_02_rough_1k.jpg +0 -0
- package/starter-assets/boulder_01/boulder-mid.glb +0 -0
- package/starter-assets/boulder_01/boulder-near.glb +0 -0
- package/starter-assets/cliff_side/cliff_side_ao_1k.jpg +0 -0
- package/starter-assets/cliff_side/cliff_side_diff_1k.jpg +0 -0
- package/starter-assets/cliff_side/cliff_side_nor_gl_1k.jpg +0 -0
- package/starter-assets/cliff_side/cliff_side_rough_1k.jpg +0 -0
- package/starter-assets/credits.json +1022 -0
- package/starter-assets/fern_02/fern_02_alpha_512.png +0 -0
- package/starter-assets/fern_02/fern_02_diff_512.jpg +0 -0
- package/starter-assets/fern_02/fern_02_nor_gl_512.jpg +0 -0
- package/starter-assets/fir_tree_01/fir-b-lod1.glb +0 -0
- package/starter-assets/fir_tree_01/fir-b-lod2.glb +0 -0
- package/starter-assets/fir_tree_01/fir-c-lod1.glb +0 -0
- package/starter-assets/fir_tree_01/fir-c-lod2.glb +0 -0
- package/starter-assets/fir_tree_01/fir_tree_01_twig_arm_1k.jpg +0 -0
- package/starter-assets/fir_tree_01/fir_tree_01_twig_diff_1k.jpg +0 -0
- package/starter-assets/fir_tree_01/fir_tree_01_twig_nor_gl_1k.jpg +0 -0
- package/starter-assets/forest_ground_04/forest_ground_04_ao_1k.jpg +0 -0
- package/starter-assets/forest_ground_04/forest_ground_04_diff_1k.jpg +0 -0
- package/starter-assets/forest_ground_04/forest_ground_04_nor_gl_1k.jpg +0 -0
- package/starter-assets/forest_ground_04/forest_ground_04_rough_1k.jpg +0 -0
- package/starter-assets/forest_leaves_02/forest_leaves_02_arm_512.jpg +0 -0
- package/starter-assets/forest_leaves_02/forest_leaves_02_diff_512.jpg +0 -0
- package/starter-assets/forest_leaves_02/forest_leaves_02_nor_gl_512.jpg +0 -0
- package/starter-assets/grass_medium_02/grass_medium_02_alpha_512.png +0 -0
- package/starter-assets/grass_medium_02/grass_medium_02_diff_512.jpg +0 -0
- package/starter-assets/grass_medium_02/grass_medium_02_nor_gl_512.jpg +0 -0
- package/starter-assets/hdri/kloofendal_48d_partly_cloudy_1k.hdr +0 -0
- package/starter-assets/leafy_grass/leafy_grass_ao_1k.jpg +0 -0
- package/starter-assets/leafy_grass/leafy_grass_diff_1k.jpg +0 -0
- package/starter-assets/leafy_grass/leafy_grass_nor_gl_1k.jpg +0 -0
- package/starter-assets/leafy_grass/leafy_grass_rough_1k.jpg +0 -0
- package/starter-assets/lichen_rock/lichen_rock_arm_512.jpg +0 -0
- package/starter-assets/lichen_rock/lichen_rock_diff_512.jpg +0 -0
- package/starter-assets/lichen_rock/lichen_rock_nor_gl_512.jpg +0 -0
- package/starter-assets/mossy_rock/mossy_rock_ao_1k.jpg +0 -0
- package/starter-assets/mossy_rock/mossy_rock_diff_1k.jpg +0 -0
- package/starter-assets/mossy_rock/mossy_rock_nor_gl_1k.jpg +0 -0
- package/starter-assets/mossy_rock/mossy_rock_rough_1k.jpg +0 -0
- package/starter-assets/needle-atlas.png +0 -0
- package/starter-assets/needle-surface.png +0 -0
- package/starter-assets/river_small_rocks/river_small_rocks_arm_512.jpg +0 -0
- package/starter-assets/river_small_rocks/river_small_rocks_diff_512.jpg +0 -0
- package/starter-assets/river_small_rocks/river_small_rocks_nor_gl_512.jpg +0 -0
- package/starter-assets/rock_boulder_dry/rock_boulder_dry_arm_512.jpg +0 -0
- package/starter-assets/rock_boulder_dry/rock_boulder_dry_diff_512.jpg +0 -0
- package/starter-assets/rock_boulder_dry/rock_boulder_dry_nor_gl_512.jpg +0 -0
- package/starter-assets/rocks/boulder-mid.glb +0 -0
- package/starter-assets/rocks/boulder-near.glb +0 -0
- package/starter-assets/rocks/boulder-prep.json +37 -0
- package/starter-assets/rocks/rock01-mid.glb +0 -0
- package/starter-assets/rocks/rock01-near.glb +0 -0
- package/starter-assets/rocks/rock01-prep.json +37 -0
- package/starter-assets/rocks/rock04-mid.glb +0 -0
- package/starter-assets/rocks/rock04-near.glb +0 -0
- package/starter-assets/rocks/rock04-prep.json +37 -0
- package/starter-assets/sand_01/sand_01_ao_1k.jpg +0 -0
- package/starter-assets/sand_01/sand_01_diff_1k.jpg +0 -0
- package/starter-assets/sand_01/sand_01_nor_gl_1k.jpg +0 -0
- package/starter-assets/sand_01/sand_01_rough_1k.jpg +0 -0
- package/starter-assets/snow_02/snow_02_ao_1k.jpg +0 -0
- package/starter-assets/snow_02/snow_02_diff_1k.jpg +0 -0
- package/starter-assets/snow_02/snow_02_nor_gl_1k.jpg +0 -0
- package/starter-assets/snow_02/snow_02_rough_1k.jpg +0 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
export { L as LayerPatch, O as OperationOptions, P as PatchCommand, T as Terrain, a as TerrainEvaluator } from './terrain-gPnkCU6S.js';
|
|
2
|
+
import { M as MaterialId, a as IMask, i as ISampledGrid, O as OperationType, d as ITerrainDocument, I as ITerrainState, j as IBakeMeshOptions, g as IBakedMesh, k as IBakeTerrainOptions, l as IBakedTerrain, h as IPlacementOverride, m as IDecodeHeightPngOptions, n as IDecodeRaw16Options, o as IHeightRange, p as IRaw16Options, q as IExportFile, E as ExportKind, r as IExportArchive } from './types-Ant8-Axc.js';
|
|
3
|
+
export { s as IBiomeParams, t as IBrushParams, u as IClearParams, f as ICopyRegionOptions, v as IDecodedHeightPng, w as IErodeParams, x as IErosionMaps, e as IEvaluateOptions, y as IFlattenParams, z as IGradeParams, A as IGrid, B as IHeightData, C as IHeightPngMetadata, D as IHeightmapParams, F as ILayer, G as IMaterialRule, H as IMaterialsParams, J as INoiseParams, K as IPaintParams, N as IPasteParams, P as IPlacement, Q as IRampParams, R as IRiver, S as IRiverParams, T as IRoadParams, U as IScatterClear, V as IScatterParams, W as IScatterRule, X as ISculptParams, Y as ISmoothParams, Z as ISplatPng, _ as IStampParams, $ as ITerraceParams, c as ITerrainConfig, a0 as ITerrainInspection, a1 as IWaterBody, a2 as IWaterParams, a3 as IWaterRule, L as Layer, b as LayerParams, a4 as MaskSampler, a5 as MaskType, a6 as SplinePoint } from './types-Ant8-Axc.js';
|
|
4
|
+
|
|
5
|
+
/** The eight splat channels, in channel order. Index 0 is the default base channel. */
|
|
6
|
+
declare const MATERIAL_IDS: readonly MaterialId[];
|
|
7
|
+
/**
|
|
8
|
+
* Serializable mask builders. A mask is data, never a callback, so a recipe round-trips through
|
|
9
|
+
* JSON and an editor can rewrite one field without executing anything.
|
|
10
|
+
*/
|
|
11
|
+
declare const Mask: Readonly<{
|
|
12
|
+
all: () => IMask;
|
|
13
|
+
none: () => IMask;
|
|
14
|
+
circle: (at: readonly [number, number], radius: number, softness?: number) => IMask;
|
|
15
|
+
rectangle: (at: readonly [number, number], size: number | readonly [number, number], rotation?: number, softness?: number) => IMask;
|
|
16
|
+
height: (min?: number, max?: number, fade?: number) => IMask;
|
|
17
|
+
slope: (min?: number, max?: number, fade?: number) => IMask;
|
|
18
|
+
noise: (scale?: number, threshold?: number, seed?: number, fade?: number) => IMask;
|
|
19
|
+
biome: (name: string) => IMask;
|
|
20
|
+
material: (name: MaterialId) => IMask;
|
|
21
|
+
and: (...masks: IMask[]) => IMask;
|
|
22
|
+
or: (...masks: IMask[]) => IMask;
|
|
23
|
+
not: (mask: IMask) => IMask;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
26
|
+
/** Bilinear world-space height query. It is not the rendered or collidable triangle surface. */
|
|
27
|
+
/**
|
|
28
|
+
* Bilinear query of canonical height samples; triangle sampling is a separate contract.
|
|
29
|
+
* @requires npm i @threenative/terrain
|
|
30
|
+
* @situation query an authored heightfield at world coordinates
|
|
31
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
32
|
+
* @example const height = sampleHeight(new Terrain({ resolution: 17 }).evaluate(), 0, 0);
|
|
33
|
+
*/
|
|
34
|
+
declare const sampleHeight: (grid: ISampledGrid, x: number, z: number) => number;
|
|
35
|
+
/** `[dh/dx, dh/dz]` at a world position. */
|
|
36
|
+
/**
|
|
37
|
+
* World-space height gradient from the canonical samples.
|
|
38
|
+
* @requires npm i @threenative/terrain
|
|
39
|
+
* @situation measure an authored terrain gradient in metres
|
|
40
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
41
|
+
* @example const gradient = gradientAt(new Terrain({ resolution: 17 }).evaluate(), 0, 0);
|
|
42
|
+
*/
|
|
43
|
+
declare function gradientAt(grid: ISampledGrid, x: number, z: number): [number, number];
|
|
44
|
+
/** Slope in degrees at one sample index. */
|
|
45
|
+
/**
|
|
46
|
+
* Slope in degrees at a heightfield sample.
|
|
47
|
+
* @requires npm i @threenative/terrain
|
|
48
|
+
* @situation measure terrain slope for authoring diagnostics
|
|
49
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
50
|
+
* @example const slope = slopeAtIndex(new Terrain({ resolution: 17 }).evaluate(), 0);
|
|
51
|
+
*/
|
|
52
|
+
declare function slopeAtIndex(grid: ISampledGrid, i: number): number;
|
|
53
|
+
/**
|
|
54
|
+
* A slope, in degrees, that the given share of this terrain's interior vertices lie at or below.
|
|
55
|
+
*
|
|
56
|
+
* Placement rules keyed to fixed degrees break when a world is rebaked smoother or rougher: an
|
|
57
|
+
* outcrop rule of "over 30 degrees" placed nothing on a forest whose 98th percentile is 22. Asking
|
|
58
|
+
* the terrain for its own steepest share keeps the rule meaning the same thing on every world.
|
|
59
|
+
*
|
|
60
|
+
* @requires npm i @threenative/terrain
|
|
61
|
+
* @situation place rocks or cliffs on a terrain's own steepest ground instead of a fixed slope in degrees
|
|
62
|
+
* @constraint interior vertices only (edges have one-sided differences); quantile must be in [0, 1]
|
|
63
|
+
* @example const steep = slopeQuantile(grid, 0.98); if (slopeAt(x, z) > Math.min(30, steep)) placeRock(x, z);
|
|
64
|
+
*/
|
|
65
|
+
declare function slopeQuantile(grid: ISampledGrid, quantile: number): number;
|
|
66
|
+
/**
|
|
67
|
+
* Samples a spline: Catmull-Rom horizontally to avoid corners, linear vertically to avoid
|
|
68
|
+
* overshoot. `smooth: false` walks the polyline.
|
|
69
|
+
*/
|
|
70
|
+
/**
|
|
71
|
+
* Recovered horizontal Catmull–Rom and vertically linear profile sampler.
|
|
72
|
+
* @requires npm i @threenative/terrain
|
|
73
|
+
* @situation sample a road or river profile without vertical overshoot
|
|
74
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
75
|
+
* @example const points = splinePoints([[0, 4, 0], [10, 2, 10]], 3, false);
|
|
76
|
+
*/
|
|
77
|
+
declare function splinePoints(points: readonly (readonly [number, number, number])[], step?: number, smooth?: boolean): [number, number, number][];
|
|
78
|
+
|
|
79
|
+
/** Valid grid resolutions: vertices per side, not cells. */
|
|
80
|
+
declare const RESOLUTIONS: readonly number[];
|
|
81
|
+
/** The parameters each operation accepts. Anything else is rejected before the state changes. */
|
|
82
|
+
declare const PARAMS: Readonly<Record<OperationType, readonly string[]>>;
|
|
83
|
+
/** Validates a whole recipe: version, config, layer count and unique layer IDs. */
|
|
84
|
+
/**
|
|
85
|
+
* Validates the recovered recipe schema, operation allow-lists and numeric bounds.
|
|
86
|
+
* @requires npm i @threenative/terrain
|
|
87
|
+
* @situation validate a terrain document before accepting an authoring write
|
|
88
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
89
|
+
* @example validateDocument(new Terrain({ resolution: 17 }).toJSON());
|
|
90
|
+
*/
|
|
91
|
+
declare function validateDocument(doc: ITerrainDocument): void;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Bakes the recovered indexed top surface and optional vertical skirts into caller-owned arrays.
|
|
95
|
+
* @requires npm i @threenative/terrain
|
|
96
|
+
* @situation bake an authored terrain into portable indexed mesh arrays
|
|
97
|
+
* @constraint no material is chosen; vertex colours exist only with a caller-supplied palette
|
|
98
|
+
* @example const mesh = bakeMesh(new Terrain({ resolution: 17 }).evaluate());
|
|
99
|
+
* @override step, chunk bounds, skirtDepth and palette belong to the caller
|
|
100
|
+
*/
|
|
101
|
+
declare function bakeMesh(state: ITerrainState, { step, x, z, cells, skirtDepth, palette, }?: IBakeMeshOptions): IBakedMesh;
|
|
102
|
+
/**
|
|
103
|
+
* Bakes finite LOD chunks, the same collision samples and resolved placements.
|
|
104
|
+
* @requires npm i @threenative/terrain
|
|
105
|
+
* @situation prepare terrain arrays and collision before a game starts
|
|
106
|
+
* @constraint collision origin is the southwest corner; engine Heightfield origin is its centre
|
|
107
|
+
* @example const baked = bakeTerrain(new Terrain({ resolution: 129 }).evaluate(), { chunkCells: 64 });
|
|
108
|
+
* @override chunkCells, lodSteps, skirtDepth and palette are explicit authoring choices
|
|
109
|
+
*/
|
|
110
|
+
declare function bakeTerrain(state: ITerrainState, { chunkCells, lodSteps, skirtDepth, palette, }?: IBakeTerrainOptions): IBakedTerrain;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Validate and clone stable-key placement transforms before saving or previewing them.
|
|
114
|
+
* @requires npm i -D @threenative/terrain
|
|
115
|
+
* @situation validate finite positive manual prop transforms before a terrain authoring transaction
|
|
116
|
+
* @constraint grounding defaults on only when omitted; position and scale have three components and quaternion is unit length
|
|
117
|
+
* @example const transforms = validatePlacementOverrides(document.placementOverrides);
|
|
118
|
+
* @override grounding=false preserves authored Y and keeps clearance observable
|
|
119
|
+
*/
|
|
120
|
+
declare function validatePlacementOverrides(value?: unknown): Record<string, IPlacementOverride>;
|
|
121
|
+
/**
|
|
122
|
+
* Attach manual transforms to raw evaluated candidates and report orphan keys.
|
|
123
|
+
* @requires npm i -D @threenative/terrain
|
|
124
|
+
* @situation retain manual prop transforms across terrain scatter re-evaluation
|
|
125
|
+
* @constraint headless authoring; game applies transforms against its model bounds and actual terrain surface
|
|
126
|
+
* @example const state = applyPlacementOverrides(terrain.evaluate(), document.placementOverrides ?? {});
|
|
127
|
+
* @override transform.grounding=false preserves requested Y while the game still measures clearance
|
|
128
|
+
*/
|
|
129
|
+
declare function applyPlacementOverrides(state: ITerrainState, value: unknown): ITerrainState;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Encodes finite metre elevations as an explicit-range RAW16 buffer.
|
|
133
|
+
* @requires npm i @threenative/terrain
|
|
134
|
+
* @situation export terrain heights with a numerical range sidecar
|
|
135
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
136
|
+
* @example const raw = encodeRAW16(new Float32Array([0, 1]), { min: 0, max: 1 });
|
|
137
|
+
*/
|
|
138
|
+
declare function encodeRAW16(values: ArrayLike<number> & Iterable<number>, options?: IRaw16Options): Uint8Array<ArrayBuffer>;
|
|
139
|
+
/**
|
|
140
|
+
* Validates dimensions and range before decoding numerical height samples.
|
|
141
|
+
* @requires npm i @threenative/terrain
|
|
142
|
+
* @situation import a RAW16 terrain height buffer with explicit dimensions
|
|
143
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
144
|
+
* @example const decoded = decodeRAW16(new Uint8Array(8), { width: 2, height: 2, min: 0, max: 1 });
|
|
145
|
+
*/
|
|
146
|
+
declare function decodeRAW16(input: Uint8Array | ArrayBuffer, { width, height, min, max, littleEndian }: IDecodeRaw16Options): {
|
|
147
|
+
width: number;
|
|
148
|
+
height: number;
|
|
149
|
+
values: Float32Array<ArrayBuffer>;
|
|
150
|
+
min: number;
|
|
151
|
+
max: number;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Encodes numerical grayscale PNG16 with embedded elevation range.
|
|
155
|
+
* @requires npm i @threenative/terrain
|
|
156
|
+
* @situation export a terrain heightmap without an eight-bit colour conversion
|
|
157
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
158
|
+
* @example const png = await encodeHeightPNG(new Terrain({ resolution: 17 }).evaluate());
|
|
159
|
+
*/
|
|
160
|
+
declare function encodeHeightPNG(state: ITerrainState, options?: Partial<IHeightRange>): Promise<Uint8Array<ArrayBuffer>>;
|
|
161
|
+
/**
|
|
162
|
+
* Encodes the eight linear material-weight channels as two RGBA images.
|
|
163
|
+
* @requires npm i @threenative/terrain
|
|
164
|
+
* @situation export terrain splat weights as linear data
|
|
165
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
166
|
+
* @example const maps = await encodeSplatPNGs(new Terrain({ resolution: 17 }).evaluate());
|
|
167
|
+
*/
|
|
168
|
+
declare function encodeSplatPNGs(state: ITerrainState): Promise<{
|
|
169
|
+
channels: MaterialId[];
|
|
170
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
171
|
+
}[]>;
|
|
172
|
+
/**
|
|
173
|
+
* CRC-checked bounded non-interlaced grayscale PNG height decoder.
|
|
174
|
+
* @requires npm i @threenative/terrain
|
|
175
|
+
* @situation import numerical PNG8 or PNG16 terrain elevations
|
|
176
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
177
|
+
* @example const png = await encodeHeightPNG(new Terrain({ resolution: 17 }).evaluate()); const heights = await decodeHeightPNG(png);
|
|
178
|
+
*/
|
|
179
|
+
declare function decodeHeightPNG(input: Uint8Array | ArrayBuffer, options?: IDecodeHeightPngOptions): Promise<{
|
|
180
|
+
width: number;
|
|
181
|
+
height: number;
|
|
182
|
+
values: Float32Array<ArrayBuffer>;
|
|
183
|
+
min: number;
|
|
184
|
+
max: number;
|
|
185
|
+
bitDepth: number;
|
|
186
|
+
hasEmbeddedRange: boolean;
|
|
187
|
+
}>;
|
|
188
|
+
/** Engine-independent GLB 2.0: static colored terrain geometry, no hidden external resources. */
|
|
189
|
+
/**
|
|
190
|
+
* Legacy terrain-only GLB encoding with embedded mesh arrays and no chosen material.
|
|
191
|
+
* @requires npm i @threenative/terrain
|
|
192
|
+
* @situation export baked terrain geometry without engine extensions
|
|
193
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
194
|
+
* @example const glb = encodeGLB(bakeMesh(new Terrain({ resolution: 17 }).evaluate()));
|
|
195
|
+
*/
|
|
196
|
+
declare function encodeGLB(input: IBakedMesh | readonly IBakedMesh[]): Uint8Array<ArrayBuffer>;
|
|
197
|
+
|
|
198
|
+
/** Deterministic ZIP (store method). No compression library or server required. */
|
|
199
|
+
/**
|
|
200
|
+
* Deterministic store-method ZIP with safe unique relative filenames.
|
|
201
|
+
* @requires npm i @threenative/terrain
|
|
202
|
+
* @situation archive derived terrain files without another dependency
|
|
203
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
204
|
+
* @example const archive = encodeZIP([{ name: "height.raw", bytes: new Uint8Array(8) }]);
|
|
205
|
+
*/
|
|
206
|
+
declare function encodeZIP(files: readonly IExportFile[]): Uint8Array<ArrayBuffer>;
|
|
207
|
+
/**
|
|
208
|
+
* Recovered numerical/project exports; GLB/runtime outputs contain terrain only.
|
|
209
|
+
* @requires npm i @threenative/terrain
|
|
210
|
+
* @situation export a terrain recipe and its numerical runtime data
|
|
211
|
+
* @constraint authoring data only; the game owns appearance, physics and rendering
|
|
212
|
+
* @example const terrain = new Terrain({ resolution: 17 }); const file = await makeExport(terrain.evaluate(), terrain.toJSON(), "project");
|
|
213
|
+
*/
|
|
214
|
+
declare function makeExport(state: ITerrainState, recipe: ITerrainDocument, kind: ExportKind): Promise<IExportArchive>;
|
|
215
|
+
|
|
216
|
+
/** One streamed asset: its LOD0 model, its authored bounds and the levels it swaps to. */
|
|
217
|
+
interface IWorldPackageAsset {
|
|
218
|
+
readonly glb: string;
|
|
219
|
+
readonly bounds: {
|
|
220
|
+
readonly min: readonly [number, number, number];
|
|
221
|
+
readonly max: readonly [number, number, number];
|
|
222
|
+
};
|
|
223
|
+
readonly lods?: readonly {
|
|
224
|
+
readonly glb: string;
|
|
225
|
+
readonly distance: number;
|
|
226
|
+
}[];
|
|
227
|
+
readonly maxDistance?: number;
|
|
228
|
+
}
|
|
229
|
+
/** One cell's contiguous run of placement records, eight float32 values each. */
|
|
230
|
+
interface IWorldPackageRun {
|
|
231
|
+
readonly asset: string;
|
|
232
|
+
/** Record offset into the placement buffer, not a byte offset. */
|
|
233
|
+
readonly offset: number;
|
|
234
|
+
readonly count: number;
|
|
235
|
+
}
|
|
236
|
+
/** The `world.json` contract, declared here so this addon needs no `@threenative/core` import. */
|
|
237
|
+
interface IWorldPackageManifest {
|
|
238
|
+
readonly version: 1;
|
|
239
|
+
readonly extent: {
|
|
240
|
+
readonly minX: number;
|
|
241
|
+
readonly minZ: number;
|
|
242
|
+
readonly sizeX: number;
|
|
243
|
+
readonly sizeZ: number;
|
|
244
|
+
};
|
|
245
|
+
readonly cellSize: number;
|
|
246
|
+
readonly terrain: {
|
|
247
|
+
readonly heightmap: string;
|
|
248
|
+
readonly columns: number;
|
|
249
|
+
readonly rows: number;
|
|
250
|
+
readonly spacing: number;
|
|
251
|
+
readonly heightMin: number;
|
|
252
|
+
readonly heightMax: number;
|
|
253
|
+
readonly layers?: Readonly<Record<string, string>>;
|
|
254
|
+
};
|
|
255
|
+
readonly assets: Readonly<Record<string, IWorldPackageAsset>>;
|
|
256
|
+
readonly placements: string;
|
|
257
|
+
readonly cells: readonly {
|
|
258
|
+
readonly x: number;
|
|
259
|
+
readonly z: number;
|
|
260
|
+
readonly runs: readonly IWorldPackageRun[];
|
|
261
|
+
}[];
|
|
262
|
+
}
|
|
263
|
+
/** The splat layout to copy into a terrain table: eight material masks in two RGBA8 planes. */
|
|
264
|
+
interface IWorldPackageSplat {
|
|
265
|
+
readonly size: number;
|
|
266
|
+
readonly planes: number;
|
|
267
|
+
readonly masks: Readonly<Record<string, readonly [number, "r" | "g" | "b" | "a"]>>;
|
|
268
|
+
}
|
|
269
|
+
interface IBakeWorldPackageOptions {
|
|
270
|
+
/** Every asset any instance may reference. An instance outside this set fails the bake. */
|
|
271
|
+
readonly assets: Readonly<Record<string, IWorldPackageAsset>>;
|
|
272
|
+
/** Metres per streamed cell. Defaults to 64. */
|
|
273
|
+
readonly cellSize?: number;
|
|
274
|
+
/** Extra `terrain.layers` entries, e.g. `{ table: "terrain-table.json" }`. */
|
|
275
|
+
readonly layers?: Readonly<Record<string, string>>;
|
|
276
|
+
readonly names?: {
|
|
277
|
+
readonly heightmap?: string;
|
|
278
|
+
readonly placements?: string;
|
|
279
|
+
readonly splat?: string;
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
interface IBakedWorldPackage {
|
|
283
|
+
readonly manifest: IWorldPackageManifest;
|
|
284
|
+
readonly splat: IWorldPackageSplat;
|
|
285
|
+
/** The three binary files, keyed by the manifest names that point at them. */
|
|
286
|
+
readonly files: Readonly<Record<string, Uint8Array>>;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Bake an evaluated terrain into the engine's world package: a `world.json` manifest, a uint16
|
|
290
|
+
* heightmap, a splat mask array, a placement buffer of eight float32 per instance, and the square
|
|
291
|
+
* cells that stream them. The encodings and row orders are the ones the Blender recipe
|
|
292
|
+
* `export_world.py` writes, so one runtime streams both without a second reader.
|
|
293
|
+
*
|
|
294
|
+
* @requires npm i -D @threenative/terrain
|
|
295
|
+
* @situation hand an evaluated Strata terrain to a game without a Blender round trip
|
|
296
|
+
* @constraint headless authoring; no three, no DOM, and nothing here decides how the world looks
|
|
297
|
+
* @example const { manifest, files } = bakeWorldPackage(state, { assets });
|
|
298
|
+
* @override every asset path, bound, LOD distance and cell size comes from the caller's options
|
|
299
|
+
*/
|
|
300
|
+
declare function bakeWorldPackage(state: ITerrainState, options: IBakeWorldPackageOptions): IBakedWorldPackage;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* A spatial index for water proximity: river segments, river stations and lake shores.
|
|
304
|
+
*
|
|
305
|
+
* Every caller that asks "is this point near water?" over a whole heightfield or a scatter pass
|
|
306
|
+
* otherwise scans every segment per point. In the Strata preview that cost 3.4 s (scatter) and
|
|
307
|
+
* 2.3 s (ground curvature) of a synchronous scene entry on a 612-station river (PRD-466, PRD-541).
|
|
308
|
+
* Each segment is registered in every grid cell its bounding box covers once grown by its own reach,
|
|
309
|
+
* so `nearby` returns a superset of the segments within reach of the point. The caller keeps its own
|
|
310
|
+
* exact distance and level test on that short list.
|
|
311
|
+
*/
|
|
312
|
+
interface IWaterSegment<T> {
|
|
313
|
+
/** One end, `[x, z]` in world metres. A station or a lake centre passes the same point twice. */
|
|
314
|
+
readonly a: readonly [number, number];
|
|
315
|
+
readonly b: readonly [number, number];
|
|
316
|
+
/** How far from the segment the caller's test can still answer true, in metres. */
|
|
317
|
+
readonly reach: number;
|
|
318
|
+
readonly data: T;
|
|
319
|
+
}
|
|
320
|
+
interface ISegmentIndex<T> {
|
|
321
|
+
/** Every segment whose reach may cover `(x, z)`. Never misses one; may include farther ones. */
|
|
322
|
+
nearby(x: number, z: number): readonly T[];
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Build the index once per world; ask `nearby` per scatter candidate or heightfield vertex.
|
|
326
|
+
*
|
|
327
|
+
* @requires npm i @threenative/terrain
|
|
328
|
+
* @situation test scatter candidates or terrain vertices against rivers and lakes without scanning every segment
|
|
329
|
+
* @situation find which river stations can reach a heightfield vertex when baking a wet margin
|
|
330
|
+
* @constraint returns candidates only; the caller applies its own exact distance and level test
|
|
331
|
+
* @example const rivers = createSegmentIndex(segments, 32); const wet = rivers.nearby(x, z).some(isWet);
|
|
332
|
+
*/
|
|
333
|
+
declare function createSegmentIndex<T>(segments: readonly IWaterSegment<T>[], cellSize: number): ISegmentIndex<T>;
|
|
334
|
+
|
|
335
|
+
export { ExportKind, IBakeMeshOptions, IBakeTerrainOptions, IBakedMesh, IBakedTerrain, IDecodeHeightPngOptions, IDecodeRaw16Options, IExportArchive, IExportFile, IHeightRange, IMask, IPlacementOverride, IRaw16Options, ISampledGrid, type ISegmentIndex, ITerrainDocument, ITerrainState, type IWaterSegment, MATERIAL_IDS, Mask, MaterialId, OperationType, PARAMS, RESOLUTIONS, applyPlacementOverrides, bakeMesh, bakeTerrain, bakeWorldPackage, createSegmentIndex, decodeHeightPNG, decodeRAW16, encodeGLB, encodeHeightPNG, encodeRAW16, encodeSplatPNGs, encodeZIP, gradientAt, makeExport, sampleHeight, slopeAtIndex, slopeQuantile, splinePoints, validateDocument, validatePlacementOverrides };
|