Browse Source

BatchedMesh: Add object-level bounds (#27145)

* BatchedMeh: add support for frustum culling batched elements

* comments

* Update frustum culling support

* BatchedMesh: add "perObjectFrustumCulled"

* Reduce the number of world matrix transform applications for frustum culling

* Update copy function

* Update toJSON

* Fix serialization

* BatchedMesh: Add object-level bounds

* Disable frustum culling in the batched mesh demo

* Add comment

* Add copy, toJSON support
Garrett Johnson 1 year ago
parent
commit
a8b8ce7231
3 changed files with 76 additions and 1 deletions
  1. 54 1
      examples/jsm/objects/BatchedMesh.js
  2. 4 0
      examples/webgl_mesh_batch.html
  3. 18 0
      src/core/Object3D.js

+ 54 - 1
examples/jsm/objects/BatchedMesh.js

@@ -75,7 +75,8 @@ class BatchedMesh extends Mesh {
 
 		this.isBatchedMesh = true;
 		this.perObjectFrustumCulled = true;
-		this.frustumCulled = false;
+		this.boundingBox = null;
+		this.boundingSphere = null;
 
 		this._drawRanges = [];
 		this._reservedRanges = [];
@@ -248,6 +249,56 @@ class BatchedMesh extends Mesh {
 
 	}
 
+	computeBoundingBox() {
+
+		if ( this.boundingBox === null ) {
+
+			this.boundingBox = new Box3();
+
+		}
+
+		const geometryCount = this._geometryCount;
+		const boundingBox = this.boundingBox;
+		const active = this._active;
+
+		boundingBox.makeEmpty();
+		for ( let i = 0; i < geometryCount; i ++ ) {
+
+			if ( active[ i ] === false ) continue;
+
+			this.getMatrixAt( i, _matrix );
+			this.getBoundingBoxAt( i, _box ).applyMatrix4( _matrix );
+			boundingBox.union( _box );
+
+		}
+
+	}
+
+	computeBoundingSphere() {
+
+		if ( this.boundingSphere === null ) {
+
+			this.boundingSphere = new Sphere();
+
+		}
+
+		const geometryCount = this._geometryCount;
+		const boundingSphere = this.boundingSphere;
+		const active = this._active;
+
+		boundingSphere.makeEmpty();
+		for ( let i = 0; i < geometryCount; i ++ ) {
+
+			if ( active[ i ] === false ) continue;
+
+			this.getMatrixAt( i, _matrix );
+			this.getBoundingSphereAt( i, _sphere ).applyMatrix4( _matrix );
+			boundingSphere.union( _sphere );
+
+		}
+
+	}
+
 	addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) {
 
 		this._initializeGeometry( geometry );
@@ -706,6 +757,8 @@ class BatchedMesh extends Mesh {
 
 		this.geometry = source.geometry.clone();
 		this.perObjectFrustumCulled = source.perObjectFrustumCulled;
+		this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
+		this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
 
 		this._drawRanges = source._drawRanges.map( range => ( { ...range } ) );
 		this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) );

+ 4 - 0
examples/webgl_mesh_batch.html

@@ -176,6 +176,10 @@
 			const matrix = new THREE.Matrix4();
 			mesh = new BatchedMesh( geometryCount, vertexCount, indexCount, createMaterial() );
 			mesh.userData.rotationSpeeds = [];
+
+			// disable full-object frustum culling since all of the objects can be dynamic.
+			mesh.frustumCulled = false;
+
 			ids.length = 0;
 
 			for ( let i = 0; i < api.count; i ++ ) {

+ 18 - 0
src/core/Object3D.js

@@ -748,6 +748,24 @@ class Object3D extends EventDispatcher {
 
 			object.matricesTexture = this._matricesTexture.toJSON();
 
+			if ( this.boundingSphere !== null ) {
+
+				object.boundingSphere = {
+					center: object.boundingSphere.center.toArray(),
+					radius: object.boundingSphere.radius
+				};
+
+			}
+
+			if ( this.boundingBox !== null ) {
+
+				object.boundingBox = {
+					min: object.boundingBox.min.toArray(),
+					max: object.boundingBox.max.toArray()
+				};
+
+			}
+
 		}
 
 		//