three.js の examples を眺めた結果、
どんな機能があって、どう書けば良いのか、
大体の要領がつかめて来た感じです。
そこで、
MMDなミクさんを表示してみることにしました。
同梱されているモデルファイル(PMD)を利用します。
ただ、
PMDまたはPMXなファイルを読み込むローダが
three.jsには無いので、
PmdEditorまたはPmxEditorのColladaエクスポータを利用して
Collada(DAE)形式にいったん変換します。
あとは、
sceneを作って、
適当にcameraとlightを追加。
さらに、
ColladaLoaderで読み込んだDAEを追加。
WebGLRendererを作ってsceneとcameraを渡す。
基本的にはこれだけ。
あっさり表示できてしまいました(^_^;)
実際には、
モデルのスケールの調整とか、
地面のグリッドとか、
FPS表示のためのStatsや
カメラ操作のためのTrackballControlsなどを
導入していますが、
ちょっとの手間で簡単に出来ました。
ちなみに、
ミクさんは細かい所までよく出来ているので、
全体にテクスチャを貼ってるのかと思ってましたが、
実際に貼ってあるのは眼だけで、
基本的に単色ポリゴンで構成されてるのが意外でした。
ということで、
three.jsで表示させてみたWebGLなミクさんはこちらです。
マウスでグリグリ動かせます。
※WebGL対応のブラウザで見てください。Chromeが良いと思います。
なお、
残念ながら現状では踊ったりしません(^_^;)
モーションファイルである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 & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan';
});
};
</script>
</body>
</html>