2013/10/29

WebGLを利用した3D処理で,様々な物体と動きを表現する方法

WebGLを利用した3D処理で,様々な物体と動きを表現する方法

canvas要素やWebGLを利用しての3Dでの描画が,「three.js」を利用して,簡単に行うことが出来るようになりました.
前回はワイヤーフレームの立方体を表示させましたが,最後に球体が回転していたオブジェクトがあったので,今回は回転動作が出来るようにする方法とプラスして,光源の追加方法や移動の表現方法を解説したいと思います.

目次

球体やトーラスの表示

まず,球体やトーラスを描画する方法から解説していきます.

前回,立方体を描画させるために利用したこのソースコードに手を加えていきます.

window.addEventListener("load",function() {
    functionthreeRender() {
    varrenderer =newTHREE.WebGLRenderer({
        "antialias":true
    });
    renderer.setSize(400, 400);
    document.getElementById("canvas").appendChild(renderer.domElement);
 
    varcamera =newTHREE.PerspectiveCamera(40, 1.0, 1, 10000);
    camera.position.set(50, 20, 60);
    camera.lookAt({
        x : 0,
        y : 0,
        z : 0
    });
 
    varcube =newTHREE.Mesh(newTHREE.CubeGeometry(30, 30, 30),newTHREE.MeshLambertMaterial({
        "color": 0xffffff,
        "wireframe":true
    }));
 
    varscene =newTHREE.Scene();
    scene.add(cube);
    scene.add(camera);
     
     renderer.render(scene, camera);
    }
    threeRender();
 
},false);

ではまず,球体の表示を行ってみましょう. 立方体を描画していた部分を変更し,

var sphere = new THREE.Mesh(new THREE.SphereGeometry(25, 25, 25), 
new THREE.MeshBasicMaterial({
	    "color" : 0x0000ff,
	    "wireframe" : true,
	}));

このように記述します.

パラメータは

THREE.SphereGeometry(半径, 横方向分割数,縦方向分割数,x方向の開始角度,x方向の終了角度,z方向の開始角度,z方向の終了角度)

このようになっています.いずれのパラメータも省略可能ですが,実際に変更してみて,挙動を確認してみてください.

そして,シーンへ追加するオブジェクトを球体オブジェクトに変更します.

scene.add(sphere);

このように記述することで,球体を表示させることが出来ます.

トーラスを表示させたい場合も,球体と同様にソースコードを変更します.

var torus = new THREE.Mesh(new THREE.TorusGeometry(12, 3, 10, 40), 
new THREE.MeshLambertMaterial({
	    color : 0x0000ff
	}));

パラメータは,

THREE.TorusGeometry(半径,管の太さ, 横方向の分割数,縦方向の分割数)

となっており,

scene.add(torus);

球体と同様に,シーンにトーラスオブジェクトを追加することで,描画されます.

他にも線や平面,円柱や十二面体など,様々な物体を描画することが出来ます.

光源の追加

先ほど追加したトーラスは色を指定しているにもかかわらず,真っ黒な物体が描画されていました.
これは光が当たっていないために,黒く見えてしまっているのです.

そこで.光源を追加して,見た目がどういった変化をするのか,実際に確認してみましょう.

光源オブジェクトの追加はこのように記述します.

var light = new THREE.DirectionalLight(0xffffff, 1.0);
	light.position.set(-50, 260, 100);

パラメータは,

THREE.DirectionalLight(光の色(16進数), 光源の強さ);
light.position.set(x方向の位置,y方向の位置,z方向の位置);

として指定します

光源も,シーンにオブジェクトとして追加します

scene.add(light);

このように光源オブジェクトを追加することで,色や形がハッキリ見えるようになります.
今回は平行光源を使用していますが,光源には他にも環境光・スポットライト・点光源があります.

物体の移動と回転

では次に,物体を移動および回転させる方法について説明していきます.

移動させるためには,オブジェクトのposition.x,position.y,position.zプロパティにそれぞれ移動量を与え,再描画することで物体の移動を表現します.

回転させる方法も同様に,rotation.x,rotation.y,rotation.zプロパティに回転角(ラジアン)を与え,再描画することで物体の回転を表現できます.

