Kaynağa Gözat

Box3 now supports computing minimal bounds for setFromObject (#20024)

arikwex 3 yıl önce
ebeveyn
işleme
bd42765260
3 değiştirilmiş dosya ile 62 ekleme ve 17 silme
  1. 7 5
      docs/api/en/math/Box3.html
  2. 24 10
      src/math/Box3.js
  3. 31 2
      test/unit/src/math/Box3.tests.js

+ 7 - 5
docs/api/en/math/Box3.html

@@ -121,13 +121,14 @@
 		Returns true if this box and [page:Box3 box] share the same lower and upper bounds.
 		</p>
 
-		<h3>[method:this expandByObject]( [param:Object3D object] )</h3>
+		<h3>[method:this expandByObject]( [param:Object3D object], [param:Boolean precise] )</h3>
 		<p>
-		[page:Object3D object] - [page:Object3D] to expand the box by.<br /><br />
+		[page:Object3D object] - [page:Object3D] to expand the box by.<br />
+		precise - (optional) expand the bounding box as little as necessary at the expense of more computation. Default is false.<br /><br />
 
 		Expands the boundaries of this box to include [page:Object3D object] and its children,
 		accounting for the object's, and children's, world transforms.
-		The function may result in a larger box than strictly necessary.
+		The function may result in a larger box than strictly necessary (unless the precise parameter is set to true).
 
 		</p>
 
@@ -264,9 +265,10 @@
 		in [page:Vector3 size]
 		</p>
 
-		<h3>[method:this setFromObject]( [param:Object3D object] )</h3>
+		<h3>[method:this setFromObject]( [param:Object3D object], [param:Boolean precise] )</h3>
 		<p>
-		[page:Object3D object] - [page:Object3D] to compute the bounding box of.<br /><br />
+		[page:Object3D object] - [page:Object3D] to compute the bounding box of.<br />
+		precise - (optional) compute the smallest world-axis-aligned bounding box at the expense of more computation. Default is false.<br /><br />
 
 		Computes a world-axis-aligned bounding box of an [page:Object3D] (including its children),
 		accounting for the object's, and children's, world transforms.<br /><br />

+ 24 - 10
src/math/Box3.js

@@ -109,11 +109,11 @@ class Box3 {
 
 	}
 
-	setFromObject( object ) {
+	setFromObject( object, precise = false ) {
 
 		this.makeEmpty();
 
-		return this.expandByObject( object );
+		return this.expandByObject( object, precise );
 
 	}
 
@@ -188,7 +188,7 @@ class Box3 {
 
 	}
 
-	expandByObject( object ) {
+	expandByObject( object, precise = false ) {
 
 		// Computes the world-axis-aligned bounding box of an object (including its children),
 		// accounting for both the object's, and children's, world transforms.
@@ -201,16 +201,30 @@ class Box3 {
 
 		if ( geometry !== undefined ) {
 
-			if ( geometry.boundingBox === null ) {
+			if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) {
 
-				geometry.computeBoundingBox();
+				const position = geometry.attributes.position;
+				for ( let i = 0, l = position.count; i < l; i ++ ) {
 
-			}
+					_vector.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld );
+					this.expandByPoint( _vector );
+
+				}
+
+			} else {
+
+				if ( geometry.boundingBox === null ) {
 
-			_box.copy( geometry.boundingBox );
-			_box.applyMatrix4( object.matrixWorld );
+					geometry.computeBoundingBox();
 
-			this.union( _box );
+				}
+
+				_box.copy( geometry.boundingBox );
+				_box.applyMatrix4( object.matrixWorld );
+
+				this.union( _box );
+
+			}
 
 		}
 
@@ -218,7 +232,7 @@ class Box3 {
 
 		for ( let i = 0, l = children.length; i < l; i ++ ) {
 
-			this.expandByObject( children[ i ] );
+			this.expandByObject( children[ i ], precise );
 
 		}
 

+ 31 - 2
test/unit/src/math/Box3.tests.js

@@ -8,7 +8,13 @@ import { Vector3 } from '../../../../src/math/Vector3';
 import { Matrix4 } from '../../../../src/math/Matrix4';
 import { Mesh } from '../../../../src/objects/Mesh';
 import { BufferAttribute } from '../../../../src/core/BufferAttribute';
-import { BoxGeometry } from '../../../../src/geometries/BoxGeometry';
+import {
+	BoxGeometry,
+	BoxBufferGeometry,
+} from '../../../../src/geometries/BoxGeometry';
+import {
+	SphereBufferGeometry,
+} from '../../../../src/geometries/SphereGeometry';
 import {
 	negInf3,
 	posInf3,
@@ -165,8 +171,31 @@ export default QUnit.module( 'Maths', () => {
 
 		} );
 
-		QUnit.test( 'clone', ( assert ) => {
+		QUnit.test( 'setFromObject/Precise', ( assert ) => {
+
+			var a = new Box3( zero3.clone(), one3.clone() );
+			var object = new Mesh( new SphereBufferGeometry( 1, 32, 32 ) );
+			var child = new Mesh( new SphereBufferGeometry( 2, 32, 32 ) );
+			object.add( child );
 
+			object.rotation.setFromVector3(new Vector3(0, 0, Math.PI / 4.0));
+
+			a.setFromObject( object );
+			var rotatedBox = new Box3(
+				new Vector3( - 2 * Math.SQRT2, - 2 * Math.SQRT2, - 2 ),
+				new Vector3( 2 * Math.SQRT2, 2 * Math.SQRT2, 2 )
+			);
+			assert.ok( compareBox( a, rotatedBox ), "Passed!" );
+
+			a.setFromObject( object, true );
+			var rotatedMinBox = new Box3(
+				new Vector3( - 2, - 2, - 2 ),
+				new Vector3( 2, 2, 2 )
+			);
+			assert.ok( compareBox( a, rotatedMinBox ), "Passed!" );
+		} );
+
+		QUnit.test( 'clone', ( assert ) => {
 
 			var a = new Box3( zero3.clone(), one3.clone() );