-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VRMのデータ的でのローカル軸の維持 #34
Comments
手動でTpose化すれば問題ない、自動Tpose化するとモデルが壊れるというuniVRMのTpose化issueになりませんか? ローカル軸の保持は利用アプリ上での正規化を要するものとなり規格としての標準化の意味を薄めると思います。 また、アプリからのエクスポートであればアプリ側独自のTpose化実装もできるのではないでしょうか。 |
エクスポート時に独自にTポーズ化を行うことはできるのですが、そもそもモデルのローカル軸を消してしまう仕様が元のモデルの持つローカル軸の破壊的仕様と感じました。 その為、Humanoidを扱えないような環境で読み込む場合もローカル軸の再設定を行うという処理も不要になります。 |
仕様通り正しく厳密にTposeになっていると仮定すれば、各humanoidボーンのローカル軸は固定の値を用いることができます。 なぜなら、Tpose化によってローカル軸情報-回転をジョイント・頂点座標情報にBakeされていると言えるからです。(仕様に明記されていないこと・標準に実装されているTpose化機能が問題ではありますが…) これにより、汎用的にモデルに動きをアタッチできます。 モデルにローカル軸情報を持たせることは、正規化(というより仕様準拠化)-Tpose化による上記利便性を失わせることになります。 参考: slideshare - unite-tokyo-20193dvrm の26枚目2項目目,33枚目 |
これは、ローカル軸情報を持つ上で正規化した情報を別に持つ(VRMの拡張として保持する)ことで解決することだと思いますが、その仕様ではダメな問題はあるでしょうか? そのように、モデルのボーン情報が本来持ってるローカル軸は維持してVRMの拡張情報として正規化した情報を別に持てばいいのではないかと考えます。 |
私は以下よりこの仕様は不要だと考えています。
|
(モーキャプに最適化された | 一般化されたモーションを持ったアプリに対する)3Dアバターフォーマット、から離れた使い方を使いやすくするべきという話は、VRM-Cの方々の判断すべきところであると私は考えますので、これ以上申し上げることはございません。 ただし、ボーンの向きとギズモが合わない言うのは、VRMとしてはTposeに反しているという問題です。これはuniVRMのTposeを通していればuniVRM、それ以外であればモデル固有の問題であり、ここで議論すべき問題ではないでしょう。Tpose化の問題であればuniVRMのリポジトリへissueを建てるべきです。 o0O(画像大きすぎて読みづらいです…高さタグ等で調節いただけると幸いです...e.g:)
|
画像サイズ小さくしておきました。 |
一点確認させていただきたいのですが、その2体に当てたポーズはそれぞれそれ専用に設定したモーションデータでしょうか?それとも同じデータでしょうか? 公開されているVroidのデフォルトTposeは人間が(普遍的な・見栄えよく)Tposeした時の姿勢をボーン初期姿勢として持っていると認識しています。同じポーズを適応しているのであれば、
という、人間として少し不自然な姿勢(モデリングできないので書籍頼みの知識です))から、キャリブレーション時のようなTposeを取っているときの姿勢への差分をポーズモーションへ適応しないと差異が出るのは当然と思います。ここに、仕様Tposeはモーションデータを作るときに留意すべき初期姿勢状態であるというDocumentationが必要でないか、というissueが考えられます。 |
2体に当てたモーションデータは、Humanoidモーション化した同じデータです。 ■左側 下記に該当する状態
■右側 状態としては、この仕様に準拠した状態です。仰ってる通り自然な姿勢からは逆に曲がる状態ですね。
この状態、もう一点問題がありました。
通常はこのように回転値をすべて取り除く正規化を行っても、その背骨も含めた自然な初期ポーズを取るモーションを作成し、Genericで適用した場合はそれらのキーが反映されるのでちゃんた自然なポーズになります。
現在の仕様が、「背骨が真っすぐ」が仕様となっている場合、上記現象がおきるため「背骨が真っすぐ」ではキャラの印象が上記のように損ねるのでHumanoidでは「人として自然な状態のTポーズ」になっていれば問題ない、逆にそれを真っすぐにするとキャラ性を損ねる問題があるのが分かりました。 |
理解としては、humanoidモーションの適用において、初期姿勢のキーを最初に打っても以降別のモーションを当てると初期姿勢のキーが残らないという問題ですね。 モーションを当てた場合ーアバター以外の使い方をした時に発生する(リターゲティングされたモーキャプデータであれば問題はないのではないかと思います、識者意見求む)、unity HumanoidとVRM1.0仕様のTposeとかみ合っていない問題と見えます。 また、仕様に合わせてTposeにするとアバターの印象を与えたい姿勢と(モーキャプにせよ手付モーションなどにせよ)アクターの姿勢との差異の吸収させるは解決が難しい問題だと思います。かつ別issueですね。どこにどう提起すべきなのか分からないですが… バーチャルキャストはクライアント側でそれ実装しているように感じる (tweet @virtual_cast)ので、クライアントで解決すべきという思想なのかもしれませんが。どうなの?@vrm-c 氏~識者氏~ p.s. 脚がガクガクするのは汎用IKを真っすぐ繋がったボーンにリグセットアップ・ヒント無し(blenderでいうpole targetのような物)を適応すると、優先的回転軸を見失って、フレーム毎の計算結果に一貫性が失われることによるものでしょう。理屈からいえば脊椎、腕や指でも同じことが起こりえます。VRMクライアントに専用IKが組まれていれば or インポート時にIKセットアップされるよう設定すれば-(人型前提で、デフォルト姿勢が明らかで一意であれば曲がる方向は明確なので、自動セットアップは困難ではないはず、どのみち手間はありますが、ローカル軸はTpose依存固定仕様でもモデル固有仕様でもやることは同じでしょう(見る値が違うだけ))、解決できると思います。 |
VRM的には、T-Poseからローカル軸を得てください。 また、Unityのmecanimはブラックボックスで詳細がよくわからないのでこれを基準に仕様を作ることができませんでした(mecanimがどこからどこまでの機能を指すのかよくわからないところですが・・・)。UnityのHumanoidポーズがmascle値の配列で表現されるところですが、これがリターゲットなども含んでいるようですがブラックボックスで同じ動作を作ることができません。 VRMとUnityHumanoidの共通点は、
あたりで詳細は特に互換性がありません。 |
たしかに3軸全部完全にあわせる必要なさそう。 ボーンに沿った軸が必要な場合は、以下のようにローカル空間を各ボーンで求めてください。 // spine の例
var y = (tail - head).normalized;
var x = Vector3.right; // ボーンごとにワールドと一致するべき軸が異なる
var z = Vector3.cross(x, y);
// x, y, zが正規直行基底 ローカル空間がボーンに沿ったものになるはずです。 |
社内での議論の様子をまとめました:
したがって、ひとまずVRMとしてはHumanoidボーンの回転値について制約を設けない方針に切り替えるのが良いと思いました。 |
既存のプログラムが壊れて互換性無くなるので、それはできません。 |
私は、むしろ変えるなら今しかないと思っています。 あまり良くわかっていないのですが、各ボーン軸をワールド軸に向ける処理というのは、アプリケーション側で実行するのはそんなに難しいのでしょうか? |
口頭で議論を行いました。 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 のような実装に頼らずとも、プラットフォーム間でアニメーションの互換性をある程度保つ事が可能ではないでしょうか。アバターとアニメーションは切り離して考えるべき、と言う意見もあるかもしれませんが、アバターを用いてアニメーションやボーン操作を行わないという事は原則あり得ません。ボーンアニメーションのデータには基本的に相対値が用いられますが、アニメーションを作成するアバターと適用するアバターでローカル方向が異なると回転方向が変わってしまうので、ローカル方向の定義が重要になります。 |
Unity 以外のゲームエンジンでゲームやアニメーション用途での VRM 使用を検討しているのですが、ここまでの議論を拝見すると TokageItLab さんやしげぽんさんの仰る通り今後様々な用途での VRM 利用を考えるとボーンのローカル軸を破棄する仕様には無理があると考えています。破棄するのではなく glTF の拡張情報として正規化に必要となる情報を持たせる案に賛成です。 VRM の思想としてルックの一貫性・ポータビリティを担保したいという意図はわかりますが、情報が破棄されると元に戻せないのが問題だと考えています。 glTF の拡張情報として正規化に必要となる情報を持たせて、VRM の仕様としては正規化されたデータを見てください、という仕様では駄目でしょうか? |
本件と関連して #214 を新しい issue として追加しました。メッシュやボーンの情報などソースとなる3Dデータに対する破壊的変更に関連して VRM としてより広い思想の転換が必要かと思い問題提起させていただきました。VRM に必要な情報は VRM の extension として格納すべきだというのが私の意見です。 |
本件 #214 のような根本解決を望みますが、とりあえず影響範囲が少なそうな折衷案としてはアドホックですが『元の姿勢がどうであったか』という情報だけ追加プロパティとして持たせるというのはとりあえずの対策として(根本解決を何年も待つよりは)考えていいのかもしれません。回転だけバッファに格納すれば追加サイズは1ノードにつき |
本件に関しまして私の方でも問題点と解決案をまとめていまして、今月末に開催される VRM 勉強会で発表するように考えていました。 本件はいくつかの issue に跨がる問題であり、また Unity 以外の環境についても考慮・説明する必要があるので、まとめるのに手間取っておりますが、少なくとも一つ言えるのは現状のロール軸の定義に2軸使っているような定義では親指の回転方向を定義する事が明らかに不可能なので Unity 依存を断ち切る上では定義の変更は避けられないという事です。 |
BlenderのVRMアドオンに言及があったので補足です。VRMアドオンは最近のアップデートで、Blender 2.83以降の場合のボーン方向の推定にglTF 2.0アドオンのFortuneを使うようになりました。Blender 2.83未満の場合はFortuneが無いのでこれまで通りオリジナルのロジックを用いて方向推定を行います。Fortune自体も、もともとglTF 2.0アドオンのVRM対応のために導入されたっぽく見えます |
恐れながら、ローカル軸の破棄により起こる問題と改善案をまとめさせて頂きました。 https://qiita.com/TokageItLab/items/e5880123a9f508b2769d 改善案についてはあくまで提案なので、完全にこの通りにしろというわけではなく(して頂ければ幸いですが)、そこは議論していく所だと思いますが、記事中のまとめ部分に記述したように、最低限以下の2つは「プラットフォームを越える汎用アバターフォーマット」として必要であると考えます。
関連 |
議論に参加させていただきます。 私もローカル軸の情報は残した方が相互運用性と互換性(現実的な意味でどのソフトでも作り手やユーザーが望む結果になるという意味での)がむしろ高まると思います。 しげぽんさんの以下の指摘については、これはMaya等のボーン自体の姿勢によらずボーンの回転の基準となる座標系をボーンごとに決められる(Mayaのジョイント方向=ローカル方向軸=Local Rotation Axis)DCCツールでなければできないと考えており、
例えば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)にリセットしてしまうのが問題なのではないでしょうか。 現状、プログラム制御でVRMモデルを(モーキャプなどでの回転値の上書き以外の方法で)動かしたい人たちは、VRM Addonなどのボーン方向(ローカル軸)の推定機能を使ってなんとか運用しようとしてますが、これらの推定は作り手がDCCツール上で意図したボーンのローカル軸と完全には一致しません。その結果、「ソフト間で挙動が異なってしまう」「作り手の想定どおりのアニメーション結果にならない」という現実的な相互運用性・互換性の欠如につながってしまう現状があると思います。 また、今後の議論としてはDCCレベルでのローカル軸機能(ボーン姿勢とは別に回転の基準座標をボーンごとに設定できる機能)とglTFレベルでのローカル軸は概念として明確に区別して議論した方が混乱が少ないと思います。 自分の参考ツイート: https://twitter.com/emadurandal_cgj/status/1377396480953122819 |
そうですね。Mayaのジョイント方向は少し特殊なので、私が言い表したいのは回転値がボーンの向きに反してワールド座標に正規化されることを、ローカル軸が破棄されると表現しています。 分かりやすいのは、この背骨ボーンがボーンの接続方向に対してワールドにリセットされてる状態(その上で接続されている) 例えば、この画像はMetasequoiaでglTFとして読み込んだ状態です。 vrm-c/UniVRM#731 ボーン回転バックアップ、ボーン回転復旧機能 逆にこういった正規化処理を行いたいのであれば、このように元の回転値情報は維持してVRMのインポート時にその処理を行うというのが理想です。 その上で、UnityでFBXをイポートしてHumanoidをセットアップしたときのようにリターゲットシステムが、リグとして設定される。そして、アニメーションとして動作させるのはそのリグである。(これが理想) そうすれば、VRMインポーターを作る際にその処理を実装するれば正規化処理が行え |
@emadurandal 整理するために一度「レスト」と「ポーズ」という単語を使わせて下さい。(ポーズの起点がレストです) Maya については Joint orient = レスト、Transform rotate = ポーズ であり、そして Maya からエクスポートされる glTF 内のジョイントが持つ回転はレストであるという事で合ってますでしょうか? また、この issue ではレスト = ローカル軸と呼んでいます。ローカル軸 が local axis rotation だとして、rest rotation と pose rotation のように回転にも種類があるので、個人的には rest という言葉を入れる、もしくは orient と rotate のように明確に単語を分けるなどしたほうが、もし VRM の方で呼称を統一するとしたら分かりやすいのかなと思ったりしてます。 追記:こんな感じで用語の混同が起きている気がします...(間違っていたらすみません) How to notate rest and pose state
|
@pixiv-sigepon @TokageItLab はい、多分認識は共有できていると思います。
はい、ここらへん呼び方を区別した方がスムーズにみんなで議論できそうです。MayaやBlender等のDCCに通じている方たちの意見もさらに増えてくると良い議論になりそうな気はしております。 |
@pixiv-sigepon 私もこれが現実解の一つのように思います。 もしくは、 @TokageItLab さんがQiita記事で提案されているように、多くの需要を過不足無く満たす新たな正規化仕様またはガイドラインをVRMとして決めて、VRMの各実装はそれに従ってもらう。という方向性のどちらかが良いと思います。 個人的には何かしら方向性(汎用性を犠牲にしない程度の新しい制約)を示してあげた方が迷いがなくなるので、後者までやりきれれば理想と思いますが……。 |
ボーン回転方向について、おそらく Kinect での使用を意識していると思われる Microsoft Rocketbox アバターでのボーン回転を確認してみました。ご参考まで。 TokageItLabさんの記事の通り、手と足について屈伸方向の回転を行うと、胎児のように縮こまるポーズになります。足が三角座りのようになり手がクロスする方向に動いてより胎児のようなポーズになっているのが特徴かと思います。 モデルはこちらで確認できます Female_Adult_01.fbx |
@infosia そちらのモデルで手がクロスするのは A スタンスだからですね、ちなみに肩の屈曲方向に関しては筋収縮(大きく動く側)で統一するのであれば、上側に、いわゆる肩をすくめる時の方向になると考えています。 記事の方には書きませんでしたが、屈伸・捻り・開閉のような3軸で考えるという手法は Unity Humanoid の Muscle 値の方でも用いられているので(単語は異なったりしますが)その辺りの互換性も踏まえて、軸の役割を優先した定義を行うのが適切なのではないかと提案させて頂きました。 また上腕に関して、kinect では T ポーズから上腕を前後へ動かす回転を屈伸とみなしているように見受けられるのですが、恐らくこれは人間工学・解剖学分野からの引用で、解剖学では直立姿勢を基準として、上腕を前後に振る回転を屈曲(flexion)・伸展(extension)と見なしているので、それに対応付けた結果だと思われます。 参考: https://brookbushinstitute.com/article/joint-actions ただし解剖学の流用が 3DCG 分野の T ポーズが基準となるというケースにおいて最適であるかどうかは分かりません。そこまで拘ることでもありませんが、私個人としては T ポーズから上腕を前後へ動かすよりも、T ポーズから上腕を上下に動かす回転の方がメインの運動を行う回転すなわち筋収縮として適切であると考え、記事に記載したモデルでは(恐らく解剖学的には外転・内転)を屈伸と見なしました。 解剖学の知識が前提にあると部分的に用語の混乱が起こるかもしれませんが、そもそも解剖学とは基準のポーズが異なり、「3DCG 的には T ポーズを起点として複数の回転が混在する動き」を「解剖学では一つの屈伸としている」ので、3DCG と解剖学では「屈伸」という単語は別のものとして考えるべきではないかと考えています。[※1] とはいえ、既に存在している解剖学に合わせたほうが都合が良い可能性も捨てきれません。その場合、上腕だけでなく肩に関しても解剖学的には前に倒すほうが屈曲となる筈です(有識者意見求む)。回転させても胎児のポーズにはなりませんが、これはこれでロールが肩から肘まで一致するので整っていないこともないと思います。 要は「T ポーズからの筋収縮を屈曲とするか」「解剖学の用語に合わせたものを屈曲とするか」といった所なのですが、もし軸への再定義を行うのであればその辺りの最終的な判断はコンソーシアムの方へお任せします。 ※1: ちなみに Unity Humanoid Muscle では上腕の動きに関して解剖学の概念は流用しておらず、Down-Up / Front-Back と定義されています。また複数のボーンで見られる Twist in-out というのは少し解剖学の概念(内旋・外旋)が入ってきているように思えますが、捻りの方向を明白にするという点で有用です。このように全てを解剖学から流用する必要はなく、3DCG にとって便利であるような定義を行うというのが理想的だと考えています。 |
最近リリースされた Meta Avatars SDK にサンプルとして添付されていた Meta アバターのファイル形式が glTF (圧縮された .glb、独自 extension 含む) だったので、ボーンの構造だけ抽出してみました。 https://github.com/infosia/themachinery-issues/blob/master/0017/0_quest.blend (Blender が必要です) mixamo などともちょっと違う変わったボーン構成のようですが上腕のボーンなどはローカルのX軸を回転させると屈伸します。上腕の回転は前後(Kinnect と同じ)のようです。 ご参考まで。 |
VRM1.0のリリースに伴って要旨は満たされましたので、本issueはクローズします。 今後、本件に伴って別の問題が発生した際は、別途issueを立ててください。 |
UniVRMの方とどちらが適切か悩みましたが仕様に関わる部分だと思うのでこちらに投稿致します。
現在の、UniVRMで正規化処理を行うとボーンをUnityのHumanoidに最適化したポーズを取り各ボーンの軸がすべてワールド座標に向いて正規化されます。
UniVRMで出力されたデータを、GLTFローダーなどで読み込むと分かりやすいです。
例えば、このように指に対して適切にローカル軸を設定したボーンが
このように、UniVRMでHumanoid向けに正規化されるとメッシュに対してローカル軸が消え、ワールド方向に向き曲がる方向がおかしくなってしまいます。
VRMの仕様定義で、各ノードに回転は無いこととあるのですが回転値を0値にするのは構わないですが、Humanoidに最適化したポーズに変形して上記の正規化処理を行うとローカル軸が消えてしまい、Humanoidが実装されている環境以外で読み込むと曲げる方向がおかしくなってしまったりします。
例えば、FBXをHumanoidのセットアップを行った場合元のローカル軸は維持されその上でHumanoidの設定が適用されます。
VRMの仕様的にも同様に、ベースのGLTFのデータ的には元のローカル軸を維持してその上でHumanoidに対応する処理を行う仕様になって欲しいです。
UnityのHumanoidのTポーズ化に依存しないで、ローカル軸の値を0値にした場合指はこのように真っすぐに向いてメッシュと軸方向がちゃんと一致した状態になります。
UniVRMで行われている処理は、正規化時にボーンのParentをすべて解除してワールド方向に向けて再Parentしているのではないかと思います。
こちらのエンジニアの方で、ローカル軸を維持したVRMデータを作成できるように検証を行ってもらいましたが、ローカル軸を維持した状態のVRMも作成でき問題なく動作しているようでした。
The text was updated successfully, but these errors were encountered: