animation - three.js:使用骨骼动画获取更新的顶点?
问题描述
类似于此堆栈溢出问题Three.js: Get updated vertices with morph targets我对如何使用骨骼动画获取网格顶点的“实际”位置感兴趣。
我尝试打印出位置值,但它们实际上从未更新(据我所知,这是因为它们是在 GPU 上计算的,而不是在 CPU 上)。上面提到的问题的答案在 CPU 上与在 GPU 上进行相同的计算以获得变形目标动画的最新顶点位置,但是有没有办法对骨骼动画执行相同的方法?如果是这样,怎么办??
此外,对于变形目标,有人指出此代码已经存在于 Mesh.raycast 函数中(https://github.com/mrdoob/three.js/blob/master/src/objects/Mesh.js#L115)。但是,我看不到光线投射如何与骨骼动画网格一起工作——它如何知道面部的更新位置?
谢谢!
解决方案
前段时间在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 ) {
// indexed geometry
for ( i = 0; i < index.count; i ++ ) {
vertex.fromBufferAttribute( position, index[ i ] );
skinIndices.fromBufferAttribute( skinIndex, index[ i ] );
skinWeights.fromBufferAttribute( skinWeigth, index[ i ] );
// the following code section is normally implemented in the vertex shader
vertex.applyMatrix4( bindMatrix ); // transform to bind space
skinned.set( 0, 0, 0 );
for ( j = 0; j < 4; j ++ ) {
si = skinIndices.getComponent( j );
sw = skinWeights.getComponent( j );
boneMatrix.fromArray( boneMatrices, si * 16 );
// weighted vertex transformation
temp.copy( vertex ).applyMatrix4( boneMatrix ).multiplyScalar( sw );
skinned.add( temp );
}
skinned.applyMatrix4( bindMatrixInverse ); // back to local space
// expand aabb
aabb.expandByPoint( skinned );
}
} else {
// non-indexed geometry
for ( i = 0; i < position.count; i ++ ) {
vertex.fromBufferAttribute( position, i );
skinIndices.fromBufferAttribute( skinIndex, i );
skinWeights.fromBufferAttribute( skinWeigth, i );
// the following code section is normally implemented in the vertex shader
vertex.applyMatrix4( bindMatrix ); // transform to bind space
skinned.set( 0, 0, 0 );
for ( j = 0; j < 4; j ++ ) {
si = skinIndices.getComponent( j );
sw = skinWeights.getComponent( j );
boneMatrix.fromArray( boneMatrices, si * 16 );
// weighted vertex transformation
temp.copy( vertex ).applyMatrix4( boneMatrix ).multiplyScalar( sw );
skinned.add( temp );
}
skinned.applyMatrix4( bindMatrixInverse ); // back to local space
// expand aabb
aabb.expandByPoint( skinned );
}
}
aabb.applyMatrix4( skinnedMesh.matrixWorld );
}
此外,对于变形目标,有人指出此代码已经存在于 Mesh.raycast 函数中
是的,您可以针对变形网格进行光线投射。尚不支持针对蒙皮网格的光线投射。里面的代码Mesh.raycast()
已经很复杂了。我认为在进一步增强之前,它需要进行一些认真的重构。同时,您可以使用提供的代码片段自行构建解决方案。顶点位移逻辑实际上是最复杂的部分。
现场演示:https ://jsfiddle.net/fnjkeg9x/1/
three.js R107
推荐阅读
- javascript - 为什么 Javascript 不断更改我的数据?
- azure - 使用 powershell 更改 Azure SQL Server 的“允许访问 Azure 服务”设置
- php - Laravel 将 excel 文件导入数据库
- javascript - 如何从 Ionic 4 中的 Native Storage ZoneAwarePromise 获取价值
- swift - 从json字符串保存实体对象的问题-如何从可编码继承?
- php - 如何在 php 中修复“未选择的选择选项”
- powershell - 将字符串解析为日期时间格式
- linux - 仅返回匹配模式之后的行的一部分
- python-3.x - 无法在 Windows 上安装 pylibmc
- angular - 如何在 4/6/7 角完成的所有 HTTP 请求上隐藏加载程序?