[Three.js]入門してみる

2012/09/03

3DやWebGLをネーティブでコーディイングするのはやっぱり大変! Flashだと「Alternativa3D」「 Away3D」「Papervision3D」らが有名ですが、JavaScriptの場合は「Three.js」「Sprite3D.js」「jQuery 3D」とかでしょうか?

この中でも「Three.js」が一番強力そう(妄想)なので試してみる事に。

GitHub

GitHub mrdoob / three.js

この中に「example」があるので動作確認できます。

ドキュメント

three.js

THREE.js Doc 引数説明とサンプルがあるので、どういう動作するのかの材料になるかと。

使ってみる

ライブラリを読み込み

とりあえずメインの「three.js(three.min.js)」とパフォーマンス監視ツール「Stats.js」を読み込む




3D描画の土台

グラフィック描画するベースのhtml要素を追加し、JavaScriptで取得する。 ここまでは、何の知識もいらないかと。



var container;
container = document.getElementById('container');

Cameraの追加

3Dオブジェクトの視点であるCameraを追加するが、今回はOrthographicCamera()を利用する。


var left = window.innerWidth / - 2;
var right = window.innerWidth / 2;
var top = window.innerHeight / 2;
var bottom = window.innerHeight / - 2;
var camera = new THREE.OrthographicCamera(left, right, top, bottom, -2000, 1000);
camera.position.x = 200;
camera.position.y = 100;
camera.position.z = 200;

引数の内容は、


OrthographicCamera(left, right, top, bottom, near, far, projectionMatrix)

ちなみに、現在3種類のカメラがある。

・THREE.OrthographicCamera:平行投影(正投影) ・THREE.PerspectiveCamera:透視投影 ・THREE.CombinedCamera:透視投影と平行投影の複合

透視投影と平行投影の図的表現の違い

Sceneの追加

Sceneはグラフィックオブジェクトを配置する元のオブジェクトです。


scene = new THREE.Scene();

3Dオブジェクトの追加

Three.jsの3Dオブジェクトは以下のものがあります。

・THREE.CubeGeometry ・THREE.CylinderGeometry ・THREE.ExtrudeGeometry ・THREE.IcosahedronGeometry ・THREE.LatheGeometry ・THREE.OctahedronGeometry ・THREE.PlaneGeometry ・THREE.SphereGeometry ・THREE.TorusGeometry ・THREE.TorusKnotGeometry ・THREE.BinaryLoader ・THREE.UTF8Loader

だいたい名前で想像がつくが、今回は直方体の CubeGeometry を利用。

MeshLambertMaterial() で光反射のマテリアルを作成。 元の3Dオブジェクトとマテリアルを引数に、Mesh()でCubeオブジェクトを作成し、Sceneに追加します。 (Three.jsの場合、Cubeオブジェクトというよりメッシュと言った方が通じるか?)


var geometry = new THREE.CubeGeometry(50, 50, 50);
var params =  {
    color: 0xffffff,
    shading: THREE.FlatShading,
    overdraw: true
};
var material = new THREE.MeshLambertMaterial(params);
var cube = new THREE.Mesh(geometry, material);
cube.scale.y = Math.floor(Math.random() * 2 + 1);
cube.position.x = Math.floor((Math.random() * 1000 - 500) / 50) * 50 + 25;
cube.position.y = (cube.scale.y * 50) / 2;
cube.position.z = Math.floor((Math.random() * 1000 - 500) / 50) * 50 + 25;
scene.add(cube);

SceneにLightを追加

Lightを追加する事で、3Dに影をつけて奥行き感を出します。


var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.x = 0.5;
directionalLight.position.y = 1.5;
directionalLight.position.z = 3.5;
directionalLight.position.normalize();
scene.add(directionalLight);

var ambientLight = new THREE.AmbientLight(0x10);
scene.add(ambientLight);

Lightには以下のものがある。

・THREE.AmbientLight ・THREE.DirectionalLight ・THREE.PointLight ・THREE.SpotLight

どう違うかは、後に調べてみよう。。。

レンダリングする

Renderer系には以下の種類があるようだが、今回は無難に CanvasRenderer を利用する。

・CanvasRenderer ・WebGLRenderer ・DOMRenderer ・SVGRenderer

CanvasRenderer.domElement をcontainer(HTML要素)に追加後、Scene と Camera をレンダリングする。


renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
renderer.render(scene, camera);

とりあえず3D静止オブジェクトが描画される。

アニメーションさせる

アニメーションさせる場合は requestAnimationFrame() で時間軸をつけてやる。


function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    var timer = Date.now() * 0.0001;
    camera.position.x = Math.cos(timer) * 200;
    camera.position.z = Math.sin(timer) * 200;
    camera.lookAt(scene.position);
    renderer.render(scene, camera);
}

animate() でrequestAnimationFrame()を連続で呼び、render()で状態に応じてレンダリング処理している。

Demo・サンプルソース

Demo




    
        Cube Sample
        
        
        
    
    

        

Chrome環境で、テクスチャーをつけてないので結構スムーズに動きます。 何となく、Papervision3Dに近い気がしました。 ただ、これだけのサンプルだと何のイベントもないので「で?」ですねw 次は、イベント使ったサンプルを調べてみよう。

メモ:モデル

iClone Real-time Filmmaking