3

アニメーションが進行中の Three.js プロジェクトがあり、さまざまな時点でスケルトン ボーンの位置を見つけたいと考えています。

たとえば、https ://modelviewer.dev/examples/animation/index.html に移動し て、Three.js シーンを見つけた場合:

  const modelViewer = document.querySelector("model-viewer");
  const scene = modelViewer[Object.getOwnPropertySymbols(modelViewer)[14]];

次に、たとえば、LowerArmRこの場合にアニメーション化された の位置にアクセスできます。

scene.children[0].children[0].children[0].children[0].children[1].children[0].skeleton.bones.find(b => b.name == "LowerArmR").position

これを行うと、アニメーションのさまざまなポイントで、常に同じ位置になります。

{x: 1.86264503820865e-10, y: 0.00575238140299916, z: -1.02445485428149e-9}

アニメーション中に現在の骨格位置にアクセスするにはどうすればよいですか?

ヒューマノイド アバターのアニメーションでこのプロセスを実行し、ボーンの位置をプロットしようとすると、T ポーズだけが得られますが、特定の時間ごとの実際の位置は得られません。 ここに画像の説明を入力

ここから、次のことがわかります。

スケルタル アニメーションは GPU で処理されるため、実行時に js コードでこのデータに正確にアクセスすることはできません。

おそらく誰かが回避策を知っているかもしれませんが、私が知る限り、何もありません。

そして、その回避策または標準的な方法を探しています。

4

1 に答える 1

2

GPU 1上の個々のメッシュ頂点にスケルタル アニメーション (または「スキニング」) が適用されます。これは、多くの場合、ボーンよりも多くの頂点が存在し、CPU でそれらすべてを更新すると計算コストが高くなるためです。

ただし、ボーン自体の変換は、three.jsの CPU で計算されます。ここでは明らかでないかもしれない違いは次のとおりです。

  1. THREE.Object3D の .positionプロパティ.positionから継承されたボーンのプロパティは、その親の位置に相対的なローカル位置であり、その親などです。
  2. ほとんどのスケルトン アニメーションは、個々のボーンを移動するのではなく、回転することによって動作します。たとえば、肩の回転は、そのボーンの子孫 (腕の残りの部分) の移動と回転の両方の効果があります。

これらすべてをまとめると、見つけたいのは、特定のボーンのローカル位置ではなく、ワールド位置です。Object3D 親クラスには、これを支援するメソッドobject.getWorldPositionがあります。

const position = new THREE.Vector3();

bone.getWorldPosition( position );

このメソッドは、現在のワールド位置を計算する前に、最初にボーンのワールド マトリックスを更新し、祖先をトラバースするため、パフォーマンスのオーバーヘッドが少し発生することに注意してください。多くのボーンの位置、またはワールドの回転やスケールなどの他のプロパティが必要な場合は、すべてのグローバル変換が一度 (必要に応じて) 最新であることを確認してからscene.updateMatrixWorld()、オブジェクトの を分解することをお勧めし.matrixWorldます。

const position = new THREE.Vector3();

position.setFromMatrixPosition( bone.matrixWorld );

1 CPU 上の特定の頂点の位置を計算する必要が生じた場合、three.js の SkinnedMesh クラスには、このためのヘルパー メソッド.boneTransform()があります。

于 2021-05-19T03:09:05.080 に答える