diff --git a/docs/api/en/objects/InstancedMesh.html b/docs/api/en/objects/InstancedMesh.html index 044b2cc7dc090b..ab3fa5eb5c60a0 100644 --- a/docs/api/en/objects/InstancedMesh.html +++ b/docs/api/en/objects/InstancedMesh.html @@ -37,6 +37,16 @@
See the base [page:Mesh] class for common properties.
++ This bounding box encloses all instances of the [name]. Can be calculated with [page:.computeBoundingBox](). Default is `null`. +
+ ++ This bounding sphere encloses all instances of the [name]. Can be calculated with [page:.computeBoundingSphere](). Default is `null`. +
+The number of instances. The `count` value passed into the constructor represents the maximum number of @@ -67,6 +77,18 @@
See the base [page:Mesh] class for common methods.
+
+ Computes the bounding box, updating [page:.boundingBox] attribute.
+ Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+
+ Computes the bounding sphere, updating [page:.boundingSphere] attribute.
+ Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+
Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. diff --git a/docs/api/it/objects/InstancedMesh.html b/docs/api/it/objects/InstancedMesh.html index 2b5bc774e6984e..82367c746a05da 100644 --- a/docs/api/it/objects/InstancedMesh.html +++ b/docs/api/it/objects/InstancedMesh.html @@ -38,6 +38,16 @@
Vedi la classe base [page:Mesh] per le proprietà comuni.
++ Bounding box per la [name], che può essere calcolato con [page:.computeBoundingBox](). Il valore predefinito è `null`. +
+ ++ Bounding sphere per la [name], che può essere calcolato con [page:.computeBoundingSphere](). Il valore predefinito è `null`. +
+Il numero di istanze. Il valore `count` passato nel costruttore rappresenta il numero @@ -70,6 +80,20 @@
Vedi la classe base [page:Mesh] per i metodi comuni.
+
+ Calcola il bounding box, aggiornando l'attributo [page:.boundingBox].
+ I Bounding box non sono calcolati per impostazione predefinita. Devono essere calcolati esplicitamente,
+ altrimenti sono `null`.
+
+ Calcola il bounding sphere, aggiornando l'attributo [page:.boundingSphere].
+ I Bounding sphere non sono calcolati per impostazione predefinita. Devono essere calcolati esplicitamente,
+ altrimenti sono `null`.
+
Libera le risorse relative alla GPU allocate da questa istanza. diff --git a/docs/api/zh/objects/InstancedMesh.html b/docs/api/zh/objects/InstancedMesh.html index da3ccaf99fa3bc..83ea9ce4fae6aa 100644 --- a/docs/api/zh/objects/InstancedMesh.html +++ b/docs/api/zh/objects/InstancedMesh.html @@ -36,6 +36,16 @@
See the base [page:Mesh] class for common properties.
++ 当前 [name] 的外边界矩形。可以通过 [page:.computeBoundingBox]() 计算。默认值是 *null*。 +
+ ++ 当前 [name] 的外边界球形。可以通过 [page:.computeBoundingSphere]() 计算。默认值是 *null*。 +
+实例的数量。被传入到构造函数中的*count*表示mesh实例数量的最大值。 @@ -66,6 +76,18 @@
See the base [page:Mesh] class for common methods.
+
+ 计算当前几何体的的边界矩形,该操作会更新已有 [param:.boundingBox]。
+ 边界矩形不会默认计算,需要调用该接口指定计算边界矩形,否则保持默认值 *null*。
+
+ 计算当前几何体的的边界球形,该操作会更新已有 [param:.boundingSphere]。
+ 边界球形不会默认计算,需要调用该接口指定计算边界球形,否则保持默认值 *null*。
+
Frees the internal resources of this instance. diff --git a/examples/jsm/modifiers/CurveModifier.js b/examples/jsm/modifiers/CurveModifier.js index 8a10796d9013f3..fc3f49c2761c87 100644 --- a/examples/jsm/modifiers/CurveModifier.js +++ b/examples/jsm/modifiers/CurveModifier.js @@ -270,6 +270,7 @@ export class InstancedFlow extends Flow { count ); mesh.instanceMatrix.setUsage( DynamicDrawUsage ); + mesh.frustumCulled = false; super( mesh, curveCount ); this.offsets = new Array( count ).fill( 0 ); diff --git a/examples/jsm/physics/AmmoPhysics.js b/examples/jsm/physics/AmmoPhysics.js index 20e129f5c6566b..637c5ca7fd89d6 100644 --- a/examples/jsm/physics/AmmoPhysics.js +++ b/examples/jsm/physics/AmmoPhysics.js @@ -222,6 +222,7 @@ async function AmmoPhysics() { } mesh.instanceMatrix.needsUpdate = true; + mesh.computeBoundingSphere(); } else if ( mesh.isMesh ) { diff --git a/examples/jsm/physics/OimoPhysics.js b/examples/jsm/physics/OimoPhysics.js index a13cd281f8411b..b874f3089fbad1 100644 --- a/examples/jsm/physics/OimoPhysics.js +++ b/examples/jsm/physics/OimoPhysics.js @@ -172,6 +172,7 @@ async function OimoPhysics() { } mesh.instanceMatrix.needsUpdate = true; + mesh.computeBoundingSphere(); } else if ( mesh.isMesh ) { diff --git a/examples/webgl_buffergeometry_instancing_interleaved.html b/examples/webgl_buffergeometry_instancing_interleaved.html index 56c9bc4b802086..dde75d1dcf57c6 100644 --- a/examples/webgl_buffergeometry_instancing_interleaved.html +++ b/examples/webgl_buffergeometry_instancing_interleaved.html @@ -221,6 +221,7 @@ } mesh.instanceMatrix.needsUpdate = true; + mesh.computeBoundingSphere(); lastTime = time; diff --git a/examples/webgl_instancing_dynamic.html b/examples/webgl_instancing_dynamic.html index 7c3e5b6ab0ea66..7b13c7eb8217aa 100644 --- a/examples/webgl_instancing_dynamic.html +++ b/examples/webgl_instancing_dynamic.html @@ -139,6 +139,7 @@ } mesh.instanceMatrix.needsUpdate = true; + mesh.computeBoundingSphere(); } diff --git a/examples/webgl_instancing_scatter.html b/examples/webgl_instancing_scatter.html index 5f958e150b9dde..37881b74b4d416 100644 --- a/examples/webgl_instancing_scatter.html +++ b/examples/webgl_instancing_scatter.html @@ -310,6 +310,9 @@ stemMesh.instanceMatrix.needsUpdate = true; blossomMesh.instanceMatrix.needsUpdate = true; + stemMesh.computeBoundingSphere(); + blossomMesh.computeBoundingSphere(); + } renderer.render( scene, camera ); diff --git a/src/math/Box3.js b/src/math/Box3.js index 5ece865ee5b465..44863617391d43 100644 --- a/src/math/Box3.js +++ b/src/math/Box3.js @@ -159,32 +159,49 @@ class Box3 { object.updateWorldMatrix( false, false ); - const geometry = object.geometry; + if ( object.boundingBox !== undefined ) { - if ( geometry !== undefined ) { + if ( object.boundingBox === null ) { - if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) { + object.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 ); + _box.copy( object.boundingBox ); + _box.applyMatrix4( object.matrixWorld ); - } + this.union( _box ); - } else { + } else { - if ( geometry.boundingBox === null ) { + const geometry = object.geometry; - geometry.computeBoundingBox(); + if ( geometry !== undefined ) { - } + if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) { + + 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 ); + + } - _box.copy( geometry.boundingBox ); - _box.applyMatrix4( object.matrixWorld ); + } else { - this.union( _box ); + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + _box.copy( geometry.boundingBox ); + _box.applyMatrix4( object.matrixWorld ); + + this.union( _box ); + + } } diff --git a/src/math/Frustum.js b/src/math/Frustum.js index fc6b928a31ff5b..03ab34a309f7f4 100644 --- a/src/math/Frustum.js +++ b/src/math/Frustum.js @@ -64,11 +64,21 @@ class Frustum { intersectsObject( object ) { - const geometry = object.geometry; + if ( object.boundingSphere !== undefined ) { - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + if ( object.boundingSphere === null ) object.computeBoundingSphere(); - _sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + _sphere.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } else { + + const geometry = object.geometry; + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } return this.intersectsSphere( _sphere ); diff --git a/src/objects/InstancedMesh.js b/src/objects/InstancedMesh.js index e1c842bc633b0c..5cf45f4fb8bf36 100644 --- a/src/objects/InstancedMesh.js +++ b/src/objects/InstancedMesh.js @@ -1,14 +1,18 @@ import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js'; import { Mesh } from './Mesh.js'; +import { Box3 } from '../math/Box3.js'; import { Matrix4 } from '../math/Matrix4.js'; +import { Sphere } from '../math/Sphere.js'; const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); const _instanceIntersects = []; +const _box3 = /*@__PURE__*/ new Box3(); const _identity = /*@__PURE__*/ new Matrix4(); const _mesh = /*@__PURE__*/ new Mesh(); +const _sphere = /*@__PURE__*/ new Sphere(); class InstancedMesh extends Mesh { @@ -23,7 +27,8 @@ class InstancedMesh extends Mesh { this.count = count; - this.frustumCulled = false; + this.boundingBox = null; + this.boundingSphere = null; for ( let i = 0; i < count; i ++ ) { @@ -33,6 +38,68 @@ class InstancedMesh extends Mesh { } + computeBoundingBox() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + this.boundingBox.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingBox.union( _box3 ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + this.boundingSphere.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _sphere.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingSphere.union( _sphere ); + + } + + } + copy( source, recursive ) { super.copy( source, recursive );