uetokyo / UnrealVRM

A VRM (VR Avator 3D Format) Support Project for Unreal Engine

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Approach of Loading VRM file(VRMの読み込み処理の実装についての方針)

emadurandal opened this issue · comments

VRMはglTF2.0ベースです。glTF2.0に対する拡張として、JSONトップ階層の"extensions"という部分に拡張情報を格納するフォーマットになっています。
そのため、読み込み処理としての切り分けがかなりやりやすいです。

標準実装であるUniVRMでは、VRMのglTF2.0部分の読み込みについてはUniGLTFというほぼ純粋なglTF2.0ローダーライブラリに依存し、それ以外の拡張部分を別の箇所で読み込み処理の記述を行なっています。

本プロジェクト「UnrealVRM」でも、同様のアプローチが取れるのではないかと思います。
すなわち、VRMのglTF2.0部分の読み込み処理は、UE4 4.19以降で搭載される標準のglTFローダーに任せ、それ以外の部分を自作するという方針です。

commented

現状のUE4(4.19)には高度なglTFローダーはついておらず、必要最低限の実装となっています。
Engine/Plugins/Editor/GLTFImporter/Private/GLTFReader.cpp .h

glTF2.0の内容を網羅しているわけでもなく、拡張しないといけないことを考えるとそのまま利用するのは難しいと考えています。UE4自体はJSONを扱うためのライブラリーを持っているので、そのまま使えるはずという認識です。

ただ、考え方や使い方は流用できると思います。

現状のUE4(4.19)には高度なglTFローダーはついておらず、必要最低限の実装となっています。

はい、そうなのですが、こちらも隙間時間くらいしか開発時間が取れないはずなので、GLTFReader.cpp .hの成長に合わせて、一緒に作っていくのもいいのかな、という意味でした。

VRMインポーターは**としてランタイムでの利用が必要だという認識ですが、GLTFImporterモジュールはEditorModuleとして実装されているので、プルリクして設計から変えない限りは今後も利用できないと思います。

@HogeTatu
ご意見ありがとうございます! 大変助かります!
そうか、確かにランタイムに読み込んでスポーンさせる、といったことにそのまま対応できませんね。
ちょっとここは考えどころですね。

commented

UE4のアセットはランタイムで読み込むことをあまり想定していません。
ので、厳密に対応させるのは少々骨が折れます…が、一応このような形でプロシージャルメッシュコンポーネントを使うことで読み込めないことはありませ
ん。

https://github.com/LaP0573/ue4-fbx-importer

ただテクスチャーやマテリアルの作成は別となるので、その辺りの扱いも難しいです…
とりあえず一旦ランタイムは忘れたいところです。

commented

しっかり確認していないですが既にあるglTFローダーを使用するのはどうなのでしょうか?

https://github.com/syoyo/tinygltf

commented

@durswd
どちらかと言えばこちらはパーサーライブラリーとなっており、結局はUE4専用のインポーターは用意する必要があるのでこのままでは使えません。

ファイルパーサーとしては上記で問題なさそうな気がします。パースさえできれば後はランタイムでマテリアル等を作るのも結局は各種UObjectをTransientPackageとして生成することで実現できそうです。VRMで提供されるシェーダーも種類は多くないので、テンプレートとしてマテリアルは予め作っておき、MaterialInstanceをランタイムで作ってプロパティのアサインで乗り切れそうな気も。とはいえ骨周りとかで実現性が不明瞭な部分はありますね。

皆さん、積極的にご意見をくださってありがとうございます。大変心強く思います。

実現難易度の問題はもちろん軽視できませんが、一旦それをおいて、VRMの**というか想定のユースケースを想像してみますと、どうもVRアバターの双方向のやりとりやコミュニケーション、そういった動的なものをかなり意識しているようです。

そのため、あらかじめアセットとして静的にパッケージしたモデルしか、そのUE4実行バイナリで扱えないとなると、UnityのVRMプラットフォームと比べて、どうしても汎用性に劣った限定的なものと見なされてしまいそうな気はします。

実装をステップ式にして、最初は静的なアセットとして実現。もう少ししたら動的に、という開発計画もありえますが、その場合でも、なるべく最初から動的利用を意識した設計を目指したくはありますね。

glTFローダーを
Engine/Plugins/Editor/GLTFImporter/Private/GLTFReader.cpp .h
に頼らず、自作するか外部ライブラリに頼るか、の部分についても考慮点がいくつかあると考えています。

UE4自体はJSONを扱うためのライブラリーを持っているので

alweiさんのおっしゃるように、JSONレイヤーのライブラリを使うアプローチももちろん考えられます。
その場合、JSONとしての読み込み以外の以下については、自作することになります。

  1. 頂点データやアニメーションデータなどのバイナリ部分の読み込み
  2. JSONで定義されている各種node同士の親子関係や、Mesh -> Materialの依存関係などを認識し、実際に繋ぐ処理
    (glTF JSON内でのnodeなどの各要素は、依存する他要素をただインデックスで指し示しているに過ぎないためです)
  3. glTFの各要素を、各種UE4アセットなどのUE4ネイティブ形式に変換する。

2の「依存関係をつなぐ処理」も、どのレイヤーで実現するかが考えどころです。
以下の2種が考えられると思います。

2-a. VRM(glTF)データの各要素を、一旦そのglTFローダー独自の各クラスオブジェクトに取り込んで、そのクラスオブジェクト間で依存するもの同士を参照し合う。
glTFローダーレベルから自作する場合は、このアプローチは無駄が多いかもしれません。ただし、外部ライブラリではそもそもこうした設計アプローチのものも多くあり得るでしょう。
2-b. VRM(glTF)データの各要素をUE4ネイティブの形式に変換し、互いにオブジェクトとして参照させ合う。
こちらの方が中間クラスオブジェクト表現を挟まずに済み、無駄はないですね(デメリットはあるでしょうか? 皆さんどう思われますか?)

ここら辺は地味に開発効率に関ってくる話かもしれません。