@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
package/dist/instanced/index.js
CHANGED
|
@@ -1,349 +1,290 @@
|
|
|
1
|
-
import { Box3,
|
|
1
|
+
import { Box3, Object3D, Sphere } from "three/webgpu";
|
|
2
2
|
import { at } from "../at.js";
|
|
3
|
-
import { levelBox, measureLevels, prepareBounds } from "../bounds.js";
|
|
4
3
|
import { disposeCopies } from "../dispose.js";
|
|
5
|
-
import {
|
|
4
|
+
import { EncodedLevels, emptyLevels, levelsFrom } from "../levels/index.js";
|
|
5
|
+
import { fadeSourceOf } from "../levels/fade.js";
|
|
6
|
+
import { levelsToLoad } from "../levels/load.js";
|
|
7
|
+
import { LodLevelLoadManager } from "../levels/manager.js";
|
|
6
8
|
import { Lod } from "../lod.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
const
|
|
21
|
-
const inverse = new Matrix4();
|
|
9
|
+
import { inShadowMap } from "../levels/renderer.js";
|
|
10
|
+
import { sameClass } from "../three.js";
|
|
11
|
+
import { WIND } from "../wind/hooks.js";
|
|
12
|
+
import { copyWind } from "../wind/index.js";
|
|
13
|
+
import { ChunkSet } from "./chunks.js";
|
|
14
|
+
import { cullIn, emptyCull } from "./cull.js";
|
|
15
|
+
import { MeshesByLevel } from "./levels.js";
|
|
16
|
+
import { InstanceLists, frustumIn, listedOf } from "./lists.js";
|
|
17
|
+
import { localCamera, shownBy, walk } from "./camera.js";
|
|
18
|
+
import { drawMatrices } from "./meshes.js";
|
|
19
|
+
import { raycastInstances } from "./raycast.js";
|
|
20
|
+
import { InstanceShape } from "./shape.js";
|
|
21
|
+
import { MAX_SURVIVOR_SCALE, instanceLevel } from "./measure.js";
|
|
22
|
+
const DEFAULT_INSTANCES = 16384;
|
|
22
23
|
/**
|
|
23
|
-
* Independently
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* the
|
|
24
|
+
* Independently drawn copies of one object, sorted into indirect draws per camera on the GPU. Instances arrive and
|
|
25
|
+
* leave in chunks (see `addChunk`), from the CPU or written by the app's GPU passes; `cullDistance` thins them out with
|
|
26
|
+
* distance. Thresholds, fades, loading and global settings follow Lod: each instance draws what levelsToDraw gives for
|
|
27
|
+
* its height. Each camera draws only the instances in its frustum, and each shadow map is a camera of its own: it draws
|
|
28
|
+
* the casters in its frustum, each at the level its texels resolve, as an orthographic camera would (an instance
|
|
29
|
+
* smaller than a texel casts nothing). Instance matrices may scale arbitrarily; the InstancedLod's own transform and its
|
|
30
|
+
* parents should scale uniformly. Scale 0 draws nothing.
|
|
27
31
|
*
|
|
28
|
-
* Level templates are cloned, then their meshes are instanced
|
|
29
|
-
*
|
|
30
|
-
* detail, leave level 0 empty and draw the instances that
|
|
32
|
+
* Level templates are cloned, then their meshes are instanced; it sets each level mesh's `visible` per camera, so hide
|
|
33
|
+
* the InstancedLod itself, never its level meshes. Skinned meshes, InstancedMeshes (except ImpostorMesh)
|
|
34
|
+
* and nested Lods are unsupported. For external detail, leave level 0 empty and draw the instances that
|
|
35
|
+
* `chunk.getLevelAt` reports there.
|
|
31
36
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
37
|
+
* Every level mesh's `geometry.boundingBox` and `boundingSphere` bound all its instances, not one, so
|
|
38
|
+
* `new Box3().setFromObject(lod)` bounds them once a level has loaded; with `precise` it walks a level's vertices once,
|
|
39
|
+
* at no instance, as it cannot see them. Measure one instance by a level's `object`, scaled by its matrix.
|
|
40
|
+
*
|
|
41
|
+
* Instances live in its LodGpu's pool, and every InstancedLod of a LodGpu sorts for a camera in one compute call.
|
|
42
|
+
* Requires WebGPU `indirect-first-instance`. Sequential cameras are supported; a nested render with a camera that the
|
|
43
|
+
* outer render also draws with replaces that camera's instance lists, so exclude this InstancedLod from it with camera
|
|
44
|
+
* layers.
|
|
34
45
|
*/
|
|
35
46
|
export class InstancedLod extends Object3D {
|
|
47
|
+
gpu;
|
|
36
48
|
isLOD = true;
|
|
37
49
|
isInstancedLod = true;
|
|
38
50
|
/** Let the renderer call `update` with its camera every frame. */
|
|
39
51
|
autoUpdate = true;
|
|
40
|
-
/** Draw only this level
|
|
52
|
+
/** Draw only this level, without fades, once the coarsest level that draws something has loaded. */
|
|
41
53
|
forceLevel = null;
|
|
42
|
-
levels
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.dispatchEvent({ type: "levelschange" });
|
|
51
|
-
}, (error) => this.dispatchEvent({ type: "levelserror", error }));
|
|
54
|
+
/** The levels, each `object` the template its level meshes are made from, once there is one (never in the scene). */
|
|
55
|
+
levels = [];
|
|
56
|
+
/** Thins the instances out with distance from a camera, in every camera; null draws them at any distance. */
|
|
57
|
+
cullDistance = null;
|
|
58
|
+
/** The levels as they were given, which a copy is made from. */
|
|
59
|
+
inputs = [];
|
|
60
|
+
/** What it is made of for its levels and sizes, which a copy makes anew. */
|
|
61
|
+
built;
|
|
52
62
|
disposed = false;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
reaches = [];
|
|
63
|
-
/** Logical demand at the initial default viewport, separate from first-draw visibility. */
|
|
64
|
-
demand = [];
|
|
65
|
-
/** Source-radius padding for the shadow caster cutoff; culling pads every level separately. */
|
|
66
|
-
padding = 0;
|
|
67
|
-
blocks;
|
|
68
|
-
last = { selected: false, eye: new Vector3(), scale: 0, ortho: false, fades: false, forced: null };
|
|
69
|
-
get pending() {
|
|
70
|
-
return this.residency.pending;
|
|
71
|
-
}
|
|
72
|
-
get error() {
|
|
73
|
-
return this.residency.error;
|
|
74
|
-
}
|
|
75
|
-
/** `levels[0]` is the source. Empty only as the target of `copy`. */
|
|
76
|
-
constructor(levels = [], count = 0) {
|
|
63
|
+
/** Around every instance, survivors grown: what every level mesh is culled and boxed by. */
|
|
64
|
+
bounds = { sphere: new Sphere(), box: new Box3() };
|
|
65
|
+
/** What `cullIn` writes cullDistance into, in this InstancedLod's space. */
|
|
66
|
+
cull = emptyCull();
|
|
67
|
+
/**
|
|
68
|
+
* `levels[0]` is the source. Empty only as the target of `copy`. It holds no instances until chunks are added. `gpu`
|
|
69
|
+
* is what it shares with every Lod drawing with its renderer.
|
|
70
|
+
*/
|
|
71
|
+
constructor(levels, gpu, options = {}) {
|
|
77
72
|
super();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.
|
|
86
|
-
|
|
87
|
-
build(inputs) {
|
|
88
|
-
const { own, placed } = measureLevels(inputs, "InstancedLod");
|
|
89
|
-
this.sphere.copy(placed);
|
|
90
|
-
inputs.forEach((input, i) => {
|
|
91
|
-
this.entries.push(new Level(input, i, this.entries));
|
|
92
|
-
this.reaches.push(new Sphere());
|
|
93
|
-
this.demand.push(new Sphere());
|
|
94
|
-
this.envelope.union(levelBox(input));
|
|
95
|
-
});
|
|
96
|
-
estimate(this.entries, 2 * own.radius);
|
|
97
|
-
validate(this.entries);
|
|
98
|
-
this.residency.reset();
|
|
99
|
-
this.boundLevels();
|
|
100
|
-
const templates = this.entries.map(({ object }, i) => (object ? parts(object, i) : []));
|
|
101
|
-
this.probes.add(templates[0] ?? []);
|
|
102
|
-
const draws = templates.flatMap((parts) => parts.map((part) => part.draw));
|
|
103
|
-
const selection = new Selection(this.store.matrices, this.sphere, templates.map((parts, i) => parts.length > 0 || at(inputs, i).box?.isEmpty() === false), draws, this.residency.fallback);
|
|
104
|
-
this.selection = selection;
|
|
105
|
-
this.store.attach(selection);
|
|
106
|
-
const meshes = new Meshes(selection, this.reaches, this.drawRadius, {
|
|
107
|
-
live: () => !this.disposed,
|
|
108
|
-
drawn: (camera, mesh) => this.residency.drawn(camera, mesh),
|
|
109
|
-
});
|
|
110
|
-
this.meshes = meshes;
|
|
111
|
-
let offset = 0;
|
|
112
|
-
templates.forEach((parts, i) => {
|
|
113
|
-
const made = meshes.make(at(this.entries, i), parts, offset);
|
|
114
|
-
offset += made.length * ARGS_BYTES;
|
|
115
|
-
meshes.byLevel[i] = made;
|
|
116
|
-
for (const mesh of made)
|
|
117
|
-
this.add(mesh);
|
|
118
|
-
});
|
|
119
|
-
if (draws.length === 0)
|
|
120
|
-
watchContext(this);
|
|
121
|
-
return draws.length;
|
|
73
|
+
this.gpu = gpu;
|
|
74
|
+
// Each level's draws start at its list (see update.ts).
|
|
75
|
+
if (!gpu.renderer.hasFeature("indirect-first-instance"))
|
|
76
|
+
throw new Error("InstancedLod: needs the GPU feature indirect-first-instance, which this device lacks");
|
|
77
|
+
const maxInstanceCount = options.maxInstanceCount ?? DEFAULT_INSTANCES;
|
|
78
|
+
if (!Number.isInteger(maxInstanceCount) || maxInstanceCount < 1)
|
|
79
|
+
throw new RangeError(`InstancedLod: maxInstanceCount must be a positive integer, got ${maxInstanceCount}`);
|
|
80
|
+
this.built = this.init(levels, maxInstanceCount);
|
|
81
|
+
this.built.loads.item.given = options.manager;
|
|
122
82
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const { selection, meshes } = this;
|
|
126
|
-
if (!selection || !meshes)
|
|
127
|
-
throw new Error("InstancedLod: missing selection");
|
|
128
|
-
const staged = new Object3D();
|
|
129
|
-
const object = template.clone();
|
|
130
|
-
if (level.box)
|
|
131
|
-
prepareBounds(object, level.box);
|
|
132
|
-
const found = parts(object, level.index);
|
|
133
|
-
const offset = selection.append(found.map((part) => part.draw));
|
|
134
|
-
// A deferred level has no upfront mesh count, so its indirect draw table can relocate.
|
|
135
|
-
meshes.relocate();
|
|
136
|
-
const made = meshes.make(level, found, offset);
|
|
137
|
-
for (const mesh of made)
|
|
138
|
-
staged.add(mesh);
|
|
139
|
-
const abandon = () => {
|
|
140
|
-
for (const mesh of made)
|
|
141
|
-
meshes.free(mesh);
|
|
142
|
-
disposeCopies(object);
|
|
143
|
-
};
|
|
144
|
-
try {
|
|
145
|
-
refreshWind(this, staged);
|
|
146
|
-
await compileLevel(staged, context);
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
abandon();
|
|
150
|
-
throw error;
|
|
151
|
-
}
|
|
152
|
-
if (this.disposed) {
|
|
153
|
-
abandon();
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
level.object = object;
|
|
157
|
-
if (made.length > 0)
|
|
158
|
-
unwatchContext(this);
|
|
159
|
-
if (level.index === 0)
|
|
160
|
-
this.probes.add(found);
|
|
161
|
-
meshes.byLevel[level.index] = made;
|
|
162
|
-
for (const mesh of made)
|
|
163
|
-
this.add(mesh);
|
|
83
|
+
get pending() {
|
|
84
|
+
return this.built.loads.pending;
|
|
164
85
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.rest.copy(this.sphere);
|
|
168
|
-
if (this.envelope.isEmpty())
|
|
169
|
-
return;
|
|
170
|
-
const { center } = this.rest;
|
|
171
|
-
const { min, max } = this.envelope;
|
|
172
|
-
this.rest.radius = Math.max(this.rest.radius, Math.hypot(Math.max(Math.abs(min.x - center.x), Math.abs(max.x - center.x)), Math.max(Math.abs(min.y - center.y), Math.abs(max.y - center.y)), Math.max(Math.abs(min.z - center.z), Math.abs(max.z - center.z))));
|
|
86
|
+
get error() {
|
|
87
|
+
return this.built.loads.error;
|
|
173
88
|
}
|
|
174
|
-
|
|
175
|
-
|
|
89
|
+
/** Where the item of levels a camera misses goes (see `LodOptions.manager`). */
|
|
90
|
+
get manager() {
|
|
91
|
+
return this.built.loads.item.manager;
|
|
176
92
|
}
|
|
177
|
-
|
|
178
|
-
|
|
93
|
+
set manager(manager) {
|
|
94
|
+
this.built.loads.item.given = manager;
|
|
179
95
|
}
|
|
180
|
-
/**
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.store.setColor(index, color);
|
|
184
|
-
if (first)
|
|
185
|
-
this.meshes?.recolor();
|
|
96
|
+
/** Its chunks, in the order they were added. */
|
|
97
|
+
get chunks() {
|
|
98
|
+
return this.built.chunks.keys();
|
|
186
99
|
}
|
|
187
|
-
/**
|
|
188
|
-
|
|
189
|
-
|
|
100
|
+
/** What this InstancedLod is made of for `inputs` and `maxInstanceCount`: its levels, their meshes and their loading. */
|
|
101
|
+
init(inputs, maxInstanceCount) {
|
|
102
|
+
const shape = new InstanceShape(inputs);
|
|
103
|
+
const { pool, renderer } = this.gpu;
|
|
104
|
+
const lists = new InstanceLists(this.gpu.sorter, listedOf(inputs), maxInstanceCount);
|
|
105
|
+
const chunks = new ChunkSet(pool, lists.row, this.bounds, () => shape.originReach, (chunk, index, camera) => this.levelAt(chunk, index, camera));
|
|
106
|
+
const drawn = { matrices: pool.matrices, colors: pool.colors };
|
|
107
|
+
const drawing = { shape, lists, drawn };
|
|
108
|
+
this.inputs = inputs;
|
|
109
|
+
if (inputs.length > 0)
|
|
110
|
+
this.levels.push(...levelsFrom(inputs, 2 * shape.ownRadius, "InstancedLod"));
|
|
111
|
+
const encoded = new EncodedLevels(this.levels, emptyLevels(inputs), "InstancedLod");
|
|
112
|
+
const drawFor = (renderer, camera) => this.built.loads.guard(() => {
|
|
113
|
+
if (renderer !== this.gpu.renderer)
|
|
114
|
+
throw new Error("InstancedLod: another renderer than its LodGpu's drew it");
|
|
115
|
+
lists.drawFor(camera);
|
|
116
|
+
});
|
|
117
|
+
const meshes = new MeshesByLevel(this, this.levels, drawing, this.bounds, drawFor);
|
|
118
|
+
const loads = new LodLevelLoadManager(this, this.gpu, `InstancedLod ${this.uuid}`, inputs, encoded.get(null, true), (level, loaded) => meshes.prepare(level, loaded), (level) => meshes.of(level), async () => {
|
|
119
|
+
const instances = await pool.status(renderer, chunks.slots());
|
|
120
|
+
if (instances !== null && instances > maxInstanceCount)
|
|
121
|
+
throw new Error(`InstancedLod: its chunks hold ${instances} instances, more than its lists hold: raise its maxInstanceCount (${maxInstanceCount})`);
|
|
122
|
+
return instances !== null;
|
|
123
|
+
});
|
|
124
|
+
return { maxInstanceCount, chunks, ...drawing, meshes, loads, encoded };
|
|
190
125
|
}
|
|
191
126
|
/**
|
|
192
|
-
*
|
|
193
|
-
*
|
|
127
|
+
* Add `parameters`' instances as one chunk, from the CPU or the GPU (see `InstancedLodChunkParameters`). The next
|
|
128
|
+
* render that updates this InstancedLod copies them into its pages. Its item (see `LodOptions.manager`) stays held
|
|
129
|
+
* until the GPU shows every chunk copied; a chunk the pool lacks pages for draws the instances it got until it is
|
|
130
|
+
* removed, and is this InstancedLod's error (see `error`).
|
|
194
131
|
*/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return null;
|
|
205
|
-
let height = 2 * r * last.scale;
|
|
206
|
-
if (!last.ortho) {
|
|
207
|
-
const dx = at(store.spheres, offset) - last.eye.x;
|
|
208
|
-
const dy = at(store.spheres, offset + 1) - last.eye.y;
|
|
209
|
-
const dz = at(store.spheres, offset + 2) - last.eye.z;
|
|
210
|
-
height /= Math.max(Math.sqrt(dx * dx + dy * dy + dz * dz), 1e-6);
|
|
211
|
-
}
|
|
212
|
-
const level = levelAt(this.entries, height, last.forced);
|
|
213
|
-
const selected = last.fades && fadeProgress(this.entries, level, height) > 0 ? level.index - 1 : level.index;
|
|
214
|
-
const ready = at(this.residency.fallback, selected);
|
|
215
|
-
return ready < 0 ? null : ready;
|
|
132
|
+
addChunk(parameters) {
|
|
133
|
+
if (this.disposed)
|
|
134
|
+
throw new Error("InstancedLod: it was disposed");
|
|
135
|
+
if (this.levels.length === 0)
|
|
136
|
+
throw new Error("InstancedLod: give it levels before chunks");
|
|
137
|
+
const chunk = this.built.chunks.add(parameters);
|
|
138
|
+
this.measureBounds();
|
|
139
|
+
this.built.loads.chunksChanged();
|
|
140
|
+
return chunk;
|
|
216
141
|
}
|
|
217
|
-
/**
|
|
218
|
-
|
|
219
|
-
|
|
142
|
+
/** Remove `chunk`'s instances; its pages return to the pool in the next render. */
|
|
143
|
+
removeChunk(chunk) {
|
|
144
|
+
this.built.chunks.remove(chunk);
|
|
145
|
+
this.measureBounds();
|
|
146
|
+
this.built.loads.chunksChanged();
|
|
220
147
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
this.
|
|
224
|
-
// The wind shape comes from the source, but taller/offset levels can sway farther.
|
|
225
|
-
const reach = slope * Math.max(Math.abs(this.envelope.min.y - baseY), Math.abs(this.envelope.max.y - baseY));
|
|
226
|
-
this.blocks.pad(this.rest.radius > 0 ? reach / this.rest.radius : 0);
|
|
227
|
-
this.blocks.refit();
|
|
148
|
+
/** Bound every chunk's instances, survivors grown. */
|
|
149
|
+
measureBounds() {
|
|
150
|
+
this.built.chunks.bound(this.cullDistance?.scaleSurvivors ? MAX_SURVIVOR_SCALE : 1);
|
|
228
151
|
}
|
|
229
|
-
|
|
152
|
+
[WIND](padding, slope, baseY) {
|
|
153
|
+
if (this.built.loads.started)
|
|
154
|
+
throw new Error("InstancedLod: apply wind before the first render");
|
|
155
|
+
this.built.shape.wind(padding, slope, baseY);
|
|
156
|
+
for (const mesh of this.built.meshes.all()) {
|
|
157
|
+
const source = fadeSourceOf(mesh);
|
|
158
|
+
if (source?.kind === "instances")
|
|
159
|
+
source.radius = this.built.shape.fadeRadius;
|
|
160
|
+
}
|
|
161
|
+
this.measureBounds();
|
|
162
|
+
}
|
|
163
|
+
/** 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`). */
|
|
230
164
|
update(camera) {
|
|
231
|
-
if (this.disposed ||
|
|
165
|
+
if (this.disposed || this.levels.length === 0)
|
|
232
166
|
return;
|
|
233
|
-
|
|
234
|
-
|
|
167
|
+
// A shadow map draws nothing of an InstancedLod whose levels cast nothing; one not loaded yet may.
|
|
168
|
+
const shadow = inShadowMap(this);
|
|
169
|
+
if (shadow && !this.levels.some(({ object }, i) => !object || this.built.meshes.of(i).some((mesh) => mesh.castShadow)))
|
|
235
170
|
return;
|
|
236
|
-
|
|
237
|
-
if (this.forceLevel !== null && !entries[this.forceLevel])
|
|
238
|
-
throw new Error(`Lod: forceLevel ${this.forceLevel} is not a level`);
|
|
239
|
-
this.store.measure(this.blocks);
|
|
240
|
-
const height = viewportHeight(camera);
|
|
241
|
-
view.begin(camera, height ?? TYPICAL_HEIGHT, this.forceLevel);
|
|
242
|
-
tintLevels(entries, Lod.debug);
|
|
243
|
-
const worldScale = this.matrixWorld.getMaxScaleOnAxis();
|
|
244
|
-
const scale = view.scale * Lod.quality * (view.ortho ? worldScale : 1);
|
|
245
|
-
const { last } = this;
|
|
246
|
-
last.eye.copy(view.eye).applyMatrix4(inverse.copy(this.matrixWorld).invert());
|
|
247
|
-
last.selected = true;
|
|
248
|
-
last.scale = scale;
|
|
249
|
-
last.ortho = view.ortho;
|
|
250
|
-
last.fades = view.fades;
|
|
251
|
-
last.forced = this.forceLevel;
|
|
252
|
-
const stable = this.blocks.select(entries, last, this.reaches, height !== null, this.matrixWorld);
|
|
253
|
-
const { residency } = this;
|
|
254
|
-
const progress = residency.progress;
|
|
255
|
-
if (selection.progress.value !== progress) {
|
|
256
|
-
selection.progress.value = progress;
|
|
257
|
-
selection.changed();
|
|
258
|
-
}
|
|
259
|
-
const needed = [];
|
|
260
|
-
if (this.bounds.isEmpty()) {
|
|
261
|
-
// Reusable crowds can be populated and drawn in the same frame.
|
|
262
|
-
for (const level of entries)
|
|
263
|
-
if (level.object)
|
|
264
|
-
needed.push(level.index);
|
|
265
|
-
}
|
|
266
|
-
else if (residency.needsDemand(camera, meshes.byLevel)) {
|
|
267
|
-
this.blocks.demand(entries, last, this.demand, this.matrixWorld);
|
|
268
|
-
// Coarsest first, so its load starts first.
|
|
269
|
-
for (let i = this.demand.length - 1; i >= 0; i--)
|
|
270
|
-
if (inView(camera, this.matrixWorld, at(this.demand, i)))
|
|
271
|
-
needed.push(i);
|
|
272
|
-
this.reroute(progress);
|
|
273
|
-
}
|
|
274
|
-
residency.demand(camera, needed);
|
|
275
|
-
residency.update(camera, meshes.byLevel);
|
|
276
|
-
selection.aim(last.eye, scale, view.ortho, view.fades, this.forceLevel, entries, stable);
|
|
277
|
-
// Selected only when something may draw: an InstancedLod with every level hidden
|
|
278
|
-
// keeps its last selection.
|
|
279
|
-
meshes.schedule(meshes.show(camera, this.matrixWorld));
|
|
171
|
+
this.built.loads.guard(() => this.sort(camera, shadow));
|
|
280
172
|
}
|
|
281
|
-
/**
|
|
282
|
-
|
|
283
|
-
const {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
173
|
+
/** Sort for `camera`, a shadow map's when `shadow`. */
|
|
174
|
+
sort(camera, shadow) {
|
|
175
|
+
const { loads, shape, lists, chunks, drawn, encoded, meshes } = this.built;
|
|
176
|
+
const { levels, eye, scale, ortho } = this.localCamera(camera, shadow);
|
|
177
|
+
if (chunks.refresh())
|
|
178
|
+
this.measureBounds();
|
|
179
|
+
// The pages change before any sorts with them.
|
|
180
|
+
const { pool } = this.gpu;
|
|
181
|
+
pool.prepare(this.gpu.renderer);
|
|
182
|
+
const survivors = this.cullDistance?.scaleSurvivors ?? false;
|
|
183
|
+
if (survivors !== (drawn.matrices !== pool.matrices))
|
|
184
|
+
this.scaleSurvivors(survivors);
|
|
185
|
+
const cull = cullIn(this.cullDistance, this.matrixWorld, this.cull);
|
|
186
|
+
const local = { levels, eye, scale, ortho, cull };
|
|
187
|
+
const found = lists.of(camera);
|
|
188
|
+
// Outside the camera's frustum, nothing draws: a shadow map, which loads nothing by heights, walks no chunk then.
|
|
189
|
+
const seen = frustumIn(found, camera, this.matrixWorld).intersectsSphere(this.bounds.sphere);
|
|
190
|
+
if (!shadow || seen)
|
|
191
|
+
walk(found, local, this.built);
|
|
192
|
+
// A shadow map draws from the levels its scene's cameras loaded.
|
|
193
|
+
loads.request(camera, shadow ? levelsToLoad([], encoded.heights(levels)) : found.wanted, shadow);
|
|
194
|
+
meshes.tint(Lod.debug);
|
|
195
|
+
lists.prune(camera, (other) => loads.requests.rendering(other));
|
|
196
|
+
const { loaded, before, progress } = loads;
|
|
197
|
+
// Three projects this InstancedLod's children for the camera after this update.
|
|
198
|
+
const shown = seen ? shownBy(found, levels, encoded, { loaded, before, progress }) : 0;
|
|
199
|
+
lists.sort(camera, {
|
|
200
|
+
...local,
|
|
201
|
+
loaded,
|
|
202
|
+
before,
|
|
203
|
+
progress,
|
|
204
|
+
bounds: this.bounds.sphere,
|
|
205
|
+
box: this.bounds.box,
|
|
206
|
+
source: shape.source,
|
|
207
|
+
reach: shape.reach,
|
|
208
|
+
onlyLevel: cull === null ? found.onlyLevel : 0,
|
|
209
|
+
chunks: chunks.version,
|
|
210
|
+
});
|
|
211
|
+
// Nothing draws from the camera's indirect draws before a sort writes them, which a level mesh's draw runs first.
|
|
212
|
+
meshes.show(found.written ? shown : 0);
|
|
213
|
+
}
|
|
214
|
+
/** `camera` in this InstancedLod's space (see `localCamera`). */
|
|
215
|
+
localCamera(camera, shadow) {
|
|
216
|
+
const { loads, encoded } = this.built;
|
|
217
|
+
return localCamera(camera, loads.heightOf(camera, shadow), this.matrixWorld, encoded, this.forceLevel);
|
|
218
|
+
}
|
|
219
|
+
/** Draw survivors' scaled matrices, or the pool's again. */
|
|
220
|
+
scaleSurvivors(survivors) {
|
|
221
|
+
const { pool, sorter } = this.gpu;
|
|
222
|
+
this.built.drawn.matrices = survivors ? sorter.scaledMatrices : pool.matrices;
|
|
223
|
+
drawMatrices(this.built.meshes.all(), this.built.drawn);
|
|
224
|
+
this.measureBounds();
|
|
225
|
+
}
|
|
226
|
+
/** The level instance `index` of `chunk` draws most of its pixels with for `camera` (see `InstancedLodChunk.getLevelAt`). */
|
|
227
|
+
levelAt(chunk, index, camera) {
|
|
228
|
+
const cull = cullIn(this.cullDistance, this.matrixWorld, this.cull);
|
|
229
|
+
const local = this.localCamera(camera, inShadowMap(this));
|
|
230
|
+
return instanceLevel(chunk.instanceMatrix.array, (chunk.start + index) * 16, cull, local, this.built.shape.source, this.built.loads.loaded);
|
|
296
231
|
}
|
|
297
232
|
/**
|
|
298
|
-
* Hits every instance
|
|
299
|
-
* InstancedLod.
|
|
233
|
+
* Hits every instance of its CPU chunks on the source level, with `instanceId` and `chunk` set (see
|
|
234
|
+
* `InstancedLodIntersection`); `object` is this InstancedLod. A GPU chunk's instances the CPU cannot see, and meshes
|
|
235
|
+
* of the source on layers the raycaster does not test, are not hit.
|
|
300
236
|
*/
|
|
301
237
|
raycast(raycaster, intersects) {
|
|
302
|
-
this.
|
|
238
|
+
raycastInstances(this, { parts: this.built.meshes.source, rest: this.built.shape.rest }, this.built.chunks.cpu(), raycaster, intersects);
|
|
303
239
|
return false;
|
|
304
240
|
}
|
|
305
241
|
/**
|
|
306
|
-
* Copies `source`'s levels,
|
|
307
|
-
*
|
|
242
|
+
* Copies `source`'s levels, CPU chunks and settings into this empty InstancedLod, one without levels or chunks (it
|
|
243
|
+
* throws otherwise); the copy shares geometry and textures with `source`, and its chunks hold copies of the source's
|
|
244
|
+
* attributes. A GPU chunk cannot be copied: its instances live on the GPU.
|
|
308
245
|
*/
|
|
309
246
|
copy(source) {
|
|
310
|
-
if (this.
|
|
311
|
-
throw new Error("InstancedLod.copy: copy into an
|
|
247
|
+
if (this.levels.length > 0 || this.built.chunks.size > 0)
|
|
248
|
+
throw new Error("InstancedLod.copy: copy into an InstancedLod without levels or chunks");
|
|
249
|
+
const chunks = source.built.chunks.copies();
|
|
250
|
+
const inputs = source.inputs.map((input, i) => ({ ...input, maxPixels: at(source.levels, i).maxPixels }));
|
|
312
251
|
super.copy(source, false);
|
|
313
|
-
this.
|
|
314
|
-
|
|
315
|
-
this.
|
|
252
|
+
this.built.chunks.dispose();
|
|
253
|
+
this.built.lists.dispose();
|
|
254
|
+
this.built = this.init(inputs, source.built.maxInstanceCount);
|
|
255
|
+
this.built.loads.item.given = source.built.loads.item.given;
|
|
316
256
|
this.forceLevel = source.forceLevel;
|
|
317
257
|
this.autoUpdate = source.autoUpdate;
|
|
258
|
+
this.cullDistance = source.cullDistance && { ...source.cullDistance };
|
|
318
259
|
copyWind(source, this);
|
|
260
|
+
for (const chunk of chunks)
|
|
261
|
+
this.addChunk(chunk);
|
|
319
262
|
return this;
|
|
320
263
|
}
|
|
321
264
|
clone() {
|
|
322
|
-
|
|
323
|
-
const clone = new InstancedLod([], this.count).copy(this);
|
|
265
|
+
const clone = new InstancedLod([], this.gpu).copy(this);
|
|
324
266
|
if (!sameClass(this, clone))
|
|
325
267
|
throw new Error("InstancedLod.clone: a subclass must override clone");
|
|
326
268
|
return clone;
|
|
327
269
|
}
|
|
328
|
-
/**
|
|
270
|
+
/**
|
|
271
|
+
* Release its buffers and what it made of its levels, once nothing it prepares or compiles still uses them. Objects
|
|
272
|
+
* you give or load, chunk attributes among them, are yours to dispose; LodLoader's are freed when the last Lod
|
|
273
|
+
* holding them is disposed (see `LodLevel.hold`).
|
|
274
|
+
*/
|
|
329
275
|
dispose() {
|
|
330
276
|
if (this.disposed)
|
|
331
277
|
return;
|
|
332
278
|
this.disposed = true;
|
|
333
|
-
|
|
334
|
-
this.
|
|
335
|
-
|
|
336
|
-
|
|
279
|
+
super.dispose();
|
|
280
|
+
this.built.chunks.dispose();
|
|
281
|
+
this.built.loads.dispose(() => {
|
|
282
|
+
this.built.meshes.dispose();
|
|
283
|
+
this.built.lists.dispose();
|
|
284
|
+
for (const { object } of this.levels)
|
|
337
285
|
if (object)
|
|
338
286
|
disposeCopies(object);
|
|
339
287
|
});
|
|
340
288
|
}
|
|
341
|
-
clearDraws() {
|
|
342
|
-
this.meshes?.dispose();
|
|
343
|
-
this.meshes = null;
|
|
344
|
-
this.selection?.dispose();
|
|
345
|
-
this.selection = null;
|
|
346
|
-
this.store.attach(null);
|
|
347
|
-
}
|
|
348
289
|
}
|
|
349
290
|
//# sourceMappingURL=index.js.map
|