ボーンが指定された方向を指すようにクォータニオンを計算する


7

この質問を解決するために、ソースポーズの各ジョイントの絶対(ワールドスペース)方向を(正規化された単位ベクトルとして)把握し、ターゲットのジョイントを回転させてその方向に合わせることにしました。問題は、ボーン(ジョイントからその子へのベクトル)がワールド空間で指定された方向になるように回転クォータニオンを計算する方法です。

更新:これが私の現在の考えです。ボーンごとに、変換行列は次のようになります。

(1) absolute transform = local rotation * relative transform to parent in bind pose * parent absolute trasform

したがって、3つの関節があるとします:肩->肘->手首。肩の絶対変換が既にあり、肘->手首がソースアニメーションと同じ方向になるように肘の回転を計算しようとしています。(1)から、絶対変換は次のようになります。

(2) ELBOW absolute = ELBOW local * SHOULDER to ELBOW relative * SHOULDER absolute

(3) WRIST absolute = WRIST local * ELBOW to WRIST relative * ELBOW absolute

代入すると、次のようになります。

(4) WRIST absolute = WRIST local * ELBOW to WRIST relative * ELBOW local *
                     SHOULDER to ELBOW relative * SHOULDER absolute

:私たちの定数であるELBOW to WRIST relativeSHOULDER to ELBOW relativeSHOULDER absoluteWRIST local回転のみで構成され、移動/スケールはありません。問題は、ELBOW localそのような値を見つけることです...

(5) normalize(position(ELBOW absolute) - position(WRIST absolute)) = desired direction

(6) ELBOW local consists only of rotations (no translation/scale)

ボーンの長さと目的の方向がわかっているので、の位置部分を推定することは可能ですWRIST absoluteが、回転は不明になります(この問題はAFAICTを再帰的に実行することは不可能のようです)。

私の最初の考えは、WRIST local回転のみであり、ループの次の反復で解決するため、の計算では完全に無視できるということでしたELBOW local。以下のスティーブンスタドニツキの回答は、骨の向きがスキニングにとって重要であるため、それほど簡単ではない可能性があることを示唆しています。ただし、これをスティックフィギュアで機能させることができれば、後でその橋を渡ることができます。


2
ええと、私がこれを正しく取得した場合、targetDir = normalize(childPos-selfPos)currDirがある場合は、軸角度からクワットを計算しないでください。ここ
teodron

@teodron-それがそれほど簡単だっただけでなく、他に3つの行列が乗算された場合。質問を更新します。
Robert Fraser

更新された質問があなたが望まない明白な答えを持っていると私は感じているので、1つの質問:なぜあなたは書きませんM = inv(childRelative) * childAbsolute * inv(parentAbsolute) * inv(selfRelative)か?そのような行列方程式のように?selfRelativeおよびchildRelativeマトリックスとは何ですか?変換チェーンを行う通常の方法は次のとおりです:childTransform = parentToChild * parentTransform。他のマトリックスは、それらの目的が何であるかについてはそれほど明白ではありません。問題は興味深いものであり、謎を解くにはうねりかもしれません:)。
teodron、2012年

@teodron-すみません、もっとはっきりしているはずです。selfRelativeは、このボーン(あなたが話すparentToChild)の親のバインドポーズマトリックスです。childRelativeは、問題の子への現在のボーンのバインド-ポーズマトリックスです。これらはスケルトンからのものであり、修正されています。「通常の行列方程式のように解かない理由」に関しては、2つの理由があります。1つ目は、Mは回転のみである必要があり、完全なchildAbsolute行列ではなく、位置の部分のみです。
Robert Fraser

1
複雑な問題で、十分に決定されていないように思われるため、最小二乗/疑似逆トリックが役立つ可能性がありますが、それは混乱であり、数値で行う必要があります。まず、回転行列だけで4つの未知数が追加elbow_localされ、非線形になりますが、8 ..は、未知数が8つの4つの方程式です。自由度が少ない運動連鎖を使用することを検討してください。あなたはを聞いたことがありDenavit-Hartenbergのが慣例?私はそれをかなりまともな結果で使用しました
teodron

回答:


3

あなたの問題の説明から、問題の核心はあなたの表現が現在データを欠いていることかもしれません。ボーンは単に1つのジョイントから次のジョイントへのベクトルではありません。これは、ワールドスペースまたは次のボーンの「チェーンの上の」ローカルフレームに関するローカルフレームの方向を表す完全な変換行列です。 。たとえば、前腕に傷があるキャラクターを想像してみてください。キャラクターの肘から手首までのベクトルがあると、手がどこに配置されるかがわかりますが、傷がどこにあるか(たとえば、上向きか下向きか)を知らせるのに十分な情報がありません。この方向情報は、ソーススケルトンの一部である必要があります。

