iOS12
usdz

[AR]iOS12の新機能を使って誰が見てもかわいいシロちゃん(+シロ組さん)を現実にお呼びする

はじめに

iOS12から AR Quick Lookを使用することで手軽にAR体験ができるようになりました。
この機能について詳しい解説は他の記事を参考にしていただければいいと思います。

Apple公式のギャラリーもあるので確認してみると面白いです。
AR Quick Lookギャラリー

この機能があれば、サーバに配置しておいたusdzファイルをiOS12のiPhone1からダウンロードするだけですぐにAR体験ができるのはとても魅力的です。
そこでいてもたってもいられなくなったのでこの機能を使って 誰が見てもかわいいシロちゃんシロ組さん を現実にお呼びしたいと思います。

最終的には以下のようなものを実現できました。

シロちゃん

シロ組さん

シロ組さんはこちらからダウンロードすることもできます。
ARシロ組さん
(リンクから直接 AR Quick Lookが起動しない理由は後述します)

usdzファイルの作成について

AR Quick Lookを使用するためにはusdzファイルを作成する必要があります。
以降はこのusdzファイルの作成についての備忘録を記載していきます。
多分記事が長くなると思いますので最初にどうやって実現したかをまとめます
なお以下の情報は2018/9/24時点での情報です。
これ以降に参照する場合はすでに修正されている可能性があることに注意してください。
お金があるならmayaとかを使用すれば簡単に行けるのではないと思いますが、未確認です。
特にこだわりがないのであればモデルをアップロードすればusdzに変換してくれるサービス(VECTARY)もあるのでそっちを使用するのも手です。
使ってないので詳細はわかりませんが。

usdz作成まとめ

シロちゃん(アニメーションなし)

  • blenderobj形式で出力

このときマテリアルやボーンの名前に日本語が入らないようにしておく。
マテリアルに使用されているテクスチャから透過情報は抜いておく。

  • usdz_converterobjからusdzに変換

正式リリースバージョンのXCode10に付属しているusdz_converterではなぜかusdzファイルが出力されなかったのでbeta版のXCode10を使用するとうまく動いた。

  • 配信するときはMIMEタイプをmodel/usdにする

これをしないとAR Quick Lookが直接起動しません。

シロ組さん(ボーンのアニメーションあり)

  • blenderでマテリアルを一つに統合する

複数プリミティブが存在する状態でアニメーションを適用するとなぜか表示されなくなった。
マテリアルを一つにしておけば最終的に1プリミティブになる?。

  • blendergltf形式で出力

アニメーションありの場合はgltfのほうがうまく動いた。
トランスレーションのアニメーションのみの場合はabcで出してusdz_converterでいいです。

  • gltf2usdusdaに変換

kcoley/gltf2usd
アニメーションがうまく変換されない場合はソースを修正する。
キーフレームが挿入されいていないフレームにおけるSRTの値が出力されず対象のジョイントがずれてしまうバグが存在する。

  • usdaのスケルトンとアニメーションのジョイントを修正する

ジョイントの一覧を書き出している場所で階層がおかしいので修正する。

  • usdaのスケルトンの名前を修正する

ルートのジョイントとスケルトンの名前が同一でないとなぜかアニメーションされない。
スケルトンの名前を変更した場合は元々の名前を参照している部分があるのですべて書き換える。

  • usdz_converterusdausdzに変換する

特にはまりどころはないです。

備忘録

モデルをusdzに変換する

usdzファイルを作成するにあたって軽くググった感じだとusdz_converterを使えばいいということがすぐにわかりました。
usdz_converterobjファイルを入力にとってusdzファイルを出力するツールで、XCodeに同梱されています。
既にusdzファイルのサンプルがappleから提供されており、ios12も正式リリースされているのですぐにうまくいくと考えていました。
(ここからアニメーションの存在しないモデルの表示に1日かかりました。)

usdzファイルが出力されない

usdzを出力するためのコマンドは以下の通りです。

xcrun usdz_converter model.obj model.usdz

実際に試してみるとconverted usdz file: model.usdzと表示されるものの、実際のファイルが出力されていません。
この時点でだいぶやる気がなくなってきました。
しかしusdz_converterでググると実際に使用できている感じの記事が見つかりました。
モデルが悪いのかと考えシンプルなCubeを出力し変換を試してみましたがうまくいきませんでした。
さすがにこれはusdz_converterにバグがあるかもしれないと思ったのでbeta版のXCodeを試してみたところうまく出力されるようになりました。

マテリアルが正常に表示されない

これがblender上でみたシロちゃんの👒です。
image.png

これがiPhoneでみたシロちゃんの👒です。
image.png

マテリアルが表示されていません。
どうやら何もオプションをつけずに変換をかけるとマテリアルの設定がされないようでした。
-v -a -lオプションをつけて実行するとテキスト形式のusdaファイルが出力されるためその中を見てみましょう。

xcrun usdz_converter model.obj model.usdz -v -a -l

usdaの中を見ると以下のような記述があります。

def "Materials"
{
    def Material "bousi"
    {
    }
}

(なんか日本語があると色々めんどくさかったのでこの時点ですべての要素から日本語を排除しています。)

