diff --git a/docs/api/en/math/Box3.html b/docs/api/en/math/Box3.html index 800b1325b04a3d..ce28e0e604a58e 100644 --- a/docs/api/en/math/Box3.html +++ b/docs/api/en/math/Box3.html @@ -121,13 +121,14 @@

[method:Boolean equals]( [param:Box3 box] )

Returns true if this box and [page:Box3 box] share the same lower and upper bounds.

-

[method:this expandByObject]( [param:Object3D object] )

+

[method:this expandByObject]( [param:Object3D object], [param:Boolean precise] )

- [page:Object3D object] - [page:Object3D] to expand the box by.

+ [page:Object3D object] - [page:Object3D] to expand the box by.
+ precise - (optional) expand the bounding box as little as necessary at the expense of more computation. Default is false.

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).

@@ -264,9 +265,10 @@

[method:this setFromCenterAndSize]( [param:Vector3 center], [param:Vector3 s in [page:Vector3 size]

-

[method:this setFromObject]( [param:Object3D object] )

+

[method:this setFromObject]( [param:Object3D object], [param:Boolean precise] )

- [page:Object3D object] - [page:Object3D] to compute the bounding box of.

+ [page:Object3D object] - [page:Object3D] to compute the bounding box of.
+ precise - (optional) compute the smallest world-axis-aligned bounding box at the expense of more computation. Default is false.

Computes the world-axis-aligned bounding box of an [page:Object3D] (including its children), accounting for the object's, and children's, world transforms. diff --git a/src/math/Box3.js b/src/math/Box3.js index 1a5e4ffd7f1254..31c7c15cfa6be5 100644 --- a/src/math/Box3.js +++ b/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 @@ -199,16 +199,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 ); + + } } @@ -216,7 +230,7 @@ class Box3 { for ( let i = 0, l = children.length; i < l; i ++ ) { - this.expandByObject( children[ i ] ); + this.expandByObject( children[ i ], precise ); } diff --git a/test/unit/src/math/Box3.tests.js b/test/unit/src/math/Box3.tests.js index 4a659c17f5d4b2..e8d14985fb027a 100644 --- a/test/unit/src/math/Box3.tests.js +++ b/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() );