three.js の examples を眺めた結果、
どんな機能があって、どう書けば良いのか、
大体の要領がつかめて来た感じです。

そこで、
MMDなミクさんを表示してみることにしました。
同梱されているモデルファイル(PMD)を利用します。

ただ、
PMDまたはPMXなファイルを読み込むローダが
three.jsには無いので、
PmdEditorまたはPmxEditorColladaエクスポータを利用して
Collada(DAE)形式にいったん変換します。

あとは、
sceneを作って、
適当にcameraとlightを追加。
さらに、
ColladaLoaderで読み込んだDAEを追加。
WebGLRendererを作ってsceneとcameraを渡す。
基本的にはこれだけ。
あっさり表示できてしまいました(^_^;)

実際には、
モデルのスケールの調整とか、
地面のグリッドとか、
FPS表示のためのStatsや
カメラ操作のためのTrackballControlsなどを
導入していますが、
ちょっとの手間で簡単に出来ました。

ちなみに、
ミクさんは細かい所までよく出来ているので、
全体にテクスチャを貼ってるのかと思ってましたが、
実際に貼ってあるのは眼だけで、
基本的に単色ポリゴンで構成されてるのが意外でした。

ということで、
three.jsで表示させてみたWebGLなミクさんはこちらです。
マウスでグリグリ動かせます。
※WebGL対応のブラウザで見てください。Chromeが良いと思います。

mytest3

なお、
残念ながら現状では踊ったりしません(^_^;)
モーションファイルであるVMDを変換して導入する術が
現状ではみつかりませんでした。
ただ、PMDから変換されたDAEを見てみると、
ボーンっぽい情報が含まれているようなので、
VMDからフレーム情報を抽出して適用できれば、
もしかしたら動くようにできるかもしれない
というか、したいなぁ(^_^;)

参考までにソースは以下の通りです。(three.js r49)

<!doctype html>
<html lang="ja">
	<head>
		<title>miku</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: Monospace;
				background-color: #eeeeee;
				margin: 0px;
				overflow: hidden;
			}
			a { color: skyblue; }
		</style>
	</head>
	<body>
		<script src="../../build/Three.js"></script>
		<script src="../js/loaders/ColladaLoader.js"></script>
		<script src="../js/Detector.js"></script>
		<script src="../js/Stats.js"></script>
		<script>
		window.onload = function() {
			var scene,
				camera, 
				renderer,
				loader,
				stats,
				controls,
				info,
				init = function(mdl) {
					var i,
						container,
						directionalLight,
						line_material,
						geometry,
						floor,
						step,
						size,
						line;

					scene = new THREE.Scene();

					// camera
					camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
					camera.position.set( 0, 3, 6 );
					//camera.lookAt( scene.position );
					scene.add( camera );

					// light
					scene.add( new THREE.AmbientLight( 0xcccccc ) );
					directionalLight = new THREE.DirectionalLight( 0xffffff );
					directionalLight.position.set( -1, 1, 1 ).normalize();
					scene.add( directionalLight );

					// grid
					line_material = new THREE.LineBasicMaterial( { color: 0x999999 } );
					geometry = new THREE.Geometry();
					floor = -0.01;
					step = 1;
					size = 14;
					for (i = 0; i <= size / step * 2; i ++ ) {
						geometry.vertices.push( new THREE.Vector3( - size, floor, i * step - size ) );
						geometry.vertices.push( new THREE.Vector3(   size, floor, i * step - size ) );
						geometry.vertices.push( new THREE.Vector3( i * step - size, floor, -size ) );
						geometry.vertices.push( new THREE.Vector3( i * step - size, floor,  size ) );
					}
					line = new THREE.Line( geometry, line_material, THREE.LinePieces );
					scene.add( line );

					// mesh
					scene.add( mdl );

					container = document.createElement( 'div' );

					renderer = new THREE.WebGLRenderer();
					renderer.setSize( window.innerWidth, window.innerHeight );
					renderer.setClearColorHex(0xeeeeee);
					container.appendChild( renderer.domElement );

					stats = new Stats();
					stats.domElement.style.position = 'absolute';
					stats.domElement.style.top = '0px';
					container.appendChild( stats.domElement );

					controls = new THREE.TrackballControls( camera );
					controls.rotateSpeed = 1.0;
					controls.zoomSpeed = 1.2;
					controls.panSpeed = 0.8;
					controls.noZoom = false;
					controls.noPan = false;
					controls.staticMoving = true;
					controls.dynamicDampingFactor = 0.3;
					controls.keys = [ 65, 83, 68 ];
					controls.target.set(0,2,0);
					//controls.addEventListener( 'change', render );

					document.body.appendChild( container );
				},
				render = function() {
					renderer.render( scene, camera );
				},
				animate = function() {
					requestAnimationFrame( animate );
					controls.update();
					render();
					stats.update();
				};

			if ( ! Detector.webgl ) {
				Detector.addGetWebGLMessage();
				return;
			}

			info = document.createElement( 'div' );
			info.style.position = 'absolute';
			info.style.width = '100%';
			info.style.color = '#f00';
			info.style.textAlign = 'center';
			info.style.zIndex = 100;
			document.body.appendChild( info );
			info.innerHTML = 'LOADING...';

			loader = new THREE.ColladaLoader();
			loader.options.convertUpAxis = true;
			loader.load( '../models/miku/miku.dae', function( collada ) {
				var dae = collada.scene;
				dae.scale.x = dae.scale.y = dae.scale.z = 0.2;
				dae.updateMatrix();
				init(dae);
				animate();
				info.style.color = '#000';
				info.innerHTML = 'MOVE mouse &amp; press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan';
			});
		};
		</script>
	</body>
</html>

コメントする

メールアドレスが公開されることはありません。が付いている欄は必須項目です。