では,球体が移動と回転を行うソースコードを見ていきます.

まず移動動作をさせるためのソースコードがこちらになります.

/* 移動用角度代入用変数 */
var degree = 0;
/* レンダリング用関数 */
	function positionRender() {
            /* y座標を正弦波のy軸に対応させる */
	    degree = degree + 5;
	    var radian = degree * Math.PI / 180;
	    var positionY = Math.sin(radian) * 10;
            /* 球体の位置プロパティに値を設定 */	    
	    sphere.position.y = positionY;

	    /* ブラウザ依存の再描画タイミングで描画開始 */
	    requestAnimationFrame(positionRender);

	    /* レンダリングオブジェクトにシーンとカメラを追加してレンダリング開始 */
	    renderer.render(scene, camera);
	}
	positionRender();

そして,回転させるためのソースコードはこちらになります.

var rotationY = 0;
function rotationRender() {
            /* y軸の回転角を設定 */
	    rotationY = rotationY + 0.01;
            /* 物体の回転角プロパティに値を設定 */
	    sphere.rotation.y = rotationY;

	    /* ブラウザ依存の再描画タイミングで描画開始 */
	    requestAnimationFrame(rotationRender);

	    /* レンダリングオブジェクトにシーンとカメラを追加してレンダリング開始 */
	    renderer.render(scene, camera);
	}
	rotationRender();

以上を踏まえて,回転する球体のソースコードはこのようになります.

window.addEventListener("load", function() {
    /* レンダリング用関数 */
    function threeRender() {
	/* レンダリングオブジェクトの初期化 */
	var renderer = new THREE.WebGLRenderer({
	    "antialias" : true
	});

	/* 描画領域のサイズ設定 */
	renderer.setSize(400, 400);
	/* レンダリングオブジェクトにはcanvas要素が内包されているのでそのままページ上に出力 */
	document.getElementById("canvas1").appendChild(renderer.domElement);

	/* カメラ初期化及び位置設定 */
	var camera = new THREE.PerspectiveCamera(40, 1.0, 1, 10000);
	camera.position.set(50, 20, 60);
	camera.lookAt({
	    x : 0,
	    y : 0,
	    z : 0
	});
	/* 光源の追加 */
	var light = new THREE.DirectionalLight(0xffffff, 1.0);
	light.position.set(-50, 260, 100);

	/* 描画するオブジェクトの初期化 */

	/* 球体 */
	var sphere = new THREE.Mesh(new THREE.SphereGeometry(20, 35, 35), new THREE.MeshBasicMaterial({
	    "color" : 0x0000ff,
	    "wireframe" : true,
	}));

	/* シーンの初期化及び描画オブジェクトとカメラの追加 */
	var scene = new THREE.Scene();
	scene.add(sphere);
	scene.add(camera);
	scene.add(light);

	
	var rotationY = 0;
	function rotationRender() {
	            /* y軸の回転角を設定 */
	            rotationY = rotationY + 0.01;
                    /* 物体の回転角プロパティに値を設定 */
	            sphere.rotation.y = rotationY;

		    /* ブラウザ依存の再描画タイミングで描画開始 */
		    requestAnimationFrame(rotationRender);

		    /* レンダリングオブジェクトにシーンとカメラを追加してレンダリング開始 */
		    renderer.render(scene, camera);
		}
		rotationRender();

    }
    threeRender();

}, false);

また,今回紹介した移動方法を組み合わせるとこのような動作を行わせる事ができます.

requestAnimationFrame()メソッドは,フォアグラウンドタブの場合はブラウザの再描画のタイミングで呼び出され,バックグラウンドタブでは再描画の回数が減少し,負荷を軽減できるというメリットがあります.

このメソッドを使用することで,再描画一度につき指定した移動量及び角度が変更されるため,動作を行っているように見せることが出来ます.

※注意点として,繰り返し描画を行う場合にはrequestAnimatonFrame()メソッド内でrequestAnimationFrame()メソッドを呼び出す必要があります.

まとめ

立方体以外にも,様々な物体の描画を行ったり,光源や位置,回転角の設定を行ったりすることで,様々な表現をすることができます.
これらの手法が基本となるので,是非覚えておきましょう.