@hello-terrain/three 0.0.0-alpha.10 → 0.0.0-alpha.12
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/dist/index.cjs +2856 -1277
- package/dist/index.d.cts +739 -226
- package/dist/index.d.mts +739 -226
- package/dist/index.d.ts +739 -226
- package/dist/index.mjs +2828 -1273
- package/package.json +4 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { BufferGeometry,
|
|
1
|
+
import { BufferGeometry, Vector3 as Vector3$1, Ray, Raycaster, Intersection } from 'three';
|
|
2
2
|
import * as three_webgpu from 'three/webgpu';
|
|
3
3
|
import { StorageArrayTexture, StorageTexture, Node, WebGPURenderer, StorageBufferAttribute, StorageBufferNode, UniformNode, Vector3, Vector3Like, InstancedMesh, NodeMaterial, ConstNode } from 'three/webgpu';
|
|
4
4
|
import Node$1 from 'three/src/nodes/core/Node.js';
|
|
5
|
-
import * as three_src_nodes_TSL_js from 'three/src/nodes/TSL.js';
|
|
6
|
-
import { ShaderCallNodeInternal } from 'three/src/nodes/TSL.js';
|
|
7
5
|
import * as _hello_terrain_work from '@hello-terrain/work';
|
|
8
6
|
import { TaskRef, Graph } from '@hello-terrain/work';
|
|
7
|
+
import * as three_src_nodes_TSL_js from 'three/src/nodes/TSL.js';
|
|
8
|
+
import { ShaderCallNodeInternal } from 'three/src/nodes/TSL.js';
|
|
9
9
|
import * as three_tsl from 'three/tsl';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -13,7 +13,14 @@ import * as three_tsl from 'three/tsl';
|
|
|
13
13
|
* This geometry ensures that corner triangles are subdivided correctly.
|
|
14
14
|
*/
|
|
15
15
|
declare class TerrainGeometry extends BufferGeometry {
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* @param flipWinding Reverse triangle winding so front faces point the
|
|
18
|
+
* opposite way. The default winding makes flat tiles front-face `+Y`; the
|
|
19
|
+
* cube-sphere maps `(u→right, v→up)`, which would otherwise leave the
|
|
20
|
+
* planet's outer shell back-facing, so it passes `flipWinding` to render
|
|
21
|
+
* the outer surface with `FrontSide`.
|
|
22
|
+
*/
|
|
23
|
+
constructor(innerSegments?: number, extendUV?: boolean, flipWinding?: boolean);
|
|
17
24
|
/**
|
|
18
25
|
* Generate indices for terrain geometry with proper skirt corner handling.
|
|
19
26
|
* The key improvement is in how corner triangles are subdivided.
|
|
@@ -116,11 +123,6 @@ interface TerrainFieldStorage {
|
|
|
116
123
|
}
|
|
117
124
|
declare function ArrayTextureBackend(edgeVertexCount: number, tileCount: number, options: Required<Pick<TerrainFieldStorageOptions, "format" | "filter">>): TerrainFieldStorage;
|
|
118
125
|
declare function AtlasBackend(edgeVertexCount: number, tileCount: number, options: Required<Pick<TerrainFieldStorageOptions, "format" | "filter">>): TerrainFieldStorage;
|
|
119
|
-
/**
|
|
120
|
-
* Placeholder backend for future true 3D storage-texture support in Three.js.
|
|
121
|
-
* We keep it present to preserve the backend API shape.
|
|
122
|
-
*/
|
|
123
|
-
declare function Texture3DBackend(edgeVertexCount: number, tileCount: number, options: Required<Pick<TerrainFieldStorageOptions, "format" | "filter">>): TerrainFieldStorage;
|
|
124
126
|
declare function createTerrainFieldStorage(edgeVertexCount: number, tileCount: number, renderer?: WebGPURenderer, options?: TerrainFieldStorageOptions): TerrainFieldStorage;
|
|
125
127
|
declare function storeTerrainField(storage: TerrainFieldStorage, ix: Node, iy: Node, tileIndex: Node, value: Node): Node;
|
|
126
128
|
declare function loadTerrainField(storage: TerrainFieldStorage, ix: Node, iy: Node, tileIndex: Node): Node;
|
|
@@ -132,20 +134,14 @@ declare function loadTerrainFieldNormal(storage: TerrainFieldStorage, ix: Node,
|
|
|
132
134
|
*/
|
|
133
135
|
declare function sampleTerrainField(storage: TerrainFieldStorage, u: Node, v: Node, tileIndex: Node): Node;
|
|
134
136
|
declare function sampleTerrainFieldElevation(storage: TerrainFieldStorage, u: Node, v: Node, tileIndex: Node): Node;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
tileLevel: Node$1;
|
|
144
|
-
tileSize: Node$1;
|
|
145
|
-
tileOriginVec2: Node$1;
|
|
146
|
-
nodeIndex: Node$1;
|
|
147
|
-
}
|
|
148
|
-
type ElevationCallback = (params: ElevationParams) => Node$1;
|
|
137
|
+
/**
|
|
138
|
+
* Pack a terrain field sample into RGBA: `[height, Nx, Ny, Nz]` where
|
|
139
|
+
* `(Nx, Ny, Nz)` is the unit world-space surface normal. Storing the full
|
|
140
|
+
* world normal (rather than a face-local tangent pair) keeps shading
|
|
141
|
+
* continuous across cube-face seams, since adjacent faces no longer rotate the
|
|
142
|
+
* normal through their own parametric tangent frame.
|
|
143
|
+
*/
|
|
144
|
+
declare function packTerrainFieldSample(height: Node, normal: Node): Node;
|
|
149
145
|
|
|
150
146
|
interface TerrainUniformsParams {
|
|
151
147
|
rootSize: number;
|
|
@@ -153,6 +149,7 @@ interface TerrainUniformsParams {
|
|
|
153
149
|
innerTileSegments: number;
|
|
154
150
|
skirtScale: number;
|
|
155
151
|
elevationScale: number;
|
|
152
|
+
radius: number;
|
|
156
153
|
instanceId: string;
|
|
157
154
|
}
|
|
158
155
|
interface TerrainUniformsContext {
|
|
@@ -161,6 +158,7 @@ interface TerrainUniformsContext {
|
|
|
161
158
|
uInnerTileSegments: UniformNode<number>;
|
|
162
159
|
uSkirtScale: UniformNode<number>;
|
|
163
160
|
uElevationScale: UniformNode<number>;
|
|
161
|
+
uRadius: UniformNode<number>;
|
|
164
162
|
}
|
|
165
163
|
interface LeafStorageState {
|
|
166
164
|
data: Int32Array<ArrayBuffer>;
|
|
@@ -168,145 +166,36 @@ interface LeafStorageState {
|
|
|
168
166
|
node: StorageBufferNode;
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
interface CreateTerrainSamplerParams {
|
|
188
|
-
terrainFieldStorage: TerrainFieldStorage;
|
|
189
|
-
spatialIndex: GpuSpatialIndexContext;
|
|
169
|
+
/** Shared (projection-independent) tile-compute helpers. */
|
|
170
|
+
type SharedTileCompute = {
|
|
171
|
+
tileLevel: (nodeIndex: Node) => Node;
|
|
172
|
+
tileFace: (nodeIndex: Node) => Node;
|
|
173
|
+
tileOriginVec2: (nodeIndex: Node) => Node;
|
|
174
|
+
/** Face-local (u, v) in [0, 1] for a grid sample, including skirt border. */
|
|
175
|
+
tileFaceUV: (nodeIndex: Node, ix: Node, iy: Node) => Node;
|
|
176
|
+
};
|
|
177
|
+
/** Projection-specific tile-compute builders. */
|
|
178
|
+
type TileComputeParts = {
|
|
179
|
+
tileSize: (nodeIndex: Node) => Node;
|
|
180
|
+
rootUV: (nodeIndex: Node, ix: Node, iy: Node) => Node;
|
|
181
|
+
tileVertexWorldPosition: (nodeIndex: Node, ix: Node, iy: Node) => Node;
|
|
182
|
+
};
|
|
183
|
+
type TileComputePartsContext = {
|
|
184
|
+
leafStorage: LeafStorageState;
|
|
190
185
|
uniforms: TerrainUniformsContext;
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
interface TerrainElevationSample {
|
|
199
|
-
elevation: number;
|
|
200
|
-
valid: boolean;
|
|
201
|
-
}
|
|
202
|
-
interface TerrainSampleBatch {
|
|
203
|
-
elevations: Float32Array;
|
|
204
|
-
normals: Float32Array;
|
|
205
|
-
valid: Uint8Array;
|
|
206
|
-
generation: number;
|
|
207
|
-
}
|
|
208
|
-
interface TerrainTile {
|
|
209
|
-
level: number;
|
|
210
|
-
x: number;
|
|
211
|
-
y: number;
|
|
212
|
-
index: number;
|
|
213
|
-
}
|
|
214
|
-
interface TerrainTileBounds extends TerrainTile {
|
|
215
|
-
minElevation: number;
|
|
216
|
-
maxElevation: number;
|
|
217
|
-
}
|
|
218
|
-
interface ElevationRange {
|
|
219
|
-
min: number;
|
|
220
|
-
max: number;
|
|
221
|
-
}
|
|
222
|
-
interface TerrainQuery {
|
|
223
|
-
getElevation(worldX: number, worldZ: number): number | null;
|
|
224
|
-
getNormal(worldX: number, worldZ: number): Vector3$1 | null;
|
|
225
|
-
getTile(worldX: number, worldZ: number): TerrainTile | null;
|
|
226
|
-
getTileBounds(worldX: number, worldZ: number): TerrainTileBounds | null;
|
|
227
|
-
getGlobalElevationRange(): ElevationRange | null;
|
|
228
|
-
sampleTerrain(worldX: number, worldZ: number): TerrainSample;
|
|
229
|
-
sampleTerrainBatch(positions: Float32Array): TerrainSampleBatch;
|
|
230
|
-
readonly generation: number;
|
|
231
|
-
}
|
|
232
|
-
interface RaycastOptions {
|
|
233
|
-
maxSteps?: number;
|
|
234
|
-
refinementSteps?: number;
|
|
235
|
-
maxDistance?: number;
|
|
236
|
-
}
|
|
237
|
-
interface TerrainRaycastResult {
|
|
238
|
-
position: Vector3$1;
|
|
239
|
-
normal: Vector3$1;
|
|
240
|
-
distance: number;
|
|
241
|
-
}
|
|
242
|
-
interface TerrainRaycast {
|
|
243
|
-
pick(ray: Ray, options?: RaycastOptions): TerrainRaycastResult | null;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
type TerrainMeshParams = {
|
|
247
|
-
innerTileSegments: number;
|
|
248
|
-
maxNodes: number;
|
|
249
|
-
material: NodeMaterial;
|
|
186
|
+
shared: SharedTileCompute;
|
|
187
|
+
};
|
|
188
|
+
type TileCompute = SharedTileCompute & {
|
|
189
|
+
tileSize: (nodeIndex: Node) => Node;
|
|
190
|
+
rootUVCompute: (nodeIndex: Node, ix: Node, iy: Node) => Node;
|
|
191
|
+
tileVertexWorldPositionCompute: (nodeIndex: Node, ix: Node, iy: Node) => Node;
|
|
250
192
|
};
|
|
251
|
-
declare class TerrainMesh extends InstancedMesh {
|
|
252
|
-
private _innerTileSegments;
|
|
253
|
-
private _maxNodes;
|
|
254
|
-
terrainRaycast: TerrainRaycast | null;
|
|
255
|
-
constructor(params?: Partial<TerrainMeshParams>);
|
|
256
|
-
get innerTileSegments(): number;
|
|
257
|
-
set innerTileSegments(tileSegments: number);
|
|
258
|
-
get maxNodes(): number;
|
|
259
|
-
set maxNodes(maxNodes: number);
|
|
260
|
-
raycast(raycaster: Raycaster, intersects: Intersection[]): void;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
interface TileBoundsContext {
|
|
264
|
-
data: Float32Array<ArrayBuffer>;
|
|
265
|
-
attribute: StorageBufferAttribute;
|
|
266
|
-
node: StorageBufferNode;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
type ComputeStageCallback = (nodeIndex: Node, globalVertexIndex: Node, uv: Node, localCoordinates: Node, texelSize: Node) => void;
|
|
270
|
-
type ComputePipeline = ComputeStageCallback[];
|
|
271
|
-
|
|
272
|
-
/** Default compile task — uses terrainFieldStageTask as the leaf. */
|
|
273
|
-
declare const compileComputeTask: _hello_terrain_work.Task<{
|
|
274
|
-
execute: (renderer: WebGPURenderer, instanceCount: number) => void;
|
|
275
|
-
}, string, unknown>;
|
|
276
|
-
/** Default execute task — dispatches the compiled kernel. */
|
|
277
|
-
declare const executeComputeTask: _hello_terrain_work.Task<any, string, {
|
|
278
|
-
renderer: WebGPURenderer;
|
|
279
|
-
}>;
|
|
280
193
|
/**
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
* the accumulation pattern (`get()` predecessor, spread, append), then pass
|
|
285
|
-
* their leaf stage to this helper to get compile + execute tasks.
|
|
286
|
-
*
|
|
287
|
-
* @example
|
|
288
|
-
* ```ts
|
|
289
|
-
* const erosionStageTask = task((get, work) => {
|
|
290
|
-
* const upstream = get(elevationFieldStageTask);
|
|
291
|
-
* return work((): ComputePipeline => [
|
|
292
|
-
* ...upstream,
|
|
293
|
-
* (nodeIndex, globalVertexIndex, uv) => {
|
|
294
|
-
* // custom erosion logic
|
|
295
|
-
* },
|
|
296
|
-
* ]);
|
|
297
|
-
* });
|
|
298
|
-
*
|
|
299
|
-
* const { compile, execute } = createComputePipelineTasks(erosionStageTask);
|
|
300
|
-
* ```
|
|
194
|
+
* Build the per-tile compute helpers, composing projection-independent
|
|
195
|
+
* decoders with the projection-specific position/size/uv builders supplied by
|
|
196
|
+
* `projection.gpu.createTileComputeParts`.
|
|
301
197
|
*/
|
|
302
|
-
declare function
|
|
303
|
-
compile: _hello_terrain_work.Task<{
|
|
304
|
-
execute: (renderer: WebGPURenderer, instanceCount: number) => void;
|
|
305
|
-
}, string, unknown>;
|
|
306
|
-
execute: _hello_terrain_work.Task<any, string, {
|
|
307
|
-
renderer: WebGPURenderer;
|
|
308
|
-
}>;
|
|
309
|
-
};
|
|
198
|
+
declare function createTileCompute(leafStorage: LeafStorageState, uniforms: TerrainUniformsContext, projection: SurfaceProjection): TileCompute;
|
|
310
199
|
|
|
311
200
|
declare const Dir: {
|
|
312
201
|
readonly LEFT: 0;
|
|
@@ -333,10 +222,32 @@ type TileBounds = {
|
|
|
333
222
|
/** conservative radius */
|
|
334
223
|
r: number;
|
|
335
224
|
};
|
|
336
|
-
|
|
225
|
+
/** Scaled world-space elevation displacement range for a tile. */
|
|
226
|
+
type ElevationRangeOut = {
|
|
227
|
+
min: number;
|
|
228
|
+
max: number;
|
|
229
|
+
};
|
|
230
|
+
type Topology = {
|
|
337
231
|
spaceCount: number;
|
|
338
232
|
/** maximum number of roots returned by `rootTiles` */
|
|
339
233
|
maxRootCount: number;
|
|
234
|
+
/**
|
|
235
|
+
* Injected surface projection strategy. Encapsulates the GPU position/normal
|
|
236
|
+
* assembly and the CPU query/raycast/LOD behavior for this topology, so the
|
|
237
|
+
* pipeline never branches on a projection kind.
|
|
238
|
+
*/
|
|
239
|
+
projection: SurfaceProjection;
|
|
240
|
+
/** Representative surface radius in world units (curved projections only). */
|
|
241
|
+
radius?: number;
|
|
242
|
+
/**
|
|
243
|
+
* Surface center in world space (curved projections only). Used to apply the
|
|
244
|
+
* camera elevation offset along the surface up-direction during LOD.
|
|
245
|
+
*/
|
|
246
|
+
center?: {
|
|
247
|
+
x: number;
|
|
248
|
+
y: number;
|
|
249
|
+
z: number;
|
|
250
|
+
};
|
|
340
251
|
/**
|
|
341
252
|
* Compute the same-level neighbor TileId in the requested direction.
|
|
342
253
|
* Returns false if the neighbor is outside the valid topology.
|
|
@@ -347,12 +258,13 @@ type Surface = {
|
|
|
347
258
|
/**
|
|
348
259
|
* Conservative camera-relative bounds for LOD decisions.
|
|
349
260
|
* Avoids absolute world coordinates so Earth-scale worlds remain stable.
|
|
261
|
+
* When `elevationRange` is provided, bounds should account for displaced geometry.
|
|
350
262
|
*/
|
|
351
263
|
tileBounds(tile: TileId, cameraOrigin: {
|
|
352
264
|
x: number;
|
|
353
265
|
y: number;
|
|
354
266
|
z: number;
|
|
355
|
-
}, out: TileBounds): void;
|
|
267
|
+
}, out: TileBounds, elevationRange?: ElevationRangeOut): void;
|
|
356
268
|
/**
|
|
357
269
|
* Fill root tiles for the current frame and return the count.
|
|
358
270
|
* Implementations should write level-0 tiles into `out[0..count)`.
|
|
@@ -400,9 +312,11 @@ type UpdateParams = {
|
|
|
400
312
|
z: number;
|
|
401
313
|
};
|
|
402
314
|
/**
|
|
403
|
-
* Terrain elevation
|
|
404
|
-
*
|
|
405
|
-
*
|
|
315
|
+
* Terrain elevation beneath the camera (from the previous frame). During
|
|
316
|
+
* refinement it offsets the camera toward the terrain surface so LOD distance
|
|
317
|
+
* is measured relative to the surface rather than the datum:
|
|
318
|
+
* - flat: subtracted from `cameraOrigin.y`.
|
|
319
|
+
* - cube-sphere: subtracted along the radial up-direction from the planet center.
|
|
406
320
|
*/
|
|
407
321
|
elevationAtCameraXZ?: number;
|
|
408
322
|
/**
|
|
@@ -421,6 +335,11 @@ type UpdateParams = {
|
|
|
421
335
|
targetPixels?: number;
|
|
422
336
|
/** Prevent flicker by separating split/merge thresholds (0..1 typical) */
|
|
423
337
|
hysteresis?: number;
|
|
338
|
+
/**
|
|
339
|
+
* Previous-frame per-tile elevation range in world-space displacement units
|
|
340
|
+
* (already scaled by `elevationScale`). Returns false when no data is available.
|
|
341
|
+
*/
|
|
342
|
+
tileElevationRange?: (space: number, level: number, x: number, y: number, out: ElevationRangeOut) => boolean;
|
|
424
343
|
};
|
|
425
344
|
type QuadtreeConfig = {
|
|
426
345
|
maxNodes: number;
|
|
@@ -487,19 +406,20 @@ type QuadtreeState = {
|
|
|
487
406
|
scratchTile: TileId;
|
|
488
407
|
scratchNeighbor: TileId;
|
|
489
408
|
scratchBounds: TileBounds;
|
|
409
|
+
scratchElevationRange: ElevationRangeOut;
|
|
490
410
|
scratchRootTiles: TileId[];
|
|
491
|
-
/**
|
|
411
|
+
/** topology space count is fixed for a given state */
|
|
492
412
|
spaceCount: number;
|
|
493
413
|
};
|
|
494
|
-
declare function createState(cfg: QuadtreeConfig,
|
|
495
|
-
declare function beginUpdate(state: QuadtreeState,
|
|
414
|
+
declare function createState(cfg: QuadtreeConfig, topology: Topology): QuadtreeState;
|
|
415
|
+
declare function beginUpdate(state: QuadtreeState, topology: Topology, params: UpdateParams): void;
|
|
496
416
|
|
|
497
417
|
/**
|
|
498
|
-
* Update the quadtree for the given
|
|
418
|
+
* Update the quadtree for the given topology + camera parameters.
|
|
499
419
|
*
|
|
500
420
|
* Produces a LeafSet of TileIds (SoA typed arrays).
|
|
501
421
|
*/
|
|
502
|
-
declare function update(state: QuadtreeState,
|
|
422
|
+
declare function update(state: QuadtreeState, topology: Topology, params: UpdateParams, outLeaves?: LeafSet): LeafSet;
|
|
503
423
|
|
|
504
424
|
/**
|
|
505
425
|
* Build a fixed-width seam/neighbor table for balanced leaves (2:1).
|
|
@@ -507,9 +427,9 @@ declare function update(state: QuadtreeState, surface: Surface, params: UpdatePa
|
|
|
507
427
|
* Output neighbors are leaf-list indices, with U32_EMPTY for missing entries.
|
|
508
428
|
* Layout: neighbors[leafIndex * 8 + edge*2 + slot].
|
|
509
429
|
*/
|
|
510
|
-
declare function buildSeams2to1(
|
|
430
|
+
declare function buildSeams2to1(topology: Topology, leaves: LeafSet, outSeams: SeamTable, outIndex?: SpatialIndex): SeamTable;
|
|
511
431
|
|
|
512
|
-
type
|
|
432
|
+
type FlatTopologyConfig = {
|
|
513
433
|
/**
|
|
514
434
|
* World-space size of the root tile edge.
|
|
515
435
|
* The root tile covers [-rootSize/2, +rootSize/2] around origin in X/Z.
|
|
@@ -520,44 +440,157 @@ type FlatSurfaceConfig = {
|
|
|
520
440
|
y: number;
|
|
521
441
|
z: number;
|
|
522
442
|
};
|
|
523
|
-
/** optional conservative vertical extent, included in bounds radius */
|
|
524
|
-
maxHeight?: number;
|
|
525
443
|
};
|
|
526
|
-
declare function
|
|
444
|
+
declare function createFlatTopology(cfg: FlatTopologyConfig): Topology;
|
|
527
445
|
|
|
528
|
-
type
|
|
446
|
+
type InfiniteFlatTopologyConfig = {
|
|
529
447
|
rootSize: number;
|
|
530
448
|
origin: {
|
|
531
449
|
x: number;
|
|
532
450
|
y: number;
|
|
533
451
|
z: number;
|
|
534
452
|
};
|
|
535
|
-
/** optional conservative vertical extent, included in bounds radius */
|
|
536
|
-
maxHeight?: number;
|
|
537
453
|
/** half-width of root grid in root tiles (1 => 3x3 roots) */
|
|
538
454
|
rootGridRadius?: number;
|
|
539
455
|
};
|
|
540
|
-
declare function
|
|
456
|
+
declare function createInfiniteFlatTopology(cfg: InfiniteFlatTopologyConfig): Topology;
|
|
541
457
|
|
|
542
|
-
type
|
|
458
|
+
type CubeSphereTopologyConfig = {
|
|
459
|
+
/** Sphere radius in world units. */
|
|
543
460
|
radius: number;
|
|
544
|
-
|
|
461
|
+
/** Planet center in world space (defaults to origin). */
|
|
462
|
+
center?: {
|
|
463
|
+
x: number;
|
|
464
|
+
y: number;
|
|
465
|
+
z: number;
|
|
466
|
+
};
|
|
467
|
+
/** When true, elevation displaces inward and skirts point outward. */
|
|
468
|
+
invert?: boolean;
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Cube-sphere topology: six quadtree faces wrapped onto a sphere.
|
|
472
|
+
*
|
|
473
|
+
* Topology (`neighborSameLevel`) is derived numerically from the shared
|
|
474
|
+
* `CUBE_FACES` basis so cross-face edges (including rotated pole edges)
|
|
475
|
+
* resolve to the correct neighbor tile without hand-coded transforms.
|
|
476
|
+
*/
|
|
477
|
+
declare function createCubeSphereTopology(cfg: CubeSphereTopologyConfig): Topology;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Canonical cube-sphere face basis.
|
|
481
|
+
*
|
|
482
|
+
* Shared single source of truth between the CPU surface topology
|
|
483
|
+
* (`cubeSphere.ts`) and the GPU position/normal assembly (`tsl/cubeSphere.ts`)
|
|
484
|
+
* so both agree on geometry and faces seam correctly.
|
|
485
|
+
*
|
|
486
|
+
* Each face maps a face-local coordinate (u, v) in [0, 1] to a point on the
|
|
487
|
+
* cube `[-1, 1]^3` via:
|
|
488
|
+
*
|
|
489
|
+
* s = 2u - 1, t = 2v - 1
|
|
490
|
+
* cube = forward + s * right + t * up
|
|
491
|
+
*
|
|
492
|
+
* Normalizing `cube` yields the unit-sphere direction for that vertex.
|
|
493
|
+
*
|
|
494
|
+
* Bases are right-handed (`forward = right x up`) and outward-facing.
|
|
495
|
+
* Space indices: 0:+X 1:-X 2:+Y 3:-Y 4:+Z 5:-Z.
|
|
496
|
+
*/
|
|
497
|
+
type Vec3 = readonly [number, number, number];
|
|
498
|
+
type CubeFace = {
|
|
499
|
+
forward: Vec3;
|
|
500
|
+
right: Vec3;
|
|
501
|
+
up: Vec3;
|
|
545
502
|
};
|
|
503
|
+
declare const CUBE_FACE_COUNT = 6;
|
|
504
|
+
declare const CUBE_FACES: readonly CubeFace[];
|
|
505
|
+
|
|
506
|
+
type Vec3Mutable$1 = [number, number, number];
|
|
507
|
+
/**
|
|
508
|
+
* Cube-space point for a face-local coordinate (u, v) in [0, 1]:
|
|
509
|
+
* cube = forward + (2u-1) * right + (2v-1) * up
|
|
510
|
+
* The result is unnormalized; normalize it to obtain the sphere direction.
|
|
511
|
+
*/
|
|
512
|
+
declare function faceUVToCube(face: number, u: number, v: number, out: Vec3Mutable$1): void;
|
|
513
|
+
/** Pick the cube face whose normal axis dominates the direction. */
|
|
514
|
+
declare function directionToFace(d: Vec3): number;
|
|
515
|
+
/** Face-local (u, v) in [0, 1] for a direction known to fall on `face`. */
|
|
516
|
+
declare function directionToFaceUV(face: number, d: Vec3, out: [number, number]): void;
|
|
546
517
|
/**
|
|
547
|
-
*
|
|
518
|
+
* Convert latitude/longitude (degrees) to a unit sphere direction.
|
|
548
519
|
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
520
|
+
* Convention matches `CUBE_FACES` (+Y is the north pole):
|
|
521
|
+
* - latitude is the angle above the equator, in `[-90, 90]`
|
|
522
|
+
* - longitude is the angle around the +Y axis, in `[-180, 180]`,
|
|
523
|
+
* measured from +Z toward +X (lon = 0 points along +Z).
|
|
551
524
|
*/
|
|
552
|
-
declare function
|
|
525
|
+
declare function latLongToDirection(latDeg: number, lonDeg: number, out: Vec3Mutable$1): void;
|
|
526
|
+
/** Inverse of {@link latLongToDirection}; returns degrees. */
|
|
527
|
+
declare function directionToLatLong(d: Vec3): {
|
|
528
|
+
latitude: number;
|
|
529
|
+
longitude: number;
|
|
530
|
+
};
|
|
553
531
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
532
|
+
type TorusTopologyConfig = {
|
|
533
|
+
/** Distance from the torus center to the tube center (the donut radius). */
|
|
534
|
+
majorRadius: number;
|
|
535
|
+
/** Radius of the tube cross-section. */
|
|
536
|
+
minorRadius: number;
|
|
537
|
+
/** Torus center in world space (defaults to origin). */
|
|
538
|
+
center?: {
|
|
539
|
+
x: number;
|
|
540
|
+
y: number;
|
|
541
|
+
z: number;
|
|
542
|
+
};
|
|
543
|
+
/** When true, elevation displaces inward and skirts point outward. */
|
|
544
|
+
invert?: boolean;
|
|
560
545
|
};
|
|
546
|
+
/**
|
|
547
|
+
* Torus (donut) topology: a single quadtree space whose `(u, v)` axes wrap
|
|
548
|
+
* around the major circle and the tube cross-section. Both axes are periodic,
|
|
549
|
+
* so every same-level neighbor exists (wrapping modulo the level resolution).
|
|
550
|
+
*
|
|
551
|
+
* Level-0 resolution is anisotropic: `baseU = round(major/minor)` tiles along
|
|
552
|
+
* `u` and `baseV = 1` along `v`, so root tiles are approximately square in
|
|
553
|
+
* world space before isotropic LOD subdivision.
|
|
554
|
+
*/
|
|
555
|
+
declare function createTorusTopology(cfg: TorusTopologyConfig): Topology;
|
|
556
|
+
|
|
557
|
+
type Vec3Mutable = [number, number, number];
|
|
558
|
+
/** Wrap a value into [0, 1). */
|
|
559
|
+
declare function wrap01(t: number): number;
|
|
560
|
+
/**
|
|
561
|
+
* Torus surface point for parameters (u, v) in [0, 1].
|
|
562
|
+
*
|
|
563
|
+
* Convention (matches `latLongToDirection`'s longitude axis):
|
|
564
|
+
* - `theta = 2*pi*u` sweeps around the +Y axis, measured from +Z toward +X.
|
|
565
|
+
* - `phi = 2*pi*v` sweeps around the tube cross-section, `phi = 0` pointing
|
|
566
|
+
* radially outward in the XZ plane and `phi = pi/2` pointing toward +Y.
|
|
567
|
+
*
|
|
568
|
+
* `displacement` is the elevation added to the tube (minor) radius.
|
|
569
|
+
*/
|
|
570
|
+
declare function torusUVToPoint(u: number, v: number, majorRadius: number, minorRadius: number, displacement: number, center: {
|
|
571
|
+
x: number;
|
|
572
|
+
y: number;
|
|
573
|
+
z: number;
|
|
574
|
+
}, out: Vec3Mutable, invert?: boolean): void;
|
|
575
|
+
/** Outward unit surface normal of the base (undisplaced) torus at (u, v). */
|
|
576
|
+
declare function torusOutwardNormal(u: number, v: number, out: Vec3Mutable, invert?: boolean): void;
|
|
577
|
+
type TorusSurfaceParams = {
|
|
578
|
+
/** Wrapped major-circle parameter in [0, 1). */
|
|
579
|
+
u: number;
|
|
580
|
+
/** Wrapped tube parameter in [0, 1). */
|
|
581
|
+
v: number;
|
|
582
|
+
/** Distance from the point to the tube center circle. */
|
|
583
|
+
tubeDistance: number;
|
|
584
|
+
};
|
|
585
|
+
/**
|
|
586
|
+
* Map a world point to torus surface parameters. `tubeDistance - minorRadius`
|
|
587
|
+
* is the signed radial displacement of the point relative to the base torus.
|
|
588
|
+
*/
|
|
589
|
+
declare function positionToTorusParams(px: number, py: number, pz: number, majorRadius: number, center: {
|
|
590
|
+
x: number;
|
|
591
|
+
y: number;
|
|
592
|
+
z: number;
|
|
593
|
+
}, out: TorusSurfaceParams): void;
|
|
561
594
|
|
|
562
595
|
type TerrainQueryConfig = {
|
|
563
596
|
rootSize: number;
|
|
@@ -567,12 +600,20 @@ type TerrainQueryConfig = {
|
|
|
567
600
|
innerTileSegments: number;
|
|
568
601
|
elevationScale: number;
|
|
569
602
|
maxLevel: number;
|
|
603
|
+
/** Representative surface radius (curved projections only). */
|
|
604
|
+
radius: number;
|
|
605
|
+
/** Level-0 tile count along u before LOD subdivision (defaults to 1). */
|
|
606
|
+
baseU?: number;
|
|
607
|
+
/** Level-0 tile count along v before LOD subdivision (defaults to 1). */
|
|
608
|
+
baseV?: number;
|
|
570
609
|
};
|
|
571
610
|
interface CpuTerrainCache {
|
|
572
611
|
readonly generation: number;
|
|
573
612
|
readonly ready: boolean;
|
|
574
613
|
updateConfig(config: TerrainQueryConfig): void;
|
|
575
614
|
triggerReadback(renderer: WebGPURenderer, attribute: StorageBufferAttribute, spatialIndex: SpatialIndex, boundsAttribute?: StorageBufferAttribute, activeLeafCount?: number): void;
|
|
615
|
+
/** Release GPU readback staging buffers owned by this cache. */
|
|
616
|
+
dispose(): void;
|
|
576
617
|
getElevation(worldX: number, worldZ: number): number | null;
|
|
577
618
|
getNormal(worldX: number, worldZ: number): Vector3$1 | null;
|
|
578
619
|
getTile(worldX: number, worldZ: number): TerrainTile | null;
|
|
@@ -580,11 +621,412 @@ interface CpuTerrainCache {
|
|
|
580
621
|
getGlobalElevationRange(): ElevationRange | null;
|
|
581
622
|
sampleTerrainBatch(positions: Float32Array): TerrainSampleBatch;
|
|
582
623
|
sampleTerrain(worldX: number, worldZ: number): TerrainSample;
|
|
624
|
+
/** True when the active projection supplies surface ops. */
|
|
625
|
+
readonly hasSurface: boolean;
|
|
626
|
+
sampleSurfaceByPosition(px: number, py: number, pz: number): TerrainSurfaceSample;
|
|
627
|
+
getElevationBySurfacePosition(px: number, py: number, pz: number): number | null;
|
|
628
|
+
getNormalBySurfacePosition(px: number, py: number, pz: number): Vector3$1 | null;
|
|
629
|
+
getTileBySurfacePosition(px: number, py: number, pz: number): TerrainTile | null;
|
|
630
|
+
getTileBoundsBySurfacePosition(px: number, py: number, pz: number): TerrainTileBounds | null;
|
|
631
|
+
sampleSurfaceBatchByPosition(positions: Float32Array): TerrainSurfaceSampleBatch;
|
|
632
|
+
/**
|
|
633
|
+
* Previous-frame raw elevation min/max for a tile (unscaled field values).
|
|
634
|
+
* Returns false when no snapshot data is available for the tile.
|
|
635
|
+
*/
|
|
636
|
+
getTileElevationRange(space: number, level: number, x: number, y: number, out: {
|
|
637
|
+
min: number;
|
|
638
|
+
max: number;
|
|
639
|
+
}): boolean;
|
|
583
640
|
}
|
|
584
641
|
|
|
642
|
+
/**
|
|
643
|
+
* CPU sampling over a snapshot elevation-field buffer laid out as
|
|
644
|
+
* `maxNodes × (edgeVertexCount × edgeVertexCount)` raw heights.
|
|
645
|
+
*
|
|
646
|
+
* Plain-number math only (no three.js, no TSL); callers build vectors at the
|
|
647
|
+
* consumer-facing boundary.
|
|
648
|
+
*/
|
|
649
|
+
interface ElevationGridShape {
|
|
650
|
+
edgeVertexCount: number;
|
|
651
|
+
verticesPerNode: number;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/** Stable projection identifier — for debugging/telemetry only, never switched on. */
|
|
655
|
+
type ProjectionKind = "flat" | "cubeSphere" | "torus" | (string & {});
|
|
656
|
+
interface Vec3Like {
|
|
657
|
+
x: number;
|
|
658
|
+
y: number;
|
|
659
|
+
z: number;
|
|
660
|
+
}
|
|
661
|
+
interface RenderVertexPositionContext {
|
|
662
|
+
leafStorage: LeafStorageState;
|
|
663
|
+
uniforms: TerrainUniformsContext;
|
|
664
|
+
terrainFieldStorage?: TerrainFieldStorage;
|
|
665
|
+
}
|
|
666
|
+
interface FieldNormalContext {
|
|
667
|
+
elevationFieldNode: Node;
|
|
668
|
+
edgeVertexCount: number;
|
|
669
|
+
tile: TileCompute;
|
|
670
|
+
uniforms: TerrainUniformsContext;
|
|
671
|
+
}
|
|
672
|
+
/** Per-vertex field-stage normal: `(nodeIndex, ix, iy) => unit world normal`. */
|
|
673
|
+
type FieldNormalFn = (nodeIndex: Node, ix: Node, iy: Node) => Node;
|
|
674
|
+
interface SurfaceProjectionGpu {
|
|
675
|
+
/** Render-path world position; also assigns the vertex normal varying. */
|
|
676
|
+
renderVertexPosition(ctx: RenderVertexPositionContext): Node;
|
|
677
|
+
/** Projection-specific compute-stage tile builders (size / uv / position). */
|
|
678
|
+
createTileComputeParts(ctx: TileComputePartsContext): TileComputeParts;
|
|
679
|
+
/** Field-stage surface normal builder. */
|
|
680
|
+
createFieldNormal(ctx: FieldNormalContext): FieldNormalFn;
|
|
681
|
+
/** Optional extra GPU samplers (e.g. sphere ByDirection); no-op for flat. */
|
|
682
|
+
augmentSampler?(sampler: TerrainSampler, params: CreateTerrainSamplerParams): void;
|
|
683
|
+
}
|
|
684
|
+
/** A world point projected onto a closed surface: tile space + face-local uv. */
|
|
685
|
+
interface SurfaceKey {
|
|
686
|
+
/** Tile space/face index (0 for torus, 0..5 for cube-sphere faces). */
|
|
687
|
+
space: number;
|
|
688
|
+
/** Face-local u in [0, 1). */
|
|
689
|
+
u: number;
|
|
690
|
+
/** Face-local v in [0, 1). */
|
|
691
|
+
v: number;
|
|
692
|
+
/** Outward unit direction at the key (for the surface sample `direction`). */
|
|
693
|
+
dirX: number;
|
|
694
|
+
dirY: number;
|
|
695
|
+
dirZ: number;
|
|
696
|
+
}
|
|
697
|
+
/** Grid neighborhood passed to {@link CpuSurfaceOps.surfaceNormal}. */
|
|
698
|
+
interface SurfaceNormalContext {
|
|
699
|
+
elevation: Float32Array;
|
|
700
|
+
shape: ElevationGridShape;
|
|
701
|
+
leafIndex: number;
|
|
702
|
+
/** Fractional grid coords of the sample within the leaf. */
|
|
703
|
+
gx: number;
|
|
704
|
+
gy: number;
|
|
705
|
+
innerTileSegments: number;
|
|
706
|
+
elevationScale: number;
|
|
707
|
+
level: number;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Projection-specific CPU surface math, injected into the terrain cache so the
|
|
711
|
+
* cache stays projection-agnostic. Implementations own their scratch (no
|
|
712
|
+
* module-scope state).
|
|
713
|
+
*/
|
|
714
|
+
interface CpuSurfaceOps {
|
|
715
|
+
/** Map a world position to a surface key; `false` if it has no projection. */
|
|
716
|
+
positionToKey(px: number, py: number, pz: number, out: SurfaceKey): boolean;
|
|
717
|
+
/** Displaced world position from a key + scaled elevation (writes `out`). */
|
|
718
|
+
surfacePosition(key: SurfaceKey, elevation: number, out: Vector3$1): void;
|
|
719
|
+
/** Unit world-space surface normal from a key + grid neighborhood. */
|
|
720
|
+
surfaceNormal(key: SurfaceKey, ctx: SurfaceNormalContext): Vector3$1;
|
|
721
|
+
}
|
|
722
|
+
interface ProjectionRaycastContext {
|
|
723
|
+
ray: Ray;
|
|
724
|
+
options?: RaycastOptions;
|
|
725
|
+
terrainQuery: TerrainQuery | null;
|
|
726
|
+
surfaceQuery: TerrainSurfaceQuery | null;
|
|
727
|
+
sphereQuery: TerrainSphereQuery | null;
|
|
728
|
+
config: TerrainRaycastConfig;
|
|
729
|
+
}
|
|
730
|
+
interface RuntimeQueries {
|
|
731
|
+
query: TerrainQuery;
|
|
732
|
+
/** Generic surface query (position/uv keyed); `null` on flat surfaces. */
|
|
733
|
+
surfaceQuery: TerrainSurfaceQuery | null;
|
|
734
|
+
/** Cube-sphere query (adds direction/lat-long); `null` unless cube-sphere. */
|
|
735
|
+
sphereQuery: TerrainSphereQuery | null;
|
|
736
|
+
}
|
|
737
|
+
interface SurfaceProjectionCpu {
|
|
738
|
+
/**
|
|
739
|
+
* Offset the camera toward the terrain surface so LOD distance is measured
|
|
740
|
+
* from the surface, not the datum. Mutates `cam` in place by `elevation`
|
|
741
|
+
* along the projection's up-direction.
|
|
742
|
+
*/
|
|
743
|
+
cameraSurfaceOffset(cam: Vec3Like, elevation: number): void;
|
|
744
|
+
/**
|
|
745
|
+
* Surface sampling ops injected into the terrain cache; `null` for flat
|
|
746
|
+
* surfaces (which have no closed-surface query).
|
|
747
|
+
*/
|
|
748
|
+
createSurfaceOps(): CpuSurfaceOps | null;
|
|
749
|
+
/** Build the runtime query objects the projection exposes. */
|
|
750
|
+
createRuntimeQueries(cache: CpuTerrainCache): RuntimeQueries;
|
|
751
|
+
/** Projection-specific CPU raycast (precise, falling back to bounds). */
|
|
752
|
+
raycast(ctx: ProjectionRaycastContext): TerrainRaycastResult | null;
|
|
753
|
+
}
|
|
754
|
+
interface SurfaceProjection {
|
|
755
|
+
/** Identifier; never switched on internally. */
|
|
756
|
+
readonly kind: ProjectionKind;
|
|
757
|
+
/** Representative radius (bounds/uniform helper); undefined for flat. */
|
|
758
|
+
readonly radius?: number;
|
|
759
|
+
/** Surface center in world space; undefined for flat. */
|
|
760
|
+
readonly center?: Vec3Like;
|
|
761
|
+
/** Closed surfaces face outward → flip triangle winding. */
|
|
762
|
+
readonly faceOutward: boolean;
|
|
763
|
+
/**
|
|
764
|
+
* Per-axis level-0 tile count before LOD subdivision. Defaults to `{ u: 1, v: 1 }`.
|
|
765
|
+
* At level `L`, resolution is `baseU * 2^L` by `baseV * 2^L` tiles.
|
|
766
|
+
*/
|
|
767
|
+
readonly baseResolution?: {
|
|
768
|
+
u: number;
|
|
769
|
+
v: number;
|
|
770
|
+
};
|
|
771
|
+
gpu: SurfaceProjectionGpu;
|
|
772
|
+
cpu: SurfaceProjectionCpu;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
interface ElevationParams {
|
|
776
|
+
worldPosition: Node$1;
|
|
777
|
+
rootSize: Node$1;
|
|
778
|
+
rootUV: Node$1;
|
|
779
|
+
tileUV: Node$1;
|
|
780
|
+
tileLevel: Node$1;
|
|
781
|
+
tileSize: Node$1;
|
|
782
|
+
tileOriginVec2: Node$1;
|
|
783
|
+
nodeIndex: Node$1;
|
|
784
|
+
}
|
|
785
|
+
type ElevationCallback = (params: ElevationParams) => Node$1;
|
|
786
|
+
|
|
787
|
+
interface GpuSpatialIndexContext {
|
|
788
|
+
data: Uint32Array<ArrayBuffer>;
|
|
789
|
+
size: number;
|
|
790
|
+
mask: number;
|
|
791
|
+
stampGen: UniformNode<number>;
|
|
792
|
+
attribute: StorageBufferAttribute;
|
|
793
|
+
node: StorageBufferNode;
|
|
794
|
+
}
|
|
795
|
+
interface TerrainSampler {
|
|
796
|
+
sampleElevation: (worldX: Node, worldZ: Node) => Node;
|
|
797
|
+
sampleNormal: (worldX: Node, worldZ: Node) => Node;
|
|
798
|
+
sampleTerrain: (worldX: Node, worldZ: Node) => Node;
|
|
799
|
+
sampleValidity: (worldX: Node, worldZ: Node) => Node;
|
|
800
|
+
evaluateElevation: (worldX: Node, worldZ: Node) => Node;
|
|
801
|
+
evaluateNormal: (worldX: Node, worldZ: Node, epsilon?: Node) => Node;
|
|
802
|
+
/** Packed `vec4(elevation, nx, ny, nz)` where the normal is tangent-space. */
|
|
803
|
+
sampleTerrainByDirection?: (direction: Node) => Node;
|
|
804
|
+
sampleElevationByDirection?: (direction: Node) => Node;
|
|
805
|
+
/** World-space surface normal reconstructed in the sphere tangent frame. */
|
|
806
|
+
sampleNormalByDirection?: (direction: Node) => Node;
|
|
807
|
+
sampleValidityByDirection?: (direction: Node) => Node;
|
|
808
|
+
}
|
|
809
|
+
interface CreateTerrainSamplerParams {
|
|
810
|
+
terrainFieldStorage: TerrainFieldStorage;
|
|
811
|
+
spatialIndex: GpuSpatialIndexContext;
|
|
812
|
+
uniforms: TerrainUniformsContext;
|
|
813
|
+
elevationCallback: ElevationCallback;
|
|
814
|
+
/** Maximum quadtree level to probe during tile lookup. */
|
|
815
|
+
maxLevel: number;
|
|
816
|
+
/** Active surface projection (drives optional GPU sampler augmentation). */
|
|
817
|
+
projection: SurfaceProjection;
|
|
818
|
+
}
|
|
819
|
+
interface TerrainSample {
|
|
820
|
+
elevation: number;
|
|
821
|
+
normal: Vector3$1;
|
|
822
|
+
valid: boolean;
|
|
823
|
+
}
|
|
824
|
+
interface TerrainSampleBatch {
|
|
825
|
+
elevations: Float32Array;
|
|
826
|
+
normals: Float32Array;
|
|
827
|
+
valid: Uint8Array;
|
|
828
|
+
generation: number;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Result of sampling a cube-sphere surface from a direction/position/lat-long.
|
|
832
|
+
*
|
|
833
|
+
* `elevation` is the radial displacement above the base radius (already scaled
|
|
834
|
+
* by `elevationScale`); `position` is the full world-space surface point
|
|
835
|
+
* `center + direction * (radius + elevation)`.
|
|
836
|
+
*/
|
|
837
|
+
interface TerrainSurfaceSample {
|
|
838
|
+
position: Vector3$1;
|
|
839
|
+
normal: Vector3$1;
|
|
840
|
+
direction: Vector3$1;
|
|
841
|
+
elevation: number;
|
|
842
|
+
valid: boolean;
|
|
843
|
+
}
|
|
844
|
+
interface TerrainSurfaceSampleBatch {
|
|
845
|
+
positions: Float32Array;
|
|
846
|
+
normals: Float32Array;
|
|
847
|
+
elevations: Float32Array;
|
|
848
|
+
valid: Uint8Array;
|
|
849
|
+
generation: number;
|
|
850
|
+
}
|
|
851
|
+
interface TerrainTile {
|
|
852
|
+
/** Surface space index: 0 for flat terrain, 0..5 for cube-sphere faces. */
|
|
853
|
+
space: number;
|
|
854
|
+
level: number;
|
|
855
|
+
x: number;
|
|
856
|
+
y: number;
|
|
857
|
+
index: number;
|
|
858
|
+
}
|
|
859
|
+
interface TerrainTileBounds extends TerrainTile {
|
|
860
|
+
minElevation: number;
|
|
861
|
+
maxElevation: number;
|
|
862
|
+
}
|
|
863
|
+
interface ElevationRange {
|
|
864
|
+
min: number;
|
|
865
|
+
max: number;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Flat (heightfield) terrain query, keyed on world XZ. For cube-sphere
|
|
869
|
+
* surfaces use {@link TerrainSphereQuery} instead.
|
|
870
|
+
*/
|
|
871
|
+
interface TerrainQuery {
|
|
872
|
+
getElevation(worldX: number, worldZ: number): number | null;
|
|
873
|
+
getNormal(worldX: number, worldZ: number): Vector3$1 | null;
|
|
874
|
+
getTile(worldX: number, worldZ: number): TerrainTile | null;
|
|
875
|
+
getTileBounds(worldX: number, worldZ: number): TerrainTileBounds | null;
|
|
876
|
+
getGlobalElevationRange(): ElevationRange | null;
|
|
877
|
+
sampleTerrain(worldX: number, worldZ: number): TerrainSample;
|
|
878
|
+
sampleTerrainBatch(positions: Float32Array): TerrainSampleBatch;
|
|
879
|
+
readonly generation: number;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Generic closed-surface terrain query, keyed on a world position projected
|
|
883
|
+
* onto the surface. Exposed for every non-flat projection (cube-sphere, torus,
|
|
884
|
+
* ...); `null` on flat surfaces. Elevation is the displacement above the base
|
|
885
|
+
* surface (already scaled by `elevationScale`); `position` is the full
|
|
886
|
+
* world-space surface point.
|
|
887
|
+
*/
|
|
888
|
+
interface TerrainSurfaceQuery {
|
|
889
|
+
readonly generation: number;
|
|
890
|
+
getElevationByPosition(position: Vector3$1): number | null;
|
|
891
|
+
getNormalByPosition(position: Vector3$1): Vector3$1 | null;
|
|
892
|
+
sampleTerrainByPosition(position: Vector3$1): TerrainSurfaceSample;
|
|
893
|
+
getTileByPosition(position: Vector3$1): TerrainTile | null;
|
|
894
|
+
getTileBoundsByPosition(position: Vector3$1): TerrainTileBounds | null;
|
|
895
|
+
/** Batch sample; `positions` is a Float32Array of xyz triples. */
|
|
896
|
+
sampleTerrainBatchByPosition(positions: Float32Array): TerrainSurfaceSampleBatch;
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Cube-sphere terrain query. Extends the generic surface query with the
|
|
900
|
+
* sphere-only direction/lat-long keys. A surface location is identified by a
|
|
901
|
+
* direction from the planet center (the canonical form); `ByPosition` projects
|
|
902
|
+
* any world point onto its direction, and `ByLatLong` takes degrees (latitude
|
|
903
|
+
* `[-90, 90]`, longitude `[-180, 180]`).
|
|
904
|
+
*
|
|
905
|
+
* Exposed only when the active surface uses the `cubeSphere` projection
|
|
906
|
+
* (otherwise `null` on the query context / runtime).
|
|
907
|
+
*/
|
|
908
|
+
interface TerrainSphereQuery extends TerrainSurfaceQuery {
|
|
909
|
+
getElevationByDirection(direction: Vector3$1): number | null;
|
|
910
|
+
getElevationByLatLong(latitudeDeg: number, longitudeDeg: number): number | null;
|
|
911
|
+
getNormalByDirection(direction: Vector3$1): Vector3$1 | null;
|
|
912
|
+
getNormalByLatLong(latitudeDeg: number, longitudeDeg: number): Vector3$1 | null;
|
|
913
|
+
sampleTerrainByDirection(direction: Vector3$1): TerrainSurfaceSample;
|
|
914
|
+
sampleTerrainByLatLong(latitudeDeg: number, longitudeDeg: number): TerrainSurfaceSample;
|
|
915
|
+
getTileByDirection(direction: Vector3$1): TerrainTile | null;
|
|
916
|
+
getTileByLatLong(latitudeDeg: number, longitudeDeg: number): TerrainTile | null;
|
|
917
|
+
getTileBoundsByDirection(direction: Vector3$1): TerrainTileBounds | null;
|
|
918
|
+
getTileBoundsByLatLong(latitudeDeg: number, longitudeDeg: number): TerrainTileBounds | null;
|
|
919
|
+
/** Batch sample; `directions` is a Float32Array of xyz triples. */
|
|
920
|
+
sampleTerrainBatchByDirection(directions: Float32Array): TerrainSurfaceSampleBatch;
|
|
921
|
+
}
|
|
922
|
+
interface RaycastOptions {
|
|
923
|
+
maxSteps?: number;
|
|
924
|
+
refinementSteps?: number;
|
|
925
|
+
maxDistance?: number;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Shared raycast bounds for the CPU marcher. Flat raycasts use the XZ extent +
|
|
929
|
+
* `[minY, maxY]`; curved projections derive their own radial shell from their
|
|
930
|
+
* geometry plus the query's global elevation range, and only read `center*`.
|
|
931
|
+
*/
|
|
932
|
+
interface TerrainRaycastConfig {
|
|
933
|
+
rootSize: number;
|
|
934
|
+
originX: number;
|
|
935
|
+
originY: number;
|
|
936
|
+
originZ: number;
|
|
937
|
+
minY: number;
|
|
938
|
+
maxY: number;
|
|
939
|
+
centerX: number;
|
|
940
|
+
centerY: number;
|
|
941
|
+
centerZ: number;
|
|
942
|
+
}
|
|
943
|
+
interface TerrainRaycastResult {
|
|
944
|
+
position: Vector3$1;
|
|
945
|
+
normal: Vector3$1;
|
|
946
|
+
distance: number;
|
|
947
|
+
}
|
|
948
|
+
interface TerrainRaycast {
|
|
949
|
+
pick(ray: Ray, options?: RaycastOptions): TerrainRaycastResult | null;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
type TerrainMeshParams = {
|
|
953
|
+
innerTileSegments: number;
|
|
954
|
+
maxNodes: number;
|
|
955
|
+
material: NodeMaterial;
|
|
956
|
+
/**
|
|
957
|
+
* Reverse tile triangle winding. Cube-sphere surfaces set this so the
|
|
958
|
+
* planet's outer shell is front-facing and renders with `FrontSide`.
|
|
959
|
+
*/
|
|
960
|
+
flipWinding: boolean;
|
|
961
|
+
};
|
|
962
|
+
declare class TerrainMesh extends InstancedMesh {
|
|
963
|
+
private _innerTileSegments;
|
|
964
|
+
private _maxNodes;
|
|
965
|
+
private _flipWinding;
|
|
966
|
+
terrainRaycast: TerrainRaycast | null;
|
|
967
|
+
constructor(params?: Partial<TerrainMeshParams>);
|
|
968
|
+
get innerTileSegments(): number;
|
|
969
|
+
set innerTileSegments(tileSegments: number);
|
|
970
|
+
get flipWinding(): boolean;
|
|
971
|
+
set flipWinding(flip: boolean);
|
|
972
|
+
get maxNodes(): number;
|
|
973
|
+
set maxNodes(maxNodes: number);
|
|
974
|
+
raycast(raycaster: Raycaster, intersects: Intersection[]): void;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
interface TileBoundsContext {
|
|
978
|
+
data: Float32Array<ArrayBuffer>;
|
|
979
|
+
attribute: StorageBufferAttribute;
|
|
980
|
+
node: StorageBufferNode;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
type ComputeStageCallback = (nodeIndex: Node, globalVertexIndex: Node, uv: Node, localCoordinates: Node, texelSize: Node) => void;
|
|
984
|
+
type ComputePipeline = ComputeStageCallback[];
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Default compile + execute tasks — uses terrainFieldStageTask as the leaf.
|
|
988
|
+
* Derived from the same factory as user pipelines to avoid duplicated logic.
|
|
989
|
+
*/
|
|
990
|
+
declare const compileComputeTask: _hello_terrain_work.Task<{
|
|
991
|
+
execute: (renderer: WebGPURenderer, instanceCount: number) => void;
|
|
992
|
+
}, string, unknown>;
|
|
993
|
+
declare const executeComputeTask: _hello_terrain_work.Task<any, string, {
|
|
994
|
+
renderer: WebGPURenderer;
|
|
995
|
+
}>;
|
|
996
|
+
/**
|
|
997
|
+
* Factory for user-extensible pipelines.
|
|
998
|
+
*
|
|
999
|
+
* Users who add custom compute stages create their own stage tasks using
|
|
1000
|
+
* the accumulation pattern (`get()` predecessor, spread, append), then pass
|
|
1001
|
+
* their leaf stage to this helper to get compile + execute tasks.
|
|
1002
|
+
*
|
|
1003
|
+
* @example
|
|
1004
|
+
* ```ts
|
|
1005
|
+
* const erosionStageTask = task((get, work) => {
|
|
1006
|
+
* const upstream = get(elevationFieldStageTask);
|
|
1007
|
+
* return work((): ComputePipeline => [
|
|
1008
|
+
* ...upstream,
|
|
1009
|
+
* (nodeIndex, globalVertexIndex, uv) => {
|
|
1010
|
+
* // custom erosion logic
|
|
1011
|
+
* },
|
|
1012
|
+
* ]);
|
|
1013
|
+
* });
|
|
1014
|
+
*
|
|
1015
|
+
* const { compile, execute } = createComputePipelineTasks(erosionStageTask);
|
|
1016
|
+
* ```
|
|
1017
|
+
*/
|
|
1018
|
+
declare function createComputePipelineTasks(leafStageTask: TaskRef<ComputePipeline>): {
|
|
1019
|
+
compile: _hello_terrain_work.Task<{
|
|
1020
|
+
execute: (renderer: WebGPURenderer, instanceCount: number) => void;
|
|
1021
|
+
}, string, unknown>;
|
|
1022
|
+
execute: _hello_terrain_work.Task<any, string, {
|
|
1023
|
+
renderer: WebGPURenderer;
|
|
1024
|
+
}>;
|
|
1025
|
+
};
|
|
1026
|
+
|
|
585
1027
|
interface QuadtreeConfigState {
|
|
586
1028
|
state: QuadtreeState;
|
|
587
|
-
|
|
1029
|
+
topology: Topology;
|
|
588
1030
|
}
|
|
589
1031
|
interface LeafGpuBufferState extends LeafStorageState {
|
|
590
1032
|
count: number;
|
|
@@ -597,6 +1039,10 @@ interface ElevationFieldContext {
|
|
|
597
1039
|
interface TerrainQueryContext {
|
|
598
1040
|
cache: CpuTerrainCache;
|
|
599
1041
|
query: TerrainQuery;
|
|
1042
|
+
/** Generic closed-surface query; `null` on flat surfaces. */
|
|
1043
|
+
surfaceQuery: TerrainSurfaceQuery | null;
|
|
1044
|
+
/** Cube-sphere query; `null` unless the topology uses the cubeSphere projection. */
|
|
1045
|
+
sphereQuery: TerrainSphereQuery | null;
|
|
600
1046
|
shapeKey: string;
|
|
601
1047
|
}
|
|
602
1048
|
/** Task refs for the standard terrain pipeline. */
|
|
@@ -604,7 +1050,7 @@ interface TerrainTasks {
|
|
|
604
1050
|
instanceId: TaskRef<string>;
|
|
605
1051
|
quadtreeConfig: TaskRef<QuadtreeConfigState>;
|
|
606
1052
|
quadtreeUpdate: TaskRef<LeafSet>;
|
|
607
|
-
|
|
1053
|
+
topology: TaskRef<Topology>;
|
|
608
1054
|
leafStorage: TaskRef<LeafStorageState>;
|
|
609
1055
|
leafGpuBuffer: TaskRef<LeafGpuBufferState>;
|
|
610
1056
|
gpuSpatialIndexStorage: TaskRef<GpuSpatialIndexContext>;
|
|
@@ -639,13 +1085,7 @@ declare const createElevationFieldContextTask: _hello_terrain_work.Task<{
|
|
|
639
1085
|
attribute: StorageBufferAttribute;
|
|
640
1086
|
node: three_webgpu.StorageBufferNode;
|
|
641
1087
|
}, string, unknown>;
|
|
642
|
-
declare const tileNodesTask: _hello_terrain_work.Task<
|
|
643
|
-
tileLevel: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
|
|
644
|
-
tileOriginVec2: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
|
|
645
|
-
tileSize: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
|
|
646
|
-
rootUVCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
|
|
647
|
-
tileVertexWorldPositionCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
|
|
648
|
-
}, string, unknown>;
|
|
1088
|
+
declare const tileNodesTask: _hello_terrain_work.Task<TileCompute, string, unknown>;
|
|
649
1089
|
/**
|
|
650
1090
|
* Root compute stage — generates elevation data and writes to the
|
|
651
1091
|
* elevation field storage buffer. Returns a single-element `ComputePipeline`.
|
|
@@ -689,22 +1129,24 @@ declare const origin: _hello_terrain_work.ParamRef<{
|
|
|
689
1129
|
z: number;
|
|
690
1130
|
}>;
|
|
691
1131
|
/**
|
|
692
|
-
*
|
|
693
|
-
*
|
|
1132
|
+
* Default number of segments per inner tile edge. The effective edge vertex
|
|
1133
|
+
* count is `innerTileSegments + 3`
|
|
694
1134
|
*/
|
|
695
1135
|
declare const innerTileSegments: _hello_terrain_work.ParamRef<number>;
|
|
696
1136
|
/** Skirt scale factor. */
|
|
697
1137
|
declare const skirtScale: _hello_terrain_work.ParamRef<number>;
|
|
698
1138
|
/** Elevation vertical scale. */
|
|
699
1139
|
declare const elevationScale: _hello_terrain_work.ParamRef<number>;
|
|
1140
|
+
/** Sphere radius in world units (cube-sphere projection only). */
|
|
1141
|
+
declare const radius: _hello_terrain_work.ParamRef<number>;
|
|
700
1142
|
/** Maximum quadtree nodes. */
|
|
701
1143
|
declare const maxNodes: _hello_terrain_work.ParamRef<number>;
|
|
702
1144
|
/** Maximum quadtree subdivision level. */
|
|
703
1145
|
declare const maxLevel: _hello_terrain_work.ParamRef<number>;
|
|
704
1146
|
/** Quadtree update configuration (camera, mode, etc.). */
|
|
705
1147
|
declare const quadtreeUpdate: _hello_terrain_work.ParamRef<UpdateParams>;
|
|
706
|
-
/** Optional custom terrain
|
|
707
|
-
declare const
|
|
1148
|
+
/** Optional custom terrain topology; defaults to bounded flat topology when null. */
|
|
1149
|
+
declare const topology: _hello_terrain_work.ParamRef<Topology | null>;
|
|
708
1150
|
/** Terrain field texture filter mode. */
|
|
709
1151
|
declare const terrainFieldFilter: _hello_terrain_work.ParamRef<"nearest" | "linear">;
|
|
710
1152
|
/** Terrain elevation control function (per vertex, in gpu compute) */
|
|
@@ -724,14 +1166,14 @@ declare const elevationFn: _hello_terrain_work.ParamRef<ElevationCallback>;
|
|
|
724
1166
|
* (e.g. buffer resize), so this task stays cached during normal quadtree
|
|
725
1167
|
* updates — no unnecessary shader rebuilds.
|
|
726
1168
|
*/
|
|
727
|
-
declare const positionNodeTask: _hello_terrain_work.Task<
|
|
1169
|
+
declare const positionNodeTask: _hello_terrain_work.Task<three_webgpu.Node, string, unknown>;
|
|
728
1170
|
|
|
729
1171
|
/**
|
|
730
|
-
* Derives the terrain
|
|
1172
|
+
* Derives the terrain topology from `rootSize` and `origin`.
|
|
731
1173
|
* Automatically recomputes when either param changes, keeping the
|
|
732
1174
|
* quadtree refinement in sync with the GPU-side tile positioning.
|
|
733
1175
|
*/
|
|
734
|
-
declare const
|
|
1176
|
+
declare const topologyTask: _hello_terrain_work.Task<Topology, string, unknown>;
|
|
735
1177
|
declare const quadtreeConfigTask: _hello_terrain_work.Task<QuadtreeConfigState, string, unknown>;
|
|
736
1178
|
declare const quadtreeUpdateTask: _hello_terrain_work.Task<LeafSet, string, unknown>;
|
|
737
1179
|
/**
|
|
@@ -763,14 +1205,13 @@ declare const createUniformsTask: _hello_terrain_work.Task<TerrainUniformsContex
|
|
|
763
1205
|
*/
|
|
764
1206
|
declare const updateUniformsTask: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
|
|
765
1207
|
|
|
766
|
-
declare function terrainGraph(): TerrainGraph;
|
|
767
1208
|
/** All terrain task refs for direct access. */
|
|
768
1209
|
declare const terrainTasks: {
|
|
769
1210
|
readonly instanceId: _hello_terrain_work.Task<`${string}-${string}-${string}-${string}-${string}`, string, unknown>;
|
|
770
1211
|
readonly quadtreeConfig: _hello_terrain_work.Task<QuadtreeConfigState, string, unknown>;
|
|
771
1212
|
readonly quadtreeUpdate: _hello_terrain_work.Task<LeafSet, string, unknown>;
|
|
772
1213
|
readonly leafStorage: _hello_terrain_work.Task<LeafStorageState, string, unknown>;
|
|
773
|
-
readonly
|
|
1214
|
+
readonly topology: _hello_terrain_work.Task<Topology, string, unknown>;
|
|
774
1215
|
readonly leafGpuBuffer: _hello_terrain_work.Task<{
|
|
775
1216
|
count: number;
|
|
776
1217
|
data: Int32Array<ArrayBuffer>;
|
|
@@ -781,19 +1222,13 @@ declare const terrainTasks: {
|
|
|
781
1222
|
readonly gpuSpatialIndexUpload: _hello_terrain_work.Task<GpuSpatialIndexContext, string, unknown>;
|
|
782
1223
|
readonly createUniforms: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
|
|
783
1224
|
readonly updateUniforms: _hello_terrain_work.Task<TerrainUniformsContext, string, unknown>;
|
|
784
|
-
readonly positionNode: _hello_terrain_work.Task<
|
|
1225
|
+
readonly positionNode: _hello_terrain_work.Task<three_webgpu.Node, string, unknown>;
|
|
785
1226
|
readonly createElevationFieldContext: _hello_terrain_work.Task<{
|
|
786
1227
|
data: Float32Array<ArrayBuffer>;
|
|
787
1228
|
attribute: three_webgpu.StorageBufferAttribute;
|
|
788
1229
|
node: three_webgpu.StorageBufferNode;
|
|
789
1230
|
}, string, unknown>;
|
|
790
|
-
readonly createTileNodes: _hello_terrain_work.Task<
|
|
791
|
-
tileLevel: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
|
|
792
|
-
tileOriginVec2: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
|
|
793
|
-
tileSize: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node]>;
|
|
794
|
-
rootUVCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
|
|
795
|
-
tileVertexWorldPositionCompute: three_src_nodes_TSL_js.ShaderNodeFn<[number | three_webgpu.Node, number | three_webgpu.Node, number | three_webgpu.Node]>;
|
|
796
|
-
}, string, unknown>;
|
|
1231
|
+
readonly createTileNodes: _hello_terrain_work.Task<TileCompute, string, unknown>;
|
|
797
1232
|
readonly createTerrainFieldTexture: _hello_terrain_work.Task<any, string, {
|
|
798
1233
|
renderer: WebGPURenderer;
|
|
799
1234
|
}>;
|
|
@@ -818,6 +1253,7 @@ declare const terrainTasks: {
|
|
|
818
1253
|
}>;
|
|
819
1254
|
readonly terrainRaycast: _hello_terrain_work.Task<TerrainRaycast, string, unknown>;
|
|
820
1255
|
};
|
|
1256
|
+
declare function terrainGraph(): TerrainGraph;
|
|
821
1257
|
|
|
822
1258
|
type ComputeDeviceLimits = {
|
|
823
1259
|
maxWorkgroupSizeX: number;
|
|
@@ -826,24 +1262,75 @@ type ComputeDeviceLimits = {
|
|
|
826
1262
|
};
|
|
827
1263
|
declare function getDeviceComputeLimits(renderer: WebGPURenderer): ComputeDeviceLimits;
|
|
828
1264
|
|
|
1265
|
+
/**
|
|
1266
|
+
* Add the cube-sphere direction samplers to a base sampler. Called from the
|
|
1267
|
+
* cube-sphere projection's `gpu.augmentSampler` hook.
|
|
1268
|
+
*/
|
|
1269
|
+
declare function augmentCubeSphereSampler(sampler: TerrainSampler, params: CreateTerrainSamplerParams): void;
|
|
829
1270
|
declare function createTerrainSampler(params: CreateTerrainSamplerParams): TerrainSampler;
|
|
830
1271
|
|
|
1272
|
+
/** Flat (heightfield) query, keyed on world XZ. */
|
|
831
1273
|
declare function createTerrainQuery(cache: CpuTerrainCache): TerrainQuery;
|
|
1274
|
+
/**
|
|
1275
|
+
* Generic closed-surface query, keyed on a world position projected onto the
|
|
1276
|
+
* surface. Cube-sphere extends this with direction/lat-long keys.
|
|
1277
|
+
*/
|
|
1278
|
+
declare function createTerrainSurfaceQuery(cache: CpuTerrainCache): TerrainSurfaceQuery;
|
|
832
1279
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
minY: number;
|
|
838
|
-
maxY: number;
|
|
839
|
-
};
|
|
840
|
-
|
|
841
|
-
type TerrainRaycastConfig = CpuRaycastConfig;
|
|
1280
|
+
/**
|
|
1281
|
+
* Build a terrain raycaster that delegates the projection-specific marching to
|
|
1282
|
+
* the active surface projection — no branching on a projection kind here.
|
|
1283
|
+
*/
|
|
842
1284
|
declare function createTerrainRaycast(params: {
|
|
1285
|
+
getProjection: () => SurfaceProjection;
|
|
843
1286
|
getTerrainQuery: () => TerrainQuery | null;
|
|
1287
|
+
getSurfaceQuery: () => TerrainSurfaceQuery | null;
|
|
1288
|
+
getSphereQuery: () => TerrainSphereQuery | null;
|
|
844
1289
|
getConfig: () => TerrainRaycastConfig;
|
|
845
1290
|
}): TerrainRaycast;
|
|
846
1291
|
|
|
1292
|
+
type CubeFaceBasis = {
|
|
1293
|
+
forward: Node;
|
|
1294
|
+
right: Node;
|
|
1295
|
+
up: Node;
|
|
1296
|
+
};
|
|
1297
|
+
/** Per-face basis vectors selected by the dynamic face index. */
|
|
1298
|
+
declare function cubeFaceBasis(face: Node): CubeFaceBasis;
|
|
1299
|
+
/**
|
|
1300
|
+
* Cube-space point for face-local (u, v) in [0, 1]:
|
|
1301
|
+
* cube = forward + (2u-1) * right + (2v-1) * up
|
|
1302
|
+
*/
|
|
1303
|
+
declare function cubeFacePoint(basis: CubeFaceBasis, u: Node, v: Node): Node;
|
|
1304
|
+
/** Unit-sphere direction for face-local (u, v). */
|
|
1305
|
+
declare function cubeFaceDirection(basis: CubeFaceBasis, u: Node, v: Node): Node;
|
|
1306
|
+
/**
|
|
1307
|
+
* Project a basis axis onto the tangent plane at `dir` and normalize.
|
|
1308
|
+
* Used to build the sphere tangent frame for normal reconstruction.
|
|
1309
|
+
*/
|
|
1310
|
+
declare function tangentFromAxis(dir: Node, axis: Node): Node;
|
|
1311
|
+
/**
|
|
1312
|
+
* Reconstruct a unit tangent-space normal from its packed horizontal
|
|
1313
|
+
* components: `ny = sqrt(max(0, 1 - nx² - nz²))`.
|
|
1314
|
+
*/
|
|
1315
|
+
declare function unpackTangentNormal(nx: Node, nz: Node): Node;
|
|
1316
|
+
/**
|
|
1317
|
+
* Rotate a tangent-space normal into the sphere tangent frame
|
|
1318
|
+
* `(tu, dir, tv)` at `dir` and normalize.
|
|
1319
|
+
*
|
|
1320
|
+
* Mirrors: the CPU `computeSphereNormal` in `query/cpu-terrain-cache.ts`.
|
|
1321
|
+
*/
|
|
1322
|
+
declare function sphereTangentFrameNormal(dir: Node, basis: CubeFaceBasis, tangentNormal: Node): Node;
|
|
1323
|
+
/**
|
|
1324
|
+
* Pick the cube face index (0..5) whose normal axis dominates `dir`.
|
|
1325
|
+
* GPU mirror of `directionToFace` in `quadtree/topology/cubeSphereInverse.ts`.
|
|
1326
|
+
*/
|
|
1327
|
+
declare function cubeFaceFromDirection(dir: Node): Node;
|
|
1328
|
+
/**
|
|
1329
|
+
* Face-local (u, v) in [0, 1] for a direction known to fall on `face`.
|
|
1330
|
+
* GPU mirror of `directionToFaceUV` in `quadtree/topology/cubeSphereInverse.ts`.
|
|
1331
|
+
*/
|
|
1332
|
+
declare function cubeFaceUVFromDirection(basis: CubeFaceBasis, dir: Node): Node;
|
|
1333
|
+
|
|
847
1334
|
/**
|
|
848
1335
|
* Maps a value or node from texture space [0, 1] to vector space [-1, 1].
|
|
849
1336
|
*
|
|
@@ -916,5 +1403,31 @@ declare const voronoiCells: three_src_nodes_TSL_js.ShaderNodeFn<[three_tsl.Proxi
|
|
|
916
1403
|
uv: Node;
|
|
917
1404
|
}>]>;
|
|
918
1405
|
|
|
919
|
-
|
|
920
|
-
|
|
1406
|
+
/** Flat heightfield projection: tiles in the XZ plane, elevation along +Y. */
|
|
1407
|
+
declare function createFlatProjection(): SurfaceProjection;
|
|
1408
|
+
|
|
1409
|
+
interface CubeSphereProjectionConfig {
|
|
1410
|
+
radius: number;
|
|
1411
|
+
center?: Vec3Like;
|
|
1412
|
+
/** When true, elevation displaces inward and skirts point outward. */
|
|
1413
|
+
invert?: boolean;
|
|
1414
|
+
}
|
|
1415
|
+
/** Cube-sphere projection: six faces wrapped radially onto a sphere. */
|
|
1416
|
+
declare function createCubeSphereProjection(config: CubeSphereProjectionConfig): SurfaceProjection;
|
|
1417
|
+
|
|
1418
|
+
interface TorusProjectionConfig {
|
|
1419
|
+
majorRadius: number;
|
|
1420
|
+
minorRadius: number;
|
|
1421
|
+
center?: Vec3Like;
|
|
1422
|
+
/** When true, elevation displaces inward and skirts point outward. */
|
|
1423
|
+
invert?: boolean;
|
|
1424
|
+
/** Level-0 tile count along u before LOD subdivision (defaults to 1). */
|
|
1425
|
+
baseU?: number;
|
|
1426
|
+
/** Level-0 tile count along v before LOD subdivision (defaults to 1). */
|
|
1427
|
+
baseV?: number;
|
|
1428
|
+
}
|
|
1429
|
+
/** Torus (donut) projection: a single closed surface periodic in both axes. */
|
|
1430
|
+
declare function createTorusProjection(config: TorusProjectionConfig): SurfaceProjection;
|
|
1431
|
+
|
|
1432
|
+
export { ArrayTextureBackend, AtlasBackend, CUBE_FACES, CUBE_FACE_COUNT, Dir, TerrainGeometry, TerrainMesh, U32_EMPTY, allocLeafSet, allocSeamTable, augmentCubeSphereSampler, beginUpdate, blendAngleCorrectedNormals, buildLeafIndex, buildSeams2to1, compileComputeTask, createComputePipelineTasks, createCubeSphereProjection, createCubeSphereTopology, createElevationFieldContextTask, createFlatProjection, createFlatTopology, createInfiniteFlatTopology, createSpatialIndex, createState, createTerrainFieldStorage, createTerrainFieldTextureTask, createTerrainQuery, createTerrainRaycast, createTerrainSampler, createTerrainSamplerTask, createTerrainSurfaceQuery, createTerrainUniforms, createTorusProjection, createTorusTopology, createUniformsTask, cubeFaceBasis, cubeFaceDirection, cubeFaceFromDirection, cubeFacePoint, cubeFaceUVFromDirection, deriveNormalZ, directionToFace, directionToFaceUV, directionToLatLong, elevationFieldStageTask, elevationFn, elevationScale, executeComputeTask, faceUVToCube, getDeviceComputeLimits, gpuSpatialIndexStorageTask, gpuSpatialIndexUploadTask, innerTileSegments, instanceIdTask, isSkirtUV, isSkirtVertex, latLongToDirection, leafGpuBufferTask, leafStorageTask, loadTerrainField, loadTerrainFieldElevation, loadTerrainFieldNormal, maxLevel, maxNodes, origin, packTerrainFieldSample, positionNodeTask, positionToTorusParams, quadtreeConfigTask, quadtreeUpdate, quadtreeUpdateTask, radius, resetLeafSet, resetSeamTable, rootSize, sampleTerrainField, sampleTerrainFieldElevation, skirtScale, sphereTangentFrameNormal, storeTerrainField, tangentFromAxis, terrainFieldFilter, terrainFieldStageTask, terrainGraph, terrainQueryTask, terrainRaycastTask, terrainReadbackTask, terrainTasks, textureSpaceToVectorSpace, tileNodesTask, topology, topologyTask, torusOutwardNormal, torusUVToPoint, unpackTangentNormal, update, updateUniformsTask, vElevation, vGlobalVertexIndex, vectorSpaceToTextureSpace, voronoiCells, wrap01 };
|
|
1433
|
+
export type { ComputePipeline, ComputeStageCallback, CpuSurfaceOps, CreateTerrainSamplerParams, CubeFace, CubeFaceBasis, CubeSphereProjectionConfig, CubeSphereTopologyConfig, ElevationCallback, ElevationFieldContext, ElevationParams, ElevationRange, ElevationRangeOut, FieldNormalContext, FieldNormalFn, FlatTopologyConfig, GpuSpatialIndexContext, InfiniteFlatTopologyConfig, IntNodeInput, LeafGpuBufferState, LeafSet, LeafStorageState, LodMode, ProjectionKind, ProjectionRaycastContext, QuadtreeConfig, QuadtreeConfigState, QuadtreeState, RaycastOptions, RenderVertexPositionContext, RuntimeQueries, SeamTable, SpatialIndex, SurfaceKey, SurfaceNormalContext, SurfaceProjection, SurfaceProjectionCpu, SurfaceProjectionGpu, TerrainFieldStorage, TerrainFieldStorageBackendType, TerrainFieldStorageFormat, TerrainFieldStorageOptions, TerrainGraph, TerrainQuery, TerrainQueryContext, TerrainRaycast, TerrainRaycastConfig, TerrainRaycastResult, TerrainSample, TerrainSampleBatch, TerrainSampler, TerrainSphereQuery, TerrainSurfaceQuery, TerrainSurfaceSample, TerrainSurfaceSampleBatch, TerrainTasks, TerrainTile, TerrainTileBounds, TerrainUniformsContext, TerrainUniformsParams, TileBounds, TileId, Topology, TorusProjectionConfig, TorusSurfaceParams, TorusTopologyConfig, UpdateParams, Vec3, Vec3Like, Vec3Mutable$1 as Vec3Mutable };
|