From 9180216db90d4c966dfff0771072b049f236ee4f Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 5 Nov 2023 21:38:56 +0900 Subject: [PATCH 01/11] BatchedMeh: add support for frustum culling batched elements --- examples/jsm/objects/BatchedMesh.js | 86 +++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index 4e80635577aa8a..d0fe525d97dc63 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -6,10 +6,16 @@ import { MathUtils, Matrix4, Mesh, - RGBAFormat + RGBAFormat, + Box3, + Sphere, + Frustum, + WebGLCoordinateSystem, + WebGPUCoordinateSystem, } from 'three'; const ID_ATTR_NAME = '_batch_id_'; +const _matrix = new Matrix4(); const _identityMatrix = new Matrix4(); const _zeroScaleMatrix = new Matrix4().set( 0, 0, 0, 0, @@ -17,6 +23,10 @@ const _zeroScaleMatrix = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 1, ); +const _projScreenMatrix = new Matrix4(); +const _frustum = new Frustum(); +const _box = new Box3(); +const _sphere = new Sphere(); // Custom shaders const batchingParsVertex = /* glsl */` @@ -106,6 +116,7 @@ class BatchedMesh extends Mesh { this._visible = []; this._active = []; + this._bounds = []; this._maxGeometryCount = maxGeometryCount; this._maxVertexCount = maxVertexCount; @@ -123,9 +134,6 @@ class BatchedMesh extends Mesh { this._matrices = []; this._matricesTexture = null; - // @TODO: Calculate the entire binding box and make frustumCulled true - this.frustumCulled = false; - this._customUniforms = { batchingTexture: { value: null } }; @@ -242,6 +250,16 @@ class BatchedMesh extends Mesh { : new Uint16Array( maxVertexCount ); geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) ); + // Use infinitely large bounds since frustum culling will occur in onBeforeRender + const box = new Box3(); + box.min.setScalar( - Infinity ); + box.max.setScalar( Infinity ); + geometry.boundingBox = box; + + const sphere = new Sphere(); + sphere.radius = Infinity; + geometry.boundingSphere = sphere; + this._geometryInitialized = true; this._multiDrawCounts = new Int32Array( maxGeometryCount ); this._multiDrawStarts = new Int32Array( maxGeometryCount ); @@ -357,6 +375,7 @@ class BatchedMesh extends Mesh { let lastRange = null; const reservedRanges = this._reservedRanges; const drawRanges = this._drawRanges; + const bounds = this._bounds; if ( this._geometryCount !== 0 ) { lastRange = reservedRanges[ reservedRanges.length - 1 ]; @@ -444,6 +463,10 @@ class BatchedMesh extends Mesh { start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart, count: - 1 } ); + bounds.push( { + box: new Box3(), + sphere: new Sphere() + } ); // set the id for the geometry const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME ); @@ -543,6 +566,23 @@ class BatchedMesh extends Mesh { } + // store the bounding boxes + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + const bound = this._bounds[ id ]; + bound.box.copy( geometry.boundingBox ); + bound.sphere.copy( geometry.boundingSphere ); + // set drawRange count const drawRange = this._drawRanges[ id ]; const posAttr = geometry.getAttribute( 'position' ); @@ -706,7 +746,7 @@ class BatchedMesh extends Mesh { } - onBeforeRender( _renderer, _scene, _camera, _geometry, material/*, _group*/ ) { + onBeforeRender( _renderer, _scene, camera, _geometry, material/*, _group*/ ) { material.defines.BATCHING = true; @@ -719,16 +759,42 @@ class BatchedMesh extends Mesh { const multiDrawStarts = this._multiDrawStarts; const multiDrawCounts = this._multiDrawCounts; const drawRanges = this._drawRanges; + const bounds = this._bounds; + const frustumCulled = this.frustumCulled; + + if ( frustumCulled ) { + + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( + _projScreenMatrix, + _renderer.isWebGPURenderer ? WebGPUCoordinateSystem : WebGLCoordinateSystem + ); + + } let count = 0; for ( let i = 0, l = visible.length; i < l; i ++ ) { if ( visible[ i ] ) { - const range = drawRanges[ i ]; - multiDrawStarts[ count ] = range.start * bytesPerElement; - multiDrawCounts[ count ] = range.count; - count ++; + let culled = false; + if ( frustumCulled ) { + + this.getMatrixAt( i, _matrix ).premultiply( this.matrixWorld ); + _box.copy( bounds[ i ].box ).applyMatrix4( _matrix ); + _sphere.copy( bounds[ i ].sphere ).applyMatrix4( _matrix ); + culled = ! _frustum.intersectsBox( _box ) || ! _frustum.intersectsSphere( _sphere ); + + } + + if ( ! culled ) { + + const range = drawRanges[ i ]; + multiDrawStarts[ count ] = range.start * bytesPerElement; + multiDrawCounts[ count ] = range.count; + count ++; + + } } @@ -736,8 +802,6 @@ class BatchedMesh extends Mesh { this._multiDrawCount = count; - // @TODO: Implement frustum culling for each geometry - // @TODO: Implement geometry sorting for transparent and opaque materials } From 1341294e6bbbe86406757a9b701f12ef6a9d8797 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Sun, 5 Nov 2023 21:47:01 +0900 Subject: [PATCH 02/11] comments --- examples/jsm/objects/BatchedMesh.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index d0fe525d97dc63..6b6d81e3588a45 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -762,6 +762,7 @@ class BatchedMesh extends Mesh { const bounds = this._bounds; const frustumCulled = this.frustumCulled; + // prepare the frustum if ( frustumCulled ) { _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); @@ -777,10 +778,14 @@ class BatchedMesh extends Mesh { if ( visible[ i ] ) { + // determine whether the batched geometry is within the frustum let culled = false; if ( frustumCulled ) { + // get the bounds in camera space this.getMatrixAt( i, _matrix ).premultiply( this.matrixWorld ); + + // get the bounds _box.copy( bounds[ i ].box ).applyMatrix4( _matrix ); _sphere.copy( bounds[ i ].sphere ).applyMatrix4( _matrix ); culled = ! _frustum.intersectsBox( _box ) || ! _frustum.intersectsSphere( _sphere ); From 1c8d3ef251bcfba8c3d05b9d0e6c74fe12bf1573 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 6 Nov 2023 19:09:29 +0900 Subject: [PATCH 03/11] Update frustum culling support --- examples/jsm/objects/BatchedMesh.js | 126 +++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 11 deletions(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index 9a625ca7bf2a04..aac5d99922c1be 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -12,6 +12,7 @@ import { Frustum, WebGLCoordinateSystem, WebGPUCoordinateSystem, + Vector3, } from 'three'; const ID_ATTR_NAME = 'batchId'; @@ -27,6 +28,7 @@ const _projScreenMatrix = new Matrix4(); const _frustum = new Frustum(); const _box = new Box3(); const _sphere = new Sphere(); +const _vector = new Vector3(); // @TODO: SkinnedMesh support? // @TODO: Future work if needed. Move into the core. Can be optimized more with WEBGL_multi_draw. @@ -370,7 +372,10 @@ class BatchedMesh extends Mesh { count: - 1 } ); bounds.push( { + boxInitialized: false, box: new Box3(), + + sphereInitialized: false, sphere: new Sphere() } ); @@ -473,21 +478,28 @@ class BatchedMesh extends Mesh { } // store the bounding boxes - if ( geometry.boundingBox === null ) { + const bound = this._bounds[ id ]; + if ( geometry.boundingBox !== null ) { + + bound.box.copy( geometry.boundingBox ); + bound.boxInitialized = true; + + } else { - geometry.computeBoundingBox(); + bound.boxInitialized = false; } - if ( geometry.boundingSphere === null ) { + if ( geometry.boundingSphere !== null ) { - geometry.computeBoundingSphere(); + bound.sphere.copy( geometry.boundingSphere ); + bound.sphereInitialized = true; - } + } else { - const bound = this._bounds[ id ]; - bound.box.copy( geometry.boundingBox ); - bound.sphere.copy( geometry.boundingSphere ); + bound.sphereInitialized = false; + + } // set drawRange count const drawRange = this._drawRanges[ id ]; @@ -519,6 +531,99 @@ class BatchedMesh extends Mesh { } + // get bounding box and compute it if it doesn't exist + getBoundingBoxAt( id, target ) { + + const active = this._active; + if ( active[ id ] === false ) { + + return this; + + } + + // compute bounding box + const bound = this._bounds[ id ]; + const box = bound.box; + const geometry = this.geometry; + if ( bound.boxInitialized === false ) { + + box.makeEmpty(); + + const index = geometry.index; + const position = geometry.attributes.position; + const drawRange = this._drawRanges[ id ]; + for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { + + let iv = i; + if ( index ) { + + iv = index.getX( iv ); + + } + + box.expandByPoint( _vector.fromBufferAttribute( position, iv ) ); + + } + + bound.boxInitialized = true; + + } + + target.copy( box ); + return target; + + } + + // get bounding sphere and compute it if it doesn't exist + getBoundingSphereAt( id, target ) { + + const active = this._active; + if ( active[ id ] === false ) { + + return this; + + } + + // compute bounding sphere + const bound = this._bounds[ id ]; + const sphere = bound.sphere; + const geometry = this.geometry; + if ( bound.sphereInitialized === false ) { + + sphere.makeEmpty(); + + this.getBoundingBoxAt( id, _box ); + _box.getCenter( sphere.center ); + + const index = geometry.index; + const position = geometry.attributes.position; + const drawRange = this._drawRanges[ id ]; + + let maxRadiusSq = 0; + for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { + + let iv = i; + if ( index ) { + + iv = index.getX( iv ); + + } + + _vector.fromBufferAttribute( position, iv ); + maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector ) ); + + } + + sphere.radius = Math.sqrt( maxRadiusSq ); + bound.sphereInitialized = true; + + } + + target.copy( sphere ); + return target; + + } + optimize() { throw new Error( 'BatchedMesh: Optimize function not implemented.' ); @@ -663,7 +768,6 @@ class BatchedMesh extends Mesh { const multiDrawStarts = this._multiDrawStarts; const multiDrawCounts = this._multiDrawCounts; const drawRanges = this._drawRanges; - const bounds = this._bounds; const frustumCulled = this.frustumCulled; // prepare the frustum @@ -690,8 +794,8 @@ class BatchedMesh extends Mesh { this.getMatrixAt( i, _matrix ).premultiply( this.matrixWorld ); // get the bounds - _box.copy( bounds[ i ].box ).applyMatrix4( _matrix ); - _sphere.copy( bounds[ i ].sphere ).applyMatrix4( _matrix ); + this.getBoundingBoxAt( i, _box ).applyMatrix4( _matrix ); + this.getBoundingSphereAt( i, _sphere ).applyMatrix4( _matrix ); culled = ! _frustum.intersectsBox( _box ) || ! _frustum.intersectsSphere( _sphere ); } From fd0f6ccbe240ecac7e555730b826047d8768b3aa Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 7 Nov 2023 12:12:46 +0900 Subject: [PATCH 04/11] BatchedMesh: add "perObjectFrustumCulled" --- examples/jsm/objects/BatchedMesh.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index c83ccbbd022df1..f44cf6e4aaf3e6 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -95,6 +95,9 @@ class BatchedMesh extends Mesh { // Local matrix per geometry by using data texture this._matricesTexture = null; + this.frustumCulled = false; + this.perObjectFrustumCulled = true; + this._initMatricesTexture(); } @@ -155,16 +158,6 @@ class BatchedMesh extends Mesh { : new Uint16Array( maxVertexCount ); geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) ); - // Use infinitely large bounds since frustum culling will occur in onBeforeRender - const box = new Box3(); - box.min.setScalar( - Infinity ); - box.max.setScalar( Infinity ); - geometry.boundingBox = box; - - const sphere = new Sphere(); - sphere.radius = Infinity; - geometry.boundingSphere = sphere; - this._geometryInitialized = true; this._multiDrawCounts = new Int32Array( maxGeometryCount ); this._multiDrawStarts = new Int32Array( maxGeometryCount ); @@ -744,10 +737,10 @@ class BatchedMesh extends Mesh { const multiDrawStarts = this._multiDrawStarts; const multiDrawCounts = this._multiDrawCounts; const drawRanges = this._drawRanges; - const frustumCulled = this.frustumCulled; + const perObjectFrustumCulled = this.perObjectFrustumCulled; // prepare the frustum - if ( frustumCulled ) { + if ( perObjectFrustumCulled ) { _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); _frustum.setFromProjectionMatrix( @@ -764,7 +757,7 @@ class BatchedMesh extends Mesh { // determine whether the batched geometry is within the frustum let culled = false; - if ( frustumCulled ) { + if ( perObjectFrustumCulled ) { // get the bounds in camera space this.getMatrixAt( i, _matrix ).premultiply( this.matrixWorld ); From e3c2c242abed3758eb64340f33881d15515fac0c Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 7 Nov 2023 12:32:18 +0900 Subject: [PATCH 05/11] Reduce the number of world matrix transform applications for frustum culling --- examples/jsm/objects/BatchedMesh.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index f44cf6e4aaf3e6..81d466982681fe 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -742,7 +742,9 @@ class BatchedMesh extends Mesh { // prepare the frustum if ( perObjectFrustumCulled ) { - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _projScreenMatrix + .multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) + .multiply( this.matrixWorld ); _frustum.setFromProjectionMatrix( _projScreenMatrix, _renderer.isWebGPURenderer ? WebGPUCoordinateSystem : WebGLCoordinateSystem @@ -760,7 +762,7 @@ class BatchedMesh extends Mesh { if ( perObjectFrustumCulled ) { // get the bounds in camera space - this.getMatrixAt( i, _matrix ).premultiply( this.matrixWorld ); + this.getMatrixAt( i, _matrix ); // get the bounds this.getBoundingBoxAt( i, _box ).applyMatrix4( _matrix ); From 66b2ed9b54de7e43a2449d210764ecc5ac81d0c1 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 7 Nov 2023 19:04:10 +0900 Subject: [PATCH 06/11] Update copy function --- examples/jsm/objects/BatchedMesh.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index dac74a1390d496..699e777bdf1329 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -74,6 +74,8 @@ class BatchedMesh extends Mesh { super( new BufferGeometry(), material ); this.isBatchedMesh = true; + this.perObjectFrustumCulled = true; + this.frustumCulled = false; this._drawRanges = []; this._reservedRanges = []; @@ -95,9 +97,6 @@ class BatchedMesh extends Mesh { // Local matrix per geometry by using data texture this._matricesTexture = null; - this.frustumCulled = false; - this.perObjectFrustumCulled = true; - this._initMatricesTexture(); } @@ -706,12 +705,20 @@ class BatchedMesh extends Mesh { super.copy( source ); this.geometry = source.geometry.clone(); + this.perObjectFrustumCulled = source.perObjectFrustumCulled; this._drawRanges = source._drawRanges.map( range => ( { ...range } ) ); this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) ); this._visible = source._visible.slice(); this._active = source._active.slice(); + this._bounds = source._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + box: bound.box.clone(), + + sphereInitialized: bound.sphereInitialized, + sphere: bound.sphere.clone() + } ) ); this._maxGeometryCount = source._maxGeometryCount; this._maxVertexCount = source._maxVertexCount; From 104f5850de9655e3d6b3f6dc65e9830e8ba64871 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 7 Nov 2023 19:06:41 +0900 Subject: [PATCH 07/11] Update toJSON --- src/core/Object3D.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 832984eb87d02b..3fed6f8f447256 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -722,11 +722,20 @@ class Object3D extends EventDispatcher { if ( this.isBatchedMesh ) { object.type = 'BatchedMesh'; + object.perObjectFrustumCulled = this.perObjectFrustumCulled; + object.drawRanges = this._drawRanges; object.reservedRanges = this._reservedRanges; object.visible = this._visible; object.active = this._active; + object.bounds = this._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + box: bound.box.toJSON(), + + sphereInitialized: bound.sphereInitialized, + sphere: bound.sphere.toJSON() + } ) ); object.maxGeometryCount = this._maxGeometryCount; object.maxVertexCount = this._maxVertexCount; From 32f84d57082c9bc6a79466eb3a9f3c490de6cf47 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 7 Nov 2023 19:41:44 +0900 Subject: [PATCH 08/11] Fix serialization --- src/core/Object3D.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 3fed6f8f447256..69e00850d31f4f 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -731,10 +731,12 @@ class Object3D extends EventDispatcher { object.active = this._active; object.bounds = this._bounds.map( bound => ( { boxInitialized: bound.boxInitialized, - box: bound.box.toJSON(), + boxMin: bound.box.min.toArray(), + boxMax: bound.box.max.toArray(), sphereInitialized: bound.sphereInitialized, - sphere: bound.sphere.toJSON() + sphereRadius: bound.sphere.radius, + sphereCenter: bound.sphere.center.toArray() } ) ); object.maxGeometryCount = this._maxGeometryCount; From 26dd0a848612b261baae6831366e4a21c4de65ce Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 6 Nov 2023 19:56:11 +0900 Subject: [PATCH 09/11] BatchedMesh: Add raycast support --- examples/jsm/objects/BatchedMesh.js | 59 ++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index 699e777bdf1329..c49e18f2c15d80 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -29,6 +29,8 @@ const _frustum = new Frustum(); const _box = new Box3(); const _sphere = new Sphere(); const _vector = new Vector3(); +const _mesh = new Mesh(); +const _batchIntersects = []; // @TODO: SkinnedMesh support? // @TODO: Future work if needed. Move into the core. Can be optimized more with WEBGL_multi_draw. @@ -694,9 +696,62 @@ class BatchedMesh extends Mesh { } - raycast() { - console.warn( 'BatchedMesh: Raycast function not implemented.' ); + raycast( raycaster, intersects ) { + + const visible = this._visible; + const active = this._active; + const geometryCount = this._geometryCount; + const matrixWorld = this.matrixWorld; + const batchGeometry = this.geometry; + + // iterate over each geometry + _mesh.material = this.material; + _mesh.geometry.index = batchGeometry.index; + _mesh.geometry.attributes = batchGeometry.attributes; + if ( _mesh.geometry.boundingBox === null ) { + + _mesh.geometry.boundingBox = new Box3(); + + } + + if ( _mesh.geometry.boundingSphere === null ) { + + _mesh.geometry.boundingSphere = new Sphere(); + + } + + for ( let i = 0; i < geometryCount; i ++ ) { + + if ( ! visible[ i ] || ! active[ i ] ) { + + continue; + + } + + // ge the intersects + this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld ); + this.getBoundingBoxAt( i, _mesh.geometry.boundingBox ); + this.getBoundingSphereAt( i, _mesh.geometry.boundingSphere ); + _mesh.raycast( raycaster, _batchIntersects ); + + // add batch id to the intersects + for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) { + + const intersect = _batchIntersects[ j ]; + intersect.object = this; + intersect.batchId = i; + intersects.push( intersect ); + + } + + _batchIntersects.length = 0; + + } + + _mesh.material = null; + _mesh.geometry.index = null; + _mesh.geometry.attributes = {}; } From a376a613bafe8e4198781bde8400c880203a5306 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 6 Nov 2023 20:14:52 +0900 Subject: [PATCH 10/11] Remove empty line --- examples/jsm/objects/BatchedMesh.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index c49e18f2c15d80..bcd4235ad36b82 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -696,7 +696,6 @@ class BatchedMesh extends Mesh { } - raycast( raycaster, intersects ) { const visible = this._visible; From c39ce0a80c04279b30d2950c75adbd2706ef7dc0 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Wed, 8 Nov 2023 12:52:52 +0900 Subject: [PATCH 11/11] Add draw range support --- examples/jsm/objects/BatchedMesh.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/jsm/objects/BatchedMesh.js b/examples/jsm/objects/BatchedMesh.js index bcd4235ad36b82..ad002e53a96cf3 100644 --- a/examples/jsm/objects/BatchedMesh.js +++ b/examples/jsm/objects/BatchedMesh.js @@ -700,6 +700,7 @@ class BatchedMesh extends Mesh { const visible = this._visible; const active = this._active; + const drawRanges = this._drawRanges; const geometryCount = this._geometryCount; const matrixWorld = this.matrixWorld; const batchGeometry = this.geometry; @@ -728,6 +729,9 @@ class BatchedMesh extends Mesh { } + const drawRange = drawRanges[ i ]; + _mesh.geometry.setDrawRange( drawRange.start, drawRange.count ); + // ge the intersects this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld ); this.getBoundingBoxAt( i, _mesh.geometry.boundingBox ); @@ -751,6 +755,7 @@ class BatchedMesh extends Mesh { _mesh.material = null; _mesh.geometry.index = null; _mesh.geometry.attributes = {}; + _mesh.geometry.setDrawRange( 0, Infinity ); }