単純な方向ベクトルではなく、完全なローカル方向フレームで表現されたものがあれば、残りの情報は簡単に抜け落ちるはずです。投稿で提案したとおりに、逆行列を使用して変換のレイヤーを「はがし」、中央のジューシーな行列Mを取得します。たとえば、あなたがchildAbsを持っている場合= childRel * M * selfRel * parentAbs、その後、乗算によってchildRel -1両側の左、そして上で、その後parentAbs -1 * selfRel -1 GET M = childRelに両側の右側に- 1 * childAbs * parentAbs -1 * selfRel -1。行列の積を反転すると、その逆数が乗算される順序が変わるため、ここで順序が重要になることに注意してください。(A * B)-1は、(一般に)A -1 * B -1ではなく、代わりにBになります。-1 * A -1

行列Mを取得したら、それを四元数に変換する方法について、Webにたくさんの情報があるはずです。その特定の手順についてのヘルプを探している場合は、私に知らせてください。これをいくつかのリンクで具体化できますが、必要になる前に、今すぐ取り組む必要のある他のいくつかの問題があるようです考慮して下さい。

編集: それについて考えて数日後、私はワールドスペースからローカル情報に移行するプロセスのこの大まかな説明を書きました。うまくいけば、これはもう少し光を当てるでしょう。

ここでは、各ボーンが回転行列とディスプレイスメントで構成される分離スキームについて説明します。回転行列はボーンのルートに適用され、変位はボーンローカル座標で与えられます。これは2つの重要なことを行います。

  1. 複数のボーンを同じソケットに接続できるため、適切な骨格ツリーが少し簡単になります。たとえば、鎖骨は肩甲骨の間の中心点に、指の骨は手首の中心点に簡単に接続できます。
  2. つまり、ボーンのほとんどのアニメーションは、そのボーンに関連付けられた回転を変更するだけで実行できます。たとえば、上腕の向きを変えることで上腕を動かすことができ、ひじの位置をずらすことができます。実際、ボーンの変位は(0、0、L)になることが多く、Lはボーンの長さです。ボーンの遠端は、ボーンのアタッチポイントからローカルZ軸に直接沿っています。

これは、必ずしも私が実装のためにお勧めしたいのアプローチではありませんが、それはのための最も簡単ですにそれを行う方法については、正確な結果はお客様の状況に直接適用されませんが、IMHOは実際には最善です。これにより、派生の仕組みと、独自のバージョンの問題に適用される正確な式を導出する方法を理解する可能性が高くなります。

作業している数量の簡単な定義:「w」の上付き文字はワールドスペース値を示し、「l」はローカル値を示します。位置にはP、回転にはRを使用します。たとえば、P w ボーンは、ボーンのワールドスペースターゲット位置です(ベース位置とは対照的に、これはもちろん親のターゲット位置です)。一方、R l ボーンは、ボーンのローカル方向です。つまり、親のフレームを基準にして回転する方法です。

これで、与えられたジョイントのターゲットの位置と方向を導き出すことができます-一部のコメントが示唆するように、関係は再帰的です。特に、

R w = R w * R l

そして

P w = P w + R w * P l

