@drawcall/lod 0.2.0 → 0.3.0
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/README.md +8 -6
- package/dist/bake.d.ts +22 -0
- package/dist/bake.js +88 -0
- package/dist/bake.js.map +1 -0
- package/dist/baked/codec.d.ts +3 -6
- package/dist/baked/codec.js +48 -154
- package/dist/baked/codec.js.map +1 -1
- package/dist/baked/coverage.d.ts +6 -3
- package/dist/baked/coverage.js +6 -3
- package/dist/baked/coverage.js.map +1 -1
- package/dist/baked/fields.d.ts +9 -0
- package/dist/baked/fields.js +22 -0
- package/dist/baked/fields.js.map +1 -0
- package/dist/baked/index.d.ts +12 -6
- package/dist/baked/index.js +22 -20
- package/dist/baked/index.js.map +1 -1
- package/dist/baked/interior/faces.d.ts +4 -3
- package/dist/baked/interior/faces.js +13 -10
- package/dist/baked/interior/faces.js.map +1 -1
- package/dist/baked/interior/material.d.ts +7 -10
- package/dist/baked/interior/material.js +29 -36
- package/dist/baked/interior/material.js.map +1 -1
- package/dist/baked/interior/rooms.js +1 -1
- package/dist/baked/interior/rooms.js.map +1 -1
- package/dist/baked/low.js +5 -4
- package/dist/baked/low.js.map +1 -1
- package/dist/baked/raster.js +6 -6
- package/dist/baked/raster.js.map +1 -1
- package/dist/baked/textures.d.ts +17 -0
- package/dist/baked/textures.js +95 -0
- package/dist/baked/textures.js.map +1 -0
- package/dist/baked/transfer.js +19 -18
- package/dist/baked/transfer.js.map +1 -1
- package/dist/baked/unwrap.js +4 -3
- package/dist/baked/unwrap.js.map +1 -1
- package/dist/baked/xatlas.js.map +1 -1
- package/dist/codec/container.d.ts +8 -0
- package/dist/codec/container.js +63 -0
- package/dist/codec/container.js.map +1 -0
- package/dist/codec/mesh.d.ts +8 -0
- package/dist/{mesh/codec.js → codec/mesh.js} +80 -52
- package/dist/codec/mesh.js.map +1 -0
- package/dist/dispose.d.ts +7 -4
- package/dist/dispose.js +20 -22
- package/dist/dispose.js.map +1 -1
- package/dist/gpu.d.ts +39 -0
- package/dist/gpu.js +41 -0
- package/dist/gpu.js.map +1 -0
- package/dist/impostor/bake/atlas.d.ts +4 -4
- package/dist/impostor/bake/atlas.js +12 -12
- package/dist/impostor/bake/atlas.js.map +1 -1
- package/dist/impostor/bake/fit.d.ts +8 -0
- package/dist/impostor/bake/fit.js +28 -0
- package/dist/impostor/bake/fit.js.map +1 -0
- package/dist/impostor/bake/index.d.ts +22 -14
- package/dist/impostor/bake/index.js +41 -134
- package/dist/impostor/bake/index.js.map +1 -1
- package/dist/impostor/bake/materials.d.ts +3 -3
- package/dist/impostor/bake/materials.js +51 -13
- package/dist/impostor/bake/materials.js.map +1 -1
- package/dist/impostor/bake/sheet.d.ts +8 -0
- package/dist/impostor/bake/sheet.js +90 -0
- package/dist/impostor/bake/sheet.js.map +1 -0
- package/dist/impostor/bake/source.d.ts +2 -2
- package/dist/impostor/bake/source.js +8 -19
- package/dist/impostor/bake/source.js.map +1 -1
- package/dist/impostor/codec.d.ts +4 -5
- package/dist/impostor/codec.js +36 -109
- package/dist/impostor/codec.js.map +1 -1
- package/dist/impostor/impostor.d.ts +31 -7
- package/dist/impostor/impostor.js +21 -6
- package/dist/impostor/impostor.js.map +1 -1
- package/dist/impostor/ktx2/encode.d.ts +26 -0
- package/dist/impostor/ktx2/encode.js +117 -0
- package/dist/impostor/ktx2/encode.js.map +1 -0
- package/dist/impostor/ktx2/transcode.d.ts +3 -0
- package/dist/impostor/ktx2/transcode.js +99 -0
- package/dist/impostor/ktx2/transcode.js.map +1 -0
- package/dist/impostor/ktx2/uastc.d.ts +7 -0
- package/dist/impostor/ktx2/uastc.js +64 -0
- package/dist/impostor/ktx2/uastc.js.map +1 -0
- package/dist/impostor/ktx2/wasm/encoder.d.ts +4 -0
- package/dist/impostor/ktx2/wasm/encoder.js +10 -0
- package/dist/impostor/ktx2/wasm/encoder.js.map +1 -0
- package/dist/impostor/ktx2/wasm/transcoder.d.ts +3 -0
- package/dist/impostor/ktx2/wasm/transcoder.js +9 -0
- package/dist/impostor/ktx2/wasm/transcoder.js.map +1 -0
- package/dist/impostor/ktx2/worker.d.ts +1 -0
- package/dist/impostor/ktx2/worker.js +12 -0
- package/dist/impostor/ktx2/worker.js.map +1 -0
- package/dist/impostor/mesh/card.d.ts +3 -3
- package/dist/impostor/mesh/card.js +7 -7
- package/dist/impostor/mesh/card.js.map +1 -1
- package/dist/impostor/mesh/index.d.ts +5 -4
- package/dist/impostor/mesh/index.js +8 -9
- package/dist/impostor/mesh/index.js.map +1 -1
- package/dist/impostor/mesh/material.d.ts +18 -9
- package/dist/impostor/mesh/material.js +40 -27
- package/dist/impostor/mesh/material.js.map +1 -1
- package/dist/impostor/mesh/surface.d.ts +1 -1
- package/dist/impostor/mesh/surface.js +13 -9
- package/dist/impostor/mesh/surface.js.map +1 -1
- package/dist/impostor/mesh/textures.d.ts +3 -3
- package/dist/impostor/mesh/textures.js +24 -34
- package/dist/impostor/mesh/textures.js.map +1 -1
- package/dist/index.d.ts +15 -10
- package/dist/index.js +13 -8
- package/dist/index.js.map +1 -1
- package/dist/instanced/camera.d.ts +46 -0
- package/dist/instanced/camera.js +70 -0
- package/dist/instanced/camera.js.map +1 -0
- package/dist/instanced/chunk.d.ts +97 -0
- package/dist/instanced/chunk.js +156 -0
- package/dist/instanced/chunk.js.map +1 -0
- package/dist/instanced/chunks.d.ts +60 -0
- package/dist/instanced/chunks.js +208 -0
- package/dist/instanced/chunks.js.map +1 -0
- package/dist/instanced/cull.d.ts +28 -0
- package/dist/instanced/cull.js +22 -0
- package/dist/instanced/cull.js.map +1 -0
- package/dist/instanced/index.d.ts +96 -66
- package/dist/instanced/index.js +229 -288
- package/dist/instanced/index.js.map +1 -1
- package/dist/instanced/key.d.ts +19 -0
- package/dist/instanced/key.js +45 -0
- package/dist/instanced/key.js.map +1 -0
- package/dist/instanced/levels.d.ts +60 -0
- package/dist/instanced/levels.js +130 -0
- package/dist/instanced/levels.js.map +1 -0
- package/dist/instanced/lists.d.ts +70 -0
- package/dist/instanced/lists.js +133 -0
- package/dist/instanced/lists.js.map +1 -0
- package/dist/instanced/measure.d.ts +28 -0
- package/dist/instanced/measure.js +203 -0
- package/dist/instanced/measure.js.map +1 -0
- package/dist/instanced/meshes.d.ts +42 -51
- package/dist/instanced/meshes.js +158 -180
- package/dist/instanced/meshes.js.map +1 -1
- package/dist/instanced/mirror.d.ts +20 -0
- package/dist/instanced/mirror.js +37 -0
- package/dist/instanced/mirror.js.map +1 -0
- package/dist/instanced/pages/buffers.d.ts +37 -0
- package/dist/instanced/pages/buffers.js +15 -0
- package/dist/instanced/pages/buffers.js.map +1 -0
- package/dist/instanced/pages/chunk.d.ts +51 -0
- package/dist/instanced/pages/chunk.js +81 -0
- package/dist/instanced/pages/chunk.js.map +1 -0
- package/dist/instanced/pages/index.d.ts +74 -0
- package/dist/instanced/pages/index.js +269 -0
- package/dist/instanced/pages/index.js.map +1 -0
- package/dist/instanced/pages/passes.d.ts +21 -0
- package/dist/instanced/pages/passes.js +52 -0
- package/dist/instanced/pages/passes.js.map +1 -0
- package/dist/instanced/pages/slots.d.ts +11 -0
- package/dist/instanced/pages/slots.js +90 -0
- package/dist/instanced/pages/slots.js.map +1 -0
- package/dist/instanced/pages/workgroup.d.ts +14 -0
- package/dist/instanced/pages/workgroup.js +38 -0
- package/dist/instanced/pages/workgroup.js.map +1 -0
- package/dist/instanced/raycast.d.ts +13 -11
- package/dist/instanced/raycast.js +33 -40
- package/dist/instanced/raycast.js.map +1 -1
- package/dist/instanced/rows.d.ts +108 -0
- package/dist/instanced/rows.js +209 -0
- package/dist/instanced/rows.js.map +1 -0
- package/dist/instanced/shape.d.ts +25 -0
- package/dist/instanced/shape.js +51 -0
- package/dist/instanced/shape.js.map +1 -0
- package/dist/instanced/sort.d.ts +63 -0
- package/dist/instanced/sort.js +162 -0
- package/dist/instanced/sort.js.map +1 -0
- package/dist/instanced/update.d.ts +30 -0
- package/dist/instanced/update.js +207 -0
- package/dist/instanced/update.js.map +1 -0
- package/dist/levels/bounds.d.ts +21 -0
- package/dist/levels/bounds.js +42 -0
- package/dist/levels/bounds.js.map +1 -0
- package/dist/levels/cameras.d.ts +48 -0
- package/dist/levels/cameras.js +122 -0
- package/dist/levels/cameras.js.map +1 -0
- package/dist/levels/compile/contexts.d.ts +30 -0
- package/dist/levels/compile/contexts.js +18 -0
- package/dist/levels/compile/contexts.js.map +1 -0
- package/dist/levels/compile/index.d.ts +39 -0
- package/dist/levels/compile/index.js +185 -0
- package/dist/levels/compile/index.js.map +1 -0
- package/dist/levels/compile/pipelines.d.ts +26 -0
- package/dist/levels/compile/pipelines.js +177 -0
- package/dist/levels/compile/pipelines.js.map +1 -0
- package/dist/levels/compiles.d.ts +29 -0
- package/dist/levels/compiles.js +50 -0
- package/dist/levels/compiles.js.map +1 -0
- package/dist/levels/draw.d.ts +102 -0
- package/dist/levels/draw.js +401 -0
- package/dist/levels/draw.js.map +1 -0
- package/dist/levels/fade.d.ts +69 -0
- package/dist/levels/fade.js +150 -0
- package/dist/levels/fade.js.map +1 -0
- package/dist/levels/index.d.ts +99 -0
- package/dist/levels/index.js +155 -0
- package/dist/levels/index.js.map +1 -0
- package/dist/levels/item.d.ts +38 -0
- package/dist/levels/item.js +97 -0
- package/dist/levels/item.js.map +1 -0
- package/dist/levels/load.d.ts +31 -0
- package/dist/levels/load.js +142 -0
- package/dist/levels/load.js.map +1 -0
- package/dist/levels/manager.d.ts +159 -0
- package/dist/levels/manager.js +339 -0
- package/dist/levels/manager.js.map +1 -0
- package/dist/{material.js → levels/material.js} +4 -3
- package/dist/levels/material.js.map +1 -0
- package/dist/levels/renderer.d.ts +29 -0
- package/dist/levels/renderer.js +41 -0
- package/dist/levels/renderer.js.map +1 -0
- package/dist/levels/requests.d.ts +49 -0
- package/dist/levels/requests.js +95 -0
- package/dist/levels/requests.js.map +1 -0
- package/dist/levels/screen.d.ts +14 -0
- package/dist/levels/screen.js +21 -0
- package/dist/levels/screen.js.map +1 -0
- package/dist/levels/wait.d.ts +27 -0
- package/dist/levels/wait.js +61 -0
- package/dist/levels/wait.js.map +1 -0
- package/dist/loader/build.d.ts +10 -0
- package/dist/loader/build.js +28 -0
- package/dist/loader/build.js.map +1 -0
- package/dist/loader/cache.d.ts +6 -9
- package/dist/loader/cache.js +17 -24
- package/dist/loader/cache.js.map +1 -1
- package/dist/loader/context.d.ts +46 -0
- package/dist/loader/context.js +91 -0
- package/dist/loader/context.js.map +1 -0
- package/dist/loader/{provenance.d.ts → dependencies.d.ts} +5 -3
- package/dist/loader/{provenance.js → dependencies.js} +12 -4
- package/dist/loader/dependencies.js.map +1 -0
- package/dist/loader/index.d.ts +62 -0
- package/dist/loader/index.js +284 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/level.d.ts +41 -0
- package/dist/loader/level.js +140 -0
- package/dist/loader/level.js.map +1 -0
- package/dist/loader/request.d.ts +87 -0
- package/dist/loader/request.js +59 -0
- package/dist/loader/request.js.map +1 -0
- package/dist/loader/url.d.ts +5 -2
- package/dist/loader/url.js +10 -6
- package/dist/loader/url.js.map +1 -1
- package/dist/lod.d.ts +81 -40
- package/dist/lod.js +196 -149
- package/dist/lod.js.map +1 -1
- package/dist/meshopt.d.ts +6 -0
- package/dist/meshopt.js +19 -0
- package/dist/meshopt.js.map +1 -0
- package/dist/simplify/cards.d.ts +14 -0
- package/dist/simplify/cards.js +128 -0
- package/dist/simplify/cards.js.map +1 -0
- package/dist/{simplify.d.ts → simplify/index.d.ts} +7 -4
- package/dist/{simplify.js → simplify/index.js} +41 -23
- package/dist/simplify/index.js.map +1 -0
- package/dist/{bounds.d.ts → source/detail.d.ts} +4 -23
- package/dist/{bounds.js → source/detail.js} +19 -51
- package/dist/source/detail.js.map +1 -0
- package/dist/source/deviation.js +6 -6
- package/dist/source/deviation.js.map +1 -1
- package/dist/source/{shading.d.ts → evaluator.d.ts} +10 -10
- package/dist/source/{shading.js → evaluator.js} +5 -5
- package/dist/source/evaluator.js.map +1 -0
- package/dist/source/{trace.d.ts → raycaster.d.ts} +6 -6
- package/dist/source/{trace.js → raycaster.js} +8 -8
- package/dist/source/raycaster.js.map +1 -0
- package/dist/source/{texels.d.ts → sampler.d.ts} +1 -1
- package/dist/source/{texels.js → sampler.js} +3 -3
- package/dist/source/sampler.js.map +1 -0
- package/dist/source/source.d.ts +1 -1
- package/dist/source/source.js +1 -1
- package/dist/source/source.js.map +1 -1
- package/dist/source/surface.js +1 -1
- package/dist/source/surface.js.map +1 -1
- package/dist/task.d.ts +6 -0
- package/dist/{pause.js → task.js} +5 -5
- package/dist/task.js.map +1 -0
- package/dist/three.d.ts +13 -24
- package/dist/three.js +26 -53
- package/dist/three.js.map +1 -1
- package/dist/tsl.d.ts +8 -12
- package/dist/tsl.js +11 -39
- package/dist/tsl.js.map +1 -1
- package/dist/typegpu.d.ts +37 -0
- package/dist/typegpu.js +37 -0
- package/dist/typegpu.js.map +1 -0
- package/dist/wind/bounds.js +2 -2
- package/dist/wind/bounds.js.map +1 -1
- package/dist/wind/hooks.d.ts +7 -4
- package/dist/wind/hooks.js +5 -2
- package/dist/wind/hooks.js.map +1 -1
- package/dist/wind/index.d.ts +2 -2
- package/dist/wind/index.js +15 -15
- package/dist/wind/index.js.map +1 -1
- package/dist/wind/sway.d.ts +2 -0
- package/dist/wind/sway.js +4 -1
- package/dist/wind/sway.js.map +1 -1
- package/package.json +18 -8
- package/skills/lod/SKILL.md +108 -31
- package/dist/bounds.js.map +0 -1
- package/dist/compile.d.ts +0 -4
- package/dist/compile.js +0 -100
- package/dist/compile.js.map +0 -1
- package/dist/deferred.d.ts +0 -12
- package/dist/deferred.js +0 -27
- package/dist/deferred.js.map +0 -1
- package/dist/fade.d.ts +0 -36
- package/dist/fade.js +0 -112
- package/dist/fade.js.map +0 -1
- package/dist/instanced/args.d.ts +0 -20
- package/dist/instanced/args.js +0 -77
- package/dist/instanced/args.js.map +0 -1
- package/dist/instanced/blocks.d.ts +0 -66
- package/dist/instanced/blocks.js +0 -294
- package/dist/instanced/blocks.js.map +0 -1
- package/dist/instanced/dirty.d.ts +0 -15
- package/dist/instanced/dirty.js +0 -96
- package/dist/instanced/dirty.js.map +0 -1
- package/dist/instanced/parts.d.ts +0 -14
- package/dist/instanced/parts.js +0 -79
- package/dist/instanced/parts.js.map +0 -1
- package/dist/instanced/select.d.ts +0 -92
- package/dist/instanced/select.js +0 -315
- package/dist/instanced/select.js.map +0 -1
- package/dist/instanced/store.d.ts +0 -31
- package/dist/instanced/store.js +0 -96
- package/dist/instanced/store.js.map +0 -1
- package/dist/levels.d.ts +0 -95
- package/dist/levels.js +0 -171
- package/dist/levels.js.map +0 -1
- package/dist/loader/bundle.d.ts +0 -25
- package/dist/loader/bundle.js +0 -241
- package/dist/loader/bundle.js.map +0 -1
- package/dist/loader/provenance.js.map +0 -1
- package/dist/loader.d.ts +0 -55
- package/dist/loader.js +0 -239
- package/dist/loader.js.map +0 -1
- package/dist/material.js.map +0 -1
- package/dist/mesh/codec.d.ts +0 -4
- package/dist/mesh/codec.js.map +0 -1
- package/dist/pause.d.ts +0 -6
- package/dist/pause.js.map +0 -1
- package/dist/queue.d.ts +0 -2
- package/dist/queue.js +0 -33
- package/dist/queue.js.map +0 -1
- package/dist/renderer.d.ts +0 -21
- package/dist/renderer.js +0 -83
- package/dist/renderer.js.map +0 -1
- package/dist/residency.d.ts +0 -44
- package/dist/residency.js +0 -205
- package/dist/residency.js.map +0 -1
- package/dist/simplify.js.map +0 -1
- package/dist/source/shading.js.map +0 -1
- package/dist/source/texels.js.map +0 -1
- package/dist/source/trace.js.map +0 -1
- package/dist/view.d.ts +0 -45
- package/dist/view.js +0 -131
- package/dist/view.js.map +0 -1
- /package/dist/{material.d.ts → levels/material.d.ts} +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Box3, InstancedBufferAttribute } from "three/webgpu";
|
|
2
|
+
import { isStorageInstanced } from "../three.js";
|
|
3
|
+
import { InstancedLodChunk, measureChunk } from "./chunk.js";
|
|
4
|
+
import { Mirror } from "./mirror.js";
|
|
5
|
+
import { MAX_SURVIVOR_SCALE } from "./measure.js";
|
|
6
|
+
/** `attribute`, a GPU chunk's, as the storage attribute InstancedLodChunk checked it is. */
|
|
7
|
+
function onGpu(attribute) {
|
|
8
|
+
if (!isStorageInstanced(attribute))
|
|
9
|
+
throw new TypeError("InstancedLod: a GPU chunk's attribute is not a storage attribute");
|
|
10
|
+
return attribute;
|
|
11
|
+
}
|
|
12
|
+
const grown = new Box3();
|
|
13
|
+
/**
|
|
14
|
+
* The chunks of one InstancedLod: their pool slots, the mirrors the pool reads CPU attributes through, and their
|
|
15
|
+
* bounds, which load levels and cull the level meshes.
|
|
16
|
+
*/
|
|
17
|
+
export class ChunkSet {
|
|
18
|
+
pool;
|
|
19
|
+
row;
|
|
20
|
+
bounds;
|
|
21
|
+
reach;
|
|
22
|
+
levelAt;
|
|
23
|
+
held = new Map();
|
|
24
|
+
mirrors = new Map();
|
|
25
|
+
/** Bumped whenever a chunk was added, removed or re-measured: what `heights` reads changed. */
|
|
26
|
+
version = 0;
|
|
27
|
+
/**
|
|
28
|
+
* Chunks over `pool`, for the InstancedLod sorting as row `row`, whose instances `bounds` bounds in the InstancedLod's space; `reach` tells how far from an
|
|
29
|
+
* instance's origin, in its space, every level and its sway reach, and `levelAt` is what a chunk's getLevelAt asks.
|
|
30
|
+
*/
|
|
31
|
+
constructor(pool, row, bounds, reach, levelAt) {
|
|
32
|
+
this.pool = pool;
|
|
33
|
+
this.row = row;
|
|
34
|
+
this.bounds = bounds;
|
|
35
|
+
this.reach = reach;
|
|
36
|
+
this.levelAt = levelAt;
|
|
37
|
+
}
|
|
38
|
+
get size() {
|
|
39
|
+
return this.held.size;
|
|
40
|
+
}
|
|
41
|
+
/** The chunks, in the order they were added. */
|
|
42
|
+
keys() {
|
|
43
|
+
return this.held.keys();
|
|
44
|
+
}
|
|
45
|
+
/** The pool slots of the chunks. */
|
|
46
|
+
slots() {
|
|
47
|
+
return [...this.held.values()].map(({ slot }) => slot);
|
|
48
|
+
}
|
|
49
|
+
/** The chunks whose instances the CPU holds. */
|
|
50
|
+
cpu() {
|
|
51
|
+
return [...this.held].flatMap(([chunk, { state }]) => (state.gpu ? [] : [chunk]));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* What makes chunks of their own with every chunk's instances, their attributes copied (see `InstancedLod.copy`). A
|
|
55
|
+
* GPU chunk cannot be copied: its instances live on the GPU.
|
|
56
|
+
*/
|
|
57
|
+
copies() {
|
|
58
|
+
const cpu = this.cpu();
|
|
59
|
+
if (cpu.length !== this.size)
|
|
60
|
+
throw new Error("InstancedLod.copy: a GPU chunk's instances live on the GPU and cannot be copied");
|
|
61
|
+
return cpu.map(({ instanceMatrix, instanceColor, start, count }) => ({
|
|
62
|
+
instanceMatrix: copyOf(instanceMatrix),
|
|
63
|
+
instanceColor: instanceColor ? copyOf(instanceColor) : undefined,
|
|
64
|
+
start,
|
|
65
|
+
count,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
/** Hold `parameters`' instances as a chunk, copied into the pool at its next run; `bound` bounds it. */
|
|
69
|
+
add(parameters) {
|
|
70
|
+
const gpu = isStorageInstanced(parameters.instanceMatrix);
|
|
71
|
+
const state = { gpu, originBox: new Box3(), minScale: 0, maxScale: 0, boundingBox: new Box3(), levelAt: null };
|
|
72
|
+
const chunk = new InstancedLodChunk(parameters, state);
|
|
73
|
+
const { instanceMatrix, instanceColor, instanceCount } = chunk;
|
|
74
|
+
const attributes = gpu
|
|
75
|
+
? // A storage attribute's RGB is padded to four floats.
|
|
76
|
+
{ matrices: onGpu(instanceMatrix), colors: instanceColor && { attribute: onGpu(instanceColor), stride: 4 }, counts: instanceCount }
|
|
77
|
+
: {
|
|
78
|
+
matrices: this.mirror(instanceMatrix, chunk).attribute,
|
|
79
|
+
colors: instanceColor && { attribute: this.mirror(instanceColor, chunk).attribute, stride: 3 },
|
|
80
|
+
counts: null,
|
|
81
|
+
};
|
|
82
|
+
const slot = this.pool.add({ attributes, start: chunk.start, count: chunk.count, countIndex: chunk.instanceCountIndex, row: this.row });
|
|
83
|
+
state.levelAt = (index, camera) => this.levelAt(chunk, index, camera);
|
|
84
|
+
this.held.set(chunk, { slot, state });
|
|
85
|
+
this.version++;
|
|
86
|
+
return chunk;
|
|
87
|
+
}
|
|
88
|
+
/** Let go of `chunk`; its pages return to the pool at its next run. */
|
|
89
|
+
remove(chunk) {
|
|
90
|
+
const held = this.held.get(chunk);
|
|
91
|
+
if (!held)
|
|
92
|
+
throw new Error("InstancedLod: the chunk is not one of its chunks");
|
|
93
|
+
this.pool.remove(held.slot);
|
|
94
|
+
held.state.levelAt = null;
|
|
95
|
+
this.held.delete(chunk);
|
|
96
|
+
this.version++;
|
|
97
|
+
for (const attribute of [chunk.instanceMatrix, chunk.instanceColor]) {
|
|
98
|
+
const shared = attribute && this.mirrors.get(attribute);
|
|
99
|
+
if (!shared)
|
|
100
|
+
continue;
|
|
101
|
+
shared.users.delete(chunk);
|
|
102
|
+
if (shared.users.size > 0)
|
|
103
|
+
continue;
|
|
104
|
+
shared.mirror.dispose();
|
|
105
|
+
this.mirrors.delete(shared.mirror.source);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Take in the CPU attributes' edits, those whose versions moved, for every chunk reading them: re-measured, and
|
|
110
|
+
* copied into the pool again at its next run. Whether any changed; `bound` bounds them.
|
|
111
|
+
*/
|
|
112
|
+
refresh() {
|
|
113
|
+
const changed = new Set();
|
|
114
|
+
for (const { mirror, users } of this.mirrors.values()) {
|
|
115
|
+
if (!mirror.refresh())
|
|
116
|
+
continue;
|
|
117
|
+
for (const chunk of users) {
|
|
118
|
+
if (chunk.instanceMatrix === mirror.source)
|
|
119
|
+
measureChunk(chunk, this.heldOf(chunk).state);
|
|
120
|
+
changed.add(chunk);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
for (const chunk of changed)
|
|
124
|
+
this.pool.change(this.heldOf(chunk).slot);
|
|
125
|
+
if (changed.size > 0)
|
|
126
|
+
this.version++;
|
|
127
|
+
return changed.size > 0;
|
|
128
|
+
}
|
|
129
|
+
/** Bound every chunk, its box (see `InstancedLodChunk.boundingBox`), and all of them, survivors grown by up to `grow`. */
|
|
130
|
+
bound(grow) {
|
|
131
|
+
const { sphere, box } = this.bounds;
|
|
132
|
+
const reach = this.reach();
|
|
133
|
+
box.makeEmpty();
|
|
134
|
+
for (const { state } of this.held.values()) {
|
|
135
|
+
if (state.originBox.isEmpty()) {
|
|
136
|
+
state.boundingBox.makeEmpty();
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
state.boundingBox.copy(state.originBox).expandByScalar(reach * state.maxScale);
|
|
140
|
+
box.union(grown.copy(state.originBox).expandByScalar(reach * state.maxScale * grow));
|
|
141
|
+
}
|
|
142
|
+
if (box.isEmpty())
|
|
143
|
+
sphere.makeEmpty();
|
|
144
|
+
else
|
|
145
|
+
box.getBoundingSphere(sphere);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The heights on a screen of `scale` from `eye`, both in the InstancedLod's space, that each chunk's instances can
|
|
149
|
+
* have, `source` an instance's source sphere: its shortest instance at its farthest, its tallest at its nearest.
|
|
150
|
+
*/
|
|
151
|
+
*heights(source, eye, scale, ortho, cull) {
|
|
152
|
+
const grow = cull?.survivors ? MAX_SURVIVOR_SCALE : 1;
|
|
153
|
+
const diameter = 2 * source.radius * scale;
|
|
154
|
+
for (const { state } of this.held.values()) {
|
|
155
|
+
const { originBox, minScale, maxScale } = state;
|
|
156
|
+
if (originBox.isEmpty() || maxScale === 0)
|
|
157
|
+
continue;
|
|
158
|
+
if (cull && originBox.distanceToPoint(cull.eye) >= cull.far)
|
|
159
|
+
continue;
|
|
160
|
+
const shortest = diameter * minScale;
|
|
161
|
+
const tallest = diameter * maxScale * grow;
|
|
162
|
+
if (ortho) {
|
|
163
|
+
yield [shortest, tallest];
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
// An instance's centre lies this far from its origin.
|
|
167
|
+
const offset = source.center.length() * maxScale * grow;
|
|
168
|
+
const near = Math.max(originBox.distanceToPoint(eye) - offset, 1e-6);
|
|
169
|
+
const far = farthest(originBox, eye) + offset;
|
|
170
|
+
yield [shortest / far, tallest / near];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** Free the chunks' slots and release the mirrors; the chunks no longer find their levels. */
|
|
174
|
+
dispose() {
|
|
175
|
+
for (const { slot, state } of this.held.values()) {
|
|
176
|
+
this.pool.remove(slot);
|
|
177
|
+
state.levelAt = null;
|
|
178
|
+
}
|
|
179
|
+
this.held.clear();
|
|
180
|
+
this.version++;
|
|
181
|
+
for (const { mirror } of this.mirrors.values())
|
|
182
|
+
mirror.dispose();
|
|
183
|
+
this.mirrors.clear();
|
|
184
|
+
}
|
|
185
|
+
/** The mirror of `attribute`, which `chunk` reads too. */
|
|
186
|
+
mirror(attribute, chunk) {
|
|
187
|
+
const shared = this.mirrors.get(attribute) ?? { mirror: new Mirror(attribute), users: new Set() };
|
|
188
|
+
this.mirrors.set(attribute, shared);
|
|
189
|
+
shared.users.add(chunk);
|
|
190
|
+
return shared.mirror;
|
|
191
|
+
}
|
|
192
|
+
heldOf(chunk) {
|
|
193
|
+
const held = this.held.get(chunk);
|
|
194
|
+
if (!held)
|
|
195
|
+
throw new Error("InstancedLod: a mirror's chunk is not one of its chunks");
|
|
196
|
+
return held;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** The distance from `point` to the farthest point of `box`. */
|
|
200
|
+
function farthest(box, point) {
|
|
201
|
+
const { min, max } = box;
|
|
202
|
+
return Math.hypot(Math.max(Math.abs(point.x - min.x), Math.abs(point.x - max.x)), Math.max(Math.abs(point.y - min.y), Math.abs(point.y - max.y)), Math.max(Math.abs(point.z - min.z), Math.abs(point.z - max.z)));
|
|
203
|
+
}
|
|
204
|
+
/** A CPU attribute of its own with `attribute`'s instances. */
|
|
205
|
+
function copyOf(attribute) {
|
|
206
|
+
return new InstancedBufferAttribute(attribute.array.slice(), attribute.itemSize);
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=chunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunks.js","sourceRoot":"","sources":["../../src/instanced/chunks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Matrix4, Vector3, type Camera } from "three/webgpu";
|
|
2
|
+
/**
|
|
3
|
+
* How an InstancedLod thins its instances out with distance from `camera`, in every camera, as Fog does: every instance
|
|
4
|
+
* draws up to `near` from it, none from `far` on, and in between a share falling linearly, chosen by a hash of each
|
|
5
|
+
* instance's origin (its matrix's translation), the same on the CPU and the GPU. An instance whose translation changes
|
|
6
|
+
* rolls a new value: it may appear or vanish as it moves. With `scaleSurvivors`, the instances drawn grow by 1/√share,
|
|
7
|
+
* up to `MAX_SURVIVOR_SCALE` (8), so a thinned field stays about as covered.
|
|
8
|
+
*/
|
|
9
|
+
export interface CullDistance {
|
|
10
|
+
camera: Camera;
|
|
11
|
+
near: number;
|
|
12
|
+
far: number;
|
|
13
|
+
scaleSurvivors?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** cullDistance in the InstancedLod's space. */
|
|
16
|
+
export interface Cull {
|
|
17
|
+
eye: Vector3;
|
|
18
|
+
near: number;
|
|
19
|
+
far: number;
|
|
20
|
+
survivors: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* `cullDistance`, checked, in the space of `space`, an InstancedLod's world matrix, written into `target`; null for
|
|
24
|
+
* none. Nothing holds on to what it answers past a sort: the sort and its keys copy its values.
|
|
25
|
+
*/
|
|
26
|
+
export declare function cullIn(cullDistance: CullDistance | null, space: Matrix4, target: Cull): Cull | null;
|
|
27
|
+
/** A Cull to write into (see `cullIn`). */
|
|
28
|
+
export declare const emptyCull: () => Cull;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Matrix4, Vector3 } from "three/webgpu";
|
|
2
|
+
const inverse = new Matrix4();
|
|
3
|
+
/**
|
|
4
|
+
* `cullDistance`, checked, in the space of `space`, an InstancedLod's world matrix, written into `target`; null for
|
|
5
|
+
* none. Nothing holds on to what it answers past a sort: the sort and its keys copy its values.
|
|
6
|
+
*/
|
|
7
|
+
export function cullIn(cullDistance, space, target) {
|
|
8
|
+
if (!cullDistance)
|
|
9
|
+
return null;
|
|
10
|
+
const { camera, near, far, scaleSurvivors = false } = cullDistance;
|
|
11
|
+
if (!(Number.isFinite(near) && Number.isFinite(far) && near >= 0 && far > near))
|
|
12
|
+
throw new RangeError(`InstancedLod: cullDistance needs 0 <= near < far, both finite, got ${near} and ${far}`);
|
|
13
|
+
const scale = space.getMaxScaleOnAxis();
|
|
14
|
+
target.eye.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(inverse.copy(space).invert());
|
|
15
|
+
target.near = near / scale;
|
|
16
|
+
target.far = far / scale;
|
|
17
|
+
target.survivors = scaleSurvivors;
|
|
18
|
+
return target;
|
|
19
|
+
}
|
|
20
|
+
/** A Cull to write into (see `cullIn`). */
|
|
21
|
+
export const emptyCull = () => ({ eye: new Vector3(), near: 0, far: 0, survivors: false });
|
|
22
|
+
//# sourceMappingURL=cull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cull.js","sourceRoot":"","sources":["../../src/instanced/cull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAe,MAAM,cAAc,CAAC;AAwB7D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,YAAiC,EAAE,KAAc,EAAE,MAAY;IACpF,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,cAAc,GAAG,KAAK,EAAE,GAAG,YAAY,CAAC;IACnE,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC;QAC7E,MAAM,IAAI,UAAU,CAAC,sEAAsE,IAAI,QAAQ,GAAG,EAAE,CAAC,CAAC;IAChH,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC;IACxC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAChG,MAAM,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;IAC3B,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC;IACzB,MAAM,CAAC,SAAS,GAAG,cAAc,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2CAA2C;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAG,GAAS,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC"}
|
|
@@ -1,90 +1,120 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type
|
|
3
|
-
import { type
|
|
4
|
-
import {
|
|
1
|
+
import { Object3D, type Camera, type Intersection, type LoadingManager, type Raycaster } from "three/webgpu";
|
|
2
|
+
import { type LodLevel, type ThresholdedLevel } from "../levels/index.js";
|
|
3
|
+
import { type LodEventMap } from "../levels/manager.js";
|
|
4
|
+
import type { LodGpu } from "../gpu.js";
|
|
5
|
+
import { type LodOptions } from "../lod.js";
|
|
6
|
+
import { WIND } from "../wind/hooks.js";
|
|
7
|
+
import type { InstancedLodChunk, InstancedLodChunkParameters } from "./chunk.js";
|
|
8
|
+
import { type CullDistance } from "./cull.js";
|
|
9
|
+
/** How an InstancedLod is made. */
|
|
10
|
+
export interface InstancedLodOptions extends LodOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The most instances it draws for a camera, over all its chunks, CPU and GPU chunks alike: 16384 by default. Its
|
|
13
|
+
* lists take 8 bytes per level that draws something per instance (about 400 KB with the defaults and three levels),
|
|
14
|
+
* and every camera that draws any InstancedLod of its LodGpu, each shadow map's included, holds the lists of every
|
|
15
|
+
* InstancedLod of that LodGpu. A camera that draws only a few InstancedLods, such as a minimap's or a reflection's,
|
|
16
|
+
* is bounded by giving those a LodGpu of their own. Chunks that together outgrow it are reported (see `error`),
|
|
17
|
+
* naming it as the limit to raise. Its LodGpu's pool holds the instances themselves (see `LodGpuOptions`).
|
|
18
|
+
*/
|
|
19
|
+
maxInstanceCount?: number;
|
|
20
|
+
}
|
|
5
21
|
/**
|
|
6
|
-
* Independently
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* the
|
|
22
|
+
* Independently drawn copies of one object, sorted into indirect draws per camera on the GPU. Instances arrive and
|
|
23
|
+
* leave in chunks (see `addChunk`), from the CPU or written by the app's GPU passes; `cullDistance` thins them out with
|
|
24
|
+
* distance. Thresholds, fades, loading and global settings follow Lod: each instance draws what levelsToDraw gives for
|
|
25
|
+
* its height. Each camera draws only the instances in its frustum, and each shadow map is a camera of its own: it draws
|
|
26
|
+
* the casters in its frustum, each at the level its texels resolve, as an orthographic camera would (an instance
|
|
27
|
+
* smaller than a texel casts nothing). Instance matrices may scale arbitrarily; the InstancedLod's own transform and its
|
|
28
|
+
* parents should scale uniformly. Scale 0 draws nothing.
|
|
29
|
+
*
|
|
30
|
+
* Level templates are cloned, then their meshes are instanced; it sets each level mesh's `visible` per camera, so hide
|
|
31
|
+
* the InstancedLod itself, never its level meshes. Skinned meshes, InstancedMeshes (except ImpostorMesh)
|
|
32
|
+
* and nested Lods are unsupported. For external detail, leave level 0 empty and draw the instances that
|
|
33
|
+
* `chunk.getLevelAt` reports there.
|
|
10
34
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
35
|
+
* Every level mesh's `geometry.boundingBox` and `boundingSphere` bound all its instances, not one, so
|
|
36
|
+
* `new Box3().setFromObject(lod)` bounds them once a level has loaded; with `precise` it walks a level's vertices once,
|
|
37
|
+
* at no instance, as it cannot see them. Measure one instance by a level's `object`, scaled by its matrix.
|
|
14
38
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
39
|
+
* Instances live in its LodGpu's pool, and every InstancedLod of a LodGpu sorts for a camera in one compute call.
|
|
40
|
+
* Requires WebGPU `indirect-first-instance`. Sequential cameras are supported; a nested render with a camera that the
|
|
41
|
+
* outer render also draws with replaces that camera's instance lists, so exclude this InstancedLod from it with camera
|
|
42
|
+
* layers.
|
|
17
43
|
*/
|
|
18
|
-
export declare class InstancedLod extends Object3D<
|
|
44
|
+
export declare class InstancedLod extends Object3D<LodEventMap> {
|
|
45
|
+
private readonly gpu;
|
|
19
46
|
readonly isLOD = true;
|
|
20
47
|
readonly isInstancedLod = true;
|
|
21
48
|
/** Let the renderer call `update` with its camera every frame. */
|
|
22
49
|
autoUpdate: boolean;
|
|
23
|
-
/** Draw only this level
|
|
50
|
+
/** Draw only this level, without fades, once the coarsest level that draws something has loaded. */
|
|
24
51
|
forceLevel: number | null;
|
|
25
|
-
|
|
26
|
-
readonly
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
52
|
+
/** The levels, each `object` the template its level meshes are made from, once there is one (never in the scene). */
|
|
53
|
+
readonly levels: ThresholdedLevel[];
|
|
54
|
+
/** Thins the instances out with distance from a camera, in every camera; null draws them at any distance. */
|
|
55
|
+
cullDistance: CullDistance | null;
|
|
56
|
+
/** The levels as they were given, which a copy is made from. */
|
|
57
|
+
private inputs;
|
|
58
|
+
/** What it is made of for its levels and sizes, which a copy makes anew. */
|
|
59
|
+
private built;
|
|
32
60
|
private disposed;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
private readonly reaches;
|
|
43
|
-
/** Logical demand at the initial default viewport, separate from first-draw visibility. */
|
|
44
|
-
private readonly demand;
|
|
45
|
-
/** Source-radius padding for the shadow caster cutoff; culling pads every level separately. */
|
|
46
|
-
private padding;
|
|
47
|
-
private blocks;
|
|
48
|
-
private readonly last;
|
|
61
|
+
/** Around every instance, survivors grown: what every level mesh is culled and boxed by. */
|
|
62
|
+
private readonly bounds;
|
|
63
|
+
/** What `cullIn` writes cullDistance into, in this InstancedLod's space. */
|
|
64
|
+
private readonly cull;
|
|
65
|
+
/**
|
|
66
|
+
* `levels[0]` is the source. Empty only as the target of `copy`. It holds no instances until chunks are added. `gpu`
|
|
67
|
+
* is what it shares with every Lod drawing with its renderer.
|
|
68
|
+
*/
|
|
69
|
+
constructor(levels: readonly LodLevel[], gpu: LodGpu, options?: InstancedLodOptions);
|
|
49
70
|
get pending(): boolean;
|
|
50
71
|
get error(): Error | undefined;
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
private
|
|
58
|
-
setMatrixAt(index: number, matrix: Matrix4): void;
|
|
59
|
-
getMatrixAt(index: number, matrix: Matrix4): Matrix4;
|
|
60
|
-
/** Tint instance `index` by `color`, as InstancedMesh.setColorAt does, in every level. */
|
|
61
|
-
setColorAt(index: number, color: Color): void;
|
|
62
|
-
/** Instance `index`'s colour: white unless set. */
|
|
63
|
-
getColorAt(index: number, color: Color): Color;
|
|
72
|
+
/** Where the item of levels a camera misses goes (see `LodOptions.manager`). */
|
|
73
|
+
get manager(): LoadingManager;
|
|
74
|
+
set manager(manager: LoadingManager | undefined);
|
|
75
|
+
/** Its chunks, in the order they were added. */
|
|
76
|
+
get chunks(): Iterable<InstancedLodChunk>;
|
|
77
|
+
/** What this InstancedLod is made of for `inputs` and `maxInstanceCount`: its levels, their meshes and their loading. */
|
|
78
|
+
private init;
|
|
64
79
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
80
|
+
* Add `parameters`' instances as one chunk, from the CPU or the GPU (see `InstancedLodChunkParameters`). The next
|
|
81
|
+
* render that updates this InstancedLod copies them into its pages. Its item (see `LodOptions.manager`) stays held
|
|
82
|
+
* until the GPU shows every chunk copied; a chunk the pool lacks pages for draws the instances it got until it is
|
|
83
|
+
* removed, and is this InstancedLod's error (see `error`).
|
|
67
84
|
*/
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
addChunk(parameters: InstancedLodChunkParameters): InstancedLodChunk;
|
|
86
|
+
/** Remove `chunk`'s instances; its pages return to the pool in the next render. */
|
|
87
|
+
removeChunk(chunk: InstancedLodChunk): void;
|
|
88
|
+
/** Bound every chunk's instances, survivors grown. */
|
|
89
|
+
private measureBounds;
|
|
90
|
+
[WIND](padding: number, slope: number, baseY: number): void;
|
|
91
|
+
/** Sort the instances into level lists for `camera`, a camera's or a shadow map's, and load the levels they need. What fails is reported (see `error`). */
|
|
73
92
|
update(camera: Camera): void;
|
|
74
|
-
/**
|
|
75
|
-
private
|
|
93
|
+
/** Sort for `camera`, a shadow map's when `shadow`. */
|
|
94
|
+
private sort;
|
|
95
|
+
/** `camera` in this InstancedLod's space (see `localCamera`). */
|
|
96
|
+
private localCamera;
|
|
97
|
+
/** Draw survivors' scaled matrices, or the pool's again. */
|
|
98
|
+
private scaleSurvivors;
|
|
99
|
+
/** The level instance `index` of `chunk` draws most of its pixels with for `camera` (see `InstancedLodChunk.getLevelAt`). */
|
|
100
|
+
private levelAt;
|
|
76
101
|
/**
|
|
77
|
-
* Hits every instance
|
|
78
|
-
* InstancedLod.
|
|
102
|
+
* Hits every instance of its CPU chunks on the source level, with `instanceId` and `chunk` set (see
|
|
103
|
+
* `InstancedLodIntersection`); `object` is this InstancedLod. A GPU chunk's instances the CPU cannot see, and meshes
|
|
104
|
+
* of the source on layers the raycaster does not test, are not hit.
|
|
79
105
|
*/
|
|
80
106
|
raycast(raycaster: Raycaster, intersects: Intersection[]): boolean;
|
|
81
107
|
/**
|
|
82
|
-
* Copies `source`'s levels,
|
|
83
|
-
*
|
|
108
|
+
* Copies `source`'s levels, CPU chunks and settings into this empty InstancedLod, one without levels or chunks (it
|
|
109
|
+
* throws otherwise); the copy shares geometry and textures with `source`, and its chunks hold copies of the source's
|
|
110
|
+
* attributes. A GPU chunk cannot be copied: its instances live on the GPU.
|
|
84
111
|
*/
|
|
85
112
|
copy(source: InstancedLod): this;
|
|
86
113
|
clone(): this;
|
|
87
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Release its buffers and what it made of its levels, once nothing it prepares or compiles still uses them. Objects
|
|
116
|
+
* you give or load, chunk attributes among them, are yours to dispose; LodLoader's are freed when the last Lod
|
|
117
|
+
* holding them is disposed (see `LodLevel.hold`).
|
|
118
|
+
*/
|
|
88
119
|
dispose(): void;
|
|
89
|
-
private clearDraws;
|
|
90
120
|
}
|