一段时间前,three.js论坛上曾经讨论过类似的话题。我在那里展示了一个计算蒙皮网格每帧AABB的代码片段。该代码实际上通过JavaScript执行了与顶点着色器中相同的顶点位移。该程序如下:
function updateAABB( skinnedMesh, aabb ) {
var skeleton = skinnedMesh.skeleton;
var boneMatrices = skeleton.boneMatrices;
var geometry = skinnedMesh.geometry;
var index = geometry.index;
var position = geometry.attributes.position;
var skinIndex = geometry.attributes.skinIndex;
var skinWeigth = geometry.attributes.skinWeight;
var bindMatrix = skinnedMesh.bindMatrix;
var bindMatrixInverse = skinnedMesh.bindMatrixInverse;
var i, j, si, sw;
aabb.makeEmpty();
if ( index !== null ) {
for ( i = 0; i < index.count; i ++ ) {
vertex.fromBufferAttribute( position, index[ i ] );
skinIndices.fromBufferAttribute( skinIndex, index[ i ] );
skinWeights.fromBufferAttribute( skinWeigth, index[ i ] );
vertex.applyMatrix4( bindMatrix );
skinned.set( 0, 0, 0 );
for ( j = 0; j < 4; j ++ ) {
si = skinIndices.getComponent( j );
sw = skinWeights.getComponent( j );
boneMatrix.fromArray( boneMatrices, si * 16 );
temp.copy( vertex ).applyMatrix4( boneMatrix ).multiplyScalar( sw );
skinned.add( temp );
}
skinned.applyMatrix4( bindMatrixInverse );
aabb.expandByPoint( skinned );
}
} else {
for ( i = 0; i < position.count; i ++ ) {
vertex.fromBufferAttribute( position, i );
skinIndices.fromBufferAttribute( skinIndex, i );
skinWeights.fromBufferAttribute( skinWeigth, i );
vertex.applyMatrix4( bindMatrix );
skinned.set( 0, 0, 0 );
for ( j = 0; j < 4; j ++ ) {
si = skinIndices.getComponent( j );
sw = skinWeights.getComponent( j );
boneMatrix.fromArray( boneMatrices, si * 16 );
temp.copy( vertex ).applyMatrix4( boneMatrix ).multiplyScalar( sw );
skinned.add( temp );
}
skinned.applyMatrix4( bindMatrixInverse );
aabb.expandByPoint( skinned );
}
}
aabb.applyMatrix4( skinnedMesh.matrixWorld );
}
同时,对于morph目标,有人指出此代码已经存在于Mesh.raycast函数中。可以使用射线投射到形变的网格上,但不能对蒙皮网格进行射线投射。Mesh.raycast()中的代码已经非常复杂,我认为在进一步增强之前需要进行严格的重构。同时你可以使用提供的代码片段自行构建解决方案。顶点位移逻辑实际上是最复杂的部分。
实时演示:
https://jsfiddle.net/fnjkeg9x/1/
three.js R107