Three.jsはじめの一歩


## やること

[Three.js](https://threejs.org/)はじめの一歩。Three.jsを使い3Dオブジェクトの作り方メモです。Three.jsでいろんな3Dオブジェクトを作ります。
<img src="https://i.gyazo.com/e6dd8c5315eb3cd119c12c83ccea97ad.gif" width="600">

## Three.jsとは

[Three.js](https://threejs.org/)を使うと、ウェブブラウザで3Dオブジェクトを描画できます。
基本的な3DオブジェクトならhtmlファイルだけでOK
今回はThree.jsの中の `Geometory` を使って3Dオブジェクト作ります。

## 参考サイト

こちらの情報を参考にさせて頂きました。

- [Geometry](https://threejs.org/docs/#api/en/core/Geometry)
    - Three.jsの公式サイトの`Geometry`に関するドキュメント
- [three.jsを学ぶの。](http://thirdjs.blog.fc2.com/)
    - 概要を理解するのに参考になりました。

## Three.jsの基本(1/2)

Three.jsの基本構成はこんな感じ。

- ①`three.min.js`モジュールを読み込む
- ②3Dオブジェクトを作成するスクリプトを書く
- ③3Dオブジェクトを埋め込む(?)canvasタグを用意する

```html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <!-- ①モジュール読み込む -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.min.js"></script>
  <script>
    // ②ここに3Dオブジェクトのスクリプトを書く
  </script>
</head>
<body>
  <!-- ③このタグに3Dオブジェクトを埋め込んでいく -->
  <canvas id="myCanvas"></canvas>
</body>
</html>
```

## Three.jsの基本(2/2)

『②ここに3Dオブジェクトのスクリプトを書く』の基本はこんな感じ。


```html
<script>
    // ②ここに3Dオブジェクトのスクリプトを書く
    // ページの読み込みを待つ
    window.addEventListener('load', init);

    function init() {
      // サイズを指定
      const width = 960;
      const height = 540;
      // レンダラーを作成
      const renderer = new THREE.WebGLRenderer({
        canvas: document.querySelector('#myCanvas')
      });
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(width, height);
      // シーンを作成
      const scene = new THREE.Scene();
      // カメラを作成
      const camera = new THREE.PerspectiveCamera(45, width / height);
      camera.position.set(0, 0, +200);

      // 箱を作成
      var geometry1 = new THREE.BoxGeometry(20,20,50,3);
      const material = new THREE.MeshNormalMaterial();
      material.wireframe=true;
      // 大きさと材質をセット。
      var cube1 = new THREE.Mesh( geometry1, material );
      cube1.position.set(-50,0,50);
      // sceneオブジェクトに立方体を追加
      scene.add( cube1 );
      // 影
      cube1.castShadow = true;
      tick();

      // 毎フレーム時に実行されるループイベント
      function tick() {
        // cubeをx軸に少しずつ回す
        cube1.rotation.x += 0.01;
        // cubeをy軸に少しずつ回す
        cube1.rotation.y += 0.01;
        renderer.render(scene, camera); // レンダリング
        requestAnimationFrame(tick);
      }
    }
</script>
```

↑のスクリプトを『Three.jsの基本(1/2)』に追記したhtmlファイルをブラウザで開くと、くるくる回る立方体が描画されます。WEBサーバーも必要ありません、便利ですね。

<img src="https://i.gyazo.com/9b6811dd6a7d3c07f3fb1f6c6ad63439.gif" width="200">


## Three.jsサンプル

作ったソースを紹介します。これから紹介したものもソースは全てgithubに置いてあります。
[https://github.com/zgw426/Three.js-FirstStep](https://github.com/zgw426/Three.js-FirstStep)


#### くるくる回る立体x3

<img src="https://i.gyazo.com/e9f651bc998750f364e5a962c3048203.gif" width="450">

- ソース：[01-BoxGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/01-BoxGeometry.html)

立方体のオブジェクト作成を3つ書くと、オブジェクトも3つにできます。`material.wireframe=true`とすることでワイヤーフレームになります。`material.wireframe=false`とすれば平面になります。

```html:01-BoxGeometry.html（抜粋）

<script>
function init() {

    // ー省略ー

    // 箱を作成
    var geometry1 = new THREE.BoxGeometry(20,20,50,3);
    var geometry2 = new THREE.BoxGeometry(20,20,50,10);
    var geometry3 = new THREE.BoxGeometry(20,20,50,32);

    const material = new THREE.MeshNormalMaterial();
    material.wireframe=true;

    // 大きさと材質をセット。
    var obj1 = new THREE.Mesh( geometry1, material );
    var obj2 = new THREE.Mesh( geometry2, material );
    var obj3 = new THREE.Mesh( geometry3, material );

    obj1.position.set(-50,0,50);
    obj2.position.set(0,0,0);
    obj3.position.set(50,0,-50);
    
    // sceneオブジェクトに立方体を追加
    scene.add( obj1 );
    scene.add( obj2 );
    scene.add( obj3 );

    // 影
    obj1.castShadow = true;
    obj2.castShadow = true;
    obj3.castShadow = true;
    
    tick();

    // 毎フレーム時に実行されるループイベント
    function tick() {
    // objをx軸に少しずつ回す
    obj1.rotation.x += 0.01;
    obj2.rotation.x += 0.01;
    obj3.rotation.x += 0.01;
    // objをy軸に少しずつ回す
    obj1.rotation.y += 0.01;
    obj2.rotation.y += 0.01;
    obj3.rotation.y += 0.01;
    renderer.render(scene, camera); // レンダリング
    requestAnimationFrame(tick);
    }
}
</script>
```

#### くるくる回る皿x3

<img src="https://i.gyazo.com/2db9daf70f4b17b44c76957755baf497.gif" width="450">

- ソース：[02-CircleGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/02-CircleGeometry.html)

『くるくる回る立体x3』とほぼ同じです。違いは`xxxGeometory`というところ。以下のような違いがあります。

|||
|---|---|
|くるくる回る立体x3|var geometry1 = new THREE.BoxGeometry(20,20,50,3);|
|くるくる回る皿x3|var geometry1 = new THREE.CircleGeometry(30,3);|

#### くるくる回る筒x3

<img src="https://i.gyazo.com/5ccde95ec8dbfb5317e20ab3d5168eda.gif" width="450">

- ソース：[03-CylinderGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/03-CylinderGeometry.html)

`THREE.BoxGeometry(xxx)`の行を`THREE.CylinderGeometry(xxx)`に変更すると円柱になります。

```
THREE.CylinderGeometry
 (
  radiusTop,
  radiusBottom,
  height,
  radiusSegments,
  heightSegments,
  openEnded
 );
```

https://threejs.org/docs/#api/en/geometries/CylinderGeometry

<img src="https://i.gyazo.com/d876d953cf533823eb6ed4508379472b.gif" width="450">

|||
|---|---|
|radiusTop|上面の半径です。0にすると円錐になります。|
|radiusBottom|底面の半径です。|
|height|高さです。|
|radiusSegments|円周の分割数です。|
|heightSegments|高さの分割数です。|
|openEnded|true：フタをしない,false：フタをする　|

#### くるくる回る板x3

<img src="https://i.gyazo.com/9fde6fcae89fa4c88208a25d6bda1f03.gif" width="450">

- ソース：[03-CylinderGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/04-PlaneGeometry.html)

`THREE.BoxGeometry(xxx)`の行を`THREE.PlaneGeometry(xxx)`に変更すると板になります。メッシュにすると板チョコみたいでうまそう。



#### くるくる回るサイコロ（四面体）x3

<img src="https://i.gyazo.com/2cc51045da88bb270ad4e7c8880059a6.gif" width="450">

- ソース：[05-TetrahedronGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/05-TetrahedronGeometry.html)

`THREE.BoxGeometry(xxx)`の行を`THREE.TetrahedronGeometry(xxx)`に変更すると板になります。パラメータによっては三角錐になったり、丸っこくなったりします。パラメータ変更でどのように変わるのかは、公式サイトで確認するのが一番わかりやすいです。

https://threejs.org/docs/#api/en/geometries/TetrahedronGeometry
<img src="https://i.gyazo.com/3ba621c081f3c21ddca1a1f133d857a4.gif" width="450">


#### くるくる回るパラボラ

<img src="https://i.gyazo.com/abcff80d9aa07a3422e75822f46d53ef.gif" width="450">

- ソース：[06-LatheBufferGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/06-LatheBufferGeometry.html)

`THREE.BoxGeometry(xxx)`とは書き方がちょっと違います。詳細は`06-LatheBufferGeometry.html`を見てください。

https://threejs.org/docs/#api/en/geometries/LatheBufferGeometry

<img src="https://i.gyazo.com/c3f417db0f866fb9bd3f2b576b89bc43.gif" width="450">


#### くるくる回る板

<img src="https://i.gyazo.com/5a18294232dd91a5a0fcf74e0a92a02d.gif" width="450">

- ソース：[07-PlaneGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/07-PlaneGeometry.html)


#### くるくる回るジャガイモ（多面体）

<img src="https://i.gyazo.com/12f11e1b3d792c25fdb575073442bed2.gif" width="450">

- ソース：[08-PolyhedronBufferGeometry.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/08-PolyhedronBufferGeometry.html)



#### くるくる回るハート💛

<img src="https://i.gyazo.com/bb7fdaaa1168588ce948b3a66ea8a686.gif" width="450">

- ソース：[09-heartShape.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/09-heartShape.html)


#### くるくる回るドーナツ

<img src="https://i.gyazo.com/6edb7c4721f5279753f34b06497a1335.gif" width="450">

- ソース：[10-MeshBasicMaterial.html](https://github.com/zgw426/Three.js-FirstStep/blob/master/10-MeshBasicMaterial.html)


#### くるくる回る文字

※調査中※　わっかんねー

フォント情報を持つjsonファイルを用意して、うんたらかんたらしたらテキストデータを3Dオブジェクトできるみたいですが、まだ動かせてません。うーん、どうやるんだろう。。

## おわりに

Three.jsでいろんな形状の3Dオブジェクトが作れそうです。また、外部から3Dデータをインポートすることもできるようです。新しいことがわかったら、また紹介したいと思います。