super-three 0.169.1 → 0.170.1
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/build/three.cjs +24628 -24228
- package/build/three.core.js +37002 -0
- package/build/three.core.min.js +6 -0
- package/build/three.module.js +10519 -47108
- package/build/three.module.min.js +1 -1
- package/build/three.tsl.js +533 -0
- package/build/three.tsl.min.js +6 -0
- package/build/three.webgpu.js +17071 -53583
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +17134 -53623
- package/build/three.webgpu.nodes.min.js +1 -1
- package/examples/jsm/Addons.js +3 -3
- package/examples/jsm/animation/MMDAnimationHelper.js +2 -0
- package/examples/jsm/animation/MMDPhysics.js +2 -0
- package/examples/jsm/capabilities/WebGPU.js +1 -10
- package/examples/jsm/controls/ArcballControls.js +25 -21
- package/examples/jsm/controls/OrbitControls.js +41 -9
- package/examples/jsm/controls/PointerLockControls.js +2 -5
- package/examples/jsm/controls/TransformControls.js +22 -6
- package/examples/jsm/csm/CSM.js +2 -2
- package/examples/jsm/csm/CSMFrustum.js +7 -4
- package/examples/jsm/csm/CSMHelper.js +2 -0
- package/examples/jsm/csm/CSMShadowNode.js +437 -0
- package/examples/jsm/curves/NURBSCurve.js +34 -3
- package/examples/jsm/exporters/GLTFExporter.js +138 -71
- package/examples/jsm/exporters/KTX2Exporter.js +35 -12
- package/examples/jsm/exporters/MMDExporter.js +6 -0
- package/examples/jsm/exporters/USDZExporter.js +21 -3
- package/examples/jsm/geometries/DecalGeometry.js +70 -21
- package/examples/jsm/geometries/InstancedPointsGeometry.js +2 -0
- package/examples/jsm/helpers/TextureHelperGPU.js +175 -0
- package/examples/jsm/interactive/HTMLMesh.js +1 -0
- package/examples/jsm/lighting/TiledLighting.js +18 -0
- package/examples/jsm/lights/RectAreaLightTexturesLib.js +1 -1
- package/examples/jsm/lines/LineGeometry.js +25 -0
- package/examples/jsm/lines/LineMaterial.js +0 -1
- package/examples/jsm/lines/LineSegmentsGeometry.js +2 -0
- package/examples/jsm/lines/webgpu/Line2.js +2 -1
- package/examples/jsm/lines/webgpu/LineSegments2.js +2 -16
- package/examples/jsm/lines/webgpu/Wireframe.js +57 -0
- package/examples/jsm/loaders/3DMLoader.js +1 -0
- package/examples/jsm/loaders/3MFLoader.js +91 -0
- package/examples/jsm/loaders/FBXLoader.js +12 -2
- package/examples/jsm/loaders/GLTFLoader.js +2 -0
- package/examples/jsm/loaders/KTX2Loader.js +143 -49
- package/examples/jsm/loaders/LDrawLoader.js +22 -136
- package/examples/jsm/loaders/LottieLoader.js +1 -0
- package/examples/jsm/loaders/MMDLoader.js +3 -0
- package/examples/jsm/loaders/MaterialXLoader.js +2 -2
- package/examples/jsm/materials/LDrawConditionalLineMaterial.js +143 -0
- package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +114 -0
- package/examples/jsm/math/ColorSpaces.js +76 -0
- package/examples/jsm/misc/ProgressiveLightMap.js +52 -40
- package/examples/jsm/misc/ProgressiveLightMapGPU.js +293 -0
- package/examples/jsm/misc/VolumeSlice.js +1 -0
- package/examples/jsm/objects/InstancedPoints.js +2 -4
- package/examples/jsm/objects/LensflareMesh.js +4 -2
- package/examples/jsm/objects/SkyMesh.js +5 -3
- package/examples/jsm/objects/Water2Mesh.js +7 -3
- package/examples/jsm/objects/WaterMesh.js +12 -10
- package/examples/jsm/postprocessing/AfterimagePass.js +14 -3
- package/examples/jsm/postprocessing/SSRPass.js +6 -0
- package/examples/jsm/renderers/CSS2DRenderer.js +6 -3
- package/examples/jsm/renderers/CSS3DRenderer.js +7 -4
- package/examples/jsm/shaders/FXAAShader.js +225 -224
- package/examples/jsm/transpiler/AST.js +2 -2
- package/examples/jsm/transpiler/GLSLDecoder.js +57 -25
- package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
- package/examples/jsm/transpiler/TSLEncoder.js +11 -6
- package/{src/nodes → examples/jsm/tsl}/display/AfterImageNode.js +18 -21
- package/{src/nodes → examples/jsm/tsl}/display/AnaglyphPassNode.js +2 -6
- package/{src/nodes → examples/jsm/tsl}/display/AnamorphicNode.js +12 -18
- package/{src/nodes → examples/jsm/tsl}/display/BleachBypass.js +1 -3
- package/{src/nodes → examples/jsm/tsl}/display/BloomNode.js +12 -41
- package/{src/nodes → examples/jsm/tsl}/display/DenoiseNode.js +60 -47
- package/{src/nodes → examples/jsm/tsl}/display/DepthOfFieldNode.js +4 -9
- package/{src/nodes → examples/jsm/tsl}/display/DotScreenNode.js +2 -9
- package/examples/jsm/tsl/display/FXAANode.js +316 -0
- package/{src/nodes → examples/jsm/tsl}/display/FilmNode.js +4 -7
- package/{src/nodes → examples/jsm/tsl}/display/GTAONode.js +73 -78
- package/{src/nodes → examples/jsm/tsl}/display/GaussianBlurNode.js +78 -42
- package/examples/jsm/tsl/display/LensflareNode.js +161 -0
- package/{src/nodes → examples/jsm/tsl}/display/Lut3DNode.js +3 -5
- package/{src/nodes → examples/jsm/tsl}/display/MotionBlur.js +2 -3
- package/examples/jsm/tsl/display/OutlineNode.js +434 -0
- package/{src/nodes → examples/jsm/tsl}/display/ParallaxBarrierPassNode.js +2 -5
- package/{src/nodes → examples/jsm/tsl}/display/PixelationPassNode.js +5 -17
- package/{src/nodes → examples/jsm/tsl}/display/RGBShiftNode.js +2 -6
- package/examples/jsm/tsl/display/SMAANode.js +620 -0
- package/{src/nodes → examples/jsm/tsl}/display/SSAAPassNode.js +10 -25
- package/examples/jsm/tsl/display/SSRNode.js +366 -0
- package/{src/nodes → examples/jsm/tsl}/display/Sepia.js +1 -2
- package/{src/nodes → examples/jsm/tsl}/display/SobelOperatorNode.js +4 -12
- package/{src/nodes → examples/jsm/tsl}/display/StereoCompositePassNode.js +9 -11
- package/{src/nodes → examples/jsm/tsl}/display/StereoPassNode.js +10 -11
- package/examples/jsm/tsl/display/TRAAPassNode.js +355 -0
- package/{src/nodes → examples/jsm/tsl}/display/TransitionNode.js +3 -7
- package/examples/jsm/tsl/display/hashBlur.js +24 -0
- package/examples/jsm/tsl/lighting/TiledLightsNode.js +389 -0
- package/examples/jsm/utils/SceneOptimizer.js +410 -0
- package/examples/jsm/utils/UVsDebug.js +1 -1
- package/examples/jsm/utils/{TextureUtilsGPU.js → WebGPUTextureUtils.js} +2 -1
- package/examples/jsm/webxr/OculusHandPointerModel.js +21 -21
- package/examples/jsm/webxr/Text2D.js +6 -6
- package/package.json +4 -4
- package/src/Three.Core.js +178 -0
- package/src/Three.TSL.js +526 -0
- package/src/Three.WebGPU.Nodes.js +9 -186
- package/src/Three.WebGPU.js +8 -186
- package/src/Three.js +1 -177
- package/src/animation/AnimationClip.js +2 -2
- package/src/animation/AnimationObjectGroup.js +2 -2
- package/src/audio/Audio.js +38 -0
- package/src/cameras/PerspectiveCamera.js +6 -6
- package/src/cameras/StereoCamera.js +2 -2
- package/src/constants.js +1 -6
- package/src/core/BufferGeometry.js +48 -8
- package/src/core/InterleavedBuffer.js +4 -4
- package/src/core/Object3D.js +2 -2
- package/src/extras/core/Curve.js +3 -3
- package/src/extras/core/Shape.js +2 -2
- package/src/geometries/CylinderGeometry.js +2 -2
- package/src/geometries/EdgesGeometry.js +2 -2
- package/src/geometries/LatheGeometry.js +2 -2
- package/src/lights/SpotLightShadow.js +2 -2
- package/src/materials/LineDashedMaterial.js +0 -1
- package/src/materials/Material.js +2 -2
- package/src/materials/MeshPhongMaterial.js +1 -1
- package/src/materials/MeshPhysicalMaterial.js +2 -2
- package/src/materials/MeshStandardMaterial.js +2 -2
- package/src/materials/nodes/Line2NodeMaterial.js +32 -13
- package/src/materials/nodes/LineDashedNodeMaterial.js +4 -2
- package/src/materials/nodes/NodeMaterial.js +93 -23
- package/src/materials/nodes/SpriteNodeMaterial.js +11 -2
- package/src/materials/nodes/manager/NodeMaterialObserver.js +119 -7
- package/src/math/ColorManagement.js +143 -102
- package/src/math/Line3.js +2 -2
- package/src/math/Quaternion.js +2 -2
- package/src/math/Spherical.js +3 -3
- package/src/math/Vector2.js +7 -7
- package/src/math/Vector3.js +9 -9
- package/src/math/Vector4.js +22 -9
- package/src/nodes/Nodes.js +2 -21
- package/src/nodes/TSL.js +9 -25
- package/src/nodes/accessors/Arrays.js +27 -0
- package/src/nodes/accessors/BuiltinNode.js +26 -0
- package/src/nodes/accessors/Camera.js +0 -1
- package/src/nodes/accessors/ClippingNode.js +76 -42
- package/src/nodes/accessors/InstanceNode.js +17 -20
- package/src/nodes/accessors/InstancedMeshNode.js +26 -0
- package/src/nodes/accessors/Lights.js +32 -0
- package/src/nodes/accessors/SceneNode.js +35 -1
- package/src/nodes/accessors/StorageBufferNode.js +61 -19
- package/src/nodes/accessors/StorageTextureNode.js +10 -4
- package/src/nodes/accessors/TextureNode.js +1 -1
- package/src/nodes/accessors/VelocityNode.js +13 -3
- package/src/nodes/code/FunctionCallNode.js +16 -5
- package/src/nodes/code/ScriptableNode.js +4 -4
- package/src/nodes/core/Node.js +1 -0
- package/src/nodes/core/NodeBuilder.js +31 -14
- package/src/nodes/core/NodeUtils.js +28 -0
- package/src/nodes/core/VarNode.js +15 -3
- package/src/nodes/core/constants.js +6 -0
- package/src/nodes/display/BlendModes.js +99 -0
- package/src/nodes/display/ColorAdjustment.js +53 -4
- package/src/nodes/display/ColorSpaceFunctions.js +5 -5
- package/src/nodes/display/ColorSpaceNode.js +27 -39
- package/src/nodes/display/PassNode.js +6 -4
- package/src/nodes/display/ToneMappingNode.js +1 -1
- package/src/nodes/display/ToonOutlinePassNode.js +3 -3
- package/src/nodes/display/ViewportDepthNode.js +48 -1
- package/src/nodes/functions/PhysicalLightingModel.js +21 -15
- package/src/nodes/functions/material/getAlphaHashThreshold.js +70 -0
- package/src/nodes/functions/material/getGeometryRoughness.js +8 -2
- package/src/nodes/functions/material/getParallaxCorrectNormal.js +22 -0
- package/src/nodes/gpgpu/ComputeNode.js +9 -1
- package/src/nodes/lighting/AnalyticLightNode.js +23 -419
- package/src/nodes/lighting/LightsNode.js +24 -12
- package/src/nodes/lighting/PointLightNode.js +41 -22
- package/src/nodes/lighting/PointShadowNode.js +254 -0
- package/src/nodes/lighting/RectAreaLightNode.js +3 -0
- package/src/nodes/lighting/ShadowNode.js +593 -0
- package/src/nodes/lighting/SpotLightNode.js +14 -2
- package/src/nodes/utils/LoopNode.js +2 -2
- package/src/nodes/utils/Oscillators.js +6 -0
- package/src/nodes/utils/PostProcessingUtils.js +89 -0
- package/src/nodes/utils/RTTNode.js +9 -1
- package/src/nodes/utils/ReflectorNode.js +101 -15
- package/src/nodes/utils/StorageArrayElementNode.js +2 -2
- package/src/nodes/utils/Timer.js +29 -0
- package/src/objects/BatchedMesh.js +472 -296
- package/src/objects/ClippingGroup.js +19 -0
- package/src/objects/Skeleton.js +2 -2
- package/src/renderers/WebGLRenderer.js +183 -109
- package/src/renderers/common/Animation.js +23 -11
- package/src/renderers/common/Attributes.js +4 -0
- package/src/renderers/common/Backend.js +2 -0
- package/src/renderers/common/Background.js +15 -5
- package/src/renderers/common/Bindings.js +23 -6
- package/src/renderers/common/ClippingContext.js +77 -85
- package/src/renderers/common/Constants.js +2 -1
- package/src/renderers/common/Geometries.js +20 -0
- package/src/renderers/common/IndirectStorageBufferAttribute.js +15 -0
- package/src/renderers/common/Lighting.js +45 -0
- package/src/renderers/common/PostProcessingUtils.js +86 -0
- package/src/renderers/common/RenderList.js +48 -17
- package/src/renderers/common/RenderLists.js +4 -2
- package/src/renderers/common/RenderObject.js +45 -28
- package/src/renderers/common/RenderObjects.js +12 -6
- package/src/renderers/common/Renderer.js +222 -77
- package/src/renderers/common/Textures.js +41 -17
- package/src/renderers/common/UniformsGroup.js +16 -4
- package/src/renderers/common/extras/PMREMGenerator.js +89 -13
- package/src/renderers/common/nodes/NodeLibrary.js +2 -15
- package/src/renderers/common/nodes/NodeStorageBuffer.js +2 -3
- package/src/renderers/common/nodes/NodeUniform.js +42 -0
- package/src/renderers/common/nodes/Nodes.js +2 -2
- package/src/renderers/shaders/ShaderChunk/colorspace_pars_fragment.glsl.js +4 -24
- package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +8 -0
- package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +2 -2
- package/src/renderers/webgl/WebGLBackground.js +20 -1
- package/src/renderers/webgl/WebGLBufferRenderer.js +2 -6
- package/src/renderers/webgl/WebGLCapabilities.js +0 -7
- package/src/renderers/webgl/WebGLGeometries.js +0 -28
- package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +2 -6
- package/src/renderers/webgl/WebGLProgram.js +24 -28
- package/src/renderers/webgl/WebGLPrograms.js +5 -2
- package/src/renderers/webgl/WebGLState.js +37 -1
- package/src/renderers/webgl/WebGLTextures.js +29 -12
- package/src/renderers/webgl-fallback/WebGLBackend.js +111 -37
- package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +2 -7
- package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +43 -12
- package/src/renderers/webgl-fallback/utils/WebGLState.js +26 -1
- package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +37 -9
- package/src/renderers/webgpu/WebGPUBackend.js +152 -56
- package/src/renderers/webgpu/WebGPURenderer.Nodes.js +1 -1
- package/src/renderers/webgpu/WebGPURenderer.js +1 -1
- package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +0 -8
- package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +13 -34
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +192 -92
- package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +12 -4
- package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +15 -2
- package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +72 -7
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +29 -9
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +29 -7
- package/src/renderers/webgpu/utils/WebGPUUtils.js +0 -1
- package/src/renderers/webxr/WebXRManager.js +4 -4
- package/src/textures/Source.js +2 -2
- package/src/textures/Texture.js +2 -2
- package/examples/jsm/cameras/CinematicCamera.js +0 -208
- package/src/nodes/display/BlendMode.js +0 -54
- package/src/nodes/display/FXAANode.js +0 -332
- package/src/nodes/utils/OscNode.js +0 -85
- package/src/nodes/utils/TimerNode.js +0 -97
- /package/examples/jsm/utils/{TextureUtils.js → WebGLTextureUtils.js} +0 -0
|
@@ -12,6 +12,12 @@ import { Frustum } from '../math/Frustum.js';
|
|
|
12
12
|
import { Vector3 } from '../math/Vector3.js';
|
|
13
13
|
import { Color } from '../math/Color.js';
|
|
14
14
|
|
|
15
|
+
function ascIdSort( a, b ) {
|
|
16
|
+
|
|
17
|
+
return a - b;
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
function sortOpaque( a, b ) {
|
|
16
22
|
|
|
17
23
|
return a.z - b.z;
|
|
@@ -34,7 +40,7 @@ class MultiDrawRenderList {
|
|
|
34
40
|
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
push(
|
|
43
|
+
push( start, count, z, index ) {
|
|
38
44
|
|
|
39
45
|
const pool = this.pool;
|
|
40
46
|
const list = this.list;
|
|
@@ -55,8 +61,8 @@ class MultiDrawRenderList {
|
|
|
55
61
|
list.push( item );
|
|
56
62
|
this.index ++;
|
|
57
63
|
|
|
58
|
-
item.start =
|
|
59
|
-
item.count =
|
|
64
|
+
item.start = start;
|
|
65
|
+
item.count = count;
|
|
60
66
|
item.z = z;
|
|
61
67
|
item.index = index;
|
|
62
68
|
|
|
@@ -72,10 +78,7 @@ class MultiDrawRenderList {
|
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
const _matrix = /*@__PURE__*/ new Matrix4();
|
|
75
|
-
const _invMatrixWorld = /*@__PURE__*/ new Matrix4();
|
|
76
|
-
const _identityMatrix = /*@__PURE__*/ new Matrix4();
|
|
77
81
|
const _whiteColor = /*@__PURE__*/ new Color( 1, 1, 1 );
|
|
78
|
-
const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
|
|
79
82
|
const _frustum = /*@__PURE__*/ new Frustum();
|
|
80
83
|
const _box = /*@__PURE__*/ new Box3();
|
|
81
84
|
const _sphere = /*@__PURE__*/ new Sphere();
|
|
@@ -86,13 +89,6 @@ const _renderList = /*@__PURE__*/ new MultiDrawRenderList();
|
|
|
86
89
|
const _mesh = /*@__PURE__*/ new Mesh();
|
|
87
90
|
const _batchIntersects = [];
|
|
88
91
|
|
|
89
|
-
// @TODO: SkinnedMesh support?
|
|
90
|
-
// @TODO: geometry.groups support?
|
|
91
|
-
// @TODO: geometry.drawRange support?
|
|
92
|
-
// @TODO: geometry.morphAttributes support?
|
|
93
|
-
// @TODO: Support uniform parameter per geometry
|
|
94
|
-
// @TODO: Add an "optimize" function to pack geometry and remove data gaps
|
|
95
|
-
|
|
96
92
|
// copies data from attribute "src" into "target" starting at "targetOffset"
|
|
97
93
|
function copyAttributeData( src, target, targetOffset = 0 ) {
|
|
98
94
|
|
|
@@ -123,6 +119,29 @@ function copyAttributeData( src, target, targetOffset = 0 ) {
|
|
|
123
119
|
|
|
124
120
|
}
|
|
125
121
|
|
|
122
|
+
// safely copies array contents to a potentially smaller array
|
|
123
|
+
function copyArrayContents( src, target ) {
|
|
124
|
+
|
|
125
|
+
if ( src.constructor !== target.constructor ) {
|
|
126
|
+
|
|
127
|
+
// if arrays are of a different type (eg due to index size increasing) then data must be per-element copied
|
|
128
|
+
const len = Math.min( src.length, target.length );
|
|
129
|
+
for ( let i = 0; i < len; i ++ ) {
|
|
130
|
+
|
|
131
|
+
target[ i ] = src[ i ];
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
} else {
|
|
136
|
+
|
|
137
|
+
// if the arrays use the same data layout we can use a fast block copy
|
|
138
|
+
const len = Math.min( src.length, target.length );
|
|
139
|
+
target.set( new src.constructor( src.buffer, 0, len ) );
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
126
145
|
class BatchedMesh extends Mesh {
|
|
127
146
|
|
|
128
147
|
get maxInstanceCount() {
|
|
@@ -131,6 +150,24 @@ class BatchedMesh extends Mesh {
|
|
|
131
150
|
|
|
132
151
|
}
|
|
133
152
|
|
|
153
|
+
get instanceCount() {
|
|
154
|
+
|
|
155
|
+
return this._instanceInfo.length - this._availableInstanceIds.length;
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get unusedVertexCount() {
|
|
160
|
+
|
|
161
|
+
return this._maxVertexCount - this._nextVertexStart;
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
get unusedIndexCount() {
|
|
166
|
+
|
|
167
|
+
return this._maxIndexCount - this._nextIndexStart;
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
134
171
|
constructor( maxInstanceCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
|
|
135
172
|
|
|
136
173
|
super( new BufferGeometry(), material );
|
|
@@ -142,28 +179,33 @@ class BatchedMesh extends Mesh {
|
|
|
142
179
|
this.boundingSphere = null;
|
|
143
180
|
this.customSort = null;
|
|
144
181
|
|
|
145
|
-
// stores visible, active, and geometry id per
|
|
146
|
-
this.
|
|
182
|
+
// stores visible, active, and geometry id per instance and reserved buffer ranges for geometries
|
|
183
|
+
this._instanceInfo = [];
|
|
184
|
+
this._geometryInfo = [];
|
|
147
185
|
|
|
148
|
-
// instance ids that have been set as inactive, and are available to be overwritten
|
|
186
|
+
// instance, geometry ids that have been set as inactive, and are available to be overwritten
|
|
149
187
|
this._availableInstanceIds = [];
|
|
188
|
+
this._availableGeometryIds = [];
|
|
189
|
+
|
|
190
|
+
// used to track where the next point is that geometry should be inserted
|
|
191
|
+
this._nextIndexStart = 0;
|
|
192
|
+
this._nextVertexStart = 0;
|
|
193
|
+
this._geometryCount = 0;
|
|
150
194
|
|
|
151
|
-
//
|
|
152
|
-
this.
|
|
153
|
-
this.
|
|
154
|
-
this._bounds = [];
|
|
195
|
+
// flags
|
|
196
|
+
this._visibilityChanged = true;
|
|
197
|
+
this._geometryInitialized = false;
|
|
155
198
|
|
|
199
|
+
// cached user options
|
|
156
200
|
this._maxInstanceCount = maxInstanceCount;
|
|
157
201
|
this._maxVertexCount = maxVertexCount;
|
|
158
202
|
this._maxIndexCount = maxIndexCount;
|
|
159
203
|
|
|
160
|
-
|
|
161
|
-
this._geometryCount = 0;
|
|
204
|
+
// buffers for multi draw
|
|
162
205
|
this._multiDrawCounts = new Int32Array( maxInstanceCount );
|
|
163
206
|
this._multiDrawStarts = new Int32Array( maxInstanceCount );
|
|
164
207
|
this._multiDrawCount = 0;
|
|
165
208
|
this._multiDrawInstances = null;
|
|
166
|
-
this._visibilityChanged = true;
|
|
167
209
|
|
|
168
210
|
// Local matrix per geometry by using data texture
|
|
169
211
|
this._matricesTexture = null;
|
|
@@ -264,7 +306,7 @@ class BatchedMesh extends Mesh {
|
|
|
264
306
|
const batchGeometry = this.geometry;
|
|
265
307
|
if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
|
|
266
308
|
|
|
267
|
-
throw new Error( 'BatchedMesh: All geometries must consistently have "index".' );
|
|
309
|
+
throw new Error( 'THREE.BatchedMesh: All geometries must consistently have "index".' );
|
|
268
310
|
|
|
269
311
|
}
|
|
270
312
|
|
|
@@ -272,7 +314,7 @@ class BatchedMesh extends Mesh {
|
|
|
272
314
|
|
|
273
315
|
if ( ! geometry.hasAttribute( attributeName ) ) {
|
|
274
316
|
|
|
275
|
-
throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
|
|
317
|
+
throw new Error( `THREE.BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
|
|
276
318
|
|
|
277
319
|
}
|
|
278
320
|
|
|
@@ -280,7 +322,7 @@ class BatchedMesh extends Mesh {
|
|
|
280
322
|
const dstAttribute = batchGeometry.getAttribute( attributeName );
|
|
281
323
|
if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
|
|
282
324
|
|
|
283
|
-
throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
|
|
325
|
+
throw new Error( 'THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
|
|
284
326
|
|
|
285
327
|
}
|
|
286
328
|
|
|
@@ -288,6 +330,29 @@ class BatchedMesh extends Mesh {
|
|
|
288
330
|
|
|
289
331
|
}
|
|
290
332
|
|
|
333
|
+
validateInstanceId( instanceId ) {
|
|
334
|
+
|
|
335
|
+
const instanceInfo = this._instanceInfo;
|
|
336
|
+
if ( instanceId < 0 || instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
337
|
+
|
|
338
|
+
throw new Error( `THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instance is either out of range or has been deleted.` );
|
|
339
|
+
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
validateGeometryId( geometryId ) {
|
|
345
|
+
|
|
346
|
+
const geometryInfoList = this._geometryInfo;
|
|
347
|
+
if ( geometryId < 0 || geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
|
|
348
|
+
|
|
349
|
+
throw new Error( `THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometry is either out of range or has been deleted.` );
|
|
350
|
+
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
|
|
291
356
|
setCustomSort( func ) {
|
|
292
357
|
|
|
293
358
|
this.customSort = func;
|
|
@@ -304,14 +369,14 @@ class BatchedMesh extends Mesh {
|
|
|
304
369
|
}
|
|
305
370
|
|
|
306
371
|
const boundingBox = this.boundingBox;
|
|
307
|
-
const
|
|
372
|
+
const instanceInfo = this._instanceInfo;
|
|
308
373
|
|
|
309
374
|
boundingBox.makeEmpty();
|
|
310
|
-
for ( let i = 0, l =
|
|
375
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
311
376
|
|
|
312
|
-
if (
|
|
377
|
+
if ( instanceInfo[ i ].active === false ) continue;
|
|
313
378
|
|
|
314
|
-
const geometryId =
|
|
379
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
315
380
|
this.getMatrixAt( i, _matrix );
|
|
316
381
|
this.getBoundingBoxAt( geometryId, _box ).applyMatrix4( _matrix );
|
|
317
382
|
boundingBox.union( _box );
|
|
@@ -329,14 +394,14 @@ class BatchedMesh extends Mesh {
|
|
|
329
394
|
}
|
|
330
395
|
|
|
331
396
|
const boundingSphere = this.boundingSphere;
|
|
332
|
-
const
|
|
397
|
+
const instanceInfo = this._instanceInfo;
|
|
333
398
|
|
|
334
399
|
boundingSphere.makeEmpty();
|
|
335
|
-
for ( let i = 0, l =
|
|
400
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
336
401
|
|
|
337
|
-
if (
|
|
402
|
+
if ( instanceInfo[ i ].active === false ) continue;
|
|
338
403
|
|
|
339
|
-
const geometryId =
|
|
404
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
340
405
|
this.getMatrixAt( i, _matrix );
|
|
341
406
|
this.getBoundingSphereAt( geometryId, _sphere ).applyMatrix4( _matrix );
|
|
342
407
|
boundingSphere.union( _sphere );
|
|
@@ -347,16 +412,16 @@ class BatchedMesh extends Mesh {
|
|
|
347
412
|
|
|
348
413
|
addInstance( geometryId ) {
|
|
349
414
|
|
|
350
|
-
const atCapacity = this.
|
|
415
|
+
const atCapacity = this._instanceInfo.length >= this.maxInstanceCount;
|
|
351
416
|
|
|
352
417
|
// ensure we're not over geometry
|
|
353
418
|
if ( atCapacity && this._availableInstanceIds.length === 0 ) {
|
|
354
419
|
|
|
355
|
-
throw new Error( 'BatchedMesh: Maximum item count reached.' );
|
|
420
|
+
throw new Error( 'THREE.BatchedMesh: Maximum item count reached.' );
|
|
356
421
|
|
|
357
422
|
}
|
|
358
423
|
|
|
359
|
-
const
|
|
424
|
+
const instanceInfo = {
|
|
360
425
|
visible: true,
|
|
361
426
|
active: true,
|
|
362
427
|
geometryIndex: geometryId,
|
|
@@ -367,19 +432,20 @@ class BatchedMesh extends Mesh {
|
|
|
367
432
|
// Prioritize using previously freed instance ids
|
|
368
433
|
if ( this._availableInstanceIds.length > 0 ) {
|
|
369
434
|
|
|
370
|
-
|
|
371
|
-
|
|
435
|
+
this._availableInstanceIds.sort( ascIdSort );
|
|
436
|
+
|
|
437
|
+
drawId = this._availableInstanceIds.shift();
|
|
438
|
+
this._instanceInfo[ drawId ] = instanceInfo;
|
|
372
439
|
|
|
373
440
|
} else {
|
|
374
441
|
|
|
375
|
-
drawId = this.
|
|
376
|
-
this.
|
|
442
|
+
drawId = this._instanceInfo.length;
|
|
443
|
+
this._instanceInfo.push( instanceInfo );
|
|
377
444
|
|
|
378
445
|
}
|
|
379
446
|
|
|
380
447
|
const matricesTexture = this._matricesTexture;
|
|
381
|
-
|
|
382
|
-
_identityMatrix.toArray( matricesArray, drawId * 16 );
|
|
448
|
+
_matrix.identity().toArray( matricesTexture.image.data, drawId * 16 );
|
|
383
449
|
matricesTexture.needsUpdate = true;
|
|
384
450
|
|
|
385
451
|
const colorsTexture = this._colorsTexture;
|
|
@@ -390,118 +456,85 @@ class BatchedMesh extends Mesh {
|
|
|
390
456
|
|
|
391
457
|
}
|
|
392
458
|
|
|
459
|
+
this._visibilityChanged = true;
|
|
393
460
|
return drawId;
|
|
394
461
|
|
|
395
462
|
}
|
|
396
463
|
|
|
397
|
-
addGeometry( geometry,
|
|
464
|
+
addGeometry( geometry, reservedVertexCount = - 1, reservedIndexCount = - 1 ) {
|
|
398
465
|
|
|
399
466
|
this._initializeGeometry( geometry );
|
|
400
467
|
|
|
401
468
|
this._validateGeometry( geometry );
|
|
402
469
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
throw new Error( 'BatchedMesh: Maximum item count reached.' );
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// get the necessary range fo the geometry
|
|
411
|
-
const reservedRange = {
|
|
470
|
+
const geometryInfo = {
|
|
471
|
+
// geometry information
|
|
412
472
|
vertexStart: - 1,
|
|
413
473
|
vertexCount: - 1,
|
|
474
|
+
reservedVertexCount: - 1,
|
|
475
|
+
|
|
414
476
|
indexStart: - 1,
|
|
415
477
|
indexCount: - 1,
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
let lastRange = null;
|
|
419
|
-
const reservedRanges = this._reservedRanges;
|
|
420
|
-
const drawRanges = this._drawRanges;
|
|
421
|
-
const bounds = this._bounds;
|
|
422
|
-
if ( this._geometryCount !== 0 ) {
|
|
423
|
-
|
|
424
|
-
lastRange = reservedRanges[ reservedRanges.length - 1 ];
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if ( vertexCount === - 1 ) {
|
|
429
|
-
|
|
430
|
-
reservedRange.vertexCount = geometry.getAttribute( 'position' ).count;
|
|
431
|
-
|
|
432
|
-
} else {
|
|
433
|
-
|
|
434
|
-
reservedRange.vertexCount = vertexCount;
|
|
435
|
-
|
|
436
|
-
}
|
|
478
|
+
reservedIndexCount: - 1,
|
|
437
479
|
|
|
438
|
-
|
|
480
|
+
// draw range information
|
|
481
|
+
start: - 1,
|
|
482
|
+
count: - 1,
|
|
439
483
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
484
|
+
// state
|
|
485
|
+
boundingBox: null,
|
|
486
|
+
boundingSphere: null,
|
|
487
|
+
active: true,
|
|
488
|
+
};
|
|
445
489
|
|
|
446
|
-
|
|
490
|
+
const geometryInfoList = this._geometryInfo;
|
|
491
|
+
geometryInfo.vertexStart = this._nextVertexStart;
|
|
492
|
+
geometryInfo.reservedVertexCount = reservedVertexCount === - 1 ? geometry.getAttribute( 'position' ).count : reservedVertexCount;
|
|
447
493
|
|
|
448
494
|
const index = geometry.getIndex();
|
|
449
495
|
const hasIndex = index !== null;
|
|
450
496
|
if ( hasIndex ) {
|
|
451
497
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
reservedRange.indexCount = index.count;
|
|
455
|
-
|
|
456
|
-
} else {
|
|
498
|
+
geometryInfo.indexStart = this._nextIndexStart;
|
|
499
|
+
geometryInfo.reservedIndexCount = reservedIndexCount === - 1 ? index.count : reservedIndexCount;
|
|
457
500
|
|
|
458
|
-
|
|
501
|
+
}
|
|
459
502
|
|
|
460
|
-
|
|
503
|
+
if (
|
|
504
|
+
geometryInfo.indexStart !== - 1 &&
|
|
505
|
+
geometryInfo.indexStart + geometryInfo.reservedIndexCount > this._maxIndexCount ||
|
|
506
|
+
geometryInfo.vertexStart + geometryInfo.reservedVertexCount > this._maxVertexCount
|
|
507
|
+
) {
|
|
461
508
|
|
|
462
|
-
|
|
509
|
+
throw new Error( 'THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
|
|
463
510
|
|
|
464
|
-
|
|
511
|
+
}
|
|
465
512
|
|
|
466
|
-
|
|
513
|
+
// update id
|
|
514
|
+
let geometryId;
|
|
515
|
+
if ( this._availableGeometryIds.length > 0 ) {
|
|
467
516
|
|
|
468
|
-
|
|
517
|
+
this._availableGeometryIds.sort( ascIdSort );
|
|
469
518
|
|
|
470
|
-
|
|
519
|
+
geometryId = this._availableGeometryIds.shift();
|
|
520
|
+
geometryInfoList[ geometryId ] = geometryInfo;
|
|
471
521
|
|
|
472
|
-
}
|
|
473
522
|
|
|
474
|
-
|
|
475
|
-
reservedRange.indexStart !== - 1 &&
|
|
476
|
-
reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount ||
|
|
477
|
-
reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount
|
|
478
|
-
) {
|
|
523
|
+
} else {
|
|
479
524
|
|
|
480
|
-
|
|
525
|
+
geometryId = this._geometryCount;
|
|
526
|
+
this._geometryCount ++;
|
|
527
|
+
geometryInfoList.push( geometryInfo );
|
|
481
528
|
|
|
482
529
|
}
|
|
483
530
|
|
|
484
|
-
// update id
|
|
485
|
-
const geometryId = this._geometryCount;
|
|
486
|
-
this._geometryCount ++;
|
|
487
|
-
|
|
488
|
-
// add the reserved range and draw range objects
|
|
489
|
-
reservedRanges.push( reservedRange );
|
|
490
|
-
drawRanges.push( {
|
|
491
|
-
start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart,
|
|
492
|
-
count: - 1
|
|
493
|
-
} );
|
|
494
|
-
bounds.push( {
|
|
495
|
-
boxInitialized: false,
|
|
496
|
-
box: new Box3(),
|
|
497
|
-
|
|
498
|
-
sphereInitialized: false,
|
|
499
|
-
sphere: new Sphere()
|
|
500
|
-
} );
|
|
501
|
-
|
|
502
531
|
// update the geometry
|
|
503
532
|
this.setGeometryAt( geometryId, geometry );
|
|
504
533
|
|
|
534
|
+
// increment the next geometry position
|
|
535
|
+
this._nextIndexStart = geometryInfo.indexStart + geometryInfo.reservedIndexCount;
|
|
536
|
+
this._nextVertexStart = geometryInfo.vertexStart + geometryInfo.reservedVertexCount;
|
|
537
|
+
|
|
505
538
|
return geometryId;
|
|
506
539
|
|
|
507
540
|
}
|
|
@@ -510,7 +543,7 @@ class BatchedMesh extends Mesh {
|
|
|
510
543
|
|
|
511
544
|
if ( geometryId >= this._geometryCount ) {
|
|
512
545
|
|
|
513
|
-
throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
|
|
546
|
+
throw new Error( 'THREE.BatchedMesh: Maximum geometry count reached.' );
|
|
514
547
|
|
|
515
548
|
}
|
|
516
549
|
|
|
@@ -520,20 +553,22 @@ class BatchedMesh extends Mesh {
|
|
|
520
553
|
const hasIndex = batchGeometry.getIndex() !== null;
|
|
521
554
|
const dstIndex = batchGeometry.getIndex();
|
|
522
555
|
const srcIndex = geometry.getIndex();
|
|
523
|
-
const
|
|
556
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
524
557
|
if (
|
|
525
558
|
hasIndex &&
|
|
526
|
-
srcIndex.count >
|
|
527
|
-
geometry.attributes.position.count >
|
|
559
|
+
srcIndex.count > geometryInfo.reservedIndexCount ||
|
|
560
|
+
geometry.attributes.position.count > geometryInfo.reservedVertexCount
|
|
528
561
|
) {
|
|
529
562
|
|
|
530
|
-
throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' );
|
|
563
|
+
throw new Error( 'THREE.BatchedMesh: Reserved space not large enough for provided geometry.' );
|
|
531
564
|
|
|
532
565
|
}
|
|
533
566
|
|
|
534
|
-
// copy geometry over
|
|
535
|
-
const vertexStart =
|
|
536
|
-
const
|
|
567
|
+
// copy geometry buffer data over
|
|
568
|
+
const vertexStart = geometryInfo.vertexStart;
|
|
569
|
+
const reservedVertexCount = geometryInfo.reservedVertexCount;
|
|
570
|
+
geometryInfo.vertexCount = geometry.getAttribute( 'position' ).count;
|
|
571
|
+
|
|
537
572
|
for ( const attributeName in batchGeometry.attributes ) {
|
|
538
573
|
|
|
539
574
|
// copy attribute data
|
|
@@ -543,7 +578,7 @@ class BatchedMesh extends Mesh {
|
|
|
543
578
|
|
|
544
579
|
// fill the rest in with zeroes
|
|
545
580
|
const itemSize = srcAttribute.itemSize;
|
|
546
|
-
for ( let i = srcAttribute.count, l =
|
|
581
|
+
for ( let i = srcAttribute.count, l = reservedVertexCount; i < l; i ++ ) {
|
|
547
582
|
|
|
548
583
|
const index = vertexStart + i;
|
|
549
584
|
for ( let c = 0; c < itemSize; c ++ ) {
|
|
@@ -555,14 +590,16 @@ class BatchedMesh extends Mesh {
|
|
|
555
590
|
}
|
|
556
591
|
|
|
557
592
|
dstAttribute.needsUpdate = true;
|
|
558
|
-
dstAttribute.addUpdateRange( vertexStart * itemSize,
|
|
593
|
+
dstAttribute.addUpdateRange( vertexStart * itemSize, reservedVertexCount * itemSize );
|
|
559
594
|
|
|
560
595
|
}
|
|
561
596
|
|
|
562
597
|
// copy index
|
|
563
598
|
if ( hasIndex ) {
|
|
564
599
|
|
|
565
|
-
const indexStart =
|
|
600
|
+
const indexStart = geometryInfo.indexStart;
|
|
601
|
+
const reservedIndexCount = geometryInfo.reservedIndexCount;
|
|
602
|
+
geometryInfo.indexCount = geometry.getIndex().count;
|
|
566
603
|
|
|
567
604
|
// copy index data over
|
|
568
605
|
for ( let i = 0; i < srcIndex.count; i ++ ) {
|
|
@@ -572,69 +609,75 @@ class BatchedMesh extends Mesh {
|
|
|
572
609
|
}
|
|
573
610
|
|
|
574
611
|
// fill the rest in with zeroes
|
|
575
|
-
for ( let i = srcIndex.count, l =
|
|
612
|
+
for ( let i = srcIndex.count, l = reservedIndexCount; i < l; i ++ ) {
|
|
576
613
|
|
|
577
614
|
dstIndex.setX( indexStart + i, vertexStart );
|
|
578
615
|
|
|
579
616
|
}
|
|
580
617
|
|
|
581
618
|
dstIndex.needsUpdate = true;
|
|
582
|
-
dstIndex.addUpdateRange( indexStart,
|
|
619
|
+
dstIndex.addUpdateRange( indexStart, geometryInfo.reservedIndexCount );
|
|
583
620
|
|
|
584
621
|
}
|
|
585
622
|
|
|
623
|
+
// update the draw range
|
|
624
|
+
geometryInfo.start = hasIndex ? geometryInfo.indexStart : geometryInfo.vertexStart;
|
|
625
|
+
geometryInfo.count = hasIndex ? geometryInfo.indexCount : geometryInfo.vertexCount;
|
|
626
|
+
|
|
586
627
|
// store the bounding boxes
|
|
587
|
-
|
|
628
|
+
geometryInfo.boundingBox = null;
|
|
588
629
|
if ( geometry.boundingBox !== null ) {
|
|
589
630
|
|
|
590
|
-
|
|
591
|
-
bound.boxInitialized = true;
|
|
592
|
-
|
|
593
|
-
} else {
|
|
594
|
-
|
|
595
|
-
bound.boxInitialized = false;
|
|
631
|
+
geometryInfo.boundingBox = geometry.boundingBox.clone();
|
|
596
632
|
|
|
597
633
|
}
|
|
598
634
|
|
|
635
|
+
geometryInfo.boundingSphere = null;
|
|
599
636
|
if ( geometry.boundingSphere !== null ) {
|
|
600
637
|
|
|
601
|
-
|
|
602
|
-
bound.sphereInitialized = true;
|
|
603
|
-
|
|
604
|
-
} else {
|
|
605
|
-
|
|
606
|
-
bound.sphereInitialized = false;
|
|
638
|
+
geometryInfo.boundingSphere = geometry.boundingSphere.clone();
|
|
607
639
|
|
|
608
640
|
}
|
|
609
641
|
|
|
610
|
-
// set drawRange count
|
|
611
|
-
const drawRange = this._drawRanges[ geometryId ];
|
|
612
|
-
const posAttr = geometry.getAttribute( 'position' );
|
|
613
|
-
drawRange.count = hasIndex ? srcIndex.count : posAttr.count;
|
|
614
642
|
this._visibilityChanged = true;
|
|
615
|
-
|
|
616
643
|
return geometryId;
|
|
617
644
|
|
|
618
645
|
}
|
|
619
646
|
|
|
620
|
-
/*
|
|
621
647
|
deleteGeometry( geometryId ) {
|
|
622
648
|
|
|
623
|
-
|
|
649
|
+
const geometryInfoList = this._geometryInfo;
|
|
650
|
+
if ( geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
|
|
624
651
|
|
|
625
|
-
|
|
626
|
-
*/
|
|
652
|
+
return this;
|
|
627
653
|
|
|
628
|
-
|
|
654
|
+
}
|
|
629
655
|
|
|
630
|
-
|
|
631
|
-
|
|
656
|
+
// delete any instances associated with this geometry
|
|
657
|
+
const instanceInfo = this._instanceInfo;
|
|
658
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
632
659
|
|
|
633
|
-
|
|
660
|
+
if ( instanceInfo[ i ].geometryIndex === geometryId ) {
|
|
661
|
+
|
|
662
|
+
this.deleteInstance( i );
|
|
663
|
+
|
|
664
|
+
}
|
|
634
665
|
|
|
635
666
|
}
|
|
636
667
|
|
|
637
|
-
|
|
668
|
+
geometryInfoList[ geometryId ].active = false;
|
|
669
|
+
this._availableGeometryIds.push( geometryId );
|
|
670
|
+
this._visibilityChanged = true;
|
|
671
|
+
|
|
672
|
+
return this;
|
|
673
|
+
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
deleteInstance( instanceId ) {
|
|
677
|
+
|
|
678
|
+
this.validateInstanceId( instanceId );
|
|
679
|
+
|
|
680
|
+
this._instanceInfo[ instanceId ].active = false;
|
|
638
681
|
this._availableInstanceIds.push( instanceId );
|
|
639
682
|
this._visibilityChanged = true;
|
|
640
683
|
|
|
@@ -642,6 +685,95 @@ class BatchedMesh extends Mesh {
|
|
|
642
685
|
|
|
643
686
|
}
|
|
644
687
|
|
|
688
|
+
optimize() {
|
|
689
|
+
|
|
690
|
+
// track the next indices to copy data to
|
|
691
|
+
let nextVertexStart = 0;
|
|
692
|
+
let nextIndexStart = 0;
|
|
693
|
+
|
|
694
|
+
// Iterate over all geometry ranges in order sorted from earliest in the geometry buffer to latest
|
|
695
|
+
// in the geometry buffer. Because draw range objects can be reused there is no guarantee of their order.
|
|
696
|
+
const geometryInfoList = this._geometryInfo;
|
|
697
|
+
const indices = geometryInfoList
|
|
698
|
+
.map( ( e, i ) => i )
|
|
699
|
+
.sort( ( a, b ) => {
|
|
700
|
+
|
|
701
|
+
return geometryInfoList[ a ].vertexStart - geometryInfoList[ b ].vertexStart;
|
|
702
|
+
|
|
703
|
+
} );
|
|
704
|
+
|
|
705
|
+
const geometry = this.geometry;
|
|
706
|
+
for ( let i = 0, l = geometryInfoList.length; i < l; i ++ ) {
|
|
707
|
+
|
|
708
|
+
// if a geometry range is inactive then don't copy anything
|
|
709
|
+
const index = indices[ i ];
|
|
710
|
+
const geometryInfo = geometryInfoList[ index ];
|
|
711
|
+
if ( geometryInfo.active === false ) {
|
|
712
|
+
|
|
713
|
+
continue;
|
|
714
|
+
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// if a geometry contains an index buffer then shift it, as well
|
|
718
|
+
if ( geometry.index !== null ) {
|
|
719
|
+
|
|
720
|
+
if ( geometryInfo.indexStart !== nextIndexStart ) {
|
|
721
|
+
|
|
722
|
+
const { indexStart, vertexStart, reservedIndexCount } = geometryInfo;
|
|
723
|
+
const index = geometry.index;
|
|
724
|
+
const array = index.array;
|
|
725
|
+
|
|
726
|
+
// shift the index pointers based on how the vertex data will shift
|
|
727
|
+
// adjusting the index must happen first so the original vertex start value is available
|
|
728
|
+
const elementDelta = nextVertexStart - vertexStart;
|
|
729
|
+
for ( let j = indexStart; j < indexStart + reservedIndexCount; j ++ ) {
|
|
730
|
+
|
|
731
|
+
array[ j ] = array[ j ] + elementDelta;
|
|
732
|
+
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
index.array.copyWithin( nextIndexStart, indexStart, indexStart + reservedIndexCount );
|
|
736
|
+
index.addUpdateRange( nextIndexStart, reservedIndexCount );
|
|
737
|
+
|
|
738
|
+
geometryInfo.indexStart = nextIndexStart;
|
|
739
|
+
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
nextIndexStart += geometryInfo.reservedIndexCount;
|
|
743
|
+
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// if a geometry needs to be moved then copy attribute data to overwrite unused space
|
|
747
|
+
if ( geometryInfo.vertexStart !== nextVertexStart ) {
|
|
748
|
+
|
|
749
|
+
const { vertexStart, reservedVertexCount } = geometryInfo;
|
|
750
|
+
const attributes = geometry.attributes;
|
|
751
|
+
for ( const key in attributes ) {
|
|
752
|
+
|
|
753
|
+
const attribute = attributes[ key ];
|
|
754
|
+
const { array, itemSize } = attribute;
|
|
755
|
+
array.copyWithin( nextVertexStart * itemSize, vertexStart * itemSize, ( vertexStart + reservedVertexCount ) * itemSize );
|
|
756
|
+
attribute.addUpdateRange( nextVertexStart * itemSize, reservedVertexCount * itemSize );
|
|
757
|
+
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
geometryInfo.vertexStart = nextVertexStart;
|
|
761
|
+
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
nextVertexStart += geometryInfo.reservedVertexCount;
|
|
765
|
+
geometryInfo.start = geometry.index ? geometryInfo.indexStart : geometryInfo.vertexStart;
|
|
766
|
+
|
|
767
|
+
// step the next geometry points to the shifted position
|
|
768
|
+
this._nextIndexStart = geometry.index ? geometryInfo.indexStart + geometryInfo.reservedIndexCount : 0;
|
|
769
|
+
this._nextVertexStart = geometryInfo.vertexStart + geometryInfo.reservedVertexCount;
|
|
770
|
+
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
return this;
|
|
774
|
+
|
|
775
|
+
}
|
|
776
|
+
|
|
645
777
|
// get bounding box and compute it if it doesn't exist
|
|
646
778
|
getBoundingBoxAt( geometryId, target ) {
|
|
647
779
|
|
|
@@ -652,17 +784,14 @@ class BatchedMesh extends Mesh {
|
|
|
652
784
|
}
|
|
653
785
|
|
|
654
786
|
// compute bounding box
|
|
655
|
-
const bound = this._bounds[ geometryId ];
|
|
656
|
-
const box = bound.box;
|
|
657
787
|
const geometry = this.geometry;
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
box.makeEmpty();
|
|
788
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
789
|
+
if ( geometryInfo.boundingBox === null ) {
|
|
661
790
|
|
|
791
|
+
const box = new Box3();
|
|
662
792
|
const index = geometry.index;
|
|
663
793
|
const position = geometry.attributes.position;
|
|
664
|
-
|
|
665
|
-
for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) {
|
|
794
|
+
for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
|
|
666
795
|
|
|
667
796
|
let iv = i;
|
|
668
797
|
if ( index ) {
|
|
@@ -675,11 +804,11 @@ class BatchedMesh extends Mesh {
|
|
|
675
804
|
|
|
676
805
|
}
|
|
677
806
|
|
|
678
|
-
|
|
807
|
+
geometryInfo.boundingBox = box;
|
|
679
808
|
|
|
680
809
|
}
|
|
681
810
|
|
|
682
|
-
target.copy(
|
|
811
|
+
target.copy( geometryInfo.boundingBox );
|
|
683
812
|
return target;
|
|
684
813
|
|
|
685
814
|
}
|
|
@@ -694,22 +823,19 @@ class BatchedMesh extends Mesh {
|
|
|
694
823
|
}
|
|
695
824
|
|
|
696
825
|
// compute bounding sphere
|
|
697
|
-
const bound = this._bounds[ geometryId ];
|
|
698
|
-
const sphere = bound.sphere;
|
|
699
826
|
const geometry = this.geometry;
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
sphere.makeEmpty();
|
|
827
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
828
|
+
if ( geometryInfo.boundingSphere === null ) {
|
|
703
829
|
|
|
830
|
+
const sphere = new Sphere();
|
|
704
831
|
this.getBoundingBoxAt( geometryId, _box );
|
|
705
832
|
_box.getCenter( sphere.center );
|
|
706
833
|
|
|
707
834
|
const index = geometry.index;
|
|
708
835
|
const position = geometry.attributes.position;
|
|
709
|
-
const drawRange = this._drawRanges[ geometryId ];
|
|
710
836
|
|
|
711
837
|
let maxRadiusSq = 0;
|
|
712
|
-
for ( let i =
|
|
838
|
+
for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
|
|
713
839
|
|
|
714
840
|
let iv = i;
|
|
715
841
|
if ( index ) {
|
|
@@ -724,29 +850,21 @@ class BatchedMesh extends Mesh {
|
|
|
724
850
|
}
|
|
725
851
|
|
|
726
852
|
sphere.radius = Math.sqrt( maxRadiusSq );
|
|
727
|
-
|
|
853
|
+
geometryInfo.boundingSphere = sphere;
|
|
728
854
|
|
|
729
855
|
}
|
|
730
856
|
|
|
731
|
-
target.copy(
|
|
857
|
+
target.copy( geometryInfo.boundingSphere );
|
|
732
858
|
return target;
|
|
733
859
|
|
|
734
860
|
}
|
|
735
861
|
|
|
736
862
|
setMatrixAt( instanceId, matrix ) {
|
|
737
863
|
|
|
738
|
-
|
|
739
|
-
// optimize() can make geometryId mismatch the index
|
|
864
|
+
this.validateInstanceId( instanceId );
|
|
740
865
|
|
|
741
|
-
const drawInfo = this._drawInfo;
|
|
742
866
|
const matricesTexture = this._matricesTexture;
|
|
743
867
|
const matricesArray = this._matricesTexture.image.data;
|
|
744
|
-
if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) {
|
|
745
|
-
|
|
746
|
-
return this;
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
|
|
750
868
|
matrix.toArray( matricesArray, instanceId * 16 );
|
|
751
869
|
matricesTexture.needsUpdate = true;
|
|
752
870
|
|
|
@@ -756,152 +874,213 @@ class BatchedMesh extends Mesh {
|
|
|
756
874
|
|
|
757
875
|
getMatrixAt( instanceId, matrix ) {
|
|
758
876
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) {
|
|
762
|
-
|
|
763
|
-
return null;
|
|
764
|
-
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
return matrix.fromArray( matricesArray, instanceId * 16 );
|
|
877
|
+
this.validateInstanceId( instanceId );
|
|
878
|
+
return matrix.fromArray( this._matricesTexture.image.data, instanceId * 16 );
|
|
768
879
|
|
|
769
880
|
}
|
|
770
881
|
|
|
771
882
|
setColorAt( instanceId, color ) {
|
|
772
883
|
|
|
884
|
+
this.validateInstanceId( instanceId );
|
|
885
|
+
|
|
773
886
|
if ( this._colorsTexture === null ) {
|
|
774
887
|
|
|
775
888
|
this._initColorsTexture();
|
|
776
889
|
|
|
777
890
|
}
|
|
778
891
|
|
|
779
|
-
|
|
780
|
-
|
|
892
|
+
color.toArray( this._colorsTexture.image.data, instanceId * 4 );
|
|
893
|
+
this._colorsTexture.needsUpdate = true;
|
|
781
894
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
895
|
+
return this;
|
|
896
|
+
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
getColorAt( instanceId, color ) {
|
|
900
|
+
|
|
901
|
+
this.validateInstanceId( instanceId );
|
|
902
|
+
return color.fromArray( this._colorsTexture.image.data, instanceId * 4 );
|
|
903
|
+
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
setVisibleAt( instanceId, value ) {
|
|
907
|
+
|
|
908
|
+
this.validateInstanceId( instanceId );
|
|
909
|
+
|
|
910
|
+
if ( this._instanceInfo[ instanceId ].visible === value ) {
|
|
786
911
|
|
|
787
912
|
return this;
|
|
788
913
|
|
|
789
914
|
}
|
|
790
915
|
|
|
791
|
-
|
|
792
|
-
|
|
916
|
+
this._instanceInfo[ instanceId ].visible = value;
|
|
917
|
+
this._visibilityChanged = true;
|
|
793
918
|
|
|
794
919
|
return this;
|
|
795
920
|
|
|
796
921
|
}
|
|
797
922
|
|
|
798
|
-
|
|
923
|
+
getVisibleAt( instanceId ) {
|
|
799
924
|
|
|
800
|
-
|
|
801
|
-
const drawInfo = this._drawInfo;
|
|
802
|
-
if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) {
|
|
925
|
+
this.validateInstanceId( instanceId );
|
|
803
926
|
|
|
804
|
-
|
|
927
|
+
return this._instanceInfo[ instanceId ].visible;
|
|
805
928
|
|
|
806
|
-
|
|
929
|
+
}
|
|
807
930
|
|
|
808
|
-
|
|
931
|
+
setGeometryIdAt( instanceId, geometryId ) {
|
|
809
932
|
|
|
810
|
-
|
|
933
|
+
this.validateInstanceId( instanceId );
|
|
934
|
+
this.validateGeometryId( geometryId );
|
|
811
935
|
|
|
812
|
-
|
|
936
|
+
this._instanceInfo[ instanceId ].geometryIndex = geometryId;
|
|
813
937
|
|
|
814
|
-
|
|
815
|
-
// does not change then return early
|
|
816
|
-
const drawInfo = this._drawInfo;
|
|
817
|
-
if (
|
|
818
|
-
instanceId >= drawInfo.length ||
|
|
819
|
-
drawInfo[ instanceId ].active === false ||
|
|
820
|
-
drawInfo[ instanceId ].visible === value
|
|
821
|
-
) {
|
|
938
|
+
return this;
|
|
822
939
|
|
|
823
|
-
|
|
940
|
+
}
|
|
824
941
|
|
|
825
|
-
|
|
942
|
+
getGeometryIdAt( instanceId ) {
|
|
826
943
|
|
|
827
|
-
|
|
828
|
-
this._visibilityChanged = true;
|
|
944
|
+
this.validateInstanceId( instanceId );
|
|
829
945
|
|
|
830
|
-
return this;
|
|
946
|
+
return this._instanceInfo[ instanceId ].geometryIndex;
|
|
831
947
|
|
|
832
948
|
}
|
|
833
949
|
|
|
834
|
-
|
|
950
|
+
getGeometryRangeAt( geometryId, target = {} ) {
|
|
835
951
|
|
|
836
|
-
|
|
837
|
-
const drawInfo = this._drawInfo;
|
|
838
|
-
if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) {
|
|
952
|
+
this.validateGeometryId( geometryId );
|
|
839
953
|
|
|
840
|
-
|
|
954
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
955
|
+
target.vertexStart = geometryInfo.vertexStart;
|
|
956
|
+
target.vertexCount = geometryInfo.vertexCount;
|
|
957
|
+
target.reservedVertexCount = geometryInfo.reservedVertexCount;
|
|
841
958
|
|
|
842
|
-
|
|
959
|
+
target.indexStart = geometryInfo.indexStart;
|
|
960
|
+
target.indexCount = geometryInfo.indexCount;
|
|
961
|
+
target.reservedIndexCount = geometryInfo.reservedIndexCount;
|
|
962
|
+
|
|
963
|
+
target.start = geometryInfo.start;
|
|
964
|
+
target.count = geometryInfo.count;
|
|
843
965
|
|
|
844
|
-
return
|
|
966
|
+
return target;
|
|
845
967
|
|
|
846
968
|
}
|
|
847
969
|
|
|
848
|
-
|
|
970
|
+
setInstanceCount( maxInstanceCount ) {
|
|
849
971
|
|
|
850
|
-
//
|
|
851
|
-
const
|
|
852
|
-
|
|
972
|
+
// shrink the available instances as much as possible
|
|
973
|
+
const availableInstanceIds = this._availableInstanceIds;
|
|
974
|
+
const instanceInfo = this._instanceInfo;
|
|
975
|
+
availableInstanceIds.sort( ascIdSort );
|
|
976
|
+
while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length ) {
|
|
853
977
|
|
|
854
|
-
|
|
978
|
+
instanceInfo.pop();
|
|
979
|
+
availableInstanceIds.pop();
|
|
855
980
|
|
|
856
981
|
}
|
|
857
982
|
|
|
858
|
-
//
|
|
859
|
-
if (
|
|
983
|
+
// throw an error if it can't be shrunk to the desired size
|
|
984
|
+
if ( maxInstanceCount < instanceInfo.length ) {
|
|
860
985
|
|
|
861
|
-
|
|
986
|
+
throw new Error( `BatchedMesh: Instance ids outside the range ${ maxInstanceCount } are being used. Cannot shrink instance count.` );
|
|
862
987
|
|
|
863
988
|
}
|
|
864
989
|
|
|
865
|
-
|
|
990
|
+
// copy the multi draw counts
|
|
991
|
+
const multiDrawCounts = new Int32Array( maxInstanceCount );
|
|
992
|
+
const multiDrawStarts = new Int32Array( maxInstanceCount );
|
|
993
|
+
copyArrayContents( this._multiDrawCounts, multiDrawCounts );
|
|
994
|
+
copyArrayContents( this._multiDrawStarts, multiDrawStarts );
|
|
866
995
|
|
|
867
|
-
|
|
996
|
+
this._multiDrawCounts = multiDrawCounts;
|
|
997
|
+
this._multiDrawStarts = multiDrawStarts;
|
|
998
|
+
this._maxInstanceCount = maxInstanceCount;
|
|
999
|
+
|
|
1000
|
+
// update texture data for instance sampling
|
|
1001
|
+
const indirectTexture = this._indirectTexture;
|
|
1002
|
+
const matricesTexture = this._matricesTexture;
|
|
1003
|
+
const colorsTexture = this._colorsTexture;
|
|
1004
|
+
|
|
1005
|
+
indirectTexture.dispose();
|
|
1006
|
+
this._initIndirectTexture();
|
|
1007
|
+
copyArrayContents( indirectTexture.image.data, this._indirectTexture.image.data );
|
|
1008
|
+
|
|
1009
|
+
matricesTexture.dispose();
|
|
1010
|
+
this._initMatricesTexture();
|
|
1011
|
+
copyArrayContents( matricesTexture.image.data, this._matricesTexture.image.data );
|
|
1012
|
+
|
|
1013
|
+
if ( colorsTexture ) {
|
|
1014
|
+
|
|
1015
|
+
colorsTexture.dispose();
|
|
1016
|
+
this._initColorsTexture();
|
|
1017
|
+
copyArrayContents( colorsTexture.image.data, this._colorsTexture.image.data );
|
|
1018
|
+
|
|
1019
|
+
}
|
|
868
1020
|
|
|
869
1021
|
}
|
|
870
1022
|
|
|
871
|
-
|
|
1023
|
+
setGeometrySize( maxVertexCount, maxIndexCount ) {
|
|
872
1024
|
|
|
873
|
-
|
|
874
|
-
|
|
1025
|
+
// Check if we can shrink to the requested vertex attribute size
|
|
1026
|
+
const validRanges = [ ...this._geometryInfo ].filter( info => info.active );
|
|
1027
|
+
const requiredVertexLength = Math.max( ...validRanges.map( range => range.vertexStart + range.reservedVertexCount ) );
|
|
1028
|
+
if ( requiredVertexLength > maxVertexCount ) {
|
|
875
1029
|
|
|
876
|
-
|
|
1030
|
+
throw new Error( `BatchedMesh: Geometry vertex values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
|
|
877
1031
|
|
|
878
1032
|
}
|
|
879
1033
|
|
|
880
|
-
|
|
1034
|
+
// Check if we can shrink to the requested index attribute size
|
|
1035
|
+
if ( this.geometry.index ) {
|
|
881
1036
|
|
|
882
|
-
|
|
1037
|
+
const requiredIndexLength = Math.max( ...validRanges.map( range => range.indexStart + range.reservedIndexCount ) );
|
|
1038
|
+
if ( requiredIndexLength > maxIndexCount ) {
|
|
883
1039
|
|
|
884
|
-
|
|
1040
|
+
throw new Error( `BatchedMesh: Geometry index values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
|
|
885
1041
|
|
|
886
|
-
|
|
1042
|
+
}
|
|
887
1043
|
|
|
888
|
-
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
//
|
|
1047
|
+
|
|
1048
|
+
// dispose of the previous geometry
|
|
1049
|
+
const oldGeometry = this.geometry;
|
|
1050
|
+
oldGeometry.dispose();
|
|
1051
|
+
|
|
1052
|
+
// recreate the geometry needed based on the previous variant
|
|
1053
|
+
this._maxVertexCount = maxVertexCount;
|
|
1054
|
+
this._maxIndexCount = maxIndexCount;
|
|
1055
|
+
|
|
1056
|
+
if ( this._geometryInitialized ) {
|
|
1057
|
+
|
|
1058
|
+
this._geometryInitialized = false;
|
|
1059
|
+
this.geometry = new BufferGeometry();
|
|
1060
|
+
this._initializeGeometry( oldGeometry );
|
|
889
1061
|
|
|
890
1062
|
}
|
|
891
1063
|
|
|
892
|
-
|
|
1064
|
+
// copy data from the previous geometry
|
|
1065
|
+
const geometry = this.geometry;
|
|
1066
|
+
if ( oldGeometry.index ) {
|
|
893
1067
|
|
|
894
|
-
|
|
895
|
-
target.count = drawRange.count;
|
|
1068
|
+
copyArrayContents( oldGeometry.index.array, geometry.index.array );
|
|
896
1069
|
|
|
897
|
-
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
for ( const key in oldGeometry.attributes ) {
|
|
1073
|
+
|
|
1074
|
+
copyArrayContents( oldGeometry.attributes[ key ].array, geometry.attributes[ key ].array );
|
|
1075
|
+
|
|
1076
|
+
}
|
|
898
1077
|
|
|
899
1078
|
}
|
|
900
1079
|
|
|
901
1080
|
raycast( raycaster, intersects ) {
|
|
902
1081
|
|
|
903
|
-
const
|
|
904
|
-
const
|
|
1082
|
+
const instanceInfo = this._instanceInfo;
|
|
1083
|
+
const geometryInfoList = this._geometryInfo;
|
|
905
1084
|
const matrixWorld = this.matrixWorld;
|
|
906
1085
|
const batchGeometry = this.geometry;
|
|
907
1086
|
|
|
@@ -921,19 +1100,19 @@ class BatchedMesh extends Mesh {
|
|
|
921
1100
|
|
|
922
1101
|
}
|
|
923
1102
|
|
|
924
|
-
for ( let i = 0, l =
|
|
1103
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
925
1104
|
|
|
926
|
-
if ( !
|
|
1105
|
+
if ( ! instanceInfo[ i ].visible || ! instanceInfo[ i ].active ) {
|
|
927
1106
|
|
|
928
1107
|
continue;
|
|
929
1108
|
|
|
930
1109
|
}
|
|
931
1110
|
|
|
932
|
-
const geometryId =
|
|
933
|
-
const
|
|
934
|
-
_mesh.geometry.setDrawRange(
|
|
1111
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
1112
|
+
const geometryInfo = geometryInfoList[ geometryId ];
|
|
1113
|
+
_mesh.geometry.setDrawRange( geometryInfo.start, geometryInfo.count );
|
|
935
1114
|
|
|
936
|
-
//
|
|
1115
|
+
// get the intersects
|
|
937
1116
|
this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld );
|
|
938
1117
|
this.getBoundingBoxAt( geometryId, _mesh.geometry.boundingBox );
|
|
939
1118
|
this.getBoundingSphereAt( geometryId, _mesh.geometry.boundingSphere );
|
|
@@ -970,17 +1149,13 @@ class BatchedMesh extends Mesh {
|
|
|
970
1149
|
this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
|
|
971
1150
|
this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
|
|
972
1151
|
|
|
973
|
-
this.
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
this._drawInfo = source._drawInfo.map( inf => ( { ...inf } ) );
|
|
977
|
-
this._bounds = source._bounds.map( bound => ( {
|
|
978
|
-
boxInitialized: bound.boxInitialized,
|
|
979
|
-
box: bound.box.clone(),
|
|
1152
|
+
this._geometryInfo = source._geometryInfo.map( info => ( {
|
|
1153
|
+
...info,
|
|
980
1154
|
|
|
981
|
-
|
|
982
|
-
|
|
1155
|
+
boundingBox: info.boundingBox !== null ? info.boundingBox.clone() : null,
|
|
1156
|
+
boundingSphere: info.boundingSphere !== null ? info.boundingSphere.clone() : null,
|
|
983
1157
|
} ) );
|
|
1158
|
+
this._instanceInfo = source._instanceInfo.map( info => ( { ...info } ) );
|
|
984
1159
|
|
|
985
1160
|
this._maxInstanceCount = source._maxInstanceCount;
|
|
986
1161
|
this._maxVertexCount = source._maxVertexCount;
|
|
@@ -1042,10 +1217,10 @@ class BatchedMesh extends Mesh {
|
|
|
1042
1217
|
const index = geometry.getIndex();
|
|
1043
1218
|
const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
|
|
1044
1219
|
|
|
1045
|
-
const
|
|
1220
|
+
const instanceInfo = this._instanceInfo;
|
|
1046
1221
|
const multiDrawStarts = this._multiDrawStarts;
|
|
1047
1222
|
const multiDrawCounts = this._multiDrawCounts;
|
|
1048
|
-
const
|
|
1223
|
+
const geometryInfoList = this._geometryInfo;
|
|
1049
1224
|
const perObjectFrustumCulled = this.perObjectFrustumCulled;
|
|
1050
1225
|
const indirectTexture = this._indirectTexture;
|
|
1051
1226
|
const indirectArray = indirectTexture.image.data;
|
|
@@ -1053,29 +1228,29 @@ class BatchedMesh extends Mesh {
|
|
|
1053
1228
|
// prepare the frustum in the local frame
|
|
1054
1229
|
if ( perObjectFrustumCulled ) {
|
|
1055
1230
|
|
|
1056
|
-
|
|
1231
|
+
_matrix
|
|
1057
1232
|
.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
|
|
1058
1233
|
.multiply( this.matrixWorld );
|
|
1059
1234
|
_frustum.setFromProjectionMatrix(
|
|
1060
|
-
|
|
1235
|
+
_matrix,
|
|
1061
1236
|
renderer.coordinateSystem
|
|
1062
1237
|
);
|
|
1063
1238
|
|
|
1064
1239
|
}
|
|
1065
1240
|
|
|
1066
|
-
let
|
|
1241
|
+
let multiDrawCount = 0;
|
|
1067
1242
|
if ( this.sortObjects ) {
|
|
1068
1243
|
|
|
1069
1244
|
// get the camera position in the local frame
|
|
1070
|
-
|
|
1071
|
-
_vector.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4(
|
|
1072
|
-
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).transformDirection(
|
|
1245
|
+
_matrix.copy( this.matrixWorld ).invert();
|
|
1246
|
+
_vector.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _matrix );
|
|
1247
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).transformDirection( _matrix );
|
|
1073
1248
|
|
|
1074
|
-
for ( let i = 0, l =
|
|
1249
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
1075
1250
|
|
|
1076
|
-
if (
|
|
1251
|
+
if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
|
|
1077
1252
|
|
|
1078
|
-
const geometryId =
|
|
1253
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
1079
1254
|
|
|
1080
1255
|
// get the bounds in world space
|
|
1081
1256
|
this.getMatrixAt( i, _matrix );
|
|
@@ -1092,8 +1267,9 @@ class BatchedMesh extends Mesh {
|
|
|
1092
1267
|
if ( ! culled ) {
|
|
1093
1268
|
|
|
1094
1269
|
// get the distance from camera used for sorting
|
|
1270
|
+
const geometryInfo = geometryInfoList[ geometryId ];
|
|
1095
1271
|
const z = _temp.subVectors( _sphere.center, _vector ).dot( _forward );
|
|
1096
|
-
_renderList.push(
|
|
1272
|
+
_renderList.push( geometryInfo.start, geometryInfo.count, z, i );
|
|
1097
1273
|
|
|
1098
1274
|
}
|
|
1099
1275
|
|
|
@@ -1117,10 +1293,10 @@ class BatchedMesh extends Mesh {
|
|
|
1117
1293
|
for ( let i = 0, l = list.length; i < l; i ++ ) {
|
|
1118
1294
|
|
|
1119
1295
|
const item = list[ i ];
|
|
1120
|
-
multiDrawStarts[
|
|
1121
|
-
multiDrawCounts[
|
|
1122
|
-
indirectArray[
|
|
1123
|
-
|
|
1296
|
+
multiDrawStarts[ multiDrawCount ] = item.start * bytesPerElement;
|
|
1297
|
+
multiDrawCounts[ multiDrawCount ] = item.count;
|
|
1298
|
+
indirectArray[ multiDrawCount ] = item.index;
|
|
1299
|
+
multiDrawCount ++;
|
|
1124
1300
|
|
|
1125
1301
|
}
|
|
1126
1302
|
|
|
@@ -1128,11 +1304,11 @@ class BatchedMesh extends Mesh {
|
|
|
1128
1304
|
|
|
1129
1305
|
} else {
|
|
1130
1306
|
|
|
1131
|
-
for ( let i = 0, l =
|
|
1307
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
1132
1308
|
|
|
1133
|
-
if (
|
|
1309
|
+
if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
|
|
1134
1310
|
|
|
1135
|
-
const geometryId =
|
|
1311
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
1136
1312
|
|
|
1137
1313
|
// determine whether the batched geometry is within the frustum
|
|
1138
1314
|
let culled = false;
|
|
@@ -1147,11 +1323,11 @@ class BatchedMesh extends Mesh {
|
|
|
1147
1323
|
|
|
1148
1324
|
if ( ! culled ) {
|
|
1149
1325
|
|
|
1150
|
-
const
|
|
1151
|
-
multiDrawStarts[
|
|
1152
|
-
multiDrawCounts[
|
|
1153
|
-
indirectArray[
|
|
1154
|
-
|
|
1326
|
+
const geometryInfo = geometryInfoList[ geometryId ];
|
|
1327
|
+
multiDrawStarts[ multiDrawCount ] = geometryInfo.start * bytesPerElement;
|
|
1328
|
+
multiDrawCounts[ multiDrawCount ] = geometryInfo.count;
|
|
1329
|
+
indirectArray[ multiDrawCount ] = i;
|
|
1330
|
+
multiDrawCount ++;
|
|
1155
1331
|
|
|
1156
1332
|
}
|
|
1157
1333
|
|
|
@@ -1162,7 +1338,7 @@ class BatchedMesh extends Mesh {
|
|
|
1162
1338
|
}
|
|
1163
1339
|
|
|
1164
1340
|
indirectTexture.needsUpdate = true;
|
|
1165
|
-
this._multiDrawCount =
|
|
1341
|
+
this._multiDrawCount = multiDrawCount;
|
|
1166
1342
|
this._visibilityChanged = false;
|
|
1167
1343
|
|
|
1168
1344
|
}
|