Live2Dで位置とサイズを調整する

前からLive2Dモデルの位置やサイズ調整する場合、行列をかけるのが正しいと思ってました。
今まで自己流で位置やサイズ調整してたけど、正しいやり方をやっと理解できました！
![000.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/f1c1eb80-eca4-7882-94d9-e0caab3758ed.gif)

詳しくはLive2Dコミュニティに書いてあります。
　→　[UnityでLive2Dモデルを表示した際の拡縮率は？](http://forum.live2d.com/discussion/100/unity%E3%81%A7live2d%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%9F%E9%9A%9B%E3%81%AE%E6%8B%A1%E7%B8%AE%E7%8E%87%E3%81%AF)

# 開発環境
・[Live2D Cubism SDK WebGL 2.0](https://sites.google.com/a/cybernoids.jp/cubism-sdk2/webgl/webgl_dl)のSimpleプロジェクトをカスタム
　→　WebGL版を使いますが、他のプラットフォームでもほぼ同様

# ソースコード
まずはHTML部分にLive2DFramework.jsを追加します。この中に含まれるL2DMatrix44クラスを使います。

```html:simple.htmlの12行目あたり
<!-- Live2D Library -->
<script src="../../lib/live2d.min.js"></script>
<script src="../../framework/Live2DFramework.js"></script>
<!-- User's Script -->
<script src="src/Simple.js"></script>
```

Simple.draw()部分の行列部分を以下のように修正します。
setWidth()でサイズ調整、setCenterPosition()で位置調整ができます！
要するにsetWidth()などの返り値（行列）を配列に変換して、配列をセットしてやるだけです。

```js:Simple.jsの150行目あたり
// 表示位置を指定するための行列を定義する
//    var s = 2.0 / live2DModel.getCanvasWidth(); //canvasの横幅を-1..1区間に収める
//    var matrix4x4 = [
//        s, 0, 0, 0,
//        0,-s, 0, 0,
//        0, 0, 1, 0,
//       -1, 1, 0, 1
//   ];
//    live2DModel.setMatrix(matrix4x4);

    // 描画してるLive2Dモデルのサイズを取得
    var height = live2DModel.getCanvasHeight();
    var width = live2DModel.getCanvasWidth();
    // Live2D用の行列定義
    var mmat = new L2DModelMatrix(width, height);
    // サイズ(幅)
    mmat.setWidth(2.0);
    // ポジション(X, Y)
    mmat.setCenterPosition(0.0, 0.0);
    // 配列をセット
    live2DModel.setMatrix(mmat.getArray());
```

# スライダーで動かしてみる
スライダーをつければこんな感じに操作できます。
![001.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/1bdb98e7-dab0-9c84-1f52-9fb570c16aa2.gif)

HTML側にはスライダーをつけます。

```html:simple.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
        <title>Live2D Simple</title>
    </meta>
</head>

<body onload="Simple()">
    <canvas id="glcanvas" width = "400px" height="400px" style="border:dashed 1px #CCC"></canvas>
    <div id="myconsole" style="color:#BBB">---- Log ----</div>
    サイズ(幅)<input type="range" id="L2D_WIDTH" value="2.0" min="0.0" max="5.0" step="0.1">
    <br>
    位置X<input type="range" id="L2D_X" value="0.0" min="-3.0" max="3.0" step="0.1">
    <br>
    位置Y<input type="range" id="L2D_Y" value="0.0" min="-3.0" max="3.0" step="0.1">
    <!-- Live2D Library -->
    <script src="../../lib/live2d.min.js"></script>
    <script src="../../framework/Live2DFramework.js"></script>
    <!-- User's Script -->
    <script src="src/Simple.js"></script>
</body>
</html>
```

スライダーで動的に位置やサイズを変える場合、先ほどと違いLive2D初期化処理のカッコ外で行います。

```js:Simple.jsの150行目あたり
var l2d_scale, l2d_x, l2d_y; // スライダー用

Simple.draw = function(gl/*WebGLコンテキスト*/)
{
	// Canvasをクリアする
	gl.clear(gl.COLOR_BUFFER_BIT);

	// Live2D初期化
	if( ! live2DModel || ! loadLive2DCompleted )
        return; //ロードが完了していないので何もしないで返る

	// ロード完了後に初回のみ初期化する
	if( ! initLive2DCompleted ){
		initLive2DCompleted = true;

        // 画像からWebGLテクスチャを生成し、モデルに登録
        for( var i = 0; i < loadedImages.length; i++ ){
            //Image型オブジェクトからテクスチャを生成
            var texName = Simple.createTexture(gl, loadedImages[i]);

            live2DModel.setTexture(i, texName); //モデルにテクスチャをセット
        }

        // テクスチャの元画像の参照をクリア
        loadedImages = null;

        // OpenGLのコンテキストをセット
        live2DModel.setGL(gl);
        // スライダーを取得
        l2d_scale = document.getElementById("L2D_WIDTH");
        l2d_x = document.getElementById("L2D_X");
        l2d_y = document.getElementById("L2D_Y");
        // 表示位置を指定するための行列を定義する
//        var s = 2.0 / live2DModel.getCanvasWidth(); //canvasの横幅を-1..1区間に収める
//        var matrix4x4 = [
//            s, 0, 0, 0,
//            0,-s, 0, 0,
//            0, 0, 1, 0,
//           -1, 1, 0, 1
//       ];
//        live2DModel.setMatrix(matrix4x4);
//
	}
            // 描画してるLive2Dモデルのサイズを取得
            var height = live2DModel.getCanvasHeight();
            var width = live2DModel.getCanvasWidth();
            // Live2D用の行列定義
            var mmat = new L2DModelMatrix(width, height);
            // サイズ(幅)
            mmat.setWidth(l2d_scale.value);
            // ポジション(X, Y)
            mmat.setCenterPosition(l2d_x.value, l2d_y.value);
            // 配列をセット
            live2DModel.setMatrix(mmat.getArray());

	// キャラクターのパラメータを適当に更新
    var t = UtSystem.getTimeMSec() * 0.001 * 2 * Math.PI; //1秒ごとに2π(1周期)増える
    var cycle = 3.0; //パラメータが一周する時間(秒)
    // PARAM_ANGLE_Xのパラメータが[cycle]秒ごとに-30から30まで変化する
    live2DModel.setParamFloat("PARAM_ANGLE_X", 30 * Math.sin(t/cycle));

    // Live2Dモデルを更新して描画
    live2DModel.update(); // 現在のパラメータに合わせて頂点等を計算
    live2DModel.draw();	// 描画
};
```

今までどうやってやるのか疑問だったけど、１つすっきりした。