【Spark AR】javascriptで3Dオブジェクトを動かす①

#Spark ARとは？
InstaramのARフィルターをSpark ARと呼びます。
Facebookが提供するSpark AR Studioを使用すると、Instagramストーリーで使用できるARフィルター提供することができます。
最近ドップリとARにはまっており、XRの扉をたたく意味でSpark ARに挑戦してみました。

[公式チュートリアル](https://sparkar.facebook.com/ar-studio/learn/tutorials/scripting#downloading-the-project)に従って実装していきます。
この記事では以下の3Dモデルを表示し、アニメーション、サウンド再生を行います。本体と、丸い部分で別々の動きをさせたいと思います。
![69528694_1079588018903892_8484091505311481856_n.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/ab1b0e02-42c3-b35d-45aa-b2752197df91.gif)

Spark AR Studioはインストール済として話を進めていきます。
#準備を整える

まず、[sample content](https://sparkar.facebook.com/micro_site/url/?click_creative_path[0]=link&click_from_context_menu=true&country=JP&destination=https%3A%2F%2Forigincache.facebook.com%2Fdevelopers%2Fresources%2F%3Fid%3DScripting.zip&event_type=click&last_nav_impression_id=0cRtsgAgX1ntDKgHK&max_percent_page_viewed=100&max_viewport_height_px=937&max_viewport_width_px=1920&orig_http_referrer=https%3A%2F%2Fsparkar.facebook.com%2Far-studio%2Flearn%2Fscripting%2Freactive-programming&orig_request_uri=https%3A%2F%2Fsparkar.facebook.com%2Far-studio%2Flearn%2Ftutorials%2Fscripting&region=apac&scrolled=false&session_id=18PDsyp5BYpwuOAua&site=spark_ar&extra_data[creative_detail]=link&extra_data[create_type]=link&extra_data[create_type_detail]=link)をダウンロードしAR Studioで開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/04776478-fa60-df11-5c4b-65b79bf8c819.png)
こんなポップアップが出てきますが、無視してopenで大丈夫です。
下のような画面が出てきたらオッケーです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/4a6b2f8d-911f-525b-b9b0-ce725143d173.png)
AssetsPanelを理解しましょう。ここには以下の２つのフォルダーが入っており、簡単に見てみると 

- BoomBox_animated
⇒3Dモデルの情報が入っています
- Audio
⇒サウンド関係の情報が入ってます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/c6efc122-79dc-16cb-0b38-2b9e23598539.png)

次に準備として、まずsceneを設定します。以下の操作で設定できます。


1. **Scene Panel** 下部の**Add Object** をクリック
2. **Plane Tracker** を選択
3. **Insert** をクリック

するとこのようになっているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/d6867f2c-d882-0086-21e6-92308a3d083b.png)

次にNull Objectを追加します。これはオブジェクトをグループ化するための空のグループで、以下の操作を行ってください。
1. **PlaneTracker0**を右クリック
2. **Add>Null Object**をクリック
3. **NUll Object0**をPlacerと改名
4. **Placer**に**boombox_animated**をドラッグ＆ドロップする

すると、Placerの下にBoomBox_animatedが追加され、Viewportにラジカセの3Dモデルが表示されるようになると思います。現在はアニメーションがついてないけど、コードを追加することで動かすことが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/01a01633-fd53-7c7c-2184-3599315b9cd5.png)

後で使いやすいようにPlacerの位置を少し修正しておきます
1. **boombox_animated**を選択
2. **Inspector Panel**（画面右側）の**z-axis Position**を0.3にしておいてください

#サウンドを追加する
サウンドも３ステップで簡単に追加することが出来ます！

- **Add Assets**から**Audio Playback Controller**を追加
- **audioPlaybackController0**を選択し、**Inspector**で**bobbmboc_loop.mp4a**を選択
- **Placer**を右クリックして、**Add>Speaker**で**Speaker0**を追加

以下のような画面になっており、サウンドが流れていたらOKです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/71597018-042c-e19b-c26f-23d4c9945a74.png)

