Calmery.me

みっかぼうずにならないようがんばる

Blenderでモデルを作りthree.jsで表示する

Blender で作成したモデルとアニメーションを three.js を使いブラウザ上で表示できたのでメモ.今月の 17,18 日に開催された 林業応援ハッカソン でブラウザ上でモデルを動かすのに必要だった.

準備

Blender にアドオンを追加する.これは three.js が提供するもので,このアドオンを使用すると three.js で使用できる JSON 形式でモデルを書き出せるようになる.README か Three.js の JSONLoader のメモ - Qiita を参考にする.というか見た方が早いと思う.

$ cp -r three.js-master/utils/exporters/blender/addons/io_three /Users/calmery/Library/Application\ Support/Blender/2.77/scripts/addons/io_three

アドオンを追加後,Blender の User Performance から Add-ons を開き,Import-Export: Three.js Format にチェックを入れれば three.js 用の JSON 形式に書き出せるようになる.
f:id:calmery:20161224234440p:plain
Blender の他にも 3ds MAX や Maya,Revit 用のアドオンもあるみたい.どれも README に手順が書かれているのでそれを見ながらやればできそう.

書き出す

わかりやすいようにキューブに色をつけた.
f:id:calmery:20161225000501p:plain
Export から Three.js(json) を選択する.
f:id:calmery:20161225041940p:plain
Face materials にチェックを入れて書き出す必要があるみたい.チェックを入れずに書き出してマテリアルが表示されず大変だった.
f:id:calmery:20161224234922p:plain

読み込む

three.js の JSONLoader を使い,書き出した JSON からモデルを読み込む.

<body></body>

<script src="resources/js/three.min.js"></script>
<script src="resources/js/TrackballControls.js"></script>
<script>
    let scene = new THREE.Scene()

    let renderer = new THREE.WebGLRenderer( { antialias: true } )
    renderer.setSize( 600, 400 )
    renderer.setClearColor( 0xffffff, 1 )
    document.body.appendChild( renderer.domElement )

    let camera = new THREE.PerspectiveCamera( 60, ( 600 / 400 ), 1, 1000 )
    camera.position.set( 0, 0, 300 )

    let directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 )
    directionalLight.position.set( 0, 150, 1000 )
    scene.add( directionalLight )

    let trackball = new THREE.TrackballControls( camera )

    let loader = new THREE.JSONLoader()
    loader.load( 'blenderToThreejs.json', ( geometry, materials ) => {
        let faceMaterial = new THREE.MeshFaceMaterial( materials )
        mesh = new THREE.Mesh( geometry, faceMaterial )
        mesh.position.set( 0, 0, 0 )
        mesh.scale.set( 50, 50, 50 )
        scene.add( mesh )

        let animation = ( function(){
            requestAnimationFrame( arguments.callee )
            renderer.render( scene, camera )
            trackball.update()
        } )()
    } )
</script>

ちゃんと表示することができた.
f:id:calmery:20161225001648p:plain
もし,書き出したモデルが正しく表示されない場合は Blender Three.js エクスポート その3( テクスチャなどがエクスポート出来ない場合) を参考にする.人のモデルを作成したまでは良かったが,頭だけ表示されてないなんてことにならないようにしたい(なった)

アニメーション

キューブが下に落ちていくアニメーションを作成した.
f:id:calmery:20161225012147p:plain
同様に Export の Three.js(json) から保存する.このとき Animation の Morph Animation と Settings の Textures にチェックを入れる必要がある.
f:id:calmery:20161225012207p:plain
f:id:calmery:20161225012204p:plain
アニメーションを再生できるように修正する.ほとんど Blender Three.js エクスポート その4( モーフアニメーション) そのままなのは気にしてはいけない.

loader.load( 'animation.json', ( geometry, materials ) => {
    // 全てのマテリアルのモーフターゲットの値を true にする
    for( let i=0, l=materials.length; i<l; i++ ) materials[i].morphTargets = true;

    let faceMaterial = new THREE.MeshFaceMaterial( materials )
    mesh = new THREE.Mesh( geometry, faceMaterial )
    mesh.position.set( 0, 0, 0 )
    mesh.scale.set( 50, 50, 50 )
    scene.add( mesh )

    let current_frame = 0,
        total_frame   = 50

    let animation = ( function(){
        requestAnimationFrame( arguments.callee )

        last_frame = current_frame
        current_frame++

        // 現在のフレーム数が合計のフレーム数以上になったら現在のフレームを始めに戻す
        if( total_frame <= current_frame ) current_frame = 0

        mesh.morphTargetInfluences[last_frame] = 0
        mesh.morphTargetInfluences[current_frame] = 1

        renderer.render( scene, camera )
        trackball.update()
    } )()
} )

動かしてみた.
f:id:calmery:20161225034936g:plain

まとめ

Blender で作成したモデルやアニメーションを three.js 上で動かすことができた.