3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MoAR - Museum of ARAdvent Calendar 2022

Day 22

MayaとUSDZでSceneKit(2)

Last updated at Posted at 2022-12-20

トラブルシューティング(Tips)

前編のMayaとUSDZでSceneKit(1)に引き続き、後編ではemocの制作を進めていく上で気付いたトラブルシューティング(Tips)をまとめています。

アセットの配置が合わない

座標系の違い

image.png
MayaからエキスポートしたUSDZファイルをXcodeでインポートすると、既存の背景データと向きが合わない問題が見られました。
同じ環境であれば起こりにくい問題ですが、座標系の異なるDCCツールやゲームエンジンの組み合わせだと注意が必要です。

  • MayaとSceneKitの座標系はY-Upの右手座標系で同じ
  • BlenderはZ-Upの右手座標系なので、そのままでは向きが合わない
  • その他のソフトでも座標系が異なるので、基本的に実装する出力先に合わせるて揃える

MayaやBlender、Cinema4DなどのDCCツール、Unity、UE4、SceneKitなどの描画エンジンで扱う座標系の違いを揃えないと向きが揃いませんし、無駄に座標変換する必要が発生してしまいます。
また、スケール値についてもデフォルトがセンチメートル単位、メートル単位が混在してますし、一部のソフトではインチ単位となっているので単位系についても注意が必要です。

今回の場合は、MayaとSceneKitの座標系は同じ内容だったのですが、背景データを作成したBlenderの座標系がMayaと異なっていました。

トランスフォームのフリーズとリセット

座標系の違いを考慮して向きを変換しても、Blender側とMaya側で位置が合わない問題が見られました。

特に屋外でのARコンテンツの場合は、地図上の特定の地点や建物の形状と合わせる必要がありますが、位置の確認をBlenderで行なっていたため、この位置合わせやチェック用のカメラアングルが合わない不都合が発生してしまいました。

image.png 
ハイライトされていない部分がBlenderデータからインポートした状態

image.png

Blenderデータ側の各階層でトランスフォーム情報にフリーズされていない状態でエキスポートされていたので、
オブジェクト -> 適用 -> 全トランスフォーム
を適切に設定した上で再エキスポートすることで解決しました。

同様にMayaで制作したキャラクターについても、ジオメトリノードは全てトランスフォームをフリーズ、リセットしてからエキスポートする必要があります。

Modify > Freeze Transformations
Modify > Reset Transformations

(補足)キャラクターの場合はスキニングする前にフリーズしておく必要があります。

XcodeにインポートしたUSDZファイルでアセットの配置がズレる場合は次の点を確認してみて下さい。

  • 使用したDCCツールと使用するゲームエンジンの座標系、単位系について違いがないか?
  • 適切にトランスフォームをフリーズ、リセットされているか?

※スケルトン関係については次の項目でまとめています。


スケルトン関係の注意点

一番上の階層のスケルトンはワールド座標原点に配置する

ジオメトリーのトランスフォームをフリーズした状態でも、スキニングされたキャラクターだけは座標軸の向きも原点からの位置、角度もズレていました。

image.png

(左) スキニングした状態のキャラをXcode上にインポートした状態だと座標軸の向きも原点からの位置、角度もズレている
(中) JointOrientをWorldに合わせてからバインドし直すと座標軸の向きと角度は解決したけど、原点からの位置がオフセットされている
(右)一番上の階層のスケルトンが腰の位置になっていたので、ワールド座標原点にダミーのスケルトンを用意することが解決

明確な答えは見つけられませんでしたが、検証したところJointOrientはWorldに合わせ、一番上のスケルトンをワールド座標原点に配置することで解決することがわかったので、スキニングされていないダミーのスケルトンを一番上の階層に用意することで対応しています。
※既にSkin_Rootというスケルトンがあったので、Skin_Originというノード名になっています。

また、必ず発生するわけではないのですが、一番上の階層のスケルトンやその上のグループノードにスキニング情報が残っていると横倒しになることがありました。


スケルトン階層の途中にスケルトン以外のノードを含めることが出来ない

USDではスケルトン階層の途中にスケルトン以外のノードを含めることが出来ないので、オフセット用にグループやロケーターを挟む事が出来ません。

シーンデータ内のリグの階層はスケルトン階層と混在させず別に用意して、USDZファイルへのエキスポート対象しないようにする事で共存可能ですが、その際エキスポート用のSetsを登録しておくと便利です。


SceneKitで扱える最大インフルエンス数

https://developer.apple.com/documentation/scenekit/scnskinner/1522986-boneweights
image.png