Materialの中に何も書いてないのでこれではマテリアルが適用されていないのも当然です。
この中身を手で書いていってもいいのですが、usdz_converterの引数でテクスチャを指定すると適切にMaterialを設定してくれるということが分かりました。
そこで以下のようにコマンドを実行しました。

# マテリアルにカラーマップしか適用されていないので-color_mapオプションを使います
xcrun usdz_converter bousi.obj bousi.usdz -m /Materials/bousi -color_map bousi.png

結果は以下の通りです。

image.png

一応色は付きましたがポリゴンの表示が明らかにおかしいです。
ここから数時間かけてusdaの中身をチェックしたり別のコンバートツールgltf2usdを使ってみたりしましたが一向に解決しませんでした。

試しに同じマテリアルをCubeに適用してみたところ以下のようになりました。

image.png

なんか透けてない:thinking:?
pngの透過を削除しました。

image.png

:astonished::astonished::astonished:

モデル全体で試してみる

(なんか暗いですが)全身を表示することができました:sparkles:

image.png

ボーンアニメーション付きのモデルをusdzに変換する

モデルの表示ができたので次はアニメーション付きのモデルを変換してみることにしました。
ググるとアニメーションが存在する場合はobjではなくabc経由でusdzに変換すればいいということが分かりました。
ググったら情報が出てくるのでこれもすぐに終わると思っていました。
(ここから1日かかりました。)

アニメーションしない

abc経由で変換しても全くアニメーションしませんでした。

https://www.youtube.com/watch?v=KAMSFm0B8lY

上記の動画で普通に動いているみたいなので試しにblenderAnimation Nodesを入れてアニメーションを作りコンバートしてみました。
こっちのほうはうまく動きました。

検証を続けると、 メッシュ連番キャッシュ モディファイアによるアニメーションはうまく変換されないことが分かりました:fearful:

もう一度ググりなおしていると以下のページが見つかりました。
How to create a .usdz animation?

このページの回答にはabcで変換する手法が書かれていたためあまり期待していなかったのですが、質問の内容を見ていると編集が続いており最終的には解決したと書かれています。
実際に動くusdzファイルも公開していました。
内容を要約すると以下のようなものでした。

gltf2usdを使えばいいよ。
ただちょっとバグっているから手で修正したよ。例えばジョイントの名前とかね。

以前使おうと思ってあきらめたgltf2usdが出てきました。
もう八方ふさがりだったので前例もあるこのgltf2usdで行くことにしました。

gltf2usdを使用する前に

gltf2usdpythonで書かれたツールです。
pythonさえ入っていれば動くと思っていましたが色々と面倒なことがあります。
結論だけ書くとpyenvhomebrewpythonを入れていると動作しません。
システムのpythonを使用してください。

gltf2usdの不具合について

  • 日本語が使えない

これは別に不具合ではないかもしれません。
ソースの修正ではなくモデルの修正を行いました。

  • テクスチャが参照できない場合がある

gltfの出力オプションで画像埋め込みを選んだ場合に拡張子の問題でうまくいかない場合があります。
埋め込みを行わないか直接gltfファイルのテクスチャの名前を編集することで回避できます。

  • ジョイントとスケルトンの名前がおかしい

これが一番謎でした。
詳しいことはわかりませんが出力したusda内をjointsで検索し、すべてのパスを一階層削除すればいいです。

"hoge/piyo", "hoge/piyo/fuga"
みたいになっているのを
"piyo", "piyo/fuga"
にする

次にスケルトンの名前をルートのジョイントと同じ名前にします。
名前の変更に合わせてスケルトンの名前を参照している部分も変更します。

  • キーフレームアニメーションがおかしい

これのみデータの修正ではどうにもならなかったのでソースを修正しました。
本来なら本家にコミットすべきかもしれませんが、gltfにもusdにも詳しくないので手元でソースの修正をするという形をとりました。

本来ならジョイントの数だけ値がなければならない部分がキーフレームの数だけになっていました。
例えばジョイントが9つあるアニメーションの場合はローテーションやスケールのアニメーションの値の配列もすべて要素数が9でなければなりません。(と思う…)
しかしgltf2usdはその秒数におけるキーフレーム分の値しか出力しないため動かすべきジョイントがずれます。

頑張ってソースを修正してください。

アニメーションを適用したら表示されなくなる

たぶんiOSのバグだと思いますが詳しくはわかりません。(usdの仕様かもしれませんが詳しく見てません。)
分かったことはusdaの中に複数プリミティブが入ってるとうまく動かないということです。
マテリアルを一つにまとめてプリミティブを一つになるようにするとうまく動くようになりました。

さいごに

現状、まだまだ周辺ツールが未成熟なのでがっつりやるのはなかなかつらいです。
どこも間違っていないはずなのになぜか表示されないということも多く原因の特定が難しいです。
動かなければプリミティブな部分から一つ一つ検証していかなければなりません。
しかし、アニメーションを適用しないオブジェクトならば現状でもなかなかいいものが作れるんじゃないかと思います。
やはり追加のアプリなしで体験できるというアドバンテージは大きいと思うのでこれからに期待できます。


  1. iPhone6sより前の端末はAR表示に対応していません。