Three.js で遊び倒す -OrbitControls でカメラを動かそう  -

Three.js day 7 となりました。

本日もカメラを使って、動かしていきます。

#1. 完成版

<p class="codepen" data-height="330" data-theme-id="0" data-default-tab="js,result" data-user="hiroyaiizuka" data-slug-hash="QoRMaV" style="height: 330px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="OrbitControls ">
  <span>See the Pen <a href="https://codepen.io/hiroyaiizuka/pen/QoRMaV/">
  OrbitControls </a> by hiroya iizuka (<a href="https://codepen.io/hiroyaiizuka">@hiroyaiizuka</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#2. 参考文献
[SterField](https://sterfield.co.jp/designer/three-js%E3%81%AEorbitcontrol-js%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%9E%E3%82%A6%E3%82%B9%E3%82%84%E3%82%BF%E3%83%83%E3%83%81%E3%81%A7%E7%B0%A1%E5%8D%98%E3%81%AB%E3%82%AB%E3%83%A1%E3%83%A9/)
[ICS MEDIA](https://ics.media/tutorial-three/index.html)
[初めてのThree.js](https://www.amazon.co.jp/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEThree-js-%E7%AC%AC2%E7%89%88-%E2%80%95WebGL%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEJavaScript-3D%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA-Dirksen/dp/4873117704)
[CodeGrid](https://app.codegrid.net/entry/threejs-location)



#3. 分解してみる

[前回](https://qiita.com/duka/items/4b144b7d09e7548e8d7d)、マウス座標を取得し、mousemove イベントを設定しました。

Three.js には、それ以外にも、カメラの動きを補助してくれる、数多くの便利なライブラリがあります。
オライリー本によると

>
・[FirstPersonControls](https://oreilly-japan.github.io/learning-three-js-2e-ja-support/chapter-09/07-first-person-camera.html):　１人称視点のシューティングゲームのような動作をするコントロール。　
・[FlyControls](https://oreilly-japan.github.io/learning-three-js-2e-ja-support/chapter-09/05-fly-controls-camera.html):　フライトシュミレーターのようなコントロール。
・[TrackBallControls](https://oreilly-japan.github.io/learning-three-js-2e-ja-support/chapter-09/04-trackball-controls-camera.html):　マウス(またはトラックボール)を使用して、シーン内を移動できるコントロール。
・[OrbitControls](https://threejs.org/examples/#misc_controls_orbit): 特定のシーンを回る軌道上の衛星をシュミレーションするコントロール。

などなど、これ以外にもたくさんあります。
今回は、OrbitControl.jsを使いましょう。

## 使い方

使い方は非常にシンプルで、主に、2段階に分かれます。

❶. OrbitControls を読み込む

GitHub [OrbitControls.js](https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js) の約1000行に渡るソースコードをコピーします。

![スクリーンショット 2019-03-27 9.50.04.png](https://qiita-image-store.s3.amazonaws.com/0/232715/b591ebda-7bed-2312-2fab-7a61e74b53a9.png)


jsディレクトリを作り、OrbitControls.js ファイルを作り、その中に、先ほどコピーした内容を貼り付けましょう。

![スクリーンショット 2019-03-27 9.54.16.png](https://qiita-image-store.s3.amazonaws.com/0/232715/d8496b6b-191b-d8d9-0db1-64c0b457bffe.png)


できましたら、index.html にscript ファイルで、このファイルを呼び込みましょう。

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
  
    //下記を追加
    <script src="js/OrbitControls.js"></script>

  </head>
```

これで、使う準備が整いました。
<br/>
❷. カメラコントローラーを作る

OrbitControls コンストラクタは、下記のように、引数に、camera オブジェクトをとります。

![スクリーンショット 2019-03-27 9.05.54.png](https://qiita-image-store.s3.amazonaws.com/0/232715/20384e4f-159f-1d1b-2072-8bfb90a6c27c.png)


```
const controls = new THREE.OrbitControls(camera) 
```

<p class="codepen" data-height="350" data-theme-id="0" data-default-tab="js,result" data-user="hiroyaiizuka" data-slug-hash="EMzXRd" style="height: 350px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="OrbitControls (experimental)">
  <span>See the Pen <a href="https://codepen.io/hiroyaiizuka/pen/EMzXRd/">
  OrbitControls (experimental)</a> by hiroya iizuka (<a href="https://codepen.io/hiroyaiizuka">@hiroyaiizuka</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

これで完成です。
こんなに簡単に、OrbitControls を使えるなんて、先人の方々には頭が上がりません。

<br/>
❸. オプションをつける。

``enableDamping`` と ``autoRotate``、`autoRotateSpeed` をつけましょう。

enableDamping は、設定することで、ドラッグするときのアニメーションを滑らかにします。
autoRotate は、自動で回転を加える事ができます。

これらを設定するときは、アニメーションの関数内で、controls.update()を書く必要があるので、気をつけましょう。

```

 const controls = new THREE.OrbitControls(camera);
 controls.enableDamping = true;
 controls.autoRotate = true;
 controls.autoRotateSpeed = 1;


 function renderScene() {
      requestAnimationFrame(renderScene);
      controls.update();
      renderer.render(scene, camera);
 }
```

<p class="codepen" data-height="330" data-theme-id="0" data-default-tab="js,result" data-user="hiroyaiizuka" data-slug-hash="QoRMaV" style="height: 330px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="OrbitControls ">
  <span>See the Pen <a href="https://codepen.io/hiroyaiizuka/pen/QoRMaV/">
  OrbitControls </a> by hiroya iizuka (<a href="https://codepen.io/hiroyaiizuka">@hiroyaiizuka</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


いい感じです！
他にも、色々なプロパティがあるので、[公式](https://threejs.org/docs/#examples/controls/OrbitControls)を参考に適宜いじってください。

##最終コード

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
    <script src="js/OrbitControls.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <canvas class="stage"></canvas>

    <script>
      function init() {
        //レンダラーを作成
        const renderer = new THREE.WebGLRenderer({
          canvas: document.querySelector(".stage")
        });
        renderer.setSize(window.innerWidth, window.innerHeight);

        //シーンを作成
        const scene = new THREE.Scene();

        starNight();
        function starNight() {
          // 形状データを作成
          const geometry = new THREE.Geometry();

          for (let i = 0; i < 1000; i++) {
            const star = new THREE.Vector3();
            star.x = THREE.Math.randFloatSpread(3000);
            star.y = THREE.Math.randFloatSpread(3000);
            star.z = THREE.Math.randFloatSpread(3000);

            geometry.vertices.push(star);
          }

          // マテリアルを作成
          const material = new THREE.PointsMaterial({
            size: 10,
            color: 0xffffff
          });
          // 物体を作成
          const star = new THREE.Points(geometry, material);
          scene.add(star);
        }

        //カメラを作成
        const camera = new THREE.PerspectiveCamera(
          50,
          window.innerWidth / window.innerHeight,
          0.1,
          2000
        );

        const controls = new THREE.OrbitControls(camera);
        controls.enableDamping = true;
        controls.autoRotate = true;
        controls.autoRotateSpeed = 1;

        camera.position.set(0, 0, 1000);

        //球を作成
        const geometry = new THREE.SphereGeometry(100, 32, 32);
        const material = new THREE.MeshNormalMaterial();
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);

        renderScene();

        //アニメーション
        function renderScene() {
          requestAnimationFrame(renderScene);
          controls.update();
          renderer.render(scene, camera);
        }
      }

      window.addEventListener("load", init);
    </script>
  </body>
</html>
```


OrbitControls は、先人の知恵が詰まった、素晴らしいライブラリでした。
それでは、また明日〜