【iOS】USDZファイルを組み込んでAR Quick Look機能でお気軽AR実装・体験

## はじめに

AR は **Augmented Reality** の略で日本語訳的には **拡張現実** と訳されます。
WWDC2017 で ARKit が発表されましたが，当時は興味が持てませんでした。
すごいと思いはするものの，どうしても難しそうと感じてしまったためです。

その後 WWDC2018 では ARKit 2.0 が発表されました。
それとプラスで USDZ ファイルを Quick Look を使うことで
楽に AR 体験出来るというのも発表され，これにまず興味を持ちました。
実装自体は **Quick Look Framework** に関する知識があれば大丈夫！
ということでとても敷居が低いのにびっくりしました。

今回触ってみて AR にしろ VR(Virtual Reality) にしろ
実際に体験してみないと始まらないなーと感じました。
まず開発者にぜひ AR を使用する機能の導入をしてみたい！と
思ってもらえなければ，アプリに組み込まれることもないわけで
つまり一般ユーザが最新の機能体験を得る機会は失われてしまいます。
そういう意味でとても AR Quick Look は有益だと感じました。

WWDC 後の社内勉強会ネタに軽く・・・と思って実装していたものの
案件対応で忙しく，機会を失ってしまったのと
ちょうど iOS 12 もリリースされたので今回このタイミングで書くことにしました。

## Quick Look[^1] とは

Mac を使っている方は結構使っている機能で Finder でファイルを選択して
Space キーを押してプレビューを見る際に使っている機能です。
iOS では iOS 4.0 からある機能だけど，業務でも個人でも実装する機会が
今までなかったです。ただ全く使っていないかと言われればそんなことはなく，
メールに付属してる PDF とか画像とかを見るときに自然と使っていますね。

今回は AR Quick Look という機能を使います。

## USDZ ファイルとは

公式サイトの ARKit のページ[^2] の
Quick Look Objects in 3D and AR 部分に説明があり下記のような感じです。

* オープンソースの **Universal Scene Description(USD)** によって構築されたファイル形式のひとつ
* ストレージや共有のために最適化されていて，iOS 上で 3D コンテンツを
ネイティブに表示および共有することが可能
* iOS 12 では，Safari / メッセージ / メール / News / メモなどの
内蔵アプリケーションで 3D や AR の仮想オブジェクトの usdz ファイルを
Quick Look でネイティブに表示することが可能
* デベロッパは Quick Look ビューをアプリケーションに組み込める

## 実装

今回は，USDZ ファイルをプロジェクトに取り込んで
各オブジェクトを AR Quick Look を用いて表示させてみます。
`CollectionView` に表示させるコンテンツのリストを用意し，
セルをタップすると Quick Look でオブジェクトを確認したり
AR モードを使えるようにします。

### 開発環境

* Xcode 10.0
* macOS High Sierra 10.13.6
* iOS 12
* Swift 4.2

AR Quick Look は iOS 12 以上対応なので，
iOS 11 以下の端末でビルドしても使用できません。
iPad Pro などの大きな画面の端末で見てみると圧巻です。

### サンプルコード

サンプルコードを Xcode 10 で再度実装し，
GitHub にあげましたので
気になる方がいらっしゃいまいしたらご覧ください。

https://github.com/MilanistaDev/SimpleARExperience

もっとこうした方がコードが良くなる・実装ミスがあるなどありましたら
ご指摘お願いいたします。


### USDZ ファイルの準備

今回は Apple が用意してくれたファイルを用います。
下記のリンクから保存します。

https://developer.apple.com/arkit/gallery/


iOS 12 の端末でアクセスすると Web でも AR 体験できます。
USDZ ファイルがあれば，Web 側・アプリ側でも
コンテンツ提供できるということになります。
Android? それは知らないっす！

DLしたらプロジェクトに追加します。

