Three.jsで遊んでみたお話。

とりあえず、まずは、three.jsの公式のドキュメントに従って、Hello World的な何かをした。

npm(yarn)から読み込む方法や、ソースコードをダウンロードして読み込む方法、CDNを利用する方法があるが、そこらへんは適宜やればいいと思う。

WebGLが使えるかどうかは、以下のソースコードを読み込めばいいようにできている(さすが)。

if (Detector.webgl) {
    // Initiate function or other initializations here
    animate();
} else {
    var warning = Detector.getWebGLErrorMessage();
    document.getElementById('container').appendChild(warning);
}

github.com

それで、Hello World相当のものがこれ。

<html>
    <head>
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
            canvas { width: 100%; height: 100% }
        </style>
    </head>
    <body>
        <script src="js/three.js"></script>
        <script>
            var scene = new THREE.Scene();
            var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            var geometry = new THREE.BoxGeometry( 1, 1, 1 );
            var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
            var cube = new THREE.Mesh( geometry, material );
            scene.add( cube );

            camera.position.z = 5;

            var animate = function () {
                requestAnimationFrame( animate );

                cube.rotation.x += 0.1;
                cube.rotation.y += 0.1;

                renderer.render(scene, camera);
            };

            animate();
        </script>
    </body>
</html>

これをブラウザで開くと、黒い画面の中央で緑色のcubeが回転するのが見れるはず。

直線を引く

直線を引くためには、次のような手順を経て描画する。

  1. 描画したい対象の見た目を指定するmaterialを定義する。
  2. 描画したい対象の形を指定するgeometryを定義する。
  3. それらを用いて、lineを定義する。
  4. sceneにlineを追加する。
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

const camera = new THREE.PerspectiveCamera(45, width/height, 1, 500);
camera.position.set(0,0,100);
camera.lookAt(new THREE.Vector3(0, 0, 0));

const scene = new THREE.Scene();

const material = new THREE.LineBasicMaterial( { color: 0xffffff } );

const geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3( -10, 0, 0));
geometry.vertices.push(new THREE.Vector3(  0, 10, 0));
geometry.vertices.push(new THREE.Vector3(  10, 0, 0));
geometry.vertices.push(new THREE.Vector3(  0, -10, 0));
geometry.vertices.push(new THREE.Vector3( -10, 0, 0));

const line = new THREE.Line(geometry, material);

scene.add(line);

renderer.render(scene, camera);

とりあえず、公式のドキュメントだとこのくらいで止まっているので、ここからは他の資料も使いながら。

Rendererについて

毎回はじめに実行しているTHREE.WebGLRendererは、以下のファイルで定義されている。具体的には、Canvasを用意し、WebGLのContextを用意し、適宜メソッドを追加しているという感じだ。

github.com

Rendererという名前の通り、与えられたワールドの情報(Scene)と視点の情報(Camera)から、Canvasに書き出すべき画像を計算し、Canvasに描画する。WebGLRendererは、バックエンドにWebGLを使うタイプだが、SVGRenderer というのもあり、こちらはSVGとして描画する。

THREE.WebGLRenderer()

const renderer = THREE.WebGLRenderer();

Renderer#setSize(width, height)

Canvasのサイズを指定するメソッド。

Scene

次に用意するものはSceneだが、ここで定義されている。が、実質Object3Dなので、Object3Dを見ると、どんなことが行われているのか分かる。おそらくだが、Object3Dにaddが定義されているので、他のObject3D(立方体など)の子要素として、Objectをaddすることもできるような気がする。Object3Dでは、そのオブジェクトの位置や回転具合、スケーリングなどの情報を持っている。

github.com

github.com

THREE.Scene()

const scene = new THREE.Scene();

Scene#add(objects)

Sceneにobjectsを追加する。正確には、ObjectsのparentにSceneのObjectを追加して、SceneのObjectのchildrenにObjectsを追加する。

Camera

フィールドが用意されても、描画するためのカメラがなければ映し出すことはできない。そのために、カメラを用意する必要がある。CameraもObject3Dなので、Object3Dのメソッドが使える。

THREE.PerspectiveCamera(fov, aspect, near, far)

透視投影カメラ。4要素を指定してカメラの描画を指定するのだが、結構癖がある。StackOverflowでも質問されていて、図が非常にわかりやすいので、引用させていただいた。緑・赤・紫色の線で囲まれた領域が実際にCanvasに描画される。field of view(fov)はy軸方向の視野角。aspectは縦横比。nearは自分から見える最も近い平面までの距離。farは自分から見える最も遠い平面までの距離。

const camera = THREE.PerspectiveCamera(fov, aspect, near, far);

f:id:proelbtn:20180325065659p:plain

stackoverflow.com

THREE.CubeCamera(near, far, cubeResolution)

六面カメラ(だと思う)を作成する。

THREE.OrthographicCamera(left, right, top, bottom, near, far)

平行投影カメラ。

THREE.StereoCamera()

2つの透視投影カメラ。3Dアナグリフなどを行う際に使われるらしい。人の目と同じようなカメラってことのはず。

Object3D

THREE.js内部で用いられている汎用の3Dオブジェクトを表す型。

Object3D#rotateXYZ

[XYZ]軸を回転の軸としてangle度回転させる。

Object3D#rotateOnAxis(axis, angle)

axisを回転の軸としてangle度回転させる。

Object3D#transformXYZ

[XYZ]軸を基準の軸としてdistanceだけ移動させる。

Object3D#transformOnAxis(axis, distance)

axisを基準の軸としてdistanceだけ移動させる。

Object3D#lookAt(x, y, z)

(x, y, z)の方向を向くように、物体を回転させる。

Object3D#add(objects)

objectsを自身の子要素にする。

Object3D#remove(objects)

objectsを自身の子要素じゃなくする。

Object3D#position.[xyz]

座標を保持している変数