Browse Source

SkinnedMesh: Add bounding volumes. (#25612)

* SkinnedMesh: Add bounding volumes.

* Docs: Update SkinnedMesh pages.

* Examples: Clean up.
Michael Herzog 2 years ago
parent
commit
6b6da56612

+ 24 - 0
docs/api/en/objects/SkinnedMesh.html

@@ -116,6 +116,16 @@
 		The base matrix that is used for resetting the bound bone transforms.
 		</p>
 
+		<h3>[property:Box3 boundingBox]</h3>
+		<p>
+			The bounding box of the [name]. Can be calculated with [page:.computeBoundingBox](). Default is `null`.
+		</p>
+
+		<h3>[property:Sphere boundingSphere]</h3>
+		<p>
+			The bounding sphere of the [name]. Can be calculated with [page:.computeBoundingSphere](). Default is `null`.
+		</p>
+
 		<h3>[property:Boolean isSkinnedMesh]</h3>
 		<p>
 			Read-only flag to check if a given object is of type [name].
@@ -145,6 +155,20 @@
 		This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.
 		</p>
 
+		<h3>[method:undefined computeBoundingBox]()</h3>
+		<p>
+		Computes the bounding box, updating [page:.boundingBox] attribute.<br />
+		Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+		If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box.
+		</p>
+
+		<h3>[method:undefined computeBoundingSphere]()</h3>
+		<p>
+		Computes the bounding sphere, updating [page:.boundingSphere] attribute.<br />
+		Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+		If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere.
+		</p>
+
 		<h3>[method:undefined normalizeSkinWeights]()</h3>
 		<p>
 		Normalizes the skin weights.

+ 24 - 0
docs/api/it/objects/SkinnedMesh.html

@@ -117,6 +117,16 @@
 			La matrice di base che viene utilizzata per reimpostare le trasformazioni ossee vincolate.
 		</p>
 
+		<h3>[property:Box3 boundingBox]</h3>
+		<p>
+			Bounding box per la [name], che può essere calcolato con [page:.computeBoundingBox](). Il valore predefinito è `null`.
+		</p>
+
+		<h3>[property:Sphere boundingSphere]</h3>
+		<p>
+			Bounding sphere per la [name], che può essere calcolato con [page:.computeBoundingSphere](). Il valore predefinito è `null`.
+		</p>
+
 		<h3>[property:Boolean isSkinnedMesh]</h3>
 		<p>
 			Flag di sola lettura per verificare se l'oggetto dato è di tipo [name].
@@ -144,6 +154,20 @@
 			Questo metodo attualmente non clona correttamente un'istanza di [name]. Si prega di utilizzare [page:SkeletonUtils.clone]() nel frattempo.
 		</p>
 
+		<h3>[method:undefined computeBoundingBox]()</h3>
+		<p>
+		Computes the bounding box, updating [page:.boundingBox] attribute.<br />
+		Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+		If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box.
+		</p>
+
+		<h3>[method:undefined computeBoundingSphere]()</h3>
+		<p>
+		Computes the bounding sphere, updating [page:.boundingSphere] attribute.<br />
+		Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+		If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere.
+		</p>
+
 		<h3>[method:undefined normalizeSkinWeights]()</h3>
 		<p>
 			Normalizza i pesi della skin.

+ 29 - 6
docs/api/zh/objects/SkinnedMesh.html

@@ -95,10 +95,6 @@
 	[page:Material material] —— (可选)一个[page:Material]实例,默认值是一个新的[page:MeshBasicMaterial]。
 		</p>
 
-
-
-
-
 		<h2>属性</h2>
 		<p>共有属性请参见其基类[page:Mesh]。</p>
 
@@ -119,6 +115,16 @@
 			该基础矩阵用于重置绑定骨骼的变换。
 		</p>
 
+		<h3>[property:Box3 boundingBox]</h3>
+		<p>
+			The bounding box of the [name]. Can be calculated with [page:.computeBoundingBox](). Default is `null`.
+		</p>
+
+		<h3>[property:Sphere boundingSphere]</h3>
+		<p>
+			The bounding sphere of the [name]. Can be calculated with [page:.computeBoundingSphere](). Default is `null`.
+		</p>
+
 		<h3>[property:Boolean isSkinnedMesh]</h3>
 		<p>
 			Read-only flag to check if a given object is of type [name].
@@ -129,11 +135,14 @@
 			用于表示蒙皮网格中骨骼的层次结构的[page:Skeleton](骨架)。
 		</p>
 
-
-
 		<h2>方法</h2>
 		<p>共有方法请参见其基类[page:Mesh]。</p>
 
+		<h3>[method:Vector3 applyBoneTransform]( [param:Integer index], [param:Vector3 vector] )</h3>
+		<p>
+		Applies the bone transform associated with the given index to the given position vector. Returns the updated vector.
+		</p>
+
 		<h3>[method:undefined bind]( [param:Skeleton skeleton], [param:Matrix4 bindMatrix] )</h3>
 		<p>
 		[page:Skeleton skeleton] —— 由一棵[page:Bone Bones]树创建的[page:Skeleton]。<br/>
@@ -146,6 +155,20 @@
 		This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.
 		</p>
 
+		<h3>[method:undefined computeBoundingBox]()</h3>
+		<p>
+		Computes the bounding box, updating [page:.boundingBox] attribute.<br />
+		Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+		If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box.
+		</p>
+
+		<h3>[method:undefined computeBoundingSphere]()</h3>
+		<p>
+		Computes the bounding sphere, updating [page:.boundingSphere] attribute.<br />
+		Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
+		If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere.
+		</p>
+
 		<h3>[method:undefined normalizeSkinWeights]()</h3>
 		<p>
 		标准化蒙皮的权重。

+ 0 - 10
examples/webgl_loader_collada_skinning.html

@@ -61,16 +61,6 @@
 					const avatar = collada.scene;
 					const animations = avatar.animations;
 
-					avatar.traverse( function ( node ) {
-
-						if ( node.isSkinnedMesh ) {
-
-							node.frustumCulled = false;
-
-						}
-
-					} );
-
 					mixer = new THREE.AnimationMixer( avatar );
 					mixer.clipAction( animations[ 0 ] ).play();
 

+ 54 - 0
src/objects/SkinnedMesh.js

@@ -1,5 +1,7 @@
 import { Mesh } from './Mesh.js';
+import { Box3 } from '../math/Box3.js';
 import { Matrix4 } from '../math/Matrix4.js';
+import { Sphere } from '../math/Sphere.js';
 import { Vector3 } from '../math/Vector3.js';
 import { Vector4 } from '../math/Vector4.js';
 
@@ -10,6 +12,7 @@ const _skinWeight = /*@__PURE__*/ new Vector4();
 
 const _vector3 = /*@__PURE__*/ new Vector3();
 const _matrix4 = /*@__PURE__*/ new Matrix4();
+const _vertex = /*@__PURE__*/ new Vector3();
 
 class SkinnedMesh extends Mesh {
 
@@ -25,6 +28,57 @@ class SkinnedMesh extends Mesh {
 		this.bindMatrix = new Matrix4();
 		this.bindMatrixInverse = new Matrix4();
 
+		this.boundingBox = null;
+		this.boundingSphere = null;
+
+	}
+
+	computeBoundingBox() {
+
+		const geometry = this.geometry;
+
+		if ( this.boundingBox === null ) {
+
+			this.boundingBox = new Box3();
+
+		}
+
+		this.boundingBox.makeEmpty();
+
+		const positionAttribute = geometry.getAttribute( 'position' );
+
+		for ( let i = 0; i < positionAttribute.count; i ++ ) {
+
+			_vertex.fromBufferAttribute( positionAttribute, i );
+			this.applyBoneTransform( i, _vertex );
+			this.boundingBox.expandByPoint( _vertex );
+
+		}
+
+	}
+
+	computeBoundingSphere() {
+
+		const geometry = this.geometry;
+
+		if ( this.boundingSphere === null ) {
+
+			this.boundingSphere = new Sphere();
+
+		}
+
+		this.boundingSphere.makeEmpty();
+
+		const positionAttribute = geometry.getAttribute( 'position' );
+
+		for ( let i = 0; i < positionAttribute.count; i ++ ) {
+
+			_vertex.fromBufferAttribute( positionAttribute, i );
+			this.applyBoneTransform( i, _vertex );
+			this.boundingSphere.expandByPoint( _vertex );
+
+		}
+
 	}
 
 	copy( source, recursive ) {