![ar_02.png](https://qiita-image-store.s3.amazonaws.com/0/88266/2b16fcb5-b0fb-25f8-c1f1-6688a5df4389.png)


### カメラのアクセス許可

AR はカメラを用いるので Info.plist にアクセス許可を求めるキーを追加し，
使用目的などの文言を追加します。

![ar_01.png](https://qiita-image-store.s3.amazonaws.com/0/88266/5e3a85d8-1143-a2d5-25b3-750aa0dd2a5f.png "ar_01.png")


### リスト画面側の実装(CollectionView)

特別な実装はないので割愛します。
気になる方がいらっしゃいましたら
GitHub のサンプルコードをご覧ください。
下記のような感じです。画像は別に png ファイルたちを作りました。

![ar_03.png](https://qiita-image-store.s3.amazonaws.com/0/88266/c57516b4-8f08-d50b-9e22-eaf0c31b33e4.png)

### Quick Look でオブジェクト表示

#### QuickLook Framework を import

```swift:ViewController.swift
import QuickLook
```

#### CollectionView のセルをタップした際の処理

セルをタップした際に Quick Look の画面を表示する処理を書く。
`QLPreviewControllerDataSource` のメソッドで
表示するアイテムを指定するために
タップしたセルの indexPath.row の値を保持しておく。


```swift:ViewController.swift
// MARK: - UICollectionViewDelegate

extension ViewController: UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // CollectionViewのセルをタップしたindex値を保持しておく
        self.selectedItemIndex = indexPath.row
        // QLPreviewControllerを開く
        let previewController = QLPreviewController()
        previewController.dataSource = self
        self.present(previewController, animated: true, completion: nil)
    }
}
```

#### Quick Look 側の実装

`QLPreviewControllerDataSource` のメソッドを実装。
表示するアイテム数を返すメソッド，表示するアイテムを返すメソッドに下記のように実装します。

```swift:ViewController.swift
// MARK:- QLPreviewController DataSource

extension ViewController: QLPreviewControllerDataSource {

    /// Quick Look で表示するアイテム数(今回は1:1)
    ///
    /// - Parameter controller: controller
    /// - Returns: Quick Look で表示するアイテム数
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return 1
    }

    /// Quick Look で表示するアイテムを返す
    ///
    /// - Parameters:
    ///   - controller: controller
    ///   - index: アイテムのindex値
    /// - Returns: Quick Look で表示するアイテム
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        // Return the file URL to the .usdz file
        let fileUrl = (self.selectedItemIndex < 0) ?
            Bundle.main.url(forResource: "cupandsaucer", withExtension: "usdz")! :
            Bundle.main.url(forResource: self.contentsArray[self.selectedItemIndex], withExtension: "usdz")!
        return fileUrl as QLPreviewItem
    }
}

```

## 動作確認

`CollectionView` のオブジェクトのリストから
確認したいオブジェクトを選択して Quick Look を使って
該当のオブジェクトを表示します。

見たいオブジェクトのセルをタップ。

![ar_04.PNG](https://qiita-image-store.s3.amazonaws.com/0/88266/3a89a033-aea7-d46c-d453-cca34eff0058.png)


今回はモーダルで `QLPreviewController` が表示される。
Object と AR 表示が選択できる。

![ar_05.PNG](https://qiita-image-store.s3.amazonaws.com/0/88266/32a941c6-0f13-07bf-7046-b7dc07a001aa.png)


AR モードを選択するとカメラが起動し，
平面認識してオブジェクトを配置できます。

![ar_06.PNG](https://qiita-image-store.s3.amazonaws.com/0/88266/16091dc6-a53f-ae95-fcaa-ce4e9045ba99.png)


画像だと伝わらないと思うので GIF を用意してみました。
ぐるぐる回したりピンチイン・アウトで拡大縮小ができます。

<a href="https://1.bp.blogspot.com/-PS1MzZio3Rc/W6eUFO-eC5I/AAAAAAAAFRo/5faPqY-K6IgKY18NO0ZItGsFszUm9fQ2QCLcBGAs/s1600/ar_gif_01.gif" imageanchor="1" ><img border="0" src="https://1.bp.blogspot.com/-PS1MzZio3Rc/W6eUFO-eC5I/AAAAAAAAFRo/5faPqY-K6IgKY18NO0ZItGsFszUm9fQ2QCLcBGAs/s1600/ar_gif_01.gif" data-original-width="400" data-original-height="866" /></a>


次に AR モードではまず平面認識させる必要があります。
認識後にドーンって感じでオブジェクトがセットされます。
オブジェクトを配置するとカメラの範囲から外れても
元の位置に設置されたままになっているのがわかると思います。
この辺りは ARKit 2.0 の機能が使われていると思われます。

<a href="https://1.bp.blogspot.com/-OYwN0PyIPV0/W6eUG8U1FXI/AAAAAAAAFRs/GAQGeYAclnIk-uqPQWdUhvGKDXi4tBr3gCLcBGAs/s1600/ar_gif_03.gif" imageanchor="1" ><img border="0" src="https://1.bp.blogspot.com/-OYwN0PyIPV0/W6eUG8U1FXI/AAAAAAAAFRs/GAQGeYAclnIk-uqPQWdUhvGKDXi4tBr3gCLcBGAs/s1600/ar_gif_03.gif" data-original-width="400" data-original-height="866" /></a>


ARKit 2.0 からごく自然に見えるように映り込みなども再現されているらしいですし，
どんどん取り入れられて，身近になっていきそうですよね。
その前にまずは我々開発者が積極的に取り入れていかないとならないですね。

## おわりに

今回は，USDZ ファイルをプロジェクトに組み込んで，AR Quick Look を使って
簡単に AR を体験できる機能をアプリ側で実装しました。
簡単なのはいいけど USDZ ファイルが簡単に準備できるかは別の問題で＾＾；
一応 AR Quick Look のページ[^3] の下の方に USDZ ファイルに関するツールが
用意されているので時間見つけて触ってみようと思います。

今回いい体験/機会を得られたので業務で使うことはなさそうですが，
個人学習で ARKit 2.0 の方も少しずつ勉強していきたいと思っています。
乱文でしたが，ご覧いただきありがとうございました！

[^1]: https://developer.apple.com/documentation/quicklook
[^2]: https://developer.apple.com/arkit/
[^3]: https://developer.apple.com/arkit/gallery/