UnityなしでVRMを読み込んでVTuber機能をアプリに組み込めるライブラリを作りました

# VRMとは


VR向けの人型3Dアバターフォーマットです。非常にポータビリティの高いフォーマットになっていて、VRアバターな世界を牽引していくかもしれないフォーマットの一つです。標準ではUnityで読み書きができる実装が公開されています。
詳しくは下記をご覧ください。

[VRM - dwango on GitHub](https://dwango.github.io/vrm/)

# iOSのネイティブアプリで扱いたい！
自分のようにSwiftでネイティブなiOSアプリを作っているエンジニアはできればSwiftで直接扱いたいと思うはずです。
また、すでにネイティブアプリとして作っているアプリにVRMのアバター表示を組み込みたいというケースもあると思います。(ネイティブアプリにUnityを埋め込むというアプローチもありますが面倒だし、アプリサイズが大きくなってしまう...)

そこで、SwiftでVRMを読み込んで表示できるVTuberKit/VRMKitを作ってみました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Unityなしで3DのVTuberの仕組みをiOSアプリに導入できるVTuberKitを公開しました。<br>VRMももちろん読み込めます。単にキャラクターを表示するViewとしても良さそうです。<br>まだ機能は少なく、できないことも多いのでこれから地道に追加していきます！<a href="https://t.co/ULND2dqeaM">https://t.co/ULND2dqeaM</a><a href="https://twitter.com/hashtag/VRM?src=hash&amp;ref_src=twsrc%5Etfw">#VRM</a> <a href="https://twitter.com/hashtag/VTuber?src=hash&amp;ref_src=twsrc%5Etfw">#VTuber</a> <a href="https://t.co/ULn7mpMPet">pic.twitter.com/ULn7mpMPet</a></p>&mdash; Tatsuya Tanaka / たなたつ (@tanakasan2525) <a href="https://twitter.com/tanakasan2525/status/1094931506760278017?ref_src=twsrc%5Etfw">2019年2月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# VTuberKit / VRMKit

https://github.com/tattn/VTuberKit
https://github.com/tattn/VRMKit

VRMのアバターを表示したり、Face Trackingで表情や頭を動かしたりできます。
どんな感じなのかは↑のTwitterやGitHubのアニメGIFをご覧ください。

## 構成
VTuberKitはVRMKitとVRMSceneKitに依存しています。

下記のような構成になっています。

<img width="1141" alt="スクリーンショット 2019-02-23 17.04.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/91631/ae4e5ee9-b211-7403-f48c-bf09bd2be73a.png">

VTuberKitを使うと簡単にアバターの表示やVTuberっぽいことができますが、より細かく扱いたい場合はVRMSceneKitなどの機能を使って操作することができます。

## 使い方

### 導入

CarthageやCocoaPodsで導入できます。下記の設定で上記の3つのフレームワークが入ります。

```ruby:Carthage
github "tattn/VTuberKit"
```

```ruby:CocoaPods
pod 'VTuberKit'
```

### アバターの表示

<div>
<img width="200px" alt="キズナアイ" src="https://qiita-image-store.s3.amazonaws.com/0/91631/4752e8d1-8e5d-f005-d48d-30aeb93bab8b.png">
<img width="200px" alt="東北ずん子" src="https://qiita-image-store.s3.amazonaws.com/0/91631/1efe7bd7-7d90-5138-6cbe-779c9ff5e8a1.png">
</div>
(C) Kizuna AI
(C) SSS LLC.

VTuberKitを使った場合。

```swift
import VTuberKit

// StoryboardでVTuberKitのAvatarViewを配置
@IBOutlet weak var avatarView: AvatarView!

// プロジェクトにあるVRMファイルを読み込んで表示
try avatarView.loadModel(withName: "model.vrm")
```

VRMSceneKitを使った場合。

```swift
import VRMKit
import VRMSceneKit

// StoryboardでSCNViewを配置
@IBOutlet weak var sceneView: SCNView!

let loader = try VRMSceneLoader(named: "model.vrm")
let scene: VRMScene = try loader.loadScene()
let node: VRMNode = scene.vrmNode

sceneView.scene = scene

// URLやDataから読み込むこともできます
let loader = try VRMSceneLoader(withURL: URL(string: "...")!)
let loader = try VRMSceneLoader(withData: Data(...))
```

### Face Tracking

Face Trackingで自分の表情をアバターに反映させたいときは下記を呼び出します。

```swift
avatarView.startFaceTracking()
```

※ 今はTrueDepth APIが使える端末でのみ利用可能ですが、今後のアップデートでどの端末でも動くようにしていきたいと思っています。

### 表情を変える

VRMでブレンドシェイプを設定していれば、表情を簡単に変えることができます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/91631/ca474213-448e-2258-3b62-3ac3c10f8c6f.png" width="100px">

```swift
let node: VRMNode = avatarView.avatar
node.setBlendShape(value: 1.0, for: .preset(.joy))
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/91631/30dbf997-2d6c-72a1-f130-fd0dc5dbb3f2.png" width="100px">

```swift
node.setBlendShape(value: 1.0, for: .preset(.angry))
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/91631/feceeb7e-9328-2f91-294d-be3b7fe216c5.png" width="100px">

```swift
// VRM標準ではない表情を表示する
node.setBlendShape(value: 1.0, for: .custom("><"))
```

可愛い

### ポーズを変える

ボーンが設定済みであれば、ポーズを変えることができます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/91631/c80e15ac-9ff0-9adb-c739-312cdaf775f4.png" width="200px">

```swift
node.humanoid.node(for: .neck)?.eulerAngles = SCNVector3(0, 0, 20.0 * .pi / 180)
node.humanoid.node(for: .leftShoulder)?.eulerAngles = SCNVector3(0, 0, 40.0 * .pi / 180)
node.humanoid.node(for: .rightShoulder)?.eulerAngles = SCNVector3(0, 0, 40.0 * .pi / 180)
```

Unityの[Mechanim](https://docs.unity3d.com/ja/2017.4/ScriptReference/HumanBone.html)と同じボーンが取得できます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/91631/7b4a5ad8-b6d2-b96a-809b-0d84e7cb7d6e.png" height="300px">

今後、いくつかのポーズのプリセットを用意して呼び出すだけで設定できるようにしたり、ユニティちゃんのポーズなどを取り込める仕組みなどを入れたり、iPhoneのカメラ画像でPose Estimationをして全身を動かしたりしたいと思っています。

# まとめ
https://github.com/tattn/VTuberKit
https://github.com/tattn/VRMKit

xRやVTuberという様式が好きなので、ライブラリを作ってみました。
世の中の色々なアプリにアバターが現れる時代が来たら嬉しいです。

今後のアップデートについては [Twitter](https://twitter.com/tanakasan2525) を見てください。

まだ全然機能が足りないですし、UniVRMが提供しているシェーダーや物理演算、レンダリング設定などを全然実装できていないので、プルリクエストをお待ちしております。
バグもまだ多いと思いますが、GitHubの方にissueやプルリクエストを投げていただけると助かります。 日本語でも大丈夫です。(管理が大変なのでQiitaのコメントには書かないでね :pray:)