super-three 0.169.1 → 0.170.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/three.cjs +974 -562
- package/build/three.module.js +975 -559
- package/build/three.module.min.js +1 -1
- package/build/three.webgpu.js +8398 -9842
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +8398 -9842
- 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/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 +435 -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 +65 -20
- 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/LineMaterial.js +7 -2
- package/examples/jsm/lines/LineSegmentsGeometry.js +2 -0
- package/examples/jsm/lines/webgpu/LineSegments2.js +0 -15
- package/examples/jsm/lines/webgpu/Wireframe.js +56 -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 +140 -49
- package/examples/jsm/loaders/LDrawLoader.js +22 -136
- package/examples/jsm/loaders/LottieLoader.js +1 -0
- package/examples/jsm/loaders/MMDLoader.js +9 -2
- package/examples/jsm/materials/LDrawConditionalLineMaterial.js +143 -0
- package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +114 -0
- package/examples/jsm/materials/MeshGouraudMaterial.js +6 -2
- 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/WaterMesh.js +8 -8
- 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/ShaderToyDecoder.js +1 -1
- package/{src/nodes → examples/jsm/tsl}/display/AfterImageNode.js +17 -20
- 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 +11 -40
- package/{src/nodes → examples/jsm/tsl}/display/DenoiseNode.js +18 -41
- package/{src/nodes → examples/jsm/tsl}/display/DepthOfFieldNode.js +2 -8
- 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 +2 -6
- package/{src/nodes → examples/jsm/tsl}/display/GTAONode.js +30 -70
- package/{src/nodes → examples/jsm/tsl}/display/GaussianBlurNode.js +74 -36
- package/examples/jsm/tsl/display/LensflareNode.js +161 -0
- package/{src/nodes → examples/jsm/tsl}/display/Lut3DNode.js +1 -4
- 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 +1 -5
- package/{src/nodes → examples/jsm/tsl}/display/PixelationPassNode.js +3 -15
- package/{src/nodes → examples/jsm/tsl}/display/RGBShiftNode.js +1 -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 +343 -0
- package/{src/nodes → examples/jsm/tsl}/display/Sepia.js +1 -2
- package/{src/nodes → examples/jsm/tsl}/display/SobelOperatorNode.js +3 -11
- 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 +1 -6
- package/examples/jsm/tsl/display/hashBlur.js +24 -0
- package/examples/jsm/tsl/lighting/TiledLightsNode.js +392 -0
- 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 +2 -2
- package/src/Three.WebGPU.Nodes.js +4 -0
- package/src/Three.WebGPU.js +4 -0
- package/src/constants.js +1 -6
- package/src/core/BufferGeometry.js +44 -6
- package/src/geometries/CylinderGeometry.js +2 -2
- package/src/materials/LineBasicMaterial.js +6 -2
- package/src/materials/LineDashedMaterial.js +6 -2
- package/src/materials/Material.js +14 -1
- package/src/materials/MeshBasicMaterial.js +6 -2
- package/src/materials/MeshDepthMaterial.js +6 -2
- package/src/materials/MeshDistanceMaterial.js +6 -2
- package/src/materials/MeshLambertMaterial.js +6 -2
- package/src/materials/MeshMatcapMaterial.js +6 -2
- package/src/materials/MeshNormalMaterial.js +6 -2
- package/src/materials/MeshPhongMaterial.js +6 -2
- package/src/materials/MeshPhysicalMaterial.js +6 -2
- package/src/materials/MeshStandardMaterial.js +6 -2
- package/src/materials/MeshToonMaterial.js +6 -2
- package/src/materials/PointsMaterial.js +6 -2
- package/src/materials/RawShaderMaterial.js +6 -2
- package/src/materials/ShaderMaterial.js +6 -2
- package/src/materials/ShadowMaterial.js +6 -2
- package/src/materials/SpriteMaterial.js +6 -2
- package/src/materials/nodes/NodeMaterial.js +31 -9
- package/src/materials/nodes/SpriteNodeMaterial.js +11 -2
- package/src/materials/nodes/manager/NodeMaterialObserver.js +111 -2
- package/src/math/ColorManagement.js +118 -85
- package/src/math/Vector4.js +11 -0
- package/src/nodes/Nodes.js +1 -21
- package/src/nodes/TSL.js +6 -24
- package/src/nodes/accessors/Camera.js +0 -1
- package/src/nodes/accessors/SceneNode.js +35 -1
- package/src/nodes/accessors/StorageBufferNode.js +32 -10
- 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 +29 -5
- package/src/nodes/core/VarNode.js +15 -3
- 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/ViewportDepthNode.js +33 -1
- package/src/nodes/functions/PhysicalLightingModel.js +21 -15
- package/src/nodes/functions/material/getAlphaHashThreshold.js +64 -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 +12 -416
- package/src/nodes/lighting/LightsNode.js +24 -12
- package/src/nodes/lighting/PointLightNode.js +36 -26
- package/src/nodes/lighting/RectAreaLightNode.js +3 -0
- package/src/nodes/lighting/ShadowNode.js +484 -0
- 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/ReflectorNode.js +101 -15
- package/src/nodes/utils/Timer.js +29 -0
- package/src/objects/BatchedMesh.js +458 -241
- package/src/renderers/WebGLRenderer.js +120 -117
- package/src/renderers/common/Attributes.js +4 -0
- package/src/renderers/common/Backend.js +2 -0
- package/src/renderers/common/Background.js +14 -4
- package/src/renderers/common/Bindings.js +3 -2
- 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 +39 -11
- package/src/renderers/common/RenderLists.js +4 -2
- package/src/renderers/common/RenderObject.js +18 -1
- package/src/renderers/common/Renderer.js +165 -26
- package/src/renderers/common/Textures.js +30 -14
- package/src/renderers/common/nodes/NodeLibrary.js +1 -14
- 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/WebGLBufferRenderer.js +2 -6
- package/src/renderers/webgl/WebGLCapabilities.js +0 -7
- 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 +98 -31
- package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +2 -7
- package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +33 -8
- package/src/renderers/webgpu/WebGPUBackend.js +105 -25
- 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 +0 -8
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +10 -20
- package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +12 -4
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +29 -9
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +24 -6
- package/src/renderers/webgpu/utils/WebGPUUtils.js +0 -1
- package/src/renderers/webxr/WebXRManager.js +4 -4
- package/examples/jsm/cameras/CinematicCamera.js +0 -208
- 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 = [];
|
|
150
189
|
|
|
151
|
-
// geometry
|
|
152
|
-
this.
|
|
153
|
-
this.
|
|
154
|
-
this.
|
|
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;
|
|
155
194
|
|
|
195
|
+
// flags
|
|
196
|
+
this._visibilityChanged = true;
|
|
197
|
+
this._geometryInitialized = false;
|
|
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;
|
|
@@ -304,14 +346,14 @@ class BatchedMesh extends Mesh {
|
|
|
304
346
|
}
|
|
305
347
|
|
|
306
348
|
const boundingBox = this.boundingBox;
|
|
307
|
-
const
|
|
349
|
+
const instanceInfo = this._instanceInfo;
|
|
308
350
|
|
|
309
351
|
boundingBox.makeEmpty();
|
|
310
|
-
for ( let i = 0, l =
|
|
352
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
311
353
|
|
|
312
|
-
if (
|
|
354
|
+
if ( instanceInfo[ i ].active === false ) continue;
|
|
313
355
|
|
|
314
|
-
const geometryId =
|
|
356
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
315
357
|
this.getMatrixAt( i, _matrix );
|
|
316
358
|
this.getBoundingBoxAt( geometryId, _box ).applyMatrix4( _matrix );
|
|
317
359
|
boundingBox.union( _box );
|
|
@@ -329,14 +371,14 @@ class BatchedMesh extends Mesh {
|
|
|
329
371
|
}
|
|
330
372
|
|
|
331
373
|
const boundingSphere = this.boundingSphere;
|
|
332
|
-
const
|
|
374
|
+
const instanceInfo = this._instanceInfo;
|
|
333
375
|
|
|
334
376
|
boundingSphere.makeEmpty();
|
|
335
|
-
for ( let i = 0, l =
|
|
377
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
336
378
|
|
|
337
|
-
if (
|
|
379
|
+
if ( instanceInfo[ i ].active === false ) continue;
|
|
338
380
|
|
|
339
|
-
const geometryId =
|
|
381
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
340
382
|
this.getMatrixAt( i, _matrix );
|
|
341
383
|
this.getBoundingSphereAt( geometryId, _sphere ).applyMatrix4( _matrix );
|
|
342
384
|
boundingSphere.union( _sphere );
|
|
@@ -347,7 +389,7 @@ class BatchedMesh extends Mesh {
|
|
|
347
389
|
|
|
348
390
|
addInstance( geometryId ) {
|
|
349
391
|
|
|
350
|
-
const atCapacity = this.
|
|
392
|
+
const atCapacity = this._instanceInfo.length >= this.maxInstanceCount;
|
|
351
393
|
|
|
352
394
|
// ensure we're not over geometry
|
|
353
395
|
if ( atCapacity && this._availableInstanceIds.length === 0 ) {
|
|
@@ -356,7 +398,7 @@ class BatchedMesh extends Mesh {
|
|
|
356
398
|
|
|
357
399
|
}
|
|
358
400
|
|
|
359
|
-
const
|
|
401
|
+
const instanceInfo = {
|
|
360
402
|
visible: true,
|
|
361
403
|
active: true,
|
|
362
404
|
geometryIndex: geometryId,
|
|
@@ -367,19 +409,20 @@ class BatchedMesh extends Mesh {
|
|
|
367
409
|
// Prioritize using previously freed instance ids
|
|
368
410
|
if ( this._availableInstanceIds.length > 0 ) {
|
|
369
411
|
|
|
370
|
-
|
|
371
|
-
|
|
412
|
+
this._availableInstanceIds.sort( ascIdSort );
|
|
413
|
+
|
|
414
|
+
drawId = this._availableInstanceIds.shift();
|
|
415
|
+
this._instanceInfo[ drawId ] = instanceInfo;
|
|
372
416
|
|
|
373
417
|
} else {
|
|
374
418
|
|
|
375
|
-
drawId = this.
|
|
376
|
-
this.
|
|
419
|
+
drawId = this._instanceInfo.length;
|
|
420
|
+
this._instanceInfo.push( instanceInfo );
|
|
377
421
|
|
|
378
422
|
}
|
|
379
423
|
|
|
380
424
|
const matricesTexture = this._matricesTexture;
|
|
381
|
-
|
|
382
|
-
_identityMatrix.toArray( matricesArray, drawId * 16 );
|
|
425
|
+
_matrix.identity().toArray( matricesTexture.image.data, drawId * 16 );
|
|
383
426
|
matricesTexture.needsUpdate = true;
|
|
384
427
|
|
|
385
428
|
const colorsTexture = this._colorsTexture;
|
|
@@ -390,118 +433,85 @@ class BatchedMesh extends Mesh {
|
|
|
390
433
|
|
|
391
434
|
}
|
|
392
435
|
|
|
436
|
+
this._visibilityChanged = true;
|
|
393
437
|
return drawId;
|
|
394
438
|
|
|
395
439
|
}
|
|
396
440
|
|
|
397
|
-
addGeometry( geometry,
|
|
441
|
+
addGeometry( geometry, reservedVertexCount = - 1, reservedIndexCount = - 1 ) {
|
|
398
442
|
|
|
399
443
|
this._initializeGeometry( geometry );
|
|
400
444
|
|
|
401
445
|
this._validateGeometry( geometry );
|
|
402
446
|
|
|
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 = {
|
|
447
|
+
const geometryInfo = {
|
|
448
|
+
// geometry information
|
|
412
449
|
vertexStart: - 1,
|
|
413
450
|
vertexCount: - 1,
|
|
451
|
+
reservedVertexCount: - 1,
|
|
452
|
+
|
|
414
453
|
indexStart: - 1,
|
|
415
454
|
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 {
|
|
455
|
+
reservedIndexCount: - 1,
|
|
433
456
|
|
|
434
|
-
|
|
457
|
+
// draw range information
|
|
458
|
+
start: - 1,
|
|
459
|
+
count: - 1,
|
|
435
460
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
} else {
|
|
443
|
-
|
|
444
|
-
reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount;
|
|
461
|
+
// state
|
|
462
|
+
boundingBox: null,
|
|
463
|
+
boundingSphere: null,
|
|
464
|
+
active: true,
|
|
465
|
+
};
|
|
445
466
|
|
|
446
|
-
|
|
467
|
+
const geometryInfoList = this._geometryInfo;
|
|
468
|
+
geometryInfo.vertexStart = this._nextVertexStart;
|
|
469
|
+
geometryInfo.reservedVertexCount = reservedVertexCount === - 1 ? geometry.getAttribute( 'position' ).count : reservedVertexCount;
|
|
447
470
|
|
|
448
471
|
const index = geometry.getIndex();
|
|
449
472
|
const hasIndex = index !== null;
|
|
450
473
|
if ( hasIndex ) {
|
|
451
474
|
|
|
452
|
-
|
|
475
|
+
geometryInfo.indexStart = this._nextIndexStart;
|
|
476
|
+
geometryInfo.reservedIndexCount = reservedIndexCount === - 1 ? index.count : reservedIndexCount;
|
|
453
477
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
} else {
|
|
457
|
-
|
|
458
|
-
reservedRange.indexCount = indexCount;
|
|
478
|
+
}
|
|
459
479
|
|
|
460
|
-
|
|
480
|
+
if (
|
|
481
|
+
geometryInfo.indexStart !== - 1 &&
|
|
482
|
+
geometryInfo.indexStart + geometryInfo.reservedIndexCount > this._maxIndexCount ||
|
|
483
|
+
geometryInfo.vertexStart + geometryInfo.reservedVertexCount > this._maxVertexCount
|
|
484
|
+
) {
|
|
461
485
|
|
|
462
|
-
|
|
486
|
+
throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
|
|
463
487
|
|
|
464
|
-
|
|
488
|
+
}
|
|
465
489
|
|
|
466
|
-
|
|
490
|
+
// update id
|
|
491
|
+
let geometryId;
|
|
492
|
+
if ( this._availableGeometryIds.length > 0 ) {
|
|
467
493
|
|
|
468
|
-
|
|
494
|
+
this._availableGeometryIds.sort( ascIdSort );
|
|
469
495
|
|
|
470
|
-
|
|
496
|
+
geometryId = this._availableGeometryIds.shift();
|
|
497
|
+
geometryInfoList[ geometryId ] = geometryInfo;
|
|
471
498
|
|
|
472
|
-
}
|
|
473
499
|
|
|
474
|
-
|
|
475
|
-
reservedRange.indexStart !== - 1 &&
|
|
476
|
-
reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount ||
|
|
477
|
-
reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount
|
|
478
|
-
) {
|
|
500
|
+
} else {
|
|
479
501
|
|
|
480
|
-
|
|
502
|
+
geometryId = this._geometryCount;
|
|
503
|
+
this._geometryCount ++;
|
|
504
|
+
geometryInfoList.push( geometryInfo );
|
|
481
505
|
|
|
482
506
|
}
|
|
483
507
|
|
|
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
508
|
// update the geometry
|
|
503
509
|
this.setGeometryAt( geometryId, geometry );
|
|
504
510
|
|
|
511
|
+
// increment the next geometry position
|
|
512
|
+
this._nextIndexStart = geometryInfo.indexStart + geometryInfo.reservedIndexCount;
|
|
513
|
+
this._nextVertexStart = geometryInfo.vertexStart + geometryInfo.reservedVertexCount;
|
|
514
|
+
|
|
505
515
|
return geometryId;
|
|
506
516
|
|
|
507
517
|
}
|
|
@@ -520,20 +530,22 @@ class BatchedMesh extends Mesh {
|
|
|
520
530
|
const hasIndex = batchGeometry.getIndex() !== null;
|
|
521
531
|
const dstIndex = batchGeometry.getIndex();
|
|
522
532
|
const srcIndex = geometry.getIndex();
|
|
523
|
-
const
|
|
533
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
524
534
|
if (
|
|
525
535
|
hasIndex &&
|
|
526
|
-
srcIndex.count >
|
|
527
|
-
geometry.attributes.position.count >
|
|
536
|
+
srcIndex.count > geometryInfo.reservedIndexCount ||
|
|
537
|
+
geometry.attributes.position.count > geometryInfo.reservedVertexCount
|
|
528
538
|
) {
|
|
529
539
|
|
|
530
540
|
throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' );
|
|
531
541
|
|
|
532
542
|
}
|
|
533
543
|
|
|
534
|
-
// copy geometry over
|
|
535
|
-
const vertexStart =
|
|
536
|
-
const
|
|
544
|
+
// copy geometry buffer data over
|
|
545
|
+
const vertexStart = geometryInfo.vertexStart;
|
|
546
|
+
const reservedVertexCount = geometryInfo.reservedVertexCount;
|
|
547
|
+
geometryInfo.vertexCount = geometry.getAttribute( 'position' ).count;
|
|
548
|
+
|
|
537
549
|
for ( const attributeName in batchGeometry.attributes ) {
|
|
538
550
|
|
|
539
551
|
// copy attribute data
|
|
@@ -543,7 +555,7 @@ class BatchedMesh extends Mesh {
|
|
|
543
555
|
|
|
544
556
|
// fill the rest in with zeroes
|
|
545
557
|
const itemSize = srcAttribute.itemSize;
|
|
546
|
-
for ( let i = srcAttribute.count, l =
|
|
558
|
+
for ( let i = srcAttribute.count, l = reservedVertexCount; i < l; i ++ ) {
|
|
547
559
|
|
|
548
560
|
const index = vertexStart + i;
|
|
549
561
|
for ( let c = 0; c < itemSize; c ++ ) {
|
|
@@ -555,14 +567,16 @@ class BatchedMesh extends Mesh {
|
|
|
555
567
|
}
|
|
556
568
|
|
|
557
569
|
dstAttribute.needsUpdate = true;
|
|
558
|
-
dstAttribute.addUpdateRange( vertexStart * itemSize,
|
|
570
|
+
dstAttribute.addUpdateRange( vertexStart * itemSize, reservedVertexCount * itemSize );
|
|
559
571
|
|
|
560
572
|
}
|
|
561
573
|
|
|
562
574
|
// copy index
|
|
563
575
|
if ( hasIndex ) {
|
|
564
576
|
|
|
565
|
-
const indexStart =
|
|
577
|
+
const indexStart = geometryInfo.indexStart;
|
|
578
|
+
const reservedIndexCount = geometryInfo.reservedIndexCount;
|
|
579
|
+
geometryInfo.indexCount = geometry.getIndex().count;
|
|
566
580
|
|
|
567
581
|
// copy index data over
|
|
568
582
|
for ( let i = 0; i < srcIndex.count; i ++ ) {
|
|
@@ -572,69 +586,80 @@ class BatchedMesh extends Mesh {
|
|
|
572
586
|
}
|
|
573
587
|
|
|
574
588
|
// fill the rest in with zeroes
|
|
575
|
-
for ( let i = srcIndex.count, l =
|
|
589
|
+
for ( let i = srcIndex.count, l = reservedIndexCount; i < l; i ++ ) {
|
|
576
590
|
|
|
577
591
|
dstIndex.setX( indexStart + i, vertexStart );
|
|
578
592
|
|
|
579
593
|
}
|
|
580
594
|
|
|
581
595
|
dstIndex.needsUpdate = true;
|
|
582
|
-
dstIndex.addUpdateRange( indexStart,
|
|
596
|
+
dstIndex.addUpdateRange( indexStart, geometryInfo.reservedIndexCount );
|
|
583
597
|
|
|
584
598
|
}
|
|
585
599
|
|
|
600
|
+
// update the draw range
|
|
601
|
+
geometryInfo.start = hasIndex ? geometryInfo.indexStart : geometryInfo.vertexStart;
|
|
602
|
+
geometryInfo.count = hasIndex ? geometryInfo.indexCount : geometryInfo.vertexCount;
|
|
603
|
+
|
|
586
604
|
// store the bounding boxes
|
|
587
|
-
|
|
605
|
+
geometryInfo.boundingBox = null;
|
|
588
606
|
if ( geometry.boundingBox !== null ) {
|
|
589
607
|
|
|
590
|
-
|
|
591
|
-
bound.boxInitialized = true;
|
|
592
|
-
|
|
593
|
-
} else {
|
|
594
|
-
|
|
595
|
-
bound.boxInitialized = false;
|
|
608
|
+
geometryInfo.boundingBox = geometry.boundingBox.clone();
|
|
596
609
|
|
|
597
610
|
}
|
|
598
611
|
|
|
612
|
+
geometryInfo.boundingSphere = null;
|
|
599
613
|
if ( geometry.boundingSphere !== null ) {
|
|
600
614
|
|
|
601
|
-
|
|
602
|
-
bound.sphereInitialized = true;
|
|
603
|
-
|
|
604
|
-
} else {
|
|
605
|
-
|
|
606
|
-
bound.sphereInitialized = false;
|
|
615
|
+
geometryInfo.boundingSphere = geometry.boundingSphere.clone();
|
|
607
616
|
|
|
608
617
|
}
|
|
609
618
|
|
|
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
619
|
this._visibilityChanged = true;
|
|
615
|
-
|
|
616
620
|
return geometryId;
|
|
617
621
|
|
|
618
622
|
}
|
|
619
623
|
|
|
620
|
-
/*
|
|
621
624
|
deleteGeometry( geometryId ) {
|
|
622
625
|
|
|
623
|
-
|
|
626
|
+
const geometryInfoList = this._geometryInfo;
|
|
627
|
+
if ( geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
|
|
628
|
+
|
|
629
|
+
return this;
|
|
630
|
+
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// delete any instances associated with this geometry
|
|
634
|
+
const instanceInfo = this._instanceInfo;
|
|
635
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
636
|
+
|
|
637
|
+
if ( instanceInfo[ i ].geometryIndex === geometryId ) {
|
|
638
|
+
|
|
639
|
+
this.deleteInstance( i );
|
|
640
|
+
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
geometryInfoList[ geometryId ].active = false;
|
|
646
|
+
this._availableGeometryIds.push( geometryId );
|
|
647
|
+
this._visibilityChanged = true;
|
|
648
|
+
|
|
649
|
+
return this;
|
|
624
650
|
|
|
625
651
|
}
|
|
626
|
-
*/
|
|
627
652
|
|
|
628
653
|
deleteInstance( instanceId ) {
|
|
629
654
|
|
|
630
|
-
const
|
|
631
|
-
if ( instanceId >=
|
|
655
|
+
const instanceInfo = this._instanceInfo;
|
|
656
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
632
657
|
|
|
633
658
|
return this;
|
|
634
659
|
|
|
635
660
|
}
|
|
636
661
|
|
|
637
|
-
|
|
662
|
+
instanceInfo[ instanceId ].active = false;
|
|
638
663
|
this._availableInstanceIds.push( instanceId );
|
|
639
664
|
this._visibilityChanged = true;
|
|
640
665
|
|
|
@@ -642,6 +667,95 @@ class BatchedMesh extends Mesh {
|
|
|
642
667
|
|
|
643
668
|
}
|
|
644
669
|
|
|
670
|
+
optimize() {
|
|
671
|
+
|
|
672
|
+
// track the next indices to copy data to
|
|
673
|
+
let nextVertexStart = 0;
|
|
674
|
+
let nextIndexStart = 0;
|
|
675
|
+
|
|
676
|
+
// Iterate over all geometry ranges in order sorted from earliest in the geometry buffer to latest
|
|
677
|
+
// in the geometry buffer. Because draw range objects can be reused there is no guarantee of their order.
|
|
678
|
+
const geometryInfoList = this._geometryInfo;
|
|
679
|
+
const indices = geometryInfoList
|
|
680
|
+
.map( ( e, i ) => i )
|
|
681
|
+
.sort( ( a, b ) => {
|
|
682
|
+
|
|
683
|
+
return geometryInfoList[ a ].vertexStart - geometryInfoList[ b ].vertexStart;
|
|
684
|
+
|
|
685
|
+
} );
|
|
686
|
+
|
|
687
|
+
const geometry = this.geometry;
|
|
688
|
+
for ( let i = 0, l = geometryInfoList.length; i < l; i ++ ) {
|
|
689
|
+
|
|
690
|
+
// if a geometry range is inactive then don't copy anything
|
|
691
|
+
const index = indices[ i ];
|
|
692
|
+
const geometryInfo = geometryInfoList[ index ];
|
|
693
|
+
if ( geometryInfo.active === false ) {
|
|
694
|
+
|
|
695
|
+
continue;
|
|
696
|
+
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// if a geometry contains an index buffer then shift it, as well
|
|
700
|
+
if ( geometry.index !== null ) {
|
|
701
|
+
|
|
702
|
+
if ( geometryInfo.indexStart !== nextIndexStart ) {
|
|
703
|
+
|
|
704
|
+
const { indexStart, vertexStart, reservedIndexCount } = geometryInfo;
|
|
705
|
+
const index = geometry.index;
|
|
706
|
+
const array = index.array;
|
|
707
|
+
|
|
708
|
+
// shift the index pointers based on how the vertex data will shift
|
|
709
|
+
// adjusting the index must happen first so the original vertex start value is available
|
|
710
|
+
const elementDelta = nextVertexStart - vertexStart;
|
|
711
|
+
for ( let j = indexStart; j < indexStart + reservedIndexCount; j ++ ) {
|
|
712
|
+
|
|
713
|
+
array[ j ] = array[ j ] + elementDelta;
|
|
714
|
+
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
index.array.copyWithin( nextIndexStart, indexStart, indexStart + reservedIndexCount );
|
|
718
|
+
index.addUpdateRange( nextIndexStart, reservedIndexCount );
|
|
719
|
+
|
|
720
|
+
geometryInfo.indexStart = nextIndexStart;
|
|
721
|
+
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
nextIndexStart += geometryInfo.reservedIndexCount;
|
|
725
|
+
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// if a geometry needs to be moved then copy attribute data to overwrite unused space
|
|
729
|
+
if ( geometryInfo.vertexStart !== nextVertexStart ) {
|
|
730
|
+
|
|
731
|
+
const { vertexStart, reservedVertexCount } = geometryInfo;
|
|
732
|
+
const attributes = geometry.attributes;
|
|
733
|
+
for ( const key in attributes ) {
|
|
734
|
+
|
|
735
|
+
const attribute = attributes[ key ];
|
|
736
|
+
const { array, itemSize } = attribute;
|
|
737
|
+
array.copyWithin( nextVertexStart * itemSize, vertexStart * itemSize, ( vertexStart + reservedVertexCount ) * itemSize );
|
|
738
|
+
attribute.addUpdateRange( nextVertexStart * itemSize, reservedVertexCount * itemSize );
|
|
739
|
+
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
geometryInfo.vertexStart = nextVertexStart;
|
|
743
|
+
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
nextVertexStart += geometryInfo.reservedVertexCount;
|
|
747
|
+
geometryInfo.start = geometry.index ? geometryInfo.indexStart : geometryInfo.vertexStart;
|
|
748
|
+
|
|
749
|
+
// step the next geometry points to the shifted position
|
|
750
|
+
this._nextIndexStart = geometry.index ? geometryInfo.indexStart + geometryInfo.reservedIndexCount : 0;
|
|
751
|
+
this._nextVertexStart = geometryInfo.vertexStart + geometryInfo.reservedVertexCount;
|
|
752
|
+
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
return this;
|
|
756
|
+
|
|
757
|
+
}
|
|
758
|
+
|
|
645
759
|
// get bounding box and compute it if it doesn't exist
|
|
646
760
|
getBoundingBoxAt( geometryId, target ) {
|
|
647
761
|
|
|
@@ -652,17 +766,14 @@ class BatchedMesh extends Mesh {
|
|
|
652
766
|
}
|
|
653
767
|
|
|
654
768
|
// compute bounding box
|
|
655
|
-
const bound = this._bounds[ geometryId ];
|
|
656
|
-
const box = bound.box;
|
|
657
769
|
const geometry = this.geometry;
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
box.makeEmpty();
|
|
770
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
771
|
+
if ( geometryInfo.boundingBox === null ) {
|
|
661
772
|
|
|
773
|
+
const box = new Box3();
|
|
662
774
|
const index = geometry.index;
|
|
663
775
|
const position = geometry.attributes.position;
|
|
664
|
-
|
|
665
|
-
for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) {
|
|
776
|
+
for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
|
|
666
777
|
|
|
667
778
|
let iv = i;
|
|
668
779
|
if ( index ) {
|
|
@@ -675,11 +786,11 @@ class BatchedMesh extends Mesh {
|
|
|
675
786
|
|
|
676
787
|
}
|
|
677
788
|
|
|
678
|
-
|
|
789
|
+
geometryInfo.boundingBox = box;
|
|
679
790
|
|
|
680
791
|
}
|
|
681
792
|
|
|
682
|
-
target.copy(
|
|
793
|
+
target.copy( geometryInfo.boundingBox );
|
|
683
794
|
return target;
|
|
684
795
|
|
|
685
796
|
}
|
|
@@ -694,22 +805,19 @@ class BatchedMesh extends Mesh {
|
|
|
694
805
|
}
|
|
695
806
|
|
|
696
807
|
// compute bounding sphere
|
|
697
|
-
const bound = this._bounds[ geometryId ];
|
|
698
|
-
const sphere = bound.sphere;
|
|
699
808
|
const geometry = this.geometry;
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
sphere.makeEmpty();
|
|
809
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
810
|
+
if ( geometryInfo.boundingSphere === null ) {
|
|
703
811
|
|
|
812
|
+
const sphere = new Sphere();
|
|
704
813
|
this.getBoundingBoxAt( geometryId, _box );
|
|
705
814
|
_box.getCenter( sphere.center );
|
|
706
815
|
|
|
707
816
|
const index = geometry.index;
|
|
708
817
|
const position = geometry.attributes.position;
|
|
709
|
-
const drawRange = this._drawRanges[ geometryId ];
|
|
710
818
|
|
|
711
819
|
let maxRadiusSq = 0;
|
|
712
|
-
for ( let i =
|
|
820
|
+
for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
|
|
713
821
|
|
|
714
822
|
let iv = i;
|
|
715
823
|
if ( index ) {
|
|
@@ -724,24 +832,21 @@ class BatchedMesh extends Mesh {
|
|
|
724
832
|
}
|
|
725
833
|
|
|
726
834
|
sphere.radius = Math.sqrt( maxRadiusSq );
|
|
727
|
-
|
|
835
|
+
geometryInfo.boundingSphere = sphere;
|
|
728
836
|
|
|
729
837
|
}
|
|
730
838
|
|
|
731
|
-
target.copy(
|
|
839
|
+
target.copy( geometryInfo.boundingSphere );
|
|
732
840
|
return target;
|
|
733
841
|
|
|
734
842
|
}
|
|
735
843
|
|
|
736
844
|
setMatrixAt( instanceId, matrix ) {
|
|
737
845
|
|
|
738
|
-
|
|
739
|
-
// optimize() can make geometryId mismatch the index
|
|
740
|
-
|
|
741
|
-
const drawInfo = this._drawInfo;
|
|
846
|
+
const instanceInfo = this._instanceInfo;
|
|
742
847
|
const matricesTexture = this._matricesTexture;
|
|
743
848
|
const matricesArray = this._matricesTexture.image.data;
|
|
744
|
-
if ( instanceId >=
|
|
849
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
745
850
|
|
|
746
851
|
return this;
|
|
747
852
|
|
|
@@ -756,9 +861,9 @@ class BatchedMesh extends Mesh {
|
|
|
756
861
|
|
|
757
862
|
getMatrixAt( instanceId, matrix ) {
|
|
758
863
|
|
|
759
|
-
const
|
|
864
|
+
const instanceInfo = this._instanceInfo;
|
|
760
865
|
const matricesArray = this._matricesTexture.image.data;
|
|
761
|
-
if ( instanceId >=
|
|
866
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
762
867
|
|
|
763
868
|
return null;
|
|
764
869
|
|
|
@@ -776,13 +881,10 @@ class BatchedMesh extends Mesh {
|
|
|
776
881
|
|
|
777
882
|
}
|
|
778
883
|
|
|
779
|
-
// @TODO: Map id to index of the arrays because
|
|
780
|
-
// optimize() can make id mismatch the index
|
|
781
|
-
|
|
782
884
|
const colorsTexture = this._colorsTexture;
|
|
783
885
|
const colorsArray = this._colorsTexture.image.data;
|
|
784
|
-
const
|
|
785
|
-
if ( instanceId >=
|
|
886
|
+
const instanceInfo = this._instanceInfo;
|
|
887
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
786
888
|
|
|
787
889
|
return this;
|
|
788
890
|
|
|
@@ -798,8 +900,8 @@ class BatchedMesh extends Mesh {
|
|
|
798
900
|
getColorAt( instanceId, color ) {
|
|
799
901
|
|
|
800
902
|
const colorsArray = this._colorsTexture.image.data;
|
|
801
|
-
const
|
|
802
|
-
if ( instanceId >=
|
|
903
|
+
const instanceInfo = this._instanceInfo;
|
|
904
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
803
905
|
|
|
804
906
|
return null;
|
|
805
907
|
|
|
@@ -813,18 +915,18 @@ class BatchedMesh extends Mesh {
|
|
|
813
915
|
|
|
814
916
|
// if the geometry is out of range, not active, or visibility state
|
|
815
917
|
// does not change then return early
|
|
816
|
-
const
|
|
918
|
+
const instanceInfo = this._instanceInfo;
|
|
817
919
|
if (
|
|
818
|
-
instanceId >=
|
|
819
|
-
|
|
820
|
-
|
|
920
|
+
instanceId >= instanceInfo.length ||
|
|
921
|
+
instanceInfo[ instanceId ].active === false ||
|
|
922
|
+
instanceInfo[ instanceId ].visible === value
|
|
821
923
|
) {
|
|
822
924
|
|
|
823
925
|
return this;
|
|
824
926
|
|
|
825
927
|
}
|
|
826
928
|
|
|
827
|
-
|
|
929
|
+
instanceInfo[ instanceId ].visible = value;
|
|
828
930
|
this._visibilityChanged = true;
|
|
829
931
|
|
|
830
932
|
return this;
|
|
@@ -834,35 +936,36 @@ class BatchedMesh extends Mesh {
|
|
|
834
936
|
getVisibleAt( instanceId ) {
|
|
835
937
|
|
|
836
938
|
// return early if the geometry is out of range or not active
|
|
837
|
-
const
|
|
838
|
-
if ( instanceId >=
|
|
939
|
+
const instanceInfo = this._instanceInfo;
|
|
940
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
839
941
|
|
|
840
942
|
return false;
|
|
841
943
|
|
|
842
944
|
}
|
|
843
945
|
|
|
844
|
-
return
|
|
946
|
+
return instanceInfo[ instanceId ].visible;
|
|
845
947
|
|
|
846
948
|
}
|
|
847
949
|
|
|
848
950
|
setGeometryIdAt( instanceId, geometryId ) {
|
|
849
951
|
|
|
850
952
|
// return early if the geometry is out of range or not active
|
|
851
|
-
const
|
|
852
|
-
|
|
953
|
+
const instanceInfo = this._instanceInfo;
|
|
954
|
+
const geometryInfoList = this._geometryInfo;
|
|
955
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
853
956
|
|
|
854
957
|
return null;
|
|
855
958
|
|
|
856
959
|
}
|
|
857
960
|
|
|
858
961
|
// check if the provided geometryId is within the valid range
|
|
859
|
-
if ( geometryId
|
|
962
|
+
if ( geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
|
|
860
963
|
|
|
861
964
|
return null;
|
|
862
965
|
|
|
863
966
|
}
|
|
864
967
|
|
|
865
|
-
|
|
968
|
+
instanceInfo[ instanceId ].geometryIndex = geometryId;
|
|
866
969
|
|
|
867
970
|
return this;
|
|
868
971
|
|
|
@@ -870,14 +973,14 @@ class BatchedMesh extends Mesh {
|
|
|
870
973
|
|
|
871
974
|
getGeometryIdAt( instanceId ) {
|
|
872
975
|
|
|
873
|
-
const
|
|
874
|
-
if ( instanceId >=
|
|
976
|
+
const instanceInfo = this._instanceInfo;
|
|
977
|
+
if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
875
978
|
|
|
876
979
|
return - 1;
|
|
877
980
|
|
|
878
981
|
}
|
|
879
982
|
|
|
880
|
-
return
|
|
983
|
+
return instanceInfo[ instanceId ].geometryIndex;
|
|
881
984
|
|
|
882
985
|
}
|
|
883
986
|
|
|
@@ -889,19 +992,136 @@ class BatchedMesh extends Mesh {
|
|
|
889
992
|
|
|
890
993
|
}
|
|
891
994
|
|
|
892
|
-
const
|
|
995
|
+
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
996
|
+
target.vertexStart = geometryInfo.vertexStart;
|
|
997
|
+
target.vertexCount = geometryInfo.vertexCount;
|
|
998
|
+
target.reservedVertexCount = geometryInfo.reservedVertexCount;
|
|
999
|
+
|
|
1000
|
+
target.indexStart = geometryInfo.indexStart;
|
|
1001
|
+
target.indexCount = geometryInfo.indexCount;
|
|
1002
|
+
target.reservedIndexCount = geometryInfo.reservedIndexCount;
|
|
893
1003
|
|
|
894
|
-
target.start =
|
|
895
|
-
target.count =
|
|
1004
|
+
target.start = geometryInfo.start;
|
|
1005
|
+
target.count = geometryInfo.count;
|
|
896
1006
|
|
|
897
1007
|
return target;
|
|
898
1008
|
|
|
899
1009
|
}
|
|
900
1010
|
|
|
1011
|
+
setInstanceCount( maxInstanceCount ) {
|
|
1012
|
+
|
|
1013
|
+
// shrink the available instances as much as possible
|
|
1014
|
+
const availableInstanceIds = this._availableInstanceIds;
|
|
1015
|
+
const instanceInfo = this._instanceInfo;
|
|
1016
|
+
availableInstanceIds.sort( ascIdSort );
|
|
1017
|
+
while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length ) {
|
|
1018
|
+
|
|
1019
|
+
instanceInfo.pop();
|
|
1020
|
+
availableInstanceIds.pop();
|
|
1021
|
+
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// throw an error if it can't be shrunk to the desired size
|
|
1025
|
+
if ( maxInstanceCount < instanceInfo.length ) {
|
|
1026
|
+
|
|
1027
|
+
throw new Error( `BatchedMesh: Instance ids outside the range ${ maxInstanceCount } are being used. Cannot shrink instance count.` );
|
|
1028
|
+
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// copy the multi draw counts
|
|
1032
|
+
const multiDrawCounts = new Int32Array( maxInstanceCount );
|
|
1033
|
+
const multiDrawStarts = new Int32Array( maxInstanceCount );
|
|
1034
|
+
copyArrayContents( this._multiDrawCounts, multiDrawCounts );
|
|
1035
|
+
copyArrayContents( this._multiDrawStarts, multiDrawStarts );
|
|
1036
|
+
|
|
1037
|
+
this._multiDrawCounts = multiDrawCounts;
|
|
1038
|
+
this._multiDrawStarts = multiDrawStarts;
|
|
1039
|
+
this._maxInstanceCount = maxInstanceCount;
|
|
1040
|
+
|
|
1041
|
+
// update texture data for instance sampling
|
|
1042
|
+
const indirectTexture = this._indirectTexture;
|
|
1043
|
+
const matricesTexture = this._matricesTexture;
|
|
1044
|
+
const colorsTexture = this._colorsTexture;
|
|
1045
|
+
|
|
1046
|
+
indirectTexture.dispose();
|
|
1047
|
+
this._initIndirectTexture();
|
|
1048
|
+
copyArrayContents( indirectTexture.image.data, this._indirectTexture.image.data );
|
|
1049
|
+
|
|
1050
|
+
matricesTexture.dispose();
|
|
1051
|
+
this._initMatricesTexture();
|
|
1052
|
+
copyArrayContents( matricesTexture.image.data, this._matricesTexture.image.data );
|
|
1053
|
+
|
|
1054
|
+
if ( colorsTexture ) {
|
|
1055
|
+
|
|
1056
|
+
colorsTexture.dispose();
|
|
1057
|
+
this._initColorsTexture();
|
|
1058
|
+
copyArrayContents( colorsTexture.image.data, this._colorsTexture.image.data );
|
|
1059
|
+
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
setGeometrySize( maxVertexCount, maxIndexCount ) {
|
|
1065
|
+
|
|
1066
|
+
// Check if we can shrink to the requested vertex attribute size
|
|
1067
|
+
const validRanges = [ ...this._geometryInfo ].filter( info => info.active );
|
|
1068
|
+
const requiredVertexLength = Math.max( ...validRanges.map( range => range.vertexStart + range.reservedVertexCount ) );
|
|
1069
|
+
if ( requiredVertexLength > maxVertexCount ) {
|
|
1070
|
+
|
|
1071
|
+
throw new Error( `BatchedMesh: Geometry vertex values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
|
|
1072
|
+
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Check if we can shrink to the requested index attribute size
|
|
1076
|
+
if ( this.geometry.index ) {
|
|
1077
|
+
|
|
1078
|
+
const requiredIndexLength = Math.max( ...validRanges.map( range => range.indexStart + range.reservedIndexCount ) );
|
|
1079
|
+
if ( requiredIndexLength > maxIndexCount ) {
|
|
1080
|
+
|
|
1081
|
+
throw new Error( `BatchedMesh: Geometry index values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
|
|
1082
|
+
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
//
|
|
1088
|
+
|
|
1089
|
+
// dispose of the previous geometry
|
|
1090
|
+
const oldGeometry = this.geometry;
|
|
1091
|
+
oldGeometry.dispose();
|
|
1092
|
+
|
|
1093
|
+
// recreate the geometry needed based on the previous variant
|
|
1094
|
+
this._maxVertexCount = maxVertexCount;
|
|
1095
|
+
this._maxIndexCount = maxIndexCount;
|
|
1096
|
+
|
|
1097
|
+
if ( this._geometryInitialized ) {
|
|
1098
|
+
|
|
1099
|
+
this._geometryInitialized = false;
|
|
1100
|
+
this.geometry = new BufferGeometry();
|
|
1101
|
+
this._initializeGeometry( oldGeometry );
|
|
1102
|
+
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// copy data from the previous geometry
|
|
1106
|
+
const geometry = this.geometry;
|
|
1107
|
+
if ( oldGeometry.index ) {
|
|
1108
|
+
|
|
1109
|
+
copyArrayContents( oldGeometry.index.array, geometry.index.array );
|
|
1110
|
+
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
for ( const key in oldGeometry.attributes ) {
|
|
1114
|
+
|
|
1115
|
+
copyArrayContents( oldGeometry.attributes[ key ].array, geometry.attributes[ key ].array );
|
|
1116
|
+
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
}
|
|
1120
|
+
|
|
901
1121
|
raycast( raycaster, intersects ) {
|
|
902
1122
|
|
|
903
|
-
const
|
|
904
|
-
const
|
|
1123
|
+
const instanceInfo = this._instanceInfo;
|
|
1124
|
+
const geometryInfoList = this._geometryInfo;
|
|
905
1125
|
const matrixWorld = this.matrixWorld;
|
|
906
1126
|
const batchGeometry = this.geometry;
|
|
907
1127
|
|
|
@@ -921,19 +1141,19 @@ class BatchedMesh extends Mesh {
|
|
|
921
1141
|
|
|
922
1142
|
}
|
|
923
1143
|
|
|
924
|
-
for ( let i = 0, l =
|
|
1144
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
925
1145
|
|
|
926
|
-
if ( !
|
|
1146
|
+
if ( ! instanceInfo[ i ].visible || ! instanceInfo[ i ].active ) {
|
|
927
1147
|
|
|
928
1148
|
continue;
|
|
929
1149
|
|
|
930
1150
|
}
|
|
931
1151
|
|
|
932
|
-
const geometryId =
|
|
933
|
-
const
|
|
934
|
-
_mesh.geometry.setDrawRange(
|
|
1152
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
1153
|
+
const geometryInfo = geometryInfoList[ geometryId ];
|
|
1154
|
+
_mesh.geometry.setDrawRange( geometryInfo.start, geometryInfo.count );
|
|
935
1155
|
|
|
936
|
-
//
|
|
1156
|
+
// get the intersects
|
|
937
1157
|
this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld );
|
|
938
1158
|
this.getBoundingBoxAt( geometryId, _mesh.geometry.boundingBox );
|
|
939
1159
|
this.getBoundingSphereAt( geometryId, _mesh.geometry.boundingSphere );
|
|
@@ -970,17 +1190,13 @@ class BatchedMesh extends Mesh {
|
|
|
970
1190
|
this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
|
|
971
1191
|
this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
|
|
972
1192
|
|
|
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(),
|
|
1193
|
+
this._geometryInfo = source._geometryInfo.map( info => ( {
|
|
1194
|
+
...info,
|
|
980
1195
|
|
|
981
|
-
|
|
982
|
-
|
|
1196
|
+
boundingBox: info.boundingBox !== null ? info.boundingBox.clone() : null,
|
|
1197
|
+
boundingSphere: info.boundingSphere !== null ? info.boundingSphere.clone() : null,
|
|
983
1198
|
} ) );
|
|
1199
|
+
this._instanceInfo = source._instanceInfo.map( info => ( { ...info } ) );
|
|
984
1200
|
|
|
985
1201
|
this._maxInstanceCount = source._maxInstanceCount;
|
|
986
1202
|
this._maxVertexCount = source._maxVertexCount;
|
|
@@ -1042,10 +1258,10 @@ class BatchedMesh extends Mesh {
|
|
|
1042
1258
|
const index = geometry.getIndex();
|
|
1043
1259
|
const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
|
|
1044
1260
|
|
|
1045
|
-
const
|
|
1261
|
+
const instanceInfo = this._instanceInfo;
|
|
1046
1262
|
const multiDrawStarts = this._multiDrawStarts;
|
|
1047
1263
|
const multiDrawCounts = this._multiDrawCounts;
|
|
1048
|
-
const
|
|
1264
|
+
const geometryInfoList = this._geometryInfo;
|
|
1049
1265
|
const perObjectFrustumCulled = this.perObjectFrustumCulled;
|
|
1050
1266
|
const indirectTexture = this._indirectTexture;
|
|
1051
1267
|
const indirectArray = indirectTexture.image.data;
|
|
@@ -1053,29 +1269,29 @@ class BatchedMesh extends Mesh {
|
|
|
1053
1269
|
// prepare the frustum in the local frame
|
|
1054
1270
|
if ( perObjectFrustumCulled ) {
|
|
1055
1271
|
|
|
1056
|
-
|
|
1272
|
+
_matrix
|
|
1057
1273
|
.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
|
|
1058
1274
|
.multiply( this.matrixWorld );
|
|
1059
1275
|
_frustum.setFromProjectionMatrix(
|
|
1060
|
-
|
|
1276
|
+
_matrix,
|
|
1061
1277
|
renderer.coordinateSystem
|
|
1062
1278
|
);
|
|
1063
1279
|
|
|
1064
1280
|
}
|
|
1065
1281
|
|
|
1066
|
-
let
|
|
1282
|
+
let multiDrawCount = 0;
|
|
1067
1283
|
if ( this.sortObjects ) {
|
|
1068
1284
|
|
|
1069
1285
|
// 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(
|
|
1286
|
+
_matrix.copy( this.matrixWorld ).invert();
|
|
1287
|
+
_vector.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _matrix );
|
|
1288
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).transformDirection( _matrix );
|
|
1073
1289
|
|
|
1074
|
-
for ( let i = 0, l =
|
|
1290
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
1075
1291
|
|
|
1076
|
-
if (
|
|
1292
|
+
if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
|
|
1077
1293
|
|
|
1078
|
-
const geometryId =
|
|
1294
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
1079
1295
|
|
|
1080
1296
|
// get the bounds in world space
|
|
1081
1297
|
this.getMatrixAt( i, _matrix );
|
|
@@ -1092,8 +1308,9 @@ class BatchedMesh extends Mesh {
|
|
|
1092
1308
|
if ( ! culled ) {
|
|
1093
1309
|
|
|
1094
1310
|
// get the distance from camera used for sorting
|
|
1311
|
+
const geometryInfo = geometryInfoList[ geometryId ];
|
|
1095
1312
|
const z = _temp.subVectors( _sphere.center, _vector ).dot( _forward );
|
|
1096
|
-
_renderList.push(
|
|
1313
|
+
_renderList.push( geometryInfo.start, geometryInfo.count, z, i );
|
|
1097
1314
|
|
|
1098
1315
|
}
|
|
1099
1316
|
|
|
@@ -1117,10 +1334,10 @@ class BatchedMesh extends Mesh {
|
|
|
1117
1334
|
for ( let i = 0, l = list.length; i < l; i ++ ) {
|
|
1118
1335
|
|
|
1119
1336
|
const item = list[ i ];
|
|
1120
|
-
multiDrawStarts[
|
|
1121
|
-
multiDrawCounts[
|
|
1122
|
-
indirectArray[
|
|
1123
|
-
|
|
1337
|
+
multiDrawStarts[ multiDrawCount ] = item.start * bytesPerElement;
|
|
1338
|
+
multiDrawCounts[ multiDrawCount ] = item.count;
|
|
1339
|
+
indirectArray[ multiDrawCount ] = item.index;
|
|
1340
|
+
multiDrawCount ++;
|
|
1124
1341
|
|
|
1125
1342
|
}
|
|
1126
1343
|
|
|
@@ -1128,11 +1345,11 @@ class BatchedMesh extends Mesh {
|
|
|
1128
1345
|
|
|
1129
1346
|
} else {
|
|
1130
1347
|
|
|
1131
|
-
for ( let i = 0, l =
|
|
1348
|
+
for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
|
|
1132
1349
|
|
|
1133
|
-
if (
|
|
1350
|
+
if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
|
|
1134
1351
|
|
|
1135
|
-
const geometryId =
|
|
1352
|
+
const geometryId = instanceInfo[ i ].geometryIndex;
|
|
1136
1353
|
|
|
1137
1354
|
// determine whether the batched geometry is within the frustum
|
|
1138
1355
|
let culled = false;
|
|
@@ -1147,11 +1364,11 @@ class BatchedMesh extends Mesh {
|
|
|
1147
1364
|
|
|
1148
1365
|
if ( ! culled ) {
|
|
1149
1366
|
|
|
1150
|
-
const
|
|
1151
|
-
multiDrawStarts[
|
|
1152
|
-
multiDrawCounts[
|
|
1153
|
-
indirectArray[
|
|
1154
|
-
|
|
1367
|
+
const geometryInfo = geometryInfoList[ geometryId ];
|
|
1368
|
+
multiDrawStarts[ multiDrawCount ] = geometryInfo.start * bytesPerElement;
|
|
1369
|
+
multiDrawCounts[ multiDrawCount ] = geometryInfo.count;
|
|
1370
|
+
indirectArray[ multiDrawCount ] = i;
|
|
1371
|
+
multiDrawCount ++;
|
|
1155
1372
|
|
|
1156
1373
|
}
|
|
1157
1374
|
|
|
@@ -1162,7 +1379,7 @@ class BatchedMesh extends Mesh {
|
|
|
1162
1379
|
}
|
|
1163
1380
|
|
|
1164
1381
|
indirectTexture.needsUpdate = true;
|
|
1165
|
-
this._multiDrawCount =
|
|
1382
|
+
this._multiDrawCount = multiDrawCount;
|
|
1166
1383
|
this._visibilityChanged = false;
|
|
1167
1384
|
|
|
1168
1385
|
}
|