SceneKitではインフルエンス数を4以下に抑えておかないとCPU処理になるのでパフォーマンスが低下する模様です。
ブレンドシェイプの扱いについての記載は見つかりませんでしたが、ブレンドシェイプターゲットごとに1個としてカウントされる可能性が高いと思います。

SceneKitに持って行けないアニメーション情報

Mayaでキーフレームを打っても、SceneKitで再現されないのアトリビュートが多くあります。

Visibility
Visibilityにキーフレームを打って表示・非表示を切り替えるアニメーションをつけても、SceneKitの表示・非表示のプロパティには反映されません。
usdviewで確認するとVisibilityのアニメーションも再現しているので、このせの制約はUSDの仕様ではなく、SceneKit側の問題だと思われます。

カスタムアトリビュート
USDのドキュメントを見るとMayaカスタムアトリビュートを扱う方法が見つかりましたが、こちらも同じくSceneKit側からアクセス出来ませんでした。

マテリアルのアトリビュート
色のパラメーターを変化させたり、点滅させたりとマテリアルのアトリビュートを変化させてもSceneKit上では確認することが出来ません。

このようなアニメーション要素をどうしても持って行きたい場合は、ダミーのスケルトンを用意して移動値などに焼き付けてSceneKit側で参照するように実装してもらう必要があります。

ファイルサイズを抑えるためにテクスチャーを圧縮する

UnityやUnrealEngineではモバイルプラットフォーム向けのテクスチャー圧縮形式(PVRTC/ASTC/ETC2)を利用することが一般的ですが、SceneKitでの実装について確認出来なかったのでMozJPEGエンコードのJPEG形式で対応しています。

textureComp1.png

このテクスチャー画像の場合、1,236KB → 164KBと約86%削減しています。

エンコーダーのインストールにはHomebrewを利用

$ brew install mozjpeg
$  mozjpeg -quality <圧縮率> -outfile <Resize File>.jpg <Source File>.jpg

ブレンドシェイプアニメーション

とにかくブレンドシェイプ関連はトラブル続きで大変でした💦

スケルトンだけで表現出来るようにセットアップを頑張るのが正解だと思います。
それでもどうしても使わないといけない人のために、いくつか書き残しておきます。

まず、登場するキャラは1体だけなのですが、各演出によって異なる形態(バリアント)が必要となりアセットデータとしては3種類用意しています。
MoAR記事のネタ.png

名称 コメント
emocS デフォルトのキャラクター
emocL ビルの屋上に登っている演出だけ巨大化している
slime ビルのモニター画面から登場してくる演出はスライム状態

image.png
emocS/Lは表情に合わせた口の形に対応してボディも変形する必要がありブレンドシェイプとスケルタルアニメーションを併用しています。

slimeはコンテの段階からブレンドシェイプアニメーション対応がリクエストされていましたので、目玉以外はブレンドシェイプ対応しています。


ブレンドシェイプを有効にしてUSDZファイルを出力するとフラットシェーディングになってしまう

スムージンググループが参照できためか法線情報がインポート出来ないみたいです。

今回ブレンドシェイプを使用したスライムについては平面のスクリーンに映し出された状態から登場する演出上、コンスタントなシェーディングを使用していたのでこのままで問題なかったのですが、通常のスムースシェーディングにするにはSceneKit側で法線情報を再計算させる必要がありそうです。

同じUSDZファイルに複数のキャラのブレンドシェイプアニメーションを含めることが出来ない

キャラ1体分だと問題がなくても、複数のキャラのブレンドシェイプアニメーションを1つのUSDZファイルにエキスポートしようとすると正常に動作しませんでした。
そのためブレンドシェイプアニメーションを使用するキャラは別のUSDZファイルに分けて用意する必要があります。

アニメーションのタイミングがズレる問題の修正箇所が増えて大変だった

後述するキーフレームアニメーションのタイミングがズレてしまう問題を修正する時、スケルトンだけでなく、ブレンドシェイプもあると修正箇所が増えてリテイク対応が大変でした。😩

最終的にブレンドシェイプアニメーションしているのはスライムだけになった

アニメーションのタイミングがズレる問題のデバッグが大変だったこともあり、emocS/Lは SSDR(Smooth Skinning Decomposition with Rigid Bones) を利用してブレンドシェイプアニメーションをスケルタルアニメーションに変換するように方針変更することになりました。

Maya上のアニメーション作業はブレンドシェイプアニメーションのまま変わらないのですが、USDZにエキスポートする前に以下のプラグインを使用してスケルタルアニメーションに変換しています。

