vrm-specification icon indicating copy to clipboard operation
vrm-specification copied to clipboard

VRMのデータ的でのローカル軸の維持

Open pixiv-sigepon opened this issue 4 years ago • 36 comments

UniVRMの方とどちらが適切か悩みましたが仕様に関わる部分だと思うのでこちらに投稿致します。 現在の、UniVRMで正規化処理を行うとボーンをUnityのHumanoidに最適化したポーズを取り各ボーンの軸がすべてワールド座標に向いて正規化されます。 UniVRMで出力されたデータを、GLTFローダーなどで読み込むと分かりやすいです。

例えば、このように指に対して適切にローカル軸を設定したボーンが

このように、UniVRMでHumanoid向けに正規化されるとメッシュに対してローカル軸が消え、ワールド方向に向き曲がる方向がおかしくなってしまいます。

VRM ヒューマノイドの要件(仮) 加えて * T-Poseになっていること * 各ノードの回転・拡大は無いこと< UniVRMでこの正規化処理でローカル軸が消え去る

VRMの仕様定義で、各ノードに回転は無いこととあるのですが回転値を0値にするのは構わないですが、Humanoidに最適化したポーズに変形して上記の正規化処理を行うとローカル軸が消えてしまい、Humanoidが実装されている環境以外で読み込むと曲げる方向がおかしくなってしまったりします。 例えば、FBXをHumanoidのセットアップを行った場合元のローカル軸は維持されその上でHumanoidの設定が適用されます。 VRMの仕様的にも同様に、ベースのGLTFのデータ的には元のローカル軸を維持してその上でHumanoidに対応する処理を行う仕様になって欲しいです。

UnityのHumanoidのTポーズ化に依存しないで、ローカル軸の値を0値にした場合指はこのように真っすぐに向いてメッシュと軸方向がちゃんと一致した状態になります。

UniVRMで行われている処理は、正規化時にボーンのParentをすべて解除してワールド方向に向けて再Parentしているのではないかと思います。 こちらのエンジニアの方で、ローカル軸を維持したVRMデータを作成できるように検証を行ってもらいましたが、ローカル軸を維持した状態のVRMも作成でき問題なく動作しているようでした。

pixiv-sigepon avatar Nov 29 '19 11:11 pixiv-sigepon

手動でTpose化すれば問題ない、自動Tpose化するとモデルが壊れるというuniVRMのTpose化issueになりませんか?

ローカル軸の保持は利用アプリ上での正規化を要するものとなり規格としての標準化の意味を薄めると思います。

また、アプリからのエクスポートであればアプリ側独自のTpose化実装もできるのではないでしょうか。 (Tpose化された)vrm由来モデルを再度vrmにする際にTpose化すると壊れるのでそのような場合はTpose化を実行しないようにという話もあります。手動(独自コード)でもTposeの仕様に沿っていればVRM出力時に絶対にuniVRMのTpose化を利用しなければならないというものではないと私は考えています。

iCyP avatar Nov 30 '19 03:11 iCyP

エクスポート時に独自にTポーズ化を行うことはできるのですが、そもそもモデルのローカル軸を消してしまう仕様が元のモデルの持つローカル軸の破壊的仕様と感じました。 その為、ローカル軸を維持した上で正規化処理した軸情報(回転値を0にするという情報)はVRMの拡張情報として持ってほしいという要望になります。 この仕様ですと、例えばGLTF化した際に元モデルのローカル軸は破壊されることなく他環境に持って行った際にVRMの拡張情報を参照してHumanoid設定を行うことができます。 また、VRMデータをGLTFとして参照する場合もローカル軸が破壊されていないデータを参照することができます。

その為、Humanoidを扱えないような環境で読み込む場合もローカル軸の再設定を行うという処理も不要になります。 現状、UnityのHumanoidは元のFBXのローカル軸を破壊せず維持した状態で持っています。 それと同様の仕様になってほしいです。

m-sigepon avatar Dec 02 '19 01:12 m-sigepon

