Skip to content

Commit 6b6da56

Browse files
authored
SkinnedMesh: Add bounding volumes. (#25612)
* SkinnedMesh: Add bounding volumes. * Docs: Update SkinnedMesh pages. * Examples: Clean up.
1 parent d879635 commit 6b6da56

File tree

5 files changed

+131
-16
lines changed

5 files changed

+131
-16
lines changed

docs/api/en/objects/SkinnedMesh.html

+24
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ <h3>[property:Matrix4 bindMatrixInverse]</h3>
116116
The base matrix that is used for resetting the bound bone transforms.
117117
</p>
118118

119+
<h3>[property:Box3 boundingBox]</h3>
120+
<p>
121+
The bounding box of the [name]. Can be calculated with [page:.computeBoundingBox](). Default is `null`.
122+
</p>
123+
124+
<h3>[property:Sphere boundingSphere]</h3>
125+
<p>
126+
The bounding sphere of the [name]. Can be calculated with [page:.computeBoundingSphere](). Default is `null`.
127+
</p>
128+
119129
<h3>[property:Boolean isSkinnedMesh]</h3>
120130
<p>
121131
Read-only flag to check if a given object is of type [name].
@@ -145,6 +155,20 @@ <h3>[method:SkinnedMesh clone]()</h3>
145155
This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.
146156
</p>
147157

158+
<h3>[method:undefined computeBoundingBox]()</h3>
159+
<p>
160+
Computes the bounding box, updating [page:.boundingBox] attribute.<br />
161+
Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
162+
If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box.
163+
</p>
164+
165+
<h3>[method:undefined computeBoundingSphere]()</h3>
166+
<p>
167+
Computes the bounding sphere, updating [page:.boundingSphere] attribute.<br />
168+
Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
169+
If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere.
170+
</p>
171+
148172
<h3>[method:undefined normalizeSkinWeights]()</h3>
149173
<p>
150174
Normalizes the skin weights.

docs/api/it/objects/SkinnedMesh.html

+24
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,16 @@ <h3>[property:Matrix4 bindMatrixInverse]</h3>
117117
La matrice di base che viene utilizzata per reimpostare le trasformazioni ossee vincolate.
118118
</p>
119119

120+
<h3>[property:Box3 boundingBox]</h3>
121+
<p>
122+
Bounding box per la [name], che può essere calcolato con [page:.computeBoundingBox](). Il valore predefinito è `null`.
123+
</p>
124+
125+
<h3>[property:Sphere boundingSphere]</h3>
126+
<p>
127+
Bounding sphere per la [name], che può essere calcolato con [page:.computeBoundingSphere](). Il valore predefinito è `null`.
128+
</p>
129+
120130
<h3>[property:Boolean isSkinnedMesh]</h3>
121131
<p>
122132
Flag di sola lettura per verificare se l'oggetto dato è di tipo [name].
@@ -144,6 +154,20 @@ <h3>[method:SkinnedMesh clone]()</h3>
144154
Questo metodo attualmente non clona correttamente un'istanza di [name]. Si prega di utilizzare [page:SkeletonUtils.clone]() nel frattempo.
145155
</p>
146156

157+
<h3>[method:undefined computeBoundingBox]()</h3>
158+
<p>
159+
Computes the bounding box, updating [page:.boundingBox] attribute.<br />
160+
Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
161+
If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box.
162+
</p>
163+
164+
<h3>[method:undefined computeBoundingSphere]()</h3>
165+
<p>
166+
Computes the bounding sphere, updating [page:.boundingSphere] attribute.<br />
167+
Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
168+
If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere.
169+
</p>
170+
147171
<h3>[method:undefined normalizeSkinWeights]()</h3>
148172
<p>
149173
Normalizza i pesi della skin.

docs/api/zh/objects/SkinnedMesh.html

+29-6
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ <h3>[name]( [param:BufferGeometry geometry], [param:Material material] )</h3>
9595
[page:Material material] —— (可选)一个[page:Material]实例,默认值是一个新的[page:MeshBasicMaterial]。
9696
</p>
9797

98-
99-
100-
101-
10298
<h2>属性</h2>
10399
<p>共有属性请参见其基类[page:Mesh]。</p>
104100

@@ -119,6 +115,16 @@ <h3>[property:Matrix4 bindMatrixInverse]</h3>
119115
该基础矩阵用于重置绑定骨骼的变换。
120116
</p>
121117

118+
<h3>[property:Box3 boundingBox]</h3>
119+
<p>
120+
The bounding box of the [name]. Can be calculated with [page:.computeBoundingBox](). Default is `null`.
121+
</p>
122+
123+
<h3>[property:Sphere boundingSphere]</h3>
124+
<p>
125+
The bounding sphere of the [name]. Can be calculated with [page:.computeBoundingSphere](). Default is `null`.
126+
</p>
127+
122128
<h3>[property:Boolean isSkinnedMesh]</h3>
123129
<p>
124130
Read-only flag to check if a given object is of type [name].
@@ -129,11 +135,14 @@ <h3>[property:Skeleton skeleton]</h3>
129135
用于表示蒙皮网格中骨骼的层次结构的[page:Skeleton](骨架)。
130136
</p>
131137

132-
133-
134138
<h2>方法</h2>
135139
<p>共有方法请参见其基类[page:Mesh]。</p>
136140

141+
<h3>[method:Vector3 applyBoneTransform]( [param:Integer index], [param:Vector3 vector] )</h3>
142+
<p>
143+
Applies the bone transform associated with the given index to the given position vector. Returns the updated vector.
144+
</p>
145+
137146
<h3>[method:undefined bind]( [param:Skeleton skeleton], [param:Matrix4 bindMatrix] )</h3>
138147
<p>
139148
[page:Skeleton skeleton] —— 由一棵[page:Bone Bones]树创建的[page:Skeleton]。<br/>
@@ -146,6 +155,20 @@ <h3>[method:SkinnedMesh clone]()</h3>
146155
This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.
147156
</p>
148157

158+
<h3>[method:undefined computeBoundingBox]()</h3>
159+
<p>
160+
Computes the bounding box, updating [page:.boundingBox] attribute.<br />
161+
Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
162+
If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box.
163+
</p>
164+
165+
<h3>[method:undefined computeBoundingSphere]()</h3>
166+
<p>
167+
Computes the bounding sphere, updating [page:.boundingSphere] attribute.<br />
168+
Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`.
169+
If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere.
170+
</p>
171+
149172
<h3>[method:undefined normalizeSkinWeights]()</h3>
150173
<p>
151174
标准化蒙皮的权重。

examples/webgl_loader_collada_skinning.html

-10
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,6 @@
6161
const avatar = collada.scene;
6262
const animations = avatar.animations;
6363

64-
avatar.traverse( function ( node ) {
65-
66-
if ( node.isSkinnedMesh ) {
67-
68-
node.frustumCulled = false;
69-
70-
}
71-
72-
} );
73-
7464
mixer = new THREE.AnimationMixer( avatar );
7565
mixer.clipAction( animations[ 0 ] ).play();
7666

src/objects/SkinnedMesh.js

+54
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Mesh } from './Mesh.js';
2+
import { Box3 } from '../math/Box3.js';
23
import { Matrix4 } from '../math/Matrix4.js';
4+
import { Sphere } from '../math/Sphere.js';
35
import { Vector3 } from '../math/Vector3.js';
46
import { Vector4 } from '../math/Vector4.js';
57

@@ -10,6 +12,7 @@ const _skinWeight = /*@__PURE__*/ new Vector4();
1012

1113
const _vector3 = /*@__PURE__*/ new Vector3();
1214
const _matrix4 = /*@__PURE__*/ new Matrix4();
15+
const _vertex = /*@__PURE__*/ new Vector3();
1316

1417
class SkinnedMesh extends Mesh {
1518

@@ -25,6 +28,57 @@ class SkinnedMesh extends Mesh {
2528
this.bindMatrix = new Matrix4();
2629
this.bindMatrixInverse = new Matrix4();
2730

31+
this.boundingBox = null;
32+
this.boundingSphere = null;
33+
34+
}
35+
36+
computeBoundingBox() {
37+
38+
const geometry = this.geometry;
39+
40+
if ( this.boundingBox === null ) {
41+
42+
this.boundingBox = new Box3();
43+
44+
}
45+
46+
this.boundingBox.makeEmpty();
47+
48+
const positionAttribute = geometry.getAttribute( 'position' );
49+
50+
for ( let i = 0; i < positionAttribute.count; i ++ ) {
51+
52+
_vertex.fromBufferAttribute( positionAttribute, i );
53+
this.applyBoneTransform( i, _vertex );
54+
this.boundingBox.expandByPoint( _vertex );
55+
56+
}
57+
58+
}
59+
60+
computeBoundingSphere() {
61+
62+
const geometry = this.geometry;
63+
64+
if ( this.boundingSphere === null ) {
65+
66+
this.boundingSphere = new Sphere();
67+
68+
}
69+
70+
this.boundingSphere.makeEmpty();
71+
72+
const positionAttribute = geometry.getAttribute( 'position' );
73+
74+
for ( let i = 0; i < positionAttribute.count; i ++ ) {
75+
76+
_vertex.fromBufferAttribute( positionAttribute, i );
77+
this.applyBoneTransform( i, _vertex );
78+
this.boundingSphere.expandByPoint( _vertex );
79+
80+
}
81+
2882
}
2983

3084
copy( source, recursive ) {

0 commit comments

Comments
 (0)