M5StickCを使ってブラウザ上で3Dモデルを動かしてみる

# はじめに
[obnizOSを搭載したM5StickC](https://obniz.io/ja/doc/m5stickc/hw_overview "M5StickC")に内蔵された角速度センサーをコントローラーにして、ブラウザ上の3Dモデルを動かしたいと思います。

ブラウザ上に3Dモデルを描画する方法として、[A-Frame](https://aframe.io/ "A-Frame")（ブラウザ上に簡単にVRや3Dを作成できるフレームワーク）を使用します。

# 完成品

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5StickCの角速度センサを使ったプログラム。<a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a> <a href="https://twitter.com/hashtag/M5StickC?src=hash&amp;ref_src=twsrc%5Etfw">#M5StickC</a> <a href="https://t.co/VpEXBfRjtC">pic.twitter.com/VpEXBfRjtC</a></p>&mdash; kohei.w (@koheiw4) <a href="https://twitter.com/koheiw4/status/1215488714547220483?ref_src=twsrc%5Etfw">January 10, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 用意するもの
- [obnizOSを搭載したM5StickC](https://obniz.io/ja/doc/m5stickc/hw_overview "M5StickC")

#作成手順

### 1. プログラムを書く

最終プログラムは以下になります。

```index.html
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
  <script src="https://aframe.io/releases/latest/aframe.min.js"></script>
  <script src="https://unpkg.com/obniz@3.1.0/obniz.js" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/m5stickcjs/m5stickc.js"></script>
  <style>
    #title{
      text-align: center;
      margin-top: 20px;
      margin-bottom: 20px;
    }
  </style>
</head>
<body>

  <div id="obniz-debug"></div>
  <h1 id="title">M5StickC 3D</h1>
  <a-scene>
    <a-cube id="cube" position="0 1.5 0" rotation="40 0 0" width="1.6" height="0.8" depth="3.4" color="#FF6600">
      <a-plane position="0 0.42 -0.5" rotation="90 0 0" width="0.8" height="1.7" color="#333333"></a-plane>
    </a-cube>
  </a-scene>
  <script>

    const m5 = new M5StickC('OBNIZ_ID_HERE');
    console.log("connecting");
    
    m5.onconnect = async function(){
      
      console.log("conncected");
      let imu = m5.wired("MPU6886",{i2c:m5.m5i2c});
      let data = await imu.getGyroWait();
      let cube = document.getElementById("cube");
      
      let a,b,c,x,y,z;
      [a,b,c,x,y,z] = [data.x,data.z,data.y,0,0,0];
      
      async function gyro(){
        let data = await imu.getGyroWait();
        x += (data.x-a)/5;
        y += (data.z-b)/5;
        z -= (data.y-c)/5;
        cube.setAttribute("rotation",{x:x,y:y,z:z});
      }
      let interval = setInterval(gyro,200);
    }

  </script>
</body>
</html>
```
</br>
各コードの解説をしていきます。

aframe.js, obniz.js, m5stickc.jsをそれぞれ読み込みます。
obniz.jsを読み込んだ後に、m5stickc.jsを読み込むようにしてください。

```html
<script src="https://aframe.io/releases/latest/aframe.min.js"></script>
<script src="https://unpkg.com/obniz@3.1.0/obniz.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/m5stickcjs/m5stickc.js"></script>
```
</br>
A-Frameの部分は以下になります。
\<a-scene>タグでシーンを作成し、\<a-cube>で四角形、\<a-plane>で平面を作成しています。
position属性で各位置、rotation属性で回転状態を決めています。


```html

<a-scene>
  <a-cube id="cube" position="0 1.5 0" rotation="40 0 0" width="1.6" height="0.8" depth="3.4" color="#FF6600">
    <a-plane position="0 0.42 -0.5" rotation="90 0 0" width="0.8" height="1.7" color="#333333"></a-plane>
  </a-cube>
</a-scene>
```
</br>
このコードでM5StickCのインスタンスを作成します。OBNIZ_ID_HEREにはあなたのobniz_idを入れてください。

```js
const m5 = new M5StickC('OBNIZ_ID_HERE');
```

</br>
M5StickCに内蔵されたMPU6886という６軸センサ（加速度、角速度）を初期化します。

```js

let imu = m5.wired("MPU6886",{i2c:m5.m5i2c});
```
</br>
.getGyroWait()で角速度を一度取得します。

```js

let data = await imu.getGyroWait();
```

</br>

ディスプレイが水平な状態にしてM5StickCを置くと、角速度の値は（x : 0, y : 0, z : 0）になるはずですが、実際に取得してみると、値には少しズレがあります。

そのため、最初にディスプレイが水平な状態で角速度の初期値を取得し、a,b,cに代入します。
その後、data.x, data.y, data.zのそれぞれから初期値 a, b, cを引くことでズレを無くしています。

gyro()という関数を0.2秒に一度実行して、回転角 x, y, zを導出し、\<a-cube>のrotation属性に代入することで、M5stickCの動きに合わせて3Dモデルも同じ動きをします。

### 2. M５StickCを電源に繋ぐ
電源が入ってもディスプレイには何も表示されません。起動したのかわかりづらいですが、電源ボタンを何度も押さないようにしましょう。

### 3. 実行

実行するとこのようにM5StickCの動きに合わせて、ブラウザ上の３Dモデルも動きます！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5StickCの角速度センサを使ったプログラム。<a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a> <a href="https://twitter.com/hashtag/M5StickC?src=hash&amp;ref_src=twsrc%5Etfw">#M5StickC</a> <a href="https://t.co/VpEXBfRjtC">pic.twitter.com/VpEXBfRjtC</a></p>&mdash; kohei.w (@koheiw4) <a href="https://twitter.com/koheiw4/status/1215488714547220483?ref_src=twsrc%5Etfw">January 10, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 最後に
今回は３Dモデルを動かしましたが、M5StickCをコントローラーにしたゲームなどを作ってみるのも面白いかもしれません。色々試してみたいと思います！
最後まで読んでいただきありがとうございました。
</br>
</br>