仕様通り正しく厳密にTposeになっていると仮定すれば、各humanoidボーンのローカル軸は固定の値を用いることができます。 なぜなら、Tpose化によってローカル軸情報-回転をジョイント・頂点座標情報にBakeされていると言えるからです。(仕様に明記されていないこと・標準に実装されているTpose化機能が問題ではありますが…) これにより、汎用的にモデルに動きをアタッチできます。 たぶん。(間違っていたらごめんなさい 

モデルにローカル軸情報を持たせることは、正規化(というより仕様準拠化)-Tpose化による上記利便性を失わせることになります。

参考: slideshare - unite-tokyo-20193dvrm の26枚目2項目目,33枚目

iCyP avatar Dec 02 '19 05:12 iCyP

モデルにローカル軸情報を持たせることは、正規化(というより仕様準拠化)-Tpose化による上記利便性を失わせることになります。

これは、ローカル軸情報を持つ上で正規化した情報を別に持つ(VRMの拡張として保持する)ことで解決することだと思いますが、その仕様ではダメな問題はあるでしょうか? 例えば、Mayaでは「回転」情報とは別にボーンのローカル軸情報を持つ「ジョイントの方向(ボーンの軸の向き)」というのを保持しています。

そのように、モデルのボーン情報が本来持ってるローカル軸は維持してVRMの拡張情報として正規化した情報を別に持てばいいのではないかと考えます。

m-sigepon avatar Dec 02 '19 05:12 m-sigepon

私は以下よりこの仕様は不要だと考えています。

  1. 先にも述べたが、正確に正規化されたモデルはローカル軸を固有する必要はない。#54 により各ボーンのローカル軸をドキュメントに明示・利用するだけで良い。むしろローカル軸の独自所有は動きのアタッチをモデルに最適化する手間が発生する。

  2. この仕様を読むか読まないかはクライアントが決定するということであれば、それはルックの一貫性を失う原因の一つになる。これはVRMのポータビリティという思想に反する。

  3. 個人的にその時点で必要最低限な方が良い(追加は楽、変更・削除は困難なため)。 現問題はTpose化の改善で解決できると感じている。

iCyP avatar Dec 02 '19 05:12 iCyP

VRMの利用想定がアバターのみでなく、今後色々な活用法をされるときにオリジナルのデータが持つローカル軸を維持するということはそのオリジナルデータの理想の状態を保証することができます。

例えば、一番問題に感じてるのはボーンの軸の向きに関わらずワールド方向にボーンが向いているという点です。

これは3Dデータとしては、基本的にこのようなデータを作成しません。 理由は、ローカル軸データを持っていないと曲がる方向の情報を失うためGLTFなど対応ソフトで読み込んだ場合、モーションを付けれるような状態ではないためです。

その為に、GLTFとしてはローカル軸方向を保持したモデル製作者が意図した最低限の状態を保持してその上でVRMに最適化されたデータが付加されるというのが理想だと考えているためです。

また、現在Tポーズ化はUnityのアバター生成のTポーズ化に依存しており完全な正規化が行えているわけではなくHumanoid依存の正規化になっているためです。(この点はVRMschema側ではなくUniVRM側で議論する問題だと思いますが) ここでいう完全な正規化というのは、ボーンの向きがワールド方向と一致していることを指します。(↓このように)

例えば、UniVRMで正規化後、背骨が湾曲してるのに対しジョイント方向がワールドの向きを向いているこの状態がおかしい状態です。(完全な正規化を行うなら人体の基礎ボーンの回転値を一度0値にしボーンの向きと軸の向きを一致させた状態が正しい正規化かと思います)

今後Unity以外でのVRMの利用を考えると、Humanoidに依存した正規化処理より元データ構造を保持してその上で、VRMに必要な情報を持たせるというのがエコシステムとして理想と感じます。

以上が、ローカル軸を維持した状態であって欲しい理由となります。

m-sigepon avatar Dec 02 '19 06:12 m-sigepon

(モーキャプに最適化された | 一般化されたモーションを持ったアプリに対する)3Dアバターフォーマット、から離れた使い方を使いやすくするべきという話は、VRM-Cの方々の判断すべきところであると私は考えますので、これ以上申し上げることはございません。

ただし、ボーンの向きとギズモが合わない言うのは、VRMとしてはTposeに反しているという問題です。これはuniVRMのTposeを通していればuniVRM、それ以外であればモデル固有の問題であり、ここで議論すべき問題ではないでしょう。Tpose化の問題であればuniVRMのリポジトリへissueを建てるべきです。

o0O(画像大きすぎて読みづらいです…高さタグ等で調節いただけると幸いです...e.g:)

<img height = "128" src=https://user-images.githubusercontent.com/3232308/69937332-d6c9b680-151d-11ea-8f39-ca5ca36a48fd.png>

iCyP avatar Dec 02 '19 07:12 iCyP

画像サイズ小さくしておきました。 Tポーズの正規化の件についてはUniVRMの方にissueを立てたいと思います。

m-sigepon avatar Dec 02 '19 07:12 m-sigepon

UniVRMの方でissueを立てる前に検証を行ったところ、純粋に全身の基本ボーンの回転値を0にしてHumanoidをセットアップしモーションを適用するとキャラの印象が大きく異なってしまうことが分かりました。 (これは、Humanoidに変換したモーションがマッスル値の差分データとして持っているからだと思います)

単純に正規化時に回転を全て0にしてギズモと軸の方向を一致する方法では難しそうでした。

FBXにHumanoidを適用してアバターを生成した場合、元のローカル軸は維持されています。恐らくHumanoidシステムは元の情報を維持してHumanoidシステムをラップ(バインド)する形で実現していると思います。 上記でも書きましたが、VRMが今後モーションキャプチャー環境だけに限らず幅広い使われ方が行われると想定するとローカル軸の維持が必要と思われるので、ベイクして焼き付けてしまうのではなくこのように維持される構造になってほしいです。

m-sigepon avatar Dec 02 '19 09:12 m-sigepon

一点確認させていただきたいのですが、その2体に当てたポーズはそれぞれそれ専用に設定したモーションデータでしょうか?それとも同じデータでしょうか?

 公開されているVroidのデフォルトTposeは人間が(普遍的な・見栄えよく)Tposeした時の姿勢をボーン初期姿勢として持っていると認識しています。同じポーズを適応しているのであれば、

  • 仕様Tpose
    • 背骨が真っすぐ(自然な姿勢からは逆に曲がっていると言える?
    • 足の骨がY軸(縦)に並行(解剖学的に言えば下に行くほど骨関節-回転軸は後ろに下がるはずでは?

という、人間として少し不自然な姿勢(モデリングできないので書籍頼みの知識です))から、キャリブレーション時のようなTposeを取っているときの姿勢への差分をポーズモーションへ適応しないと差異が出るのは当然と思います。ここに、仕様Tposeはモーションデータを作るときに留意すべき初期姿勢状態であるというDocumentationが必要でないか、というissueが考えられます。  ご回答頂けると幸いです。@m-sigepon

iCyP avatar Dec 04 '19 00:12 iCyP

一点確認させていただきたいのですが、その2体に当てたポーズはそれぞれそれ専用に設定したモーションデータでしょうか?それとも同じデータでしょうか?

2体に当てたモーションデータは、Humanoidモーション化した同じデータです。

■左側 人体の女性の背骨の湾曲に沿ってボーンが入ってる状態でHumanoidのFoce-Tポーズ化した状態

下記に該当する状態

 公開されているVroidのデフォルトTposeは人間が(普遍的な・見栄えよく)Tposeした時の姿勢をボーン初期姿勢として持っていると認識しています。

■右側 上記データの背骨が湾曲している回転値を0値にし背骨をまっすぐにする処理を事前に行ったデータです、それをFace-Tポーズ化した状態

状態としては、この仕様に準拠した状態です。仰ってる通り自然な姿勢からは逆に曲がる状態ですね。

仕様Tpose 背骨が真っすぐ(自然な姿勢からは逆に曲がっていると言える? 足の骨がY軸(縦)に並行(解剖学的に言えば下に行くほど骨関節-回転軸は後ろに下がるはずでは?

この状態、もう一点問題がありました。 足の回転値が0値にすることにより、膝が伸び切った時にがくがくなる現象が起きました。

という、人間として少し不自然な姿勢(モデリングできないので書籍頼みの知識です))から、キャリブレーション時のようなTposeを取っているときの姿勢への差分をポーズモーションへ適応しないと差異が出るのは当然と思います。

通常はこのように回転値をすべて取り除く正規化を行っても、その背骨も含めた自然な初期ポーズを取るモーションを作成し、Genericで適用した場合はそれらのキーが反映されるのでちゃんた自然なポーズになります。 今回、Humanoidシステムをベースとしてポーズが適用されており。 Humanoidシステムは、初期ポーズからの差分データに変換さるようなのでFace-Tポーズしていた際に人間として背骨が湾曲していても、その状態を維持してモーションが適用されるようです。

ここに、仕様Tposeはモーションデータを作るときに留意すべき初期姿勢状態であるというDocumentationが必要でないか、というissueが考えられます。

現在の仕様が、「背骨が真っすぐ」が仕様となっている場合、上記現象がおきるため「背骨が真っすぐ」ではキャラの印象が上記のように損ねるのでHumanoidでは「人として自然な状態のTポーズ」になっていれば問題ない、逆にそれを真っすぐにするとキャラ性を損ねる問題があるのが分かりました。 それは別issueかもしれません。

m-sigepon avatar Dec 04 '19 01:12 m-sigepon

 理解としては、humanoidモーションの適用において、初期姿勢のキーを最初に打っても以降別のモーションを当てると初期姿勢のキーが残らないという問題ですね。 モーションを当てた場合ーアバター以外の使い方をした時に発生する(リターゲティングされたモーキャプデータであれば問題はないのではないかと思います、識者意見求む)、unity HumanoidとVRM1.0仕様のTposeとかみ合っていない問題と見えます。

 また、仕様に合わせてTposeにするとアバターの印象を与えたい姿勢と(モーキャプにせよ手付モーションなどにせよ)アクターの姿勢との差異の吸収させるは解決が難しい問題だと思います。かつ別issueですね。どこにどう提起すべきなのか分からないですが… バーチャルキャストはクライアント側でそれ実装しているように感じる (tweet @virtual_cast)ので、クライアントで解決すべきという思想なのかもしれませんが。どうなの?@vrm-c 氏~識者氏~

p.s. 脚がガクガクするのは汎用IKを真っすぐ繋がったボーンにリグセットアップ・ヒント無し(blenderでいうpole targetのような物)を適応すると、優先的回転軸を見失って、フレーム毎の計算結果に一貫性が失われることによるものでしょう。理屈からいえば脊椎、腕や指でも同じことが起こりえます。VRMクライアントに専用IKが組まれていれば or インポート時にIKセットアップされるよう設定すれば-(人型前提で、デフォルト姿勢が明らかで一意であれば曲がる方向は明確なので、自動セットアップは困難ではないはず、どのみち手間はありますが、ローカル軸はTpose依存固定仕様でもモデル固有仕様でもやることは同じでしょう(見る値が違うだけ))、解決できると思います。

iCyP avatar Dec 04 '19 02:12 iCyP

VRM的には、T-Poseからローカル軸を得てください。 なので、ローカル軸がグローバル軸と一致するようにT-Poseにしてください。

また、Unityのmecanimはブラックボックスで詳細がよくわからないのでこれを基準に仕様を作ることができませんでした(mecanimがどこからどこまでの機能を指すのかよくわからないところですが・・・)。UnityのHumanoidポーズがmascle値の配列で表現されるところですが、これがリターゲットなども含んでいるようですがブラックボックスで同じ動作を作ることができません。

VRMとUnityHumanoidの共通点は、

  • Humanoidボーンが同じ親子関係を持っている

あたりで詳細は特に互換性がありません。 またUnityでHumanoidを有効に使うには、AnimatorコンポーネントにHumanoidAvatarを適用して、特定の方法でポーズをつける必要があります。 Transformにrotationを代入するタイプの処理は、Humanoid.Avatarと無関係です。

ousttrue avatar Dec 10 '19 06:12 ousttrue

@ousttrue

なので、ローカル軸がグローバル軸と一致するようにT-Poseにしてください。

これを行ったところ、以下のようになりました。 ローカル軸とグローバル軸を一致するTポーズを行うのはキャラの体形を損なうためその対応では行えません。 これは実際に、このようなデータを手元で作っていただくと分かると思います。

1.左側の状態が現状のセットアップデータ

2.中央が女性らしい形状を維持して垂直にボーンを入れる場合

3.右がVRM的にローカル軸とワールド軸を合わせたいならモデルも垂直にする状態

2.は曲がる位置がモデルに対しておかしいので基本的にこのようなボーンの入れ方はしません 3.今回、正規化処理で全ボーンの回転値を抜いて完全なTポーズとして3の状態を作ってみました。 その結果がこちらになります。 右側が3の状態で、Humanoidでポーズを反映した場合Force-Tポーズを行った状態では自然なTポーズ状態に対してポーズが適用される仕様のためかボーンを棒立ちにしたらポーズも棒立ち状態になってしまいました。

例えば、キャラの体形を女性らしいS字を保ってボーンをワールドとローカル軸が一致する場所に配置したら曲がる基点がおかしいことになります。(実際のモデルの骨を通る位置から外れた位置になったりするでしょう) その為、通常はこのようにキャラの姿勢に対応する位置にボーンを配置します。

ローカル軸とグローバル軸を一致するには寸胴な体形のキャラしか作れないことになっていしまいます。

さらに、Unityでとの話になっていますがVRMとしては今後Unity外での利用も考えられますのでUnity基準で仕様を考えない方が良いかと思います。 その為に、GLTF的には元のオブジェクトが保持しているローカル軸を保持してその上でVRMの正規化を別の情報として持つ処理を行ってほしいです。 FBXをHumanoidでセットアップしても元のローカル軸が消えないように、そのFBXを他の環境に持っていってもオリジナルのローカル軸は非破壊でそれに対する処理を行うことができます。 現状ですが、VRMにした時点でローカル軸がUnityのHumanoidに依存したForce-Tポーズに対してワールド軸に正規化されてしまうのでローカル軸の破壊的処理が入っているのが問題だと感じております。

m-sigepon avatar Dec 10 '19 06:12 m-sigepon

たしかに3軸全部完全にあわせる必要なさそう。 間違っておりました。 1軸はグローバル軸に合わせる必要がありそうです。 どの軸をワールドと合わせるべきかドキュメント化するべく検討します。

ボーンに沿った軸が必要な場合は、以下のようにローカル空間を各ボーンで求めてください。

// spine の例
var y = (tail - head).normalized;
var x = Vector3.right; // ボーンごとにワールドと一致するべき軸が異なる
var z = Vector3.cross(x, y);
// x, y, zが正規直行基底

ローカル空間がボーンに沿ったものになるはずです。 この使い方はVRMでは想定されておらず、今後の課題となります。

ousttrue avatar Dec 10 '19 07:12 ousttrue

社内での議論の様子をまとめました:

  • まず、上でしげぽんさんがおっしゃるように、アバターをTポーズにする上で、キャラクターのボーンをすべてワールド軸に平行にセットアップすることは難しいです。
  • どうやら、TransformのRotationからボーンの軸を推測するソフトウェアが存在するらしく(FinalIKなど)、それらはとりあえずどれかの軸がボーンの方向を向いていれば良いらしいです(xyz、+-問わずどれがボーンの向きを向いていても良い)。Rotationを抜くと、その推測が崩れるようです。
  • ローカル軸の必要ないソフトウェアは、後から取り除けば良いと思います。今のように、すべてのボーンの回転値を(0, 0, 0; 1)にする処理は、アプリケーション側の要求に応じてアプリケーション側で成されるべきです。

したがって、ひとまずVRMとしてはHumanoidボーンの回転値について制約を設けない方針に切り替えるのが良いと思いました。

0b5vr avatar Dec 04 '20 04:12 0b5vr

既存のプログラムが壊れて互換性無くなるので、それはできません。

ousttrue avatar Dec 04 '20 08:12 ousttrue

私は、むしろ変えるなら今しかないと思っています。

あまり良くわかっていないのですが、各ボーン軸をワールド軸に向ける処理というのは、アプリケーション側で実行するのはそんなに難しいのでしょうか? UniVRMで現状できていることなので、その処理をエンドデベロッパーにexposeすれば、アプリケーション側で必要に応じて実行できるというイメージでいたのですが。

0b5vr avatar Dec 04 '20 09:12 0b5vr

口頭で議論を行いました。

1.0においては、引き続き各ボーン軸をワールド座標系に合わせる方針で仕様を定義します。

0b5vr avatar Dec 11 '20 05:12 0b5vr

1.0においては

今後定義される可能性はあると言う事でしょうか。上でしげぽんさんが仰ったような S 字湾曲のようなケースに対しては、確かにオフセット値よりボーンのローカル方向の推定は可能です。しかし最初にある指のようなケースに対して、ロール値の推定をオフセット値から行う事は容易ではありません。 Unity の Mecanim はブラックボックスなのではっきりとは分かりませんが、モデルやアニメーションに対して恐らくインポート時にローカル方向の推定を内部的に行っているのではないかと考えられます。

ローカル方向を破棄してしまうと、例えば一つのアニメーションデータを用いて Unity の内外で同様のアニメーションを行うためには Mecanim と似た様な実装を各プラットフォームに強いる事を意味し、 Mecanim はブラックボックスである事により、一貫性が失われてしまいます(※1)。また、 Mecanim を各プラットフォームに実装する事と比較して考えると、上で FMS-Cat さんが書かれていますように、各ボーン軸をワールド軸に向ける処理をアプリケーション側の VRM インポーター等で必要に応じて実装する事の方が遥かに容易ではないでしょうか。

規格としてデータを揃える上で、ユーザーによって乱雑になりやすいデータを破棄するという事は一番簡単であり確実な方法ですが、失う物が大きいという事にも留意して頂きたいと思います。 #176 のようにローカル軸の名前を定めるのであれば、例えば Blender の Fortune アルゴリズムで推定されるようなローカル方向をロール値も含めて VRM の規格として定義し(※2)、推奨とする Humanoid ボーンのローカル方向をガイドラインとして記載し、それに従って貰う前提でローカル方向を保持するというような事も考えられるのではないかと、一つの意見を述べさせて頂きます。


※1: 現状の仕様では必然的にこの選択をとらざるを得ません。とは言え、 Unity で Mecanim を使うな、 Unity と Unreal の Humanoid の挙動を同じにしろ、というような事を言うのも無理があるので仕方がない事だとは思いますが...。

※2: Humanoid に対応するボーンだけでも基準となるローカル方向さえ決めてしまえば、 Mecanim のような実装に頼らずとも、プラットフォーム間でアニメーションの互換性をある程度保つ事が可能ではないでしょうか。アバターとアニメーションは切り離して考えるべき、と言う意見もあるかもしれませんが、アバターを用いてアニメーションやボーン操作を行わないという事は原則あり得ません。ボーンアニメーションのデータには基本的に相対値が用いられますが、アニメーションを作成するアバターと適用するアバターでローカル方向が異なると回転方向が変わってしまうので、ローカル方向の定義が重要になります。

TokageItLab avatar Jan 06 '21 21:01 TokageItLab

Unity 以外のゲームエンジンでゲームやアニメーション用途での VRM 使用を検討しているのですが、ここまでの議論を拝見すると TokageItLab さんやしげぽんさんの仰る通り今後様々な用途での VRM 利用を考えるとボーンのローカル軸を破棄する仕様には無理があると考えています。破棄するのではなく glTF の拡張情報として正規化に必要となる情報を持たせる案に賛成です。

VRM の思想としてルックの一貫性・ポータビリティを担保したいという意図はわかりますが、情報が破棄されると元に戻せないのが問題だと考えています。 glTF の拡張情報として正規化に必要となる情報を持たせて、VRM の仕様としては正規化されたデータを見てください、という仕様では駄目でしょうか?

infosia avatar Jan 22 '21 02:01 infosia

私自身、 Godot というゲームエンジンで VRM に対応するかどうかというプロジェクトに関わっておりますが、 #12 でも挙げられているように、現在の仕様ですと Unity の Mecanim から離れてボーンの操作を行う事は困難です。 Blender の VRM Importer ~~(恐らく Fortune での方向推定)~~(独自の決め打ちベースの方向推定っぽい)を用いたとしても本来のロール値は破棄されており、再編集やアニメーションの作成を行う事が困難である事に変わりはありません。

繰り返しになりますが Mecanim のようなリターゲッティングシステムの利用が前提にあると、ルックの一貫性・ポータビリティという点については Unity を離れた時点で破綻してしまいます。プラットフォーム間の互換性を考えるのであれば、ローカル方向をガイドラインで定める等してローカル軸の維持を行う必要があると強く感じております。


例えば Blender のボーンのローカル方向は進行方向が +Y となり、 VRChat のガイドラインには IK が関係するボーンのロール(ローカル Y 軸の回転)は 0° にするというようなガイドラインがあります。

https://docs.vrchat.com/docs/full-body-tracking

しかし、ロールを全て 0° (もしくは 0° 基準)にすると関節が自然に曲がる回転軸が X と Z で混在するという問題があります。


そこで、回転軸を優先した場合には #176 の参考のようになるかと思います。

https://docs.microsoft.com/en-us/azure/kinect-dk/body-joints

こちらでは全ての関節が自然に曲がる回転軸を Z と定めています(個人的には肩の軸に違和感があります)が、そもそも進行方向が X である事に加え、恐らく回転値の正負を左右で一致するように優先した結果として進行方向の軸の正負が逆転しております。また、ロール値の定義が必須(腰は 0° 、手首は 90° ...etc )となります。


個人的、及び知人のモデラーの観点からすると、どちらかと言えば後者の方が回転軸の役割が決められており理想的なのですが、 3DCG ソフトの制約上、進行方向は +Y にしたい所ではあります(軸に関してはインポータやエクスポータでローカル方向の情報を破壊せずに変換できるはずなのでデータ上は +X でも構いませんが...)。また、左右における回転値の正負の逆転はロール値の 180° 回転(右肘と左肘でロール値が 180° 異なるような形)で対応するのが理想的であると考えます。

アドオンや機能によってローカル方向を初期化する必要があるのであれば、それらを利用するアプリケーションの VRM インポータ側でローカル方向の初期化を行うべきです。また基準の値が定義される事で、例えば VRM 出力時に Humanoid ボーンにおいて基準のローカル方向と 45° 以上異なっている物がないかチェックし、もし存在すれば警告を出して変更を促すという様な実装も可能ではないでしょうか。

以上を踏まえまして、これらのローカル方向の値を数値として規格化・ガイドライン化した上でローカル軸を維持する事で、真の意味でプラットフォームを跨いでルックスを保った標準化が成り立つのでは無いかと具申致します。

TokageItLab avatar Jan 22 '21 18:01 TokageItLab

本件と関連して #214 を新しい issue として追加しました。メッシュやボーンの情報などソースとなる3Dデータに対する破壊的変更に関連して VRM としてより広い思想の転換が必要かと思い問題提起させていただきました。VRM に必要な情報は VRM の extension として格納すべきだというのが私の意見です。

infosia avatar Jan 23 '21 22:01 infosia

本件 #214 のような根本解決を望みますが、とりあえず影響範囲が少なそうな折衷案としてはアドホックですが『元の姿勢がどうであったか』という情報だけ追加プロパティとして持たせるというのはとりあえずの対策として(根本解決を何年も待つよりは)考えていいのかもしれません。回転だけバッファに格納すれば追加サイズは1ノードにつき sizeof(float) * 4 とちょっと、基本ノードの構造は VRM 0.x との互換性を保っているので既存プログラムの変更は必要なし、ローカル軸の表現が重要になってくるユースケースや Unity 以外のゲームエンジンで必要な場合だけそこを見ればいい、という感じです。こういう感じでプロパティを追加していくのは無秩序な仕様の肥大化を招きそうでよくない感じがしますが... #214 を待っていると何年もかかりそうなので案として俎上に載せたいと思います。

infosia avatar Mar 04 '21 03:03 infosia

本件に関しまして私の方でも問題点と解決案をまとめていまして、今月末に開催される VRM 勉強会で発表するように考えていました。

本件はいくつかの issue に跨がる問題であり、また Unity 以外の環境についても考慮・説明する必要があるので、まとめるのに手間取っておりますが、少なくとも一つ言えるのは現状のロール軸の定義に2軸使っているような定義では親指の回転方向を定義する事が明らかに不可能なので Unity 依存を断ち切る上では定義の変更は避けられないという事です。

TokageItLab avatar Mar 04 '21 03:03 TokageItLab

BlenderのVRMアドオンに言及があったので補足です。VRMアドオンは最近のアップデートで、Blender 2.83以降の場合のボーン方向の推定にglTF 2.0アドオンのFortuneを使うようになりました。Blender 2.83未満の場合はFortuneが無いのでこれまで通りオリジナルのロジックを用いて方向推定を行います。Fortune自体も、もともとglTF 2.0アドオンのVRM対応のために導入されたっぽく見えます

saturday06 avatar Mar 24 '21 22:03 saturday06

It is correct that the "Fortune algorithm" was designed for VRM. Prior to Fortune, the glTF importer had two options: Blender(+Y) and Temperance. It was suggested that Temperance did not point bones in the correct direction when given a VRM model. That is why the Fortune heuristic was prototyped and eventually committed. For editing VRM models, it is useful.

However... Fortune produces incorrect bone orientation in some cases, because it uses all child bones instead of only human bones. The main problem is that clothing and spring bones can cause the character rig to malfunction: for example, if I add a sleeve to the arm, it will take the average of the bones, and cause the Upper arm to point down, for example. Also, on characters with breast bones, the chest may point forward.

Some human bones may also produce incorrect results. For Hips, it will take the average of left leg, right leg and spine, which can produce an incorrect vector. For wrist, it may point in the wrong direction depending on the thumb positions, or if an extra unused bone exists between wrist and fingers.

Finally, Fortune is not sufficient for use in animation, because it does not select the correct bone roll (for example, to guarantee that X axis of bone matrix faces in a certain direction).

For casual editing in blender, Fortune is helpful. But for animation, you need perfection, not just working 80% of the time Fortune was an attempt to make some VRM files look good in the editor, but it is not correct in all cases and not sufficient for animation.

Ultimately, Fortune is only a heuristic. The problems with fortune can only be addressed with some understanding of the humanoid bones or the VRM format itself, or if the VRM format is changed to preserve the original bone roll and orientation.

Attachments for illustration, imported as .glb on Blender 2.91, using Fortune setting: Example using Miraikomachi by Bandai Namco: image You can see some issues here:

  • Spine and Chest point forward due to clothing or breast bones.
  • Head points down! because a grouping bone for springbones was placed at 0,0,0.

Example using 右近 by キツネツキ: image

  • Hips bone points slightly backwards due to tail.
  • Arm bones are dragged down due to sleeves
  • Head bone is facing forward

lyuma avatar Mar 25 '21 01:03 lyuma

恐れながら、ローカル軸の破棄により起こる問題と改善案をまとめさせて頂きました。

https://qiita.com/TokageItLab/items/e5880123a9f508b2769d

改善案についてはあくまで提案なので、完全にこの通りにしろというわけではなく(して頂ければ幸いですが)、そこは議論していく所だと思いますが、記事中のまとめ部分に記述したように、最低限以下の2つは「プラットフォームを越える汎用アバターフォーマット」として必要であると考えます。

  • 正規化処理でボーンのローカル軸の方向を破棄するような実装は避ける
  • 回転軸の役割が X Y Z で一意に決まるような定義を行う

関連 #54 Humanoid bone の向き? #83 SpringBone の回転方向の制御 #118 アニメーションデータについて #176 ローカル軸の定義

TokageItLab avatar Mar 31 '21 12:03 TokageItLab

議論に参加させていただきます。

私もローカル軸の情報は残した方が相互運用性と互換性(現実的な意味でどのソフトでも作り手やユーザーが望む結果になるという意味での)がむしろ高まると思います。 VRMが元々どこまでの用途を想定して作られたのかは私は定かではないのですが、今はモーキャプデータを元にリターゲットでVRMボーンにアニメーションを流し込んで(回転情報を上書きして)動かすだけではなく、プログラム制御で望む動きをさせたい(ローカル軸からの相対値変化で回転させたい)という需要もあり、そうした中でこのような徹底した正規化をされてしまうとそれができなくなってしまうと考えます。

しげぽんさんの以下の指摘については、これはMaya等のボーン自体の姿勢によらずボーンの回転の基準となる座標系をボーンごとに決められる(Mayaのジョイント方向=ローカル方向軸=Local Rotation Axis)DCCツールでなければできないと考えており、

(完全な正規化を行うなら人体の基礎ボーンの回転値を一度0値にしボーンの向きと軸の向きを一致させた状態が正しい正規化かと思います)

例えばMayaを例に取ると、Maya上での操作として各ボーンを平行移動値だけを使って配置しジョイント方向(ローカル方向軸:Local Rotation Axis)をボーンの向きに沿うように調整することですね。

ただし、こうしたMayaなどのDCC独自のローカル方向軸の仕様はglTFレベルではそもそも存在しませんので、glTFレベルではどうなるかというと、親指などの「作り手が意図する斜めの軸」が必要なボーンについては、Mayaのジョイント方向で設定した斜め軸情報がglTFのボーンノードのTransformとして(0, 0, 0, 1)以外のrotation(クォータニオン)値に変換されるか、あるいは(0, 0, 0, 1)に完全統一される場合でもアニメーションキーフレームの回転情報の方がMaya上とは異なる(glTFで正規化されたボーンでもアニメーション結果がMaya上と一致するような)回転情報に修正されてアニメーション情報が出力されるはずです。

それを、今のVRMの正規化仕様(及びUniVRMの正規化実装)では、こうしたさすがにrotationを残さなくてはならないボーンまですべからくrotation=(0, 0, 0, 1)にリセットしてしまうのが問題なのではないでしょうか。 仮に全てのボーンを完全にrotation=(0, 0, 0, 1)にリセットしてしまうのであれば、そのボーンに対するアニメーションを作り手の想定と一致させるため、アニメーションキーフレームの回転情報を本来のローカル軸でのアニメーション結果と一致するように修正することが必要で、それにはやはりローカル軸の情報が必要となります。

現状、プログラム制御でVRMモデルを(モーキャプなどでの回転値の上書き以外の方法で)動かしたい人たちは、VRM Addonなどのボーン方向(ローカル軸)の推定機能を使ってなんとか運用しようとしてますが、これらの推定は作り手がDCCツール上で意図したボーンのローカル軸と完全には一致しません。その結果、「ソフト間で挙動が異なってしまう」「作り手の想定どおりのアニメーション結果にならない」という現実的な相互運用性・互換性の欠如につながってしまう現状があると思います。

また、今後の議論としてはDCCレベルでのローカル軸機能(ボーン姿勢とは別に回転の基準座標をボーンごとに設定できる機能)とglTFレベルでのローカル軸は概念として明確に区別して議論した方が混乱が少ないと思います。

自分の参考ツイート: https://twitter.com/emadurandal_cgj/status/1377396480953122819 Mayaのジョイント方向についての参考リンク1: http://3dcgr2lab.com/2017/11/14/maya-setup-skeleton-rule-direction/ Mayaのジョイント方向についての参考リンク2: https://download.autodesk.com/global/docs/maya2013/ja_jp/index.html?url=files/CSS_Orient_a_joints_local_axes_manually.htm,topicNumber=d30e274617

emadurandal avatar Mar 31 '21 23:03 emadurandal

そうですね。Mayaのジョイント方向は少し特殊なので、私が言い表したいのは回転値がボーンの向きに反してワールド座標に正規化されることを、ローカル軸が破棄されると表現しています。 その為、ここではUnityのトランスフォーム情報要は回転値に対しての話をしています。

分かりやすいのは、この背骨ボーンがボーンの接続方向に対してワールドにリセットされてる状態(その上で接続されている) Unityで表現するなら、トランスフォームが回転値が同様にワールド方向にリセットされる。

例えば、この画像はMetasequoiaでglTFとして読み込んだ状態です。 このような状態になっていると、ポーズの設定などが困難になります。(特に指摘がある指など) glTFをサポートしてる環境では、ボーンの接続に対してその方向が維持されることをローカル軸を保持すると表現しています。

https://github.com/vrm-c/UniVRM/issues/731 ボーン回転バックアップ、ボーン回転復旧機能 VRMの拡張情報としてその情報を保持しておいて、「VRM」としてインポート時に復元するissueが立っていますがその方法ではglTFを単純にインポートする環境では復元することはできません。 そのため、glTFとして最低限の情報として維持してほしいという要望です。

逆にこういった正規化処理を行いたいのであれば、このように元の回転値情報は維持してVRMのインポート時にその処理を行うというのが理想です。

その上で、UnityでFBXをイポートしてHumanoidをセットアップしたときのようにリターゲットシステムが、リグとして設定される。そして、アニメーションとして動作させるのはそのリグである。(これが理想) Unityで言う、Humanoidシステム、MotionBuilderでいうコントロールリグシステム(両者の設計者は同じ) https://area.autodesk.jp/movie/motionbuilder/02-characterize-control-rig.html

そうすれば、VRMインポーターを作る際にその処理を実装するれば正規化処理が行え glTFとしては元の回転値が維持されたデータが読み込むことが可能です。

pixiv-sigepon avatar Apr 01 '21 01:04 pixiv-sigepon