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

# はじめに

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

Apple公式のギャラリーもあるので確認してみると面白いです。
[AR Quick Lookギャラリー](https://developer.apple.com/jp/arkit/gallery/)


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

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

## シロちゃん

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ようやくシロちゃんを現実世界にお呼びすることができました😊<br>昨日よみうりランド行った後にどうしても作りたくなってほぼ徹夜だったけどなんとか完成😎<a href="https://twitter.com/hashtag/SiroTalk?src=hash&amp;ref_src=twsrc%5Etfw">#SiroTalk</a> <a href="https://t.co/msMjx4xpmm">pic.twitter.com/msMjx4xpmm</a></p>&mdash; fino (@fi_n_o) <a href="https://twitter.com/fi_n_o/status/1043783554654564352?ref_src=twsrc%5Etfw">2018年9月23日</a></blockquote>

## シロ組さん

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">動くシロ組さんARも出来ました👏<a href="https://twitter.com/hashtag/SiroTalk?src=hash&amp;ref_src=twsrc%5Etfw">#SiroTalk</a> <a href="https://t.co/iLwDF7xK6R">pic.twitter.com/iLwDF7xK6R</a></p>&mdash; fino (@fi_n_o) <a href="https://twitter.com/fi_n_o/status/1044301119919337472?ref_src=twsrc%5Etfw">2018年9月24日</a></blockquote>

シロ組さんはこちらからダウンロードすることもできます。
[ARシロ組さん](https://yaegaki.github.io/ar-sirogumi3/)
(リンクから直接 AR Quick Lookが起動しない理由は後述します)

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

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

## usdz作成まとめ

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

* `blender`で`obj`形式で出力

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

* `usdz_converter`で`obj`から`usdz`に変換

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

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

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

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

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

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

* `blender`で`gltf`形式で出力

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

* `gltf2usd`で`usda`に変換

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

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

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

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

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

* `usdz_converter`で`usda`を`usdz`に変換する

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

## 備忘録

### モデルをusdzに変換する

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

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

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

```sh
xcrun usdz_converter model.obj model.usdz
```

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

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

これが`blender`上でみたシロちゃんの👒です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/42193/39536b5f-0a2c-1c22-041f-02dcb32759a4.png)

これが`iPhone`でみたシロちゃんの👒です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/42193/93977701-8690-5793-f4a2-66944d023308.png)

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

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

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

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

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

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

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

結果は以下の通りです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42193/a215aba5-473c-a01e-76c7-7e3f01cd04ac.png)

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

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42193/ed251b76-5184-140b-e974-099a4da7baa3.png)

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42193/43d0a2a4-7538-ddc6-bef4-eb2db9539d6a.png)

:astonished::astonished::astonished:

#### モデル全体で試してみる

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42193/7f37fab1-1e20-0df8-5d7a-faf85d7aeb65.png)

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

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

#### アニメーションしない

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

[https://www.youtube.com/watch?v=KAMSFm0B8lY](https://www.youtube.com/watch?v=KAMSFm0B8lY)

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

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

もう一度ググりなおしていると以下のページが見つかりました。
[How to create a .usdz animation?](https://stackoverflow.com/questions/51009105/how-to-create-a-usdz-animation)

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

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

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

#### gltf2usdを使用する前に

`gltf2usd`は`python`で書かれたツールです。
`python`さえ入っていれば動くと思っていましたが色々と面倒なことがあります。
結論だけ書くと`pyenv`や`homebrew`で`python`を入れていると動作しません。
システムの`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表示に対応していません。