@expofp/renderer 0.0.0-experimental.cf063fc
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 +145 -0
- package/dist/Renderer.d.ts +102 -0
- package/dist/Renderer.js +96 -0
- package/dist/controls/CameraControls.d.ts +108 -0
- package/dist/controls/CameraControls.js +203 -0
- package/dist/controls/Controls.d.ts +53 -0
- package/dist/controls/Controls.js +54 -0
- package/dist/controls/camera-api.d.ts +226 -0
- package/dist/controls/camera-api.js +179 -0
- package/dist/controls/gestures.d.ts +71 -0
- package/dist/controls/gestures.js +98 -0
- package/dist/controls/handlers/DoubleTapZoom.d.ts +23 -0
- package/dist/controls/handlers/DoubleTapZoom.js +82 -0
- package/dist/controls/handlers/Inertia.d.ts +60 -0
- package/dist/controls/handlers/Inertia.js +222 -0
- package/dist/controls/handlers/Pan.d.ts +23 -0
- package/dist/controls/handlers/Pan.js +212 -0
- package/dist/controls/handlers/Pitch.d.ts +19 -0
- package/dist/controls/handlers/Pitch.js +200 -0
- package/dist/controls/handlers/Roll.d.ts +30 -0
- package/dist/controls/handlers/Roll.js +196 -0
- package/dist/controls/handlers/Zoom.d.ts +28 -0
- package/dist/controls/handlers/Zoom.js +34 -0
- package/dist/controls/hooks.d.ts +136 -0
- package/dist/controls/hooks.js +200 -0
- package/dist/controls/index.d.ts +9 -0
- package/dist/controls/index.js +7 -0
- package/dist/controls/zoom-to.d.ts +89 -0
- package/dist/controls/zoom-to.js +91 -0
- package/dist/core/InstanceUniforms.d.ts +108 -0
- package/dist/core/InstanceUniforms.js +298 -0
- package/dist/core/SquareDataTexture.d.ts +277 -0
- package/dist/core/SquareDataTexture.js +476 -0
- package/dist/core/batch/BatchedMesh.d.ts +74 -0
- package/dist/core/batch/BatchedMesh.js +155 -0
- package/dist/core/instanced/FrustumCulling.d.ts +141 -0
- package/dist/core/instanced/FrustumCulling.js +246 -0
- package/dist/core/instanced/InstancedMesh.d.ts +302 -0
- package/dist/core/instanced/InstancedMesh.js +497 -0
- package/dist/core/instanced/Instances.d.ts +119 -0
- package/dist/core/instanced/Instances.js +230 -0
- package/dist/core/instanced/Raycasting.d.ts +118 -0
- package/dist/core/instanced/Raycasting.js +134 -0
- package/dist/core/instanced/instanced-material.d.ts +77 -0
- package/dist/core/instanced/instanced-material.js +228 -0
- package/dist/core/lines/BatchedLines.d.ts +137 -0
- package/dist/core/lines/BatchedLines.js +215 -0
- package/dist/core/lines/FrustumCullingLines.d.ts +44 -0
- package/dist/core/lines/FrustumCullingLines.js +85 -0
- package/dist/core/lines/RaycastingLines.d.ts +45 -0
- package/dist/core/lines/RaycastingLines.js +91 -0
- package/dist/core/lines/lines-material.d.ts +47 -0
- package/dist/core/lines/lines-material.js +124 -0
- package/dist/core/shader-source.d.ts +70 -0
- package/dist/core/shader-source.js +110 -0
- package/dist/core/sprites/BatchedSprites.d.ts +115 -0
- package/dist/core/sprites/BatchedSprites.js +173 -0
- package/dist/core/sprites/RaycastingSprites.d.ts +41 -0
- package/dist/core/sprites/RaycastingSprites.js +71 -0
- package/dist/core/sprites/sprite-material.d.ts +59 -0
- package/dist/core/sprites/sprite-material.js +192 -0
- package/dist/core/text/BatchedText.d.ts +233 -0
- package/dist/core/text/BatchedText.js +473 -0
- package/dist/core/text/MemberTexture.d.ts +90 -0
- package/dist/core/text/MemberTexture.js +289 -0
- package/dist/core/text/Text.d.ts +88 -0
- package/dist/core/text/Text.js +230 -0
- package/dist/core/text/batched-text-material.d.ts +56 -0
- package/dist/core/text/batched-text-material.js +123 -0
- package/dist/core/text/glyph-packing.d.ts +17 -0
- package/dist/core/text/glyph-packing.js +61 -0
- package/dist/core/typed-array.d.ts +16 -0
- package/dist/core/typed-array.js +20 -0
- package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
- package/dist/debug/components/DebugPanelProvider.js +50 -0
- package/dist/debug/components/DebugTools.d.ts +22 -0
- package/dist/debug/components/DebugTools.js +28 -0
- package/dist/debug/components/Gui.d.ts +22 -0
- package/dist/debug/components/Gui.js +42 -0
- package/dist/debug/components/MemoryInfo.d.ts +22 -0
- package/dist/debug/components/MemoryInfo.js +42 -0
- package/dist/debug/components/Panel.d.ts +31 -0
- package/dist/debug/components/Panel.js +104 -0
- package/dist/debug/components/Stats.d.ts +9 -0
- package/dist/debug/components/Stats.js +24 -0
- package/dist/debug/debug-chunk.d.ts +26 -0
- package/dist/debug/debug-chunk.js +32 -0
- package/dist/debug/debug-context.d.ts +41 -0
- package/dist/debug/debug-context.js +59 -0
- package/dist/debug/index.d.ts +41 -0
- package/dist/debug/index.js +43 -0
- package/dist/events/LayoutDriver.d.ts +36 -0
- package/dist/events/LayoutDriver.js +192 -0
- package/dist/events/PointerMissed.d.ts +23 -0
- package/dist/events/PointerMissed.js +58 -0
- package/dist/events/def-culling.d.ts +46 -0
- package/dist/events/def-culling.js +69 -0
- package/dist/events/layout-targets.d.ts +151 -0
- package/dist/events/layout-targets.js +397 -0
- package/dist/events/placement/box.d.ts +59 -0
- package/dist/events/placement/box.js +96 -0
- package/dist/events/placement/grid.d.ts +161 -0
- package/dist/events/placement/grid.js +235 -0
- package/dist/events/placement/index.d.ts +2 -0
- package/dist/events/placement/index.js +1 -0
- package/dist/events/placement/pass.d.ts +70 -0
- package/dist/events/placement/pass.js +617 -0
- package/dist/events/pointer.d.ts +194 -0
- package/dist/events/pointer.js +356 -0
- package/dist/external/ExternalCanvas.d.ts +56 -0
- package/dist/external/ExternalCanvas.js +177 -0
- package/dist/external/external-camera.d.ts +18 -0
- package/dist/external/external-camera.js +103 -0
- package/dist/external/external-events.d.ts +14 -0
- package/dist/external/external-events.js +33 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +14 -0
- package/dist/objects/Background.d.ts +31 -0
- package/dist/objects/Background.js +37 -0
- package/dist/objects/containers/SlotContainer.d.ts +312 -0
- package/dist/objects/containers/SlotContainer.js +311 -0
- package/dist/objects/containers/hooks.d.ts +61 -0
- package/dist/objects/containers/hooks.js +196 -0
- package/dist/objects/containers/index.d.ts +6 -0
- package/dist/objects/containers/index.js +4 -0
- package/dist/objects/containers/keys.d.ts +10 -0
- package/dist/objects/containers/keys.js +18 -0
- package/dist/objects/containers/mesh-writes.d.ts +106 -0
- package/dist/objects/containers/mesh-writes.js +97 -0
- package/dist/objects/containers/props.d.ts +33 -0
- package/dist/objects/containers/props.js +1 -0
- package/dist/objects/images/ImageInstance.d.ts +29 -0
- package/dist/objects/images/ImageInstance.js +152 -0
- package/dist/objects/images/Images.d.ts +49 -0
- package/dist/objects/images/Images.js +394 -0
- package/dist/objects/images/atlas-packer.d.ts +129 -0
- package/dist/objects/images/atlas-packer.js +287 -0
- package/dist/objects/images/image-container.d.ts +74 -0
- package/dist/objects/images/image-container.js +100 -0
- package/dist/objects/images/index.d.ts +2 -0
- package/dist/objects/images/index.js +1 -0
- package/dist/objects/images/pack-sources.d.ts +190 -0
- package/dist/objects/images/pack-sources.js +272 -0
- package/dist/objects/images/texture-budget.d.ts +120 -0
- package/dist/objects/images/texture-budget.js +215 -0
- package/dist/objects/images/worker/atlas-worker.d.ts +56 -0
- package/dist/objects/images/worker/atlas-worker.js +123 -0
- package/dist/objects/images/worker/client.d.ts +62 -0
- package/dist/objects/images/worker/client.js +249 -0
- package/dist/objects/images/worker/index.d.ts +10 -0
- package/dist/objects/images/worker/index.js +1 -0
- package/dist/objects/layer/Layer.d.ts +28 -0
- package/dist/objects/layer/Layer.js +134 -0
- package/dist/objects/layer/index.d.ts +2 -0
- package/dist/objects/layer/index.js +1 -0
- package/dist/objects/layer/layer-context.d.ts +74 -0
- package/dist/objects/layer/layer-context.js +82 -0
- package/dist/objects/layer/mount-scheduler.d.ts +131 -0
- package/dist/objects/layer/mount-scheduler.js +289 -0
- package/dist/objects/layer/visibility-gui.d.ts +19 -0
- package/dist/objects/layer/visibility-gui.js +93 -0
- package/dist/objects/lighting/Lighting.d.ts +92 -0
- package/dist/objects/lighting/Lighting.js +384 -0
- package/dist/objects/lighting/OcclusionPasses.d.ts +23 -0
- package/dist/objects/lighting/OcclusionPasses.js +271 -0
- package/dist/objects/lighting/index.d.ts +11 -0
- package/dist/objects/lighting/index.js +10 -0
- package/dist/objects/lighting/lighting-gui.d.ts +24 -0
- package/dist/objects/lighting/lighting-gui.js +114 -0
- package/dist/objects/lighting/occluder.d.ts +34 -0
- package/dist/objects/lighting/occluder.js +62 -0
- package/dist/objects/lighting/occlusion-targets.d.ts +143 -0
- package/dist/objects/lighting/occlusion-targets.js +276 -0
- package/dist/objects/lines/LineInstance.d.ts +21 -0
- package/dist/objects/lines/LineInstance.js +73 -0
- package/dist/objects/lines/Lines.d.ts +17 -0
- package/dist/objects/lines/Lines.js +31 -0
- package/dist/objects/lines/index.d.ts +2 -0
- package/dist/objects/lines/index.js +1 -0
- package/dist/objects/lines/line-container.d.ts +35 -0
- package/dist/objects/lines/line-container.js +40 -0
- package/dist/objects/materials/ColorMaterial.d.ts +92 -0
- package/dist/objects/materials/ColorMaterial.js +124 -0
- package/dist/objects/materials/LineMaterial.d.ts +44 -0
- package/dist/objects/materials/LineMaterial.js +74 -0
- package/dist/objects/materials/ModelMaterial.d.ts +53 -0
- package/dist/objects/materials/ModelMaterial.js +111 -0
- package/dist/objects/materials/TextureMaterial.d.ts +33 -0
- package/dist/objects/materials/TextureMaterial.js +48 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-pass.d.ts +77 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-pass.js +296 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-patch.d.ts +29 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-patch.js +115 -0
- package/dist/objects/materials/effects/ao/blur-pass.d.ts +61 -0
- package/dist/objects/materials/effects/ao/blur-pass.js +101 -0
- package/dist/objects/materials/effects/ao/index.d.ts +129 -0
- package/dist/objects/materials/effects/ao/index.js +72 -0
- package/dist/objects/materials/effects/color-dim.d.ts +115 -0
- package/dist/objects/materials/effects/color-dim.js +206 -0
- package/dist/objects/materials/effects/contact-shadow.d.ts +100 -0
- package/dist/objects/materials/effects/contact-shadow.js +167 -0
- package/dist/objects/materials/effects/effects-context.d.ts +53 -0
- package/dist/objects/materials/effects/effects-context.js +24 -0
- package/dist/objects/materials/shared.d.ts +24 -0
- package/dist/objects/materials/shared.js +72 -0
- package/dist/objects/models/ModelInstance.d.ts +22 -0
- package/dist/objects/models/ModelInstance.js +33 -0
- package/dist/objects/models/Models.d.ts +22 -0
- package/dist/objects/models/Models.js +186 -0
- package/dist/objects/models/gltf-cache.d.ts +17 -0
- package/dist/objects/models/gltf-cache.js +50 -0
- package/dist/objects/models/index.d.ts +2 -0
- package/dist/objects/models/index.js +1 -0
- package/dist/objects/models/model-asset.d.ts +48 -0
- package/dist/objects/models/model-asset.js +77 -0
- package/dist/objects/models/model-container.d.ts +123 -0
- package/dist/objects/models/model-container.js +207 -0
- package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
- package/dist/objects/shapes/ShapeInstance.js +39 -0
- package/dist/objects/shapes/Shapes.d.ts +21 -0
- package/dist/objects/shapes/Shapes.js +131 -0
- package/dist/objects/shapes/index.d.ts +2 -0
- package/dist/objects/shapes/index.js +1 -0
- package/dist/objects/shapes/shape-container.d.ts +141 -0
- package/dist/objects/shapes/shape-container.js +242 -0
- package/dist/objects/shapes/shape-geometry.d.ts +27 -0
- package/dist/objects/shapes/shape-geometry.js +94 -0
- package/dist/objects/text/TextInstance.d.ts +22 -0
- package/dist/objects/text/TextInstance.js +95 -0
- package/dist/objects/text/Texts.d.ts +30 -0
- package/dist/objects/text/Texts.js +43 -0
- package/dist/objects/text/index.d.ts +2 -0
- package/dist/objects/text/index.js +1 -0
- package/dist/objects/text/text-container.d.ts +121 -0
- package/dist/objects/text/text-container.js +229 -0
- package/dist/objects/text/text-layout.d.ts +92 -0
- package/dist/objects/text/text-layout.js +180 -0
- package/dist/space/Camera.d.ts +103 -0
- package/dist/space/Camera.js +321 -0
- package/dist/space/Scene.d.ts +47 -0
- package/dist/space/Scene.js +127 -0
- package/dist/space/Space.d.ts +325 -0
- package/dist/space/Space.js +359 -0
- package/dist/space/VisibleRect.d.ts +45 -0
- package/dist/space/VisibleRect.js +129 -0
- package/dist/space/camera-handle.d.ts +67 -0
- package/dist/space/camera-handle.js +63 -0
- package/dist/space/camera-kind.d.ts +26 -0
- package/dist/space/camera-kind.js +30 -0
- package/dist/space/canvas-size.d.ts +24 -0
- package/dist/space/canvas-size.js +20 -0
- package/dist/space/clipping.d.ts +69 -0
- package/dist/space/clipping.js +130 -0
- package/dist/space/layout-measure.d.ts +67 -0
- package/dist/space/layout-measure.js +175 -0
- package/dist/space/viewport.d.ts +112 -0
- package/dist/space/viewport.js +67 -0
- package/dist/types/defs.d.ts +234 -0
- package/dist/types/defs.js +1 -0
- package/dist/types/events.d.ts +198 -0
- package/dist/types/events.js +1 -0
- package/dist/types/guards.d.ts +21 -0
- package/dist/types/guards.js +52 -0
- package/dist/update/index.d.ts +3 -0
- package/dist/update/index.js +2 -0
- package/dist/update/slot-writers.d.ts +30 -0
- package/dist/update/slot-writers.js +76 -0
- package/dist/update/store.d.ts +41 -0
- package/dist/update/store.js +104 -0
- package/dist/utils/arrays.d.ts +13 -0
- package/dist/utils/arrays.js +20 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +27 -0
- package/dist/utils/hot-state.d.ts +41 -0
- package/dist/utils/hot-state.js +37 -0
- package/dist/utils/logging.d.ts +29 -0
- package/dist/utils/logging.js +55 -0
- package/dist/utils/math.d.ts +52 -0
- package/dist/utils/math.js +76 -0
- package/package.json +79 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import { extend } from '@react-three/fiber';
|
|
2
|
+
import { Box3, Color, ColorManagement, InstancedBufferAttribute, Matrix4, Mesh, Sphere, } from 'three';
|
|
3
|
+
import { InstanceUniforms } from '../InstanceUniforms';
|
|
4
|
+
import { SquareDataTexture } from '../SquareDataTexture';
|
|
5
|
+
import { FrustumCulling } from './FrustumCulling';
|
|
6
|
+
import { patchInstancedMaterial, patchInstancedShaderChunks } from './instanced-material';
|
|
7
|
+
import { Instances } from './Instances';
|
|
8
|
+
import { Raycasting } from './Raycasting';
|
|
9
|
+
// Prepare three's `ShaderChunk` when this module loads — once, guarded — so a mesh built later finds
|
|
10
|
+
// the stock chunks it compiles against already widened.
|
|
11
|
+
patchInstancedShaderChunks();
|
|
12
|
+
/**
|
|
13
|
+
* A texture-backed instanced mesh: three's `InstancedMesh` regime, but with per-instance matrices,
|
|
14
|
+
* colors and uniforms held in data textures instead of vertex attributes — so instances can be
|
|
15
|
+
* added, removed, hidden, sorted and frustum-culled individually, and the buffers grow on demand.
|
|
16
|
+
*
|
|
17
|
+
* Ported from three.ez's instanced-mesh (`InstancedMesh2` and its `feature/*` and `utils/*`
|
|
18
|
+
* modules,
|
|
19
|
+
* {@link https://github.com/agargaro/instanced-mesh/tree/master/src/core | source}) as a plain
|
|
20
|
+
* subclass rather than a re-export of theirs. Only what the 2D layers use is kept: dynamic capacity,
|
|
21
|
+
* add/remove, per-instance visibility, sorting, linear per-instance frustum culling, and uniforms.
|
|
22
|
+
* BVH, LOD, skinning, morphing, and the `InstancedEntity` object layer are all dropped.
|
|
23
|
+
*
|
|
24
|
+
* Departures from upstream:
|
|
25
|
+
*
|
|
26
|
+
* - **Batched-style texture handling.** The data textures bind as ordinary shader uniforms and
|
|
27
|
+
* flush through {@link SquareDataTexture.update}, so there is no manual texture-unit binding,
|
|
28
|
+
* `updateTextures`/`bindTextures` split, or `PropertiesOverride` — the vendored texture already
|
|
29
|
+
* works this way for `BatchedMeshImpl`.
|
|
30
|
+
* - **The draw list is a texture, not a vertex attribute.** Upstream stamps a `uint` index attribute
|
|
31
|
+
* onto whatever geometry it is handed; this fetches the instance id by `gl_InstanceID` from a texture of
|
|
32
|
+
* its own, the way `BatchedMeshImpl` resolves `gl_DrawID`. So the mesh never writes to a geometry it
|
|
33
|
+
* does not own — several may draw one cached geometry — and the cull list flushes through
|
|
34
|
+
* {@link SquareDataTexture.update} in `onBeforeRender` like every other per-instance buffer, rather
|
|
35
|
+
* than needing an attribute that owns its GL buffer to beat three's upload in `projectObject`. It
|
|
36
|
+
* is a float for the same reason `BatchedMesh`'s is: see {@link SquareDataTexture}.
|
|
37
|
+
* - **Merged color/opacity API.** {@link setColorAt}/{@link getColorAt} take and return
|
|
38
|
+
* `Color | Vector4`, alpha in the fourth channel, as `BatchedMesh` does — no separate opacity
|
|
39
|
+
* methods.
|
|
40
|
+
* - **Uniforms are added, not initialized once** ({@link addUniforms}, {@link InstanceUniforms}).
|
|
41
|
+
* - **Bounds invalidate themselves** on every mutation that can move an instance.
|
|
42
|
+
* - **No caller-supplied geometry or material.** Like `BatchedMesh`, the constructor takes only
|
|
43
|
+
* options; it seeds a throwaway geometry and material that R3F's `<planeGeometry>` and
|
|
44
|
+
* `<TextureMaterial>` children replace on mount.
|
|
45
|
+
*
|
|
46
|
+
* Render it with {@link InstancedMesh}.
|
|
47
|
+
*/
|
|
48
|
+
export class InstancedMeshImpl extends Mesh {
|
|
49
|
+
/**
|
|
50
|
+
* The number of instances rendered in the last frame.
|
|
51
|
+
* @default 0
|
|
52
|
+
*/
|
|
53
|
+
count = 0;
|
|
54
|
+
/** Marks this for three's instanced-draw path, which reads {@link count}. */
|
|
55
|
+
isInstancedMesh = true;
|
|
56
|
+
/** Placeholder three's instanced path dereferences; the real matrices live in a texture. */
|
|
57
|
+
instanceMatrix = new InstancedBufferAttribute(new Float32Array(0), 16);
|
|
58
|
+
/** Unused; present because three's instanced path reads it. */
|
|
59
|
+
instanceColor = null;
|
|
60
|
+
/**
|
|
61
|
+
* Unused, but must be `null`, not `undefined`: three enables its instanced-morph shader path on
|
|
62
|
+
* `isInstancedMesh && morphTexture !== null`, and an undefined field would satisfy that and emit
|
|
63
|
+
* morph GLSL that references an undeclared `MORPHTARGETS_COUNT`.
|
|
64
|
+
*/
|
|
65
|
+
morphTexture = null;
|
|
66
|
+
/** Sorts the render list into draw order; assigned through the `customSort` JSX prop. */
|
|
67
|
+
customSort = null;
|
|
68
|
+
/** Whether each instance is frustum-culled individually. */
|
|
69
|
+
perObjectFrustumCulled = true;
|
|
70
|
+
/** Whether instances are depth-sorted (via {@link customSort}) before drawing. */
|
|
71
|
+
sortObjects = false;
|
|
72
|
+
/** Bounding box enclosing every instance; nulled on mutation and recomputed on demand. */
|
|
73
|
+
boundingBox = null;
|
|
74
|
+
/** Bounding sphere enclosing every instance; nulled on mutation and recomputed on demand. */
|
|
75
|
+
boundingSphere = null;
|
|
76
|
+
/**
|
|
77
|
+
* Tests the ray against individual instances. Assigned by a subclass whose instances are placed
|
|
78
|
+
* some other way, to one that knows how; see {@link Raycasting.prepareInstance}.
|
|
79
|
+
*/
|
|
80
|
+
raycasting = new Raycasting();
|
|
81
|
+
/**
|
|
82
|
+
* Builds the draw list each draw. Assigned by a subclass whose instances cover more than their own
|
|
83
|
+
* bounds; see {@link FrustumCulling.instanceSphere}.
|
|
84
|
+
*/
|
|
85
|
+
culling = new FrustumCulling();
|
|
86
|
+
/** Indirect rendering texture, for each `gl_InstanceID` stores indices of matrix/color/uniforms textures */
|
|
87
|
+
indexTexture;
|
|
88
|
+
/**
|
|
89
|
+
* Per-instance transforms: one `mat4` per instance (4 channels × 4 pixels), or `null` until the
|
|
90
|
+
* first {@link setMatrixAt} — a mesh whose instances are placed some other way never allocates it,
|
|
91
|
+
* and the shader reads identity in its absence.
|
|
92
|
+
*/
|
|
93
|
+
matricesTexture = null;
|
|
94
|
+
/** Per-instance RGBA colors, or `null` until the first {@link setColorAt}. */
|
|
95
|
+
colorsTexture = null;
|
|
96
|
+
uniforms = new InstanceUniforms();
|
|
97
|
+
/** Which instances are live, visible and free to hand out. */
|
|
98
|
+
instances;
|
|
99
|
+
/** What the last draw culled to, or `null` before the first — what raycasting tests against. */
|
|
100
|
+
drawList = null;
|
|
101
|
+
/** Puts back what {@link patchInstancedMaterial} wrapped; null between draws. */
|
|
102
|
+
_unpatchMaterial = null;
|
|
103
|
+
constructor(params = {}) {
|
|
104
|
+
super();
|
|
105
|
+
const capacity = params.capacity && params.capacity > 0 ? params.capacity : DEFAULT_CAPACITY;
|
|
106
|
+
this.instances = new Instances(capacity, (grown) => this.resizeCapacity(grown));
|
|
107
|
+
this.indexTexture = new SquareDataTexture(Float32Array, 1, 1, capacity);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The instance capacity the textures currently hold.
|
|
111
|
+
*/
|
|
112
|
+
get capacity() {
|
|
113
|
+
return this.instances.capacity;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The number of active instances.
|
|
117
|
+
*/
|
|
118
|
+
get instancesCount() {
|
|
119
|
+
return this.instances.instancesCount;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Declares per-instance uniforms, merging with any already declared and rebuilding the backing
|
|
123
|
+
* texture (existing values carried across). See {@link InstanceUniforms.add}.
|
|
124
|
+
* @param schema - The uniforms to add.
|
|
125
|
+
*/
|
|
126
|
+
addUniforms(schema) {
|
|
127
|
+
this.uniforms.add(schema, this.capacity);
|
|
128
|
+
this.materialsNeedUpdate();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Reads one instance's uniform.
|
|
132
|
+
* @param id - The index of instance to read.
|
|
133
|
+
* @param name - The uniform's name.
|
|
134
|
+
* @param target - Receives the result; unused for a `float`, returned directly.
|
|
135
|
+
* @returns The value.
|
|
136
|
+
*/
|
|
137
|
+
getUniformAt(id, name, target) {
|
|
138
|
+
return this.uniforms.get(id, name, target);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Writes one instance's uniform and marks its row for upload.
|
|
142
|
+
* @param id - The index of instance to write.
|
|
143
|
+
* @param name - The uniform's name.
|
|
144
|
+
* @param value - The value to write.
|
|
145
|
+
*/
|
|
146
|
+
setUniformAt(id, name, value) {
|
|
147
|
+
this.uniforms.set(id, name, value);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Adds `count` instances, reusing removed instances first, and reports each new id through
|
|
151
|
+
* `onCreation` so the caller can capture it. New instances start visible at the identity matrix.
|
|
152
|
+
* @param count - How many to add.
|
|
153
|
+
* @param onCreation - Called with each new instance's id.
|
|
154
|
+
* @returns `this`.
|
|
155
|
+
*/
|
|
156
|
+
addInstances(count, onCreation) {
|
|
157
|
+
this.instances.addInstances(count, (id) => {
|
|
158
|
+
this.resetInstance(id);
|
|
159
|
+
onCreation?.(id);
|
|
160
|
+
});
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Removes instances by id, freeing their instances for reuse and shrinking the iteration bound past
|
|
165
|
+
* any now-trailing inactive instances.
|
|
166
|
+
* @param ids - The instances to remove.
|
|
167
|
+
* @returns `this`.
|
|
168
|
+
*/
|
|
169
|
+
removeInstances(...ids) {
|
|
170
|
+
this.instances.removeInstances(...ids);
|
|
171
|
+
this.invalidateBounds();
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Gets the visibility of a specific instance.
|
|
176
|
+
* @param id - The index of the instance.
|
|
177
|
+
* @returns Whether it is visible.
|
|
178
|
+
*/
|
|
179
|
+
getVisibleAt(id) {
|
|
180
|
+
return this.instances.getVisibleAt(id);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Sets the visibility of a specific instance.
|
|
184
|
+
* @param id - The index of the instance.
|
|
185
|
+
* @param visible - Whether it should be visible.
|
|
186
|
+
*/
|
|
187
|
+
setVisibleAt(id, visible) {
|
|
188
|
+
this.instances.setVisibleAt(id, visible);
|
|
189
|
+
// The bounds still hold — a hidden instance is still live — but the draw list does not: it names
|
|
190
|
+
// what the last frame drew, and this changes that. See {@link invalidateBounds}.
|
|
191
|
+
this.drawList = null;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Reads an instance's transform. Tolerates a read before any transform was written — every
|
|
195
|
+
* instance is then untransformed, which is what the shader draws in the same state.
|
|
196
|
+
* @param id - The index of the instance.
|
|
197
|
+
* @param matrix - Target for the result.
|
|
198
|
+
* @returns The transform matrix.
|
|
199
|
+
*/
|
|
200
|
+
getMatrixAt(id, matrix = _matrix) {
|
|
201
|
+
if (!this.matricesTexture)
|
|
202
|
+
return matrix.identity();
|
|
203
|
+
return matrix.fromArray(this.matricesTexture.data, id * 16);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Writes an instance's transform.
|
|
207
|
+
* @param id - The index of the instance.
|
|
208
|
+
* @param matrix - The transform matrix.
|
|
209
|
+
* @returns `this`.
|
|
210
|
+
*/
|
|
211
|
+
setMatrixAt(id, matrix) {
|
|
212
|
+
if (!this.matricesTexture)
|
|
213
|
+
this.initMatricesTexture();
|
|
214
|
+
const texture = this.matricesTexture;
|
|
215
|
+
matrix.toArray(texture.data, id * 16);
|
|
216
|
+
texture.enqueueUpdate(id);
|
|
217
|
+
this.invalidateBounds();
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
getColorAt(id, target = _color) {
|
|
221
|
+
if (!this.colorsTexture)
|
|
222
|
+
return target.setScalar(1);
|
|
223
|
+
const data = this.colorsTexture.data;
|
|
224
|
+
return target.fromArray(data, id * 4);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Writes an instance's color, routing a `Vector4`'s alpha to the fourth channel.
|
|
228
|
+
* @param id - The instance.
|
|
229
|
+
* @param color - The color; pass a `Vector4` to also set alpha.
|
|
230
|
+
* @returns `this`.
|
|
231
|
+
*/
|
|
232
|
+
setColorAt(id, color) {
|
|
233
|
+
if (!this.colorsTexture)
|
|
234
|
+
this.initColorsTexture();
|
|
235
|
+
const data = this.colorsTexture.data;
|
|
236
|
+
const colorObj = typeof color !== 'object' ? _color.set(color) : color;
|
|
237
|
+
colorObj.toArray(data, id * 4);
|
|
238
|
+
this.colorsTexture.enqueueUpdate(id);
|
|
239
|
+
return this;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Computes the bounding box that encloses all instances, and updates the `boundingBox` attribute.
|
|
243
|
+
*/
|
|
244
|
+
computeBoundingBox() {
|
|
245
|
+
const count = this.instances.addedInstancesCount;
|
|
246
|
+
this.boundingBox ??= new Box3();
|
|
247
|
+
this.boundingBox.makeEmpty();
|
|
248
|
+
for (let i = 0; i < count; i++) {
|
|
249
|
+
if (!this.instances.getActiveAt(i))
|
|
250
|
+
continue;
|
|
251
|
+
this.boundingBox.union(this.getBoundingBoxAt(i, _box));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Computes the bounding sphere that encloses all instances, and updates the `boundingSphere` attribute.
|
|
256
|
+
*/
|
|
257
|
+
computeBoundingSphere() {
|
|
258
|
+
const count = this.instances.addedInstancesCount;
|
|
259
|
+
this.boundingSphere ??= new Sphere();
|
|
260
|
+
this.boundingSphere.makeEmpty();
|
|
261
|
+
for (let i = 0; i < count; i++) {
|
|
262
|
+
if (!this.instances.getActiveAt(i))
|
|
263
|
+
continue;
|
|
264
|
+
this.boundingSphere.union(this.getBoundingSphereAt(i, _sphere));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Encloses one instance, in this mesh's space: the geometry's own sphere, moved onto the
|
|
269
|
+
* instance's transform.
|
|
270
|
+
*
|
|
271
|
+
* The seam frustum culling asks through, so that what encloses an instance is the mesh's business
|
|
272
|
+
* rather than something derived from a matrix every mesh is assumed to have — see
|
|
273
|
+
* {@link CullingHost}. Whole-mesh bounds go through it too, so a subclass placing its instances
|
|
274
|
+
* some other way overrides the one method and both follow.
|
|
275
|
+
* @param id - The instance.
|
|
276
|
+
* @param target - Receives the result.
|
|
277
|
+
* @returns The bounds.
|
|
278
|
+
*/
|
|
279
|
+
getBoundingSphereAt(id, target) {
|
|
280
|
+
const geometry = this.geometry;
|
|
281
|
+
if (!geometry.boundingSphere)
|
|
282
|
+
geometry.computeBoundingSphere();
|
|
283
|
+
return target.copy(geometry.boundingSphere).applyMatrix4(this.getMatrixAt(id));
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Encloses one instance in a box, in this mesh's space: the geometry's own, moved onto the
|
|
287
|
+
* instance's transform.
|
|
288
|
+
*
|
|
289
|
+
* The seam {@link computeBoundingBox} goes through, for the reason {@link getBoundingSphereAt} is
|
|
290
|
+
* the one culling asks through — a subclass overrides what encloses *one* instance, and every
|
|
291
|
+
* sweep over the set follows.
|
|
292
|
+
* @param id - The instance.
|
|
293
|
+
* @param target - Receives the result.
|
|
294
|
+
* @returns The bounds.
|
|
295
|
+
*/
|
|
296
|
+
getBoundingBoxAt(id, target) {
|
|
297
|
+
const geometry = this.geometry;
|
|
298
|
+
if (!geometry.boundingBox)
|
|
299
|
+
geometry.computeBoundingBox();
|
|
300
|
+
return target.copy(geometry.boundingBox).applyMatrix4(this.getMatrixAt(id));
|
|
301
|
+
}
|
|
302
|
+
/** Frees the data textures, which this mesh allocated rather than three. */
|
|
303
|
+
dispose() {
|
|
304
|
+
this.dispatchEvent({ type: 'dispose' });
|
|
305
|
+
this.indexTexture.dispose();
|
|
306
|
+
this.matricesTexture?.dispose();
|
|
307
|
+
this.colorsTexture?.dispose();
|
|
308
|
+
this.uniforms.dispose();
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Clears whatever an instance holds, as it is handed out.
|
|
312
|
+
*
|
|
313
|
+
* A new instance may reuse a freed id that still holds the previous tenant's state, and nothing
|
|
314
|
+
* else will clear it: `onCreation` belongs to the caller, which knows what it is about to write
|
|
315
|
+
* and not what was there before. A subclass keeping per-instance state of its own overrides this
|
|
316
|
+
* and clears that too.
|
|
317
|
+
*
|
|
318
|
+
* The matrix only when there is a matrices texture — without one every instance already reads
|
|
319
|
+
* identity, which is exactly what this would write, and writing it would allocate the texture this
|
|
320
|
+
* mesh has so far done without.
|
|
321
|
+
* @param id - The instance being handed out.
|
|
322
|
+
*/
|
|
323
|
+
resetInstance(id) {
|
|
324
|
+
if (this.matricesTexture)
|
|
325
|
+
this.setMatrixAt(id, _matrix.identity());
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Patches the material three is about to draw with, so the program it compiles reads this mesh's
|
|
329
|
+
* per-instance state — and hands back the undo.
|
|
330
|
+
*
|
|
331
|
+
* Applied and undone around every draw rather than once per material, because the material three
|
|
332
|
+
* hands over is not always the mesh's own: a scene's `overrideMaterial` is drawn with instead, and
|
|
333
|
+
* one left patched afterwards would carry this mesh's textures into every other object using it.
|
|
334
|
+
*
|
|
335
|
+
* The seam a subclass extends when its members need more of the shader than instancing — it wraps
|
|
336
|
+
* first, so that its own patch runs *inside* this one and finds the prologue already injected.
|
|
337
|
+
* @param material - The material about to draw.
|
|
338
|
+
* @returns Restores the material exactly as it arrived. Called once, after the draw.
|
|
339
|
+
*/
|
|
340
|
+
patchMaterial(material) {
|
|
341
|
+
// A snapshot of the textures, which is enough: the patch is reapplied and undone around every
|
|
342
|
+
// draw, so nothing can swap one out between here and the compile that reads them.
|
|
343
|
+
return patchInstancedMaterial(material, {
|
|
344
|
+
indexTexture: this.indexTexture,
|
|
345
|
+
matricesTexture: this.matricesTexture,
|
|
346
|
+
colorsTexture: this.colorsTexture,
|
|
347
|
+
uniforms: this.uniforms,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Nulls the cached bounds so three's next frustum test recomputes them, and the draw list with
|
|
352
|
+
* them.
|
|
353
|
+
*
|
|
354
|
+
* The draw list describes what the **last frame** drew, and {@link raycast} tests against it — so
|
|
355
|
+
* any mutation that changes what would draw leaves it lying to the next pointer event. Nulling it
|
|
356
|
+
* falls back to sweeping every live instance, which is the honest answer until a frame rebuilds
|
|
357
|
+
* it: an instance added between a mutation and the next draw is otherwise unpickable, which reads
|
|
358
|
+
* as the pointer having left something it is still sitting on.
|
|
359
|
+
*
|
|
360
|
+
* Protected to be *called*, not overridden: a subclass places its instances its own way, so its
|
|
361
|
+
* own writes are the ones this class cannot know have moved something.
|
|
362
|
+
*/
|
|
363
|
+
invalidateBounds() {
|
|
364
|
+
this.boundingBox = null;
|
|
365
|
+
this.boundingSphere = null;
|
|
366
|
+
this.drawList = null;
|
|
367
|
+
}
|
|
368
|
+
onBeforeRender(renderer, scene, camera, geometry, material, group) {
|
|
369
|
+
super.onBeforeRender(renderer, scene, camera, geometry, material, group);
|
|
370
|
+
this._unpatchMaterial = this.patchMaterial(material);
|
|
371
|
+
// Rebuild the draw list for this draw, then publish it: the ids into the texture the shader
|
|
372
|
+
// fetches by `gl_InstanceID`, the length into the count three's instanced draw reads.
|
|
373
|
+
const drawList = this.culling.performFrustumCulling(this, this.instances, camera, material);
|
|
374
|
+
this.indexTexture.data.set(drawList.ids.subarray(0, drawList.count));
|
|
375
|
+
// One mark per row the list touched; the texture merges the contiguous run into a single upload.
|
|
376
|
+
const perRow = this.indexTexture.image.width;
|
|
377
|
+
for (let i = 0; i < drawList.count; i += perRow)
|
|
378
|
+
this.indexTexture.enqueueUpdate(i);
|
|
379
|
+
this.drawList = drawList;
|
|
380
|
+
this.count = drawList.count;
|
|
381
|
+
if (this.count === 0)
|
|
382
|
+
return;
|
|
383
|
+
// Every per-instance buffer is a data texture, and each flushes what changed since the last
|
|
384
|
+
// frame — the draw list included, whose rows the write-out above just marked.
|
|
385
|
+
this.indexTexture.update(renderer);
|
|
386
|
+
this.matricesTexture?.update(renderer);
|
|
387
|
+
this.colorsTexture?.update(renderer);
|
|
388
|
+
this.uniforms.texture?.update(renderer);
|
|
389
|
+
}
|
|
390
|
+
onAfterRender(renderer, scene, camera, geometry, material, group) {
|
|
391
|
+
super.onAfterRender(renderer, scene, camera, geometry, material, group);
|
|
392
|
+
// Hands the material back exactly as it arrived. Strictly paired with the wrap above: three calls
|
|
393
|
+
// the two hooks around every draw, including the two-pass draw a transparent double-sided
|
|
394
|
+
// material takes.
|
|
395
|
+
this._unpatchMaterial?.();
|
|
396
|
+
this._unpatchMaterial = null;
|
|
397
|
+
}
|
|
398
|
+
onBeforeShadow(renderer, scene, camera, shadowCamera, geometry, depthMaterial, group) {
|
|
399
|
+
this.onBeforeRender(renderer, scene, shadowCamera, geometry, depthMaterial, group);
|
|
400
|
+
}
|
|
401
|
+
onAfterShadow(renderer, scene, camera, shadowCamera, geometry, depthMaterial, group) {
|
|
402
|
+
this.onAfterRender(renderer, scene, shadowCamera, geometry, depthMaterial, group);
|
|
403
|
+
// That pass culled to the light's frustum, which is the wrong set to raycast against.
|
|
404
|
+
this.drawList = null;
|
|
405
|
+
}
|
|
406
|
+
clone(recursive) {
|
|
407
|
+
const Constructor = this.constructor;
|
|
408
|
+
return new Constructor({ capacity: this.capacity }).copy(this, recursive);
|
|
409
|
+
}
|
|
410
|
+
copy(source, recursive) {
|
|
411
|
+
super.copy(source, recursive);
|
|
412
|
+
// `Mesh.copy` left the clone sharing the source's geometry. Sharing one is safe — nothing writes
|
|
413
|
+
// to it — but a clone is expected to be independent, so it gets its own.
|
|
414
|
+
this.geometry = source.geometry.clone();
|
|
415
|
+
this.instances.copyFrom(source.instances);
|
|
416
|
+
// The clone has not been drawn, so it has no draw list of its own yet and its `count` stays 0;
|
|
417
|
+
// its first render builds both. Until then nothing draws and raycasting falls back to sweeping
|
|
418
|
+
// every live instance. Neither is worth carrying over — three reads `count` only after
|
|
419
|
+
// `onBeforeRender`, which sets it, and nothing else here reads it at all.
|
|
420
|
+
this.drawList = null;
|
|
421
|
+
this.indexTexture = source.indexTexture.clone();
|
|
422
|
+
this.matricesTexture = source.matricesTexture ? source.matricesTexture.clone() : null;
|
|
423
|
+
this.colorsTexture = source.colorsTexture ? source.colorsTexture.clone() : null;
|
|
424
|
+
this.uniforms.copyFrom(source.uniforms);
|
|
425
|
+
if (source.boundingBox)
|
|
426
|
+
this.boundingBox = source.boundingBox.clone();
|
|
427
|
+
if (source.boundingSphere)
|
|
428
|
+
this.boundingSphere = source.boundingSphere.clone();
|
|
429
|
+
return this;
|
|
430
|
+
}
|
|
431
|
+
raycast(raycaster, intersects) {
|
|
432
|
+
this.raycasting.raycast(this, this.instances, this.drawList, raycaster, intersects);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Grows every per-instance texture to a new capacity, keeping what is written. {@link Instances} grows
|
|
436
|
+
* its own store and then calls this, so nothing here tracks capacity itself.
|
|
437
|
+
* @param newCapacity - The new capacity, always larger than the current one.
|
|
438
|
+
*/
|
|
439
|
+
resizeCapacity(newCapacity) {
|
|
440
|
+
// `SquareDataTexture.resize` disposes each old GPU texture before swapping in the grown one. The
|
|
441
|
+
// draw list needs nothing carried across: culling rewrites it every frame from the live instances.
|
|
442
|
+
this.indexTexture.resize(newCapacity);
|
|
443
|
+
// The room this adds needs no identity fill, unlike the colors below: every instance handed out
|
|
444
|
+
// has its transform reset as it is created, so the only rows left zeroed are ones no instance
|
|
445
|
+
// occupies. A color is not reset there, so an instance in the new room would read the zero.
|
|
446
|
+
this.matricesTexture?.resize(newCapacity);
|
|
447
|
+
if (this.colorsTexture) {
|
|
448
|
+
// Measured before the resize, so the fill covers exactly the room it added.
|
|
449
|
+
const previousLength = this.colorsTexture.data.length;
|
|
450
|
+
this.colorsTexture.resize(newCapacity);
|
|
451
|
+
// The instances the grown room just added read opaque white, as the original allocation does.
|
|
452
|
+
this.colorsTexture.data.fill(1, previousLength);
|
|
453
|
+
}
|
|
454
|
+
this.uniforms.resize(newCapacity);
|
|
455
|
+
}
|
|
456
|
+
initMatricesTexture() {
|
|
457
|
+
this.matricesTexture = new SquareDataTexture(Float32Array, 4, 4, this.capacity);
|
|
458
|
+
// Identity into every row, because a data texture allocates zero-filled and a zero matrix
|
|
459
|
+
// collapses what it transforms to a point — so the instances added before this existed, whose
|
|
460
|
+
// reset found no texture to write into, would draw as nothing rather than as untransformed.
|
|
461
|
+
const data = this.matricesTexture.data;
|
|
462
|
+
for (let i = 0; i < data.length; i += 16) {
|
|
463
|
+
data[i] = 1;
|
|
464
|
+
data[i + 5] = 1;
|
|
465
|
+
data[i + 10] = 1;
|
|
466
|
+
data[i + 15] = 1;
|
|
467
|
+
}
|
|
468
|
+
this.materialsNeedUpdate();
|
|
469
|
+
}
|
|
470
|
+
initColorsTexture() {
|
|
471
|
+
this.colorsTexture = new SquareDataTexture(Float32Array, 4, 1, this.capacity);
|
|
472
|
+
this.colorsTexture.colorSpace = ColorManagement.workingColorSpace;
|
|
473
|
+
this.colorsTexture.data.fill(1);
|
|
474
|
+
this.materialsNeedUpdate();
|
|
475
|
+
}
|
|
476
|
+
/** Flags the material(s) for recompilation, e.g. after a texture is added. */
|
|
477
|
+
materialsNeedUpdate() {
|
|
478
|
+
const material = this.material;
|
|
479
|
+
if (Array.isArray(material)) {
|
|
480
|
+
for (const one of material)
|
|
481
|
+
one.needsUpdate = true;
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
material.needsUpdate = true;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Registers the class as an R3F element, by value so the generated key cannot collide with the
|
|
490
|
+
* `InstancedMesh` three already puts in the catalog when the canvas mounts.
|
|
491
|
+
*/
|
|
492
|
+
export const InstancedMesh = extend(InstancedMeshImpl);
|
|
493
|
+
const DEFAULT_CAPACITY = 1000;
|
|
494
|
+
const _matrix = new Matrix4();
|
|
495
|
+
const _color = new Color();
|
|
496
|
+
const _box = new Box3();
|
|
497
|
+
const _sphere = new Sphere();
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The instance allocator: which instances are live, which are visible, which ids are free to hand
|
|
3
|
+
* out again, and how far the live range extends.
|
|
4
|
+
*
|
|
5
|
+
* Ported from three.ez's instanced-mesh — `feature/Instances.ts` for the lifecycle, the availability
|
|
6
|
+
* accessors from `InstancedMesh2.ts`, and `setInstancesArrayCount` from `feature/Capacity.ts`. The
|
|
7
|
+
* `InstancedEntity` object layer and the BVH bookkeeping woven through all three are dropped, so an
|
|
8
|
+
* instance is just an id.
|
|
9
|
+
*
|
|
10
|
+
* Upstream reaches these through prototype augmentation on `InstancedMesh2`; here they are a store
|
|
11
|
+
* the mesh holds, so frustum culling and raycasting can read availability without reaching into the
|
|
12
|
+
* mesh at all.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Instances {
|
|
15
|
+
/**
|
|
16
|
+
* What each instance holds, one entry each — so its length is the capacity, and there is no second
|
|
17
|
+
* count to keep in step with it. Never sparse; see {@link InstanceState}.
|
|
18
|
+
* @see `InstancedMesh2.availabilityArray` upstream, a pair of booleans per instance. One value
|
|
19
|
+
* cannot express "hidden and free" — which nothing wants, since the only path back to live is
|
|
20
|
+
* {@link addInstance}, and it hands the id to a different instance.
|
|
21
|
+
*/
|
|
22
|
+
private instanceStates;
|
|
23
|
+
/** Ids freed by {@link removeInstances}, handed back out newest first. */
|
|
24
|
+
private freeIds;
|
|
25
|
+
private onResize;
|
|
26
|
+
private _activeInstancesCount;
|
|
27
|
+
private _addedInstancesCount;
|
|
28
|
+
/**
|
|
29
|
+
* @param capacity - How many instances the stores start out holding.
|
|
30
|
+
* @param onResize - Grows everything the owner keeps per instance, keeping what is written.
|
|
31
|
+
* Called only when adding would overflow what the stores hold.
|
|
32
|
+
*/
|
|
33
|
+
constructor(capacity: number, onResize: (capacity: number) => void);
|
|
34
|
+
/**
|
|
35
|
+
* The number of instances the stores currently hold. Derived rather than tracked, so it cannot
|
|
36
|
+
* fall out of step with the array it describes.
|
|
37
|
+
*/
|
|
38
|
+
get capacity(): number;
|
|
39
|
+
/** The number of active instances. */
|
|
40
|
+
get instancesCount(): number;
|
|
41
|
+
/**
|
|
42
|
+
* One past the highest live id — the bound every per-instance sweep iterates to. Larger than
|
|
43
|
+
* {@link instancesCount} whenever a removal left a hole, since only trailing dead instances pull
|
|
44
|
+
* it back in.
|
|
45
|
+
*
|
|
46
|
+
* **Pulled back on removal**, unlike the batched text and line classes, whose equivalent is a
|
|
47
|
+
* pure high-water mark. Both bound a sweep; only this one shrinks. It can afford to because the
|
|
48
|
+
* textures here are sized by {@link capacity} instead, which only ever grows.
|
|
49
|
+
* @see `InstancedMesh2._instancesArrayCount` upstream, which this renames: that name reads as a
|
|
50
|
+
* count of instances, which is exactly what it is not.
|
|
51
|
+
*/
|
|
52
|
+
get addedInstancesCount(): number;
|
|
53
|
+
/**
|
|
54
|
+
* Adds `count` instances, reusing removed ids first, and reports each new id through `onCreation`
|
|
55
|
+
* so the caller can capture it. New instances start active and visible.
|
|
56
|
+
* @param count - How many to add.
|
|
57
|
+
* @param onCreation - Called with each new instance's id.
|
|
58
|
+
*/
|
|
59
|
+
addInstances(count: number, onCreation?: (id: number) => void): void;
|
|
60
|
+
/**
|
|
61
|
+
* Removes instances by id, freeing them for reuse.
|
|
62
|
+
* @param ids - The instances to remove.
|
|
63
|
+
*/
|
|
64
|
+
removeInstances(...ids: number[]): void;
|
|
65
|
+
/**
|
|
66
|
+
* Whether an instance draws — live, and not hidden. The test every per-instance sweep applies.
|
|
67
|
+
* @param id - The index of the instance.
|
|
68
|
+
* @returns Whether it is visible.
|
|
69
|
+
* @see `InstancedMesh2.getVisibilityAt` and `getActiveAndVisibilityAt` upstream, which are one
|
|
70
|
+
* predicate here: an instance cannot be visible without being live.
|
|
71
|
+
*/
|
|
72
|
+
getVisibleAt(id: number): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Shows or hides an instance. A freed id stays freed: liveness and visibility are one value, so
|
|
75
|
+
* writing visibility here would otherwise hand a dead instance back to the draw list.
|
|
76
|
+
* @param id - The index of the instance.
|
|
77
|
+
* @param visible - Whether it should be visible.
|
|
78
|
+
*/
|
|
79
|
+
setVisibleAt(id: number, visible: boolean): void;
|
|
80
|
+
/**
|
|
81
|
+
* Whether an instance is live — handed out and not yet removed, hidden or not. What the bounds
|
|
82
|
+
* sweep to, since a hidden instance still occupies space.
|
|
83
|
+
* @param id - The index of the instance.
|
|
84
|
+
* @returns Whether it is active (not deleted).
|
|
85
|
+
*/
|
|
86
|
+
getActiveAt(id: number): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Adopts another store's instances, for cloning a mesh.
|
|
89
|
+
* @param source - The store to copy.
|
|
90
|
+
*/
|
|
91
|
+
copyFrom(source: Instances): void;
|
|
92
|
+
/**
|
|
93
|
+
* Moves the live range's bound, growing every store when it would pass what they hold. Shrinking
|
|
94
|
+
* only moves the bound; the instances past it keep their data until something reuses them.
|
|
95
|
+
* @param count - One past the highest id the range should cover.
|
|
96
|
+
* @see `InstancedMesh2.setInstancesArrayCount` upstream, which is `@internal` there for the same
|
|
97
|
+
* reason it is private here: only {@link addInstances} has cause to move the bound.
|
|
98
|
+
*/
|
|
99
|
+
private setAddedInstancesCount;
|
|
100
|
+
/**
|
|
101
|
+
* Adds one instance at an id: marks it live and visible, then hands the id to `onCreation` so the
|
|
102
|
+
* owner can reset what it holds and the caller can fill in the rest.
|
|
103
|
+
*
|
|
104
|
+
* One write, so a reused id cannot inherit the hidden state of whatever freed it — the id now
|
|
105
|
+
* belongs to a different instance.
|
|
106
|
+
* @param id - The instance.
|
|
107
|
+
* @param onCreation - Called with the id.
|
|
108
|
+
*/
|
|
109
|
+
private addInstance;
|
|
110
|
+
/**
|
|
111
|
+
* Grows this store and everything the owner keeps per instance.
|
|
112
|
+
*
|
|
113
|
+
* Upstream's `resizeBuffers` grows the availability array itself; here the owner has its buffers
|
|
114
|
+
* and this has the instances, so each grows its own.
|
|
115
|
+
* @param newCapacity - The new capacity, always larger than the current one.
|
|
116
|
+
*/
|
|
117
|
+
private resize;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=Instances.d.ts.map
|