(これらはそれぞれ、「子の世界の向きは、親の世界の向きで構成されたローカルの向きです」と「子の世界の位置は、ローカルの変位によってオフセットされた親のワールドの位置です(適切なワールドスペース座標) '。)

これで、これらの方程式を解いて、与えられたワールドスペースデータの観点から、ボーンのパラメーター、つまりR lとP lを見つけることができます。これはまた、すべての関節の位置だけでなくワールド空間の方向も必要とするもう1つの理由を与えます。それはソルブに不可欠なコンポーネントです。

ローカルの方向を見つけることは簡単です。配向方程式の両側に親のワールド空間の配向の逆数を乗算するだけで、

R l = R w -1 * R w

ローカル空間からワールド空間へ移動するためのワールドスペースと変換行列の変位がわかっているため、ローカル変位も比較的簡単に計算できます(つまり、行列が逆方向であることを知っています)。

P l = R w -1 *(P w -P w

また、これらの方程式は親ボーンのローカルの位置や向きに依存せず、親と子のワールドスペース値にのみ依存することに注意してください。つまり、再帰的に感じている間(そしてボーンのワールドスペース値を見つけるための計算)結果への依存関係のため、スケルトンのルートからリーフに移動する必要があります)実際には、任意の順序で実行できます。

うまくいけば、これは何が起こっているのかについてより良い感覚を与えるでしょう-飛び交うすべての変換で行き詰まるのは簡単です。これが役立つかどうか教えてください!


ソーススケルトンは回転で構成されます。方向ベクトルは、私がそれをリターゲットするための単なる試みでした。(独自のフレームに対して)ソースの回転を簡単に取得できますが、ソースのバインドポーズが異なるため、これがどのように役立つかわかりません。あなたの投稿の2番目の部分については、問題はchildAbsoluteがどうなるかを理解することです-私は位置を知っていますが、そのローカルローテーションは知りません。
Robert Fraser

...(編集させない)現在のボーンの回転を計算するために、子ボーンのローカルの回転がどうなるかは必ずしも気にせず、正しい位置にあることだけを考慮する。
Robert Fraser

@Fraserお互いに少しだけ話をしているのではないかと心配していますが、子のボーンのローカルの回転がどうなるか気にできないのか、私には理解できません。このデータは、スケルトン上のスキニングアプリケーション、スティックフィギュアアニメーション(または2dですが、完全に別の問題について話している)には欠かせません。方向がその一部ではないようなターゲットポーズで何をしていますか?
スティーブンスタドニッキ

@Fraser「私はターゲットポーズのジョイントに位置しかなく、方向はありません」と言っており、ターゲットポーズのボーンにも適切な方向を決定する必要がある場合、それは完全に別の問題です(そしてはるかに難しい問題です)。でも、自分で「合理的な」向きを作ろうとするのではなく、ターゲットポーズデータから向きを取得する方法を理解することで、問題がはるかにうまく解決されると思います。
スティーブンスタドニッキ

私が達成しようとしていることを明確にするために質問を書き直しました。2週間前の私の進行状況の動画は次のとおりです:youtube.com/watch?v=H6Qq37TM4Pg ...ご協力ありがとうございます。
Robert Fraser、2012年

2

これが正しければ、スケルトンボーンの頂点全体を行列に格納していることになります。あなたの問題は、クォータニオン自体よりも、ボーンの格納方法に関連していると思います。

私が何を意味するのか説明しようと思います:

基本的に回転の結果(モデルとして使用する回転したボーン)があり、他のボーンに対してその結果を生成するクォータニオンを知りたいので、生成する代わりにボーンをベクトルとして保存できないのはなぜですか?マトリックス?

2点(Head、Tail)で構成されるベクトルとして保存されたボーンを使用できます。回転しているので、Headが支点となり、Tailは任意の軸を中心に回転します。それは四元数の仕事です。

ここで、ボーンAを「静止」位置にして、ボーンBの方向を一致させたいので、回転量AlphaとAxisを知る必要があります。正しい?

2つのボーンベクトルAとBの間の角度を取得するとアルファが見つかり、AxBの外積の正規化された結果は軸を取得します。

これをより複雑にしている唯一のことは、使用しているマトリックスからBone Vectorを事前に外挿する必要があることです。そうすれば、マトリックスを作成する代わりに、ボーンをベクトル(ポイントのペア)として保存することができます。

また、基本的には、その親がどのように回転されたかに関連してボーンを回転させているため(これがコードから取得したものです)、おそらく、単純にすべてのことを無視することができます。

別のボーンの位置を一致させたいので、その位置が合法であることがすでにわかっているので、相対回転に関するものはすべて必要ありません。


それらをベクトルとして保存する場合の問題は、フレーム間の補間または複数のアニメーションのブレンドです。
ロバートフレイザー

(まだ)他のユーザーの回答にコメントを付けることはできないので、とにかく、2ポイント以上のデータが必要な場合は、自分に合った方法で保存してください。これまでに得た両方の回答は同じ問題を指摘しています。データが欠落しているか、問題の原因となるフォーマットを使用しています。ボーンに回転と平行移動が含まれている場合、完全な行列を処理せずに変換全体を回避するだけで、それぞれの情報を格納できます。クォータニオンとボーンごとに2〜3ポイントを使用すると、子の位置は親の位置に依存するため、システムが自動的に処理します。
Darkwings、

この目的は、アニメーションを1つのスケルトンから別のスケルトンにリターゲットできるようにすることです。これにより、アーティストが作成したアニメーションのように訴訟を起こしたり、手続き型およびアーティストが作成したアニメーションとブレンドしたりできます。私が保存しているデータは、各フレームの親に対する各ボーンの回転クォータニオンです。これはインポートされたアニメーションで既に機能しています。結果のアニメーションの保存方法を変更したくありません-この手順は完全にパイプラインの一部です。最終結果を他のアニメーションと同じように(そして他のアニメーションと相互に作用させて)動作させたい。
Robert Fraser

ビデオを見ました。既知の軸(親ボーンを基準)を基準にした回転を簡単に格納するために、まだあなたの人生を複雑にしていると私はまだ確信しています。回転のみの行列が必要な理由は、不要な平行移動を防ぎ、親子の位置が無効になることです。クォータニオンだけを使用してバインドされた軸として親ボーンを使用している場合は、とにかく起こりえない何か。それ以外の場合は、行列から四元数に無限に変換してから、もう一度行列を作成する必要があります。要するに、私はスティーブンスタドニツキのPOVを共有します。彼はそれが単なる数学の問題ではないというのです。
Darkwings、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.