SOuP SSDR

vidiaApps vastSolver2

2つのMayaプラグインを検証したところ、emocS/Lでは変換結果の良好だったvastSolver2を使用しています。

emocLSkelton.png
トライ&エラーが多くなり検証に時間がかかりましたが、vastSolver2のパラメーターを最適化していく事でemocS/Lについては最終的にスケルトン数の増加を微増に抑えられるようになりました。

vastSolver2は一度作成したスケルトン構成を維持しながら、アニメーションを再計算することもできるのでかなり実用的なSSDRプラグインだと思います。

注意点としては、Maya2023に対応していなかったので、この部分だけMaya2022を使用しています。

slimeSkelton.png
スライムについてはSOuPのSSDRコマンドの方が良好な結果が得られましたが、それでもブレンドシェイプと同等のスムーズな変形に対応できるようにするには、大幅にスケルトン数が増加してしまうため本番採用は見送りとなり、ブレンドシェイプアニメーションを使用したUSDZファイルで対応しています。

このようにUSDZファイルとSceneKitの環境ではブレンドシェイプアニメーションをスケルタルアニメーションに変換するのは有効な方法でしたが、利点と欠点について簡単にまとめておきます。

(利点)
 ブレンドシェイプノードが含まれている複数のキャラを1つのシーンデータで扱える
 ブレンドシェイプとスケルトンのアニメーションのタイミング(キーフレーム)がズレる問題が発生しない
 フラットシェーディングの問題は発生しない

(欠点)
 形状や変形によってはスケルトン数が大幅に増加する
 変換作業に時間がかかる(サンプリング数とアニメーションの長さに依存する)

UnityやUnrealEngineだとこの辺りで苦労することはあまりないのですが…
結論としてはSceneKitの場合ブレンドシェイプアニメーションの使用は推奨しません!


アニメーションのタイミングがズレる

USDZファイルをXcodeにインポートすると、アニメーションのタイミングがズレることで建物やキャラのめり込む不具合が頻発したので、Mayaから出力されたUSDZファイルの内容とSceneKit上の動作を比較して検証したところ、次のような問題が見つかりました。

SceneKitのキーフレームの扱いについて

キーフレームをベイクしてもUSDZにエキスポートすると変化の無いキーフレームは省略される

USDファイルに出力すると変化のあるキーフレームしか出力されていない
image.png

キーフレームをベイクしてもUSDファイルには反映されていない
image.png

USD Toolsetに含まれていたusdcatコマンドでUSDZファイルを展開し、シーン情報をテキストエディターで確認してみると…
0Fからキーフレームをベイクしていても0F と1Fの値に変化がなければキーフレームが出力されていませんでした。

普通はこれで特に問題が起きることはないのですが、SceneKitでは最初のキーフレームを開始フレーム0.0秒として相対的な秒数でモーション時間が扱われているので、上記の場合であれば3F分タイミングがズレてしまうことがわかりました。

つまりemocSとLで最初の変化のあるキーフレームが0Fと3Fで異なっていると、開始フレームが3F分ズレたアニメーションが再生されることになります。

そして、ブレンドシェイプアニメーションのキーフレームも同様なので、同じキャラでもスケルトンとブレンドシェイプのタイミングがズレてしまいメリ込みが発生していました。

(補足)

  • usdviewでアニメーションを確認すると問題が見られないことからSceneKitでのキーフレームの扱いの問題だと思われます。
  • SceneKit上でuses​Scene​Time​Baseを適用しても解決しませんでした。

対応策

対処療法的な解決ですが、キーフレームの先頭にタイミングを揃えるため次のような対策を行いました。

image.png

フレーム数 コメント
0F バインドポーズでキーフレームを打つ
1F ダミーのキーフレームを打つ
2-3F バインドポーズでキーフレームを打つ
4F以降 実際に使用するキーフレーム情報

・スケルトンだけでなく、ブレンドシェイプアニメーションのキーフレームも同様です。
・ループ再生するシーンの場合ループの開始フレームまで頭出しが間に合わない不具合が見られたので、開始フレームを3F以降に調整しています。


SceneKitでUSDファイルで対応している機能


最後に

USDZとSceneKitの組み合わせは、普段のゲーム開発や映像制作とは違って慣れないファイル形式と描画エンジンで苦労も多かったのですが、今後も機会があれば取り組んで行きたいと思います。

最後に、今回このような機会を頂きWhatever Co.ならびにKASSENの皆さんに感謝申し上げます。

さとうゆーじ

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?