#コードを書く
ここまで長くなってしまいましたが、ここからコードを書いて3Dモデルを動かしていきたいと思います。
まず、**Add Asset>Script**で**Script.js**を作ります。
script.jsを開くとデフォルトコードが書いてあるので、消しときます。

###ラジカセの本体(boombox base)を動かす
- Scene内のboombox baseのオブジェクトを読みこむ

```script.js
const Scene = require('Scene');
```
``require()``はscript.jsでモジュール探す働きをしています。
定義した変数``Scene``は[Scene Module](https://sparkar.facebook.com/ar-studio/learn/reference/classes/scenemodule#classes)が利用できます。

- Baseオブジェクトにアクセスする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515470/35cca33a-cd0c-4102-db56-8fd47b89a891.png)
**boobbox_animated**を開いてみたらわかるように、この3Dモデルは、**base**,**speaker_left,_right**で構成されている。baseは全体で、left(right)は丸い部分のオブジェクト。以下のコードを追加すると、Scene内の**base.jnt**を認識するようになります

```script.js
 Scene.root.findFirst('base_jnt')
          .then(function(base) {});
```
ここまででbaseのオブジェクトは読み込めたと思います。じゃあ次はアニメーションを読み込んできます。アニメーションもSceneと同じ方法で読み込むことが出来ます。

```script.js
const Animation = require('Animation');
```
オブジェクトとアニメーションが読み込めたところで、次はbaseのアニメーションを作成していきます。
##アニメ―ションを作成する
おおまかな流れは以下の３ステップです。簡単です。
1. driver作成
2. sampler作成
3. driverとsamplerをがっちゃんこする
###driverを作る
driverは**Time driver**と**Value driver**の２種類あり、今回は**Time driver**を使っていきます。
``baseDriverParameters``でdriverのパラメータを設定した後、``baseDriver.start``で開始の合図をしてあげます。今コードはこんな感じになっていると思います。

```script.js
 const Animation = require('Animation');
 const Scene = require('Scene');
 Scene.root.findFirst('base_jnt')
  .then(function(base) {
    const baseDriverParameters = {
        durationMilliseconds: 400,
        loopCount: Infinity,
        mirror: true
    };

    const baseDriver = Animation.timeDriver(baseDriverParameters);
    baseDriver.start();
 });
```
##samplerを作る
以下のコードを追加します。samplerの0.9-1はオブジェクトの拡大縮小の割合を指しているよ。

```script.js
const baseSampler = Animation.samplers.easeInQuint(0.9,1);
```
##driverとsamplerをつなげる
ここまでで作成したdriverとsamplerをつなげて、アニメーションを作ります。

```script.js
const baseAnimation = Animation.animate(baseDriver,baseSampler);
```
コードはこんな感じ

```script.js
 const Animation = require('Animation');
 const Scene = require('Scene');
 Scene.root.findFirst('base_jnt')
  .then(function(base) {
    const baseDriverParameters = {
        durationMilliseconds: 400,
        loopCount: Infinity,
        mirror: true
    };

    const baseDriver = Animation.timeDriver(baseDriverParameters);
    baseDriver.start();
    const baseSampler = Animation.samplers.easeInQuint(0.9,1);
    const baseAnimation = Animation.animate(baseDriver,baseSampler);
 });
```
まだ動きません。baseにアニメーションを適用しなければいけません。ここまでは、base全体のスケールの変化の仕方を定義してきました。（アニメーションを作ってきました、）最後にbaseがアニメーション通りに大きさを変えるように命令します。
のこようにしてx,y,zと関連付けることで初めてアニメーションを適用することができます！
ここまで書くと、実際にラジカセの大きさが変化してることがわかると思います。
```script.js
const baseTransform = base.transform;
baseTransform.scaleX = baseAnimation;
baseTransform.scaleY = baseAnimation;
baseTransform.scaleZ = baseAnimation;
```

今回はオブジェクトのアニメーションの方法を学びました！存外簡単でした