LIGデザイナー採用
LIGデザイナー採用
2017.01.30
#34
それいけ!フロントエンド

3Dデータ(Blender)をThree.jsで表示するまでの方法

ハル

おはこんばんにちは。
最近、懐かしのアニメを見ることにはまっています。ハルです。

今回は、「3D表現がしたい!」と思い、

170127_3d

こんな感じの3D表現を、Blender で作成したデータを簡単に書き出して Three.js で簡単に表示させる方法をまとめてみました。

今回の完成ファイルをGithubに公開しています。よろしければ参考にしてください。
完成ファイル:https://github.com/hal-satoyuki/sample3d
完成ページ:https://hal-satoyuki.github.io/sample3d/

それでは早速、作っていきましょう!

今回の動作確認ブラウザについて

動作確認のブラウザには、Firefox を使います。GoogleChrome で確認すると、XMLHttpRequest のエラーが出てしまうためです。
また、手順については、MacPC での説明をしていきます。

Blenderを用意

img1

公式ページ: https://www.blender.org/

Blender は、オープンソースで開発されている3Dグラフィックソフトです。
操作にクセがあるものの、わりと簡単に3Dモデルが作成できます。設定から日本語設定もできますし、検索すると日本語チュートリアルなどもあるので入門しやすいと思います(今回は、3Dモデルを作成する詳しい操作説明等はしません)

ダウンロードページへ

img2

Blenderのダウンロードは、トップページ右下あたりの『Download Blender』からできます。

BlenderにThree.js用jsonファイル書き出しプラグインを用意

img3

先に、プラグイン導入の説明です。
three.js が用意しているプラグインを Blender に入れることで、Three.js で使用できる json ファイルを書き出すことができます。

プラグインの用意

https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender
上記URLに、プラグインが公開されています。

プラグインの設置場所

README.md に記述されていますが、

three.js/tree/master/utils/exporters/blenderaddons/io_three

io_threeフォルダごと、Blender の下記フォルダ内に設置します。

 

/Applications/blender.app/Contents/Resources/2.78/scripts/addons

上記の/2.78/の部分は、インストールされている Blender バージョンによって異なります。また、/Applications/blender.app/の場所も、保存されているディレクトリによって異なりますので気をつけてください。

最終的に、

/Applications/blender.app/Contents/Resources/2.78/scripts/addons/io_three

のようになれば大丈夫です。

 

img4

その他のOSについては、README.md(https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender)をご覧ください。

プラグインの有効化手順

設定ウィンドウを開く

img5

Blender を開いていた場合、いったん再起動してください。起動したら、設定ウィンドウ(Blender User Preferences)を開きます。
ショートカットはcommand+,で開きます。

プラグイン有効化する

img6

設定ウィンドウの、左から4つ目のタブ『Add-ons』を開きます。

そして、左の検索窓から『three』を検索すると、『Import-Export: Three.js Format』が絞り込みされるので、そのチェックボックスにチェックを入れます。

最後に、下の『Save User Settings』で、設定を保存します。これで、プラグインの設定は終わりです。

Blenderでjsonファイルをエクスポート

img7

次は、モデリングしたものをエクスポートする方法です。
サンプルとして、立体的なテキストを用意しました。ファイルはgithubに公開していますのでサンプルにどうぞ。

https://github.com/hal-satoyuki/sample3d/tree/master/blender

エクスポートする対象を選択

img8

『Object Mode』になっていることを確認し、書き出したい対象を選択します。
選択方法は操作設定にもよりますが、右クリックで選択できます。

エクスポートウィンドウを開く

img9

つぎに、 上部のInfoバーにある『File』を選択し、
『Export』から『Three.js (.json)』を選択します。

詳細設定とエクスポート

img10

すると、出力設定ができるウィンドウが開くので、左下の詳細設定の項目から『Shading』の下の『Face Materials』にチェックを入れます。
保存先とファイル名を確認し、『Export THREE』を押すと json ファイルが書き出されます。

Three.jsを使い出力

次に、ブラウザで見られるようにするため、Three.js を使い、Blender で書き出した json ファイルを読み込んでいきます。

Three.js の使い方は、こちらの記事(↓)で紹介していますので参考にどうぞ。

HTMLの用意

index.html を作成します。全体のコードは下記のようになります。

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>3d sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/threejs/r76/three.min.js"></script>
    <script src="./js/script.js"></script>
</head>
<body>
</body>
</html>

Three.js の読み込み

今回は、さっと使うため CDN を使用します。
下記ページの script に、script タグが載っています。
https://developers.google.com/speed/libraries/#threejs

<script src="https://ajax.googleapis.com/ajax/libs/threejs/r76/three.min.js"></script>

jsファイルの読み込み

次の項目から、script.js ファイルの中身を記述していきます。
まず、読み込みだけ HTMLに記述しておきます。

<script src="./js/script.js"></script>

jsファイルの用意

./js/script.jsファイルを作成していきます。

記述するコード▼

// 共通で使用する変数
var mesh, renderer, scene, camera;

// 設定
var width = 1280,
    height = 640;


document.addEventListener( 'DOMContentLoaded', function(){

});

変数用意

今回使用する変数を、最初に書いてしまいます。
width height は、出力される canvas のサイズになります。

// 共通で使用する変数
var mesh, renderer, scene, camera;

// 設定
var width = 1280,
    height = 640;

HTMLドキュメント読み込み後、発火処理

HTMLドキュメントを読み込み後 発火するように下記を記述します。次の項目から、イベントの中身にどんどんコードを書いていきます。

document.addEventListener( 'DOMContentLoaded', function(){

});

シーン・カメラ・レンダラー・ライトの用意

まず、シーン・カメラ・レンダラー・ライトのそれぞれをざっと用意していきます。
記述場所は DOMContentLoaded で発火する関数内です。

記述するコード▼

// ...省略

document.addEventListener( 'DOMContentLoaded', function(){

    // シーンの用意
    scene = new THREE.Scene();


    // カメラの設定
    var fov = 45, // 画角
        aspect = width / height, // アスペクト比
        near = 1, // 手前
        far = 700; // 奥行き
    camera = new THREE.PerspectiveCamera( fov, aspect, near, far ); // カメラの準備
    camera.position.set( 0, 0, 50 ); // カメラ位置の設定


    // レンダラーの設定
    renderer = new THREE.WebGLRenderer(); // レンダラーの用意
    renderer.setSize( width, height ); // サイズを指定
    var bgColor = 0x000000;
    renderer.setClearColor(bgColor, 1); // 背景色を指定
    document.body.appendChild( renderer.domElement ); // bodyへ追加


    // ライトの設定
    var lightColor = 0xffffff; // ライトの色
    var directionalLight = new THREE.DirectionalLight( lightColor ); // ライトの色を指定
    directionalLight.position.set( 1, 1, 1 ); // ライトの位置の設定
    scene.add( directionalLight ); // ライトの追加

});

シーンの用意

まずはじめに、シーンを用意します。

// シーンの用意
scene = new THREE.Scene();

カメラの用意

カメラの準備

画角・アスペクト比・表示領域の手間数値と、奥行きの数値を設定します。

// カメラの設定
var fov = 45, // 画角
    aspect = width / height, // アスペクト比
    near = 1, // 手前
    far = 700; // 奥行き
camera = new THREE.PerspectiveCamera( fov, aspect, near, far ); // カメラの準備
カメラ位置の指定

カメラ位置の指定をします。

camera.position.set( 0, 0, 50 ); // カメラ位置の設定

レンダラーの設定

// レンダラーの用意
renderer = new THREE.WebGLRenderer(); // レンダラーの用意
renderer.setSize( width, height ); // サイズを指定
背景の指定
var bgColor = 0x000000;
renderer.setClearColor(bgColor, 1); // 背景色を指定
レンダラーをbodyに追加
document.body.appendChild( renderer.domElement ); // bodyへ追加

ライトの設定

ライトの用意と色の指定
// ライトの設定
var lightColor = 0xffffff; // ライトの色
var directionalLight = new THREE.DirectionalLight( lightColor ); // ライトの色を指定
ライトの位置を指定
directionalLight.position.set( 1, 1, 1 ); // ライトの位置の設定
ライトの追加

シーンにライトの追加をします。

scene.add( directionalLight ); // ライトの追加

Blenderで書き出された jsonファイルを読み込む

本題の json ファイルを読み込みます。ライトの設定の後に記述していきます。

// ...省略

document.addEventListener( 'DOMContentLoaded', function(){


    // ...省略 シーンの用意からライトの設定


    // jsonファイルの読み込み
    var loader = new THREE.JSONLoader();
    var json = './json/logo.json';// jsonパスの指定
    loader.load( json, function ( geometry, materials ) {
        var faceMaterial = new THREE.MeshFaceMaterial( materials );
        var materialColor = 0xff8700; // マテリアルの色
        faceMaterial.materials[0].color = new THREE.Color(materialColor); // マテリアルの色の設定
        faceMaterial.materials[0].wireframe = true; // ワイヤーフレーム表示にする

        mesh = new THREE.Mesh( geometry, faceMaterial );
        mesh.position.set( 0,0,0); // 位置の設定
        mesh.scale.set( 10, 10, 10 ); // スケールの設定

        scene.add( mesh ); // シーンへメッシュの追加

        renderLoop(); // レンダリング実行
    } );

});

// レンダリング処理
speed変数の数値を変えることで動く数値が大きくなるので早く回転してるように見えます。
function renderLoop () {
    var speed = 0.005; // 追加される値
    // メッシュの回転
    var meshRotaX = mesh.rotation.x + speed,
        meshRotaY = mesh.rotation.y + speed,
        meshRotaZ = mesh.rotation.z + speed;
    mesh.rotation.set(meshRotaX, meshRotaY, meshRotaZ);
    renderer.render( scene, camera ); // レンダリング
    requestAnimationFrame( renderLoop ); // ループ処理
}

jsonファイルの読み込み

JSONLoader を用意し、blender で出力した json ファイルを指定します。

var loader = new THREE.JSONLoader();
var json = './json/logo.json';// jsonパスの指定
loader.load( json, function ( geometry, materials ) {

   // 詳細を記述していきます。

} );

マテリアルの指定

まず、色の設定を行います。

var faceMaterial = new THREE.Meshfacematerial( materials );
var materialColor = 0xff8700; // マテリアルの色
faceMaterial.materials[0].color = new THREE.Color(materialColor); // マテリアルの色の設定

お好みでワイヤー表示に設定

wireframe を true にすることで、ワイヤー表示に変更できます。
逆に false にすることで、ワイヤー表示ではなく、そのまま表示されます。

faceMaterial.materials[0].wireframe = true; // ワイヤーフレーム表示にする

位置と大きさの指定

mesh = new THREE.Mesh( geometry, faceMaterial );
mesh.position.set( 0,0,0); // 位置の設定
mesh.scale.set( 10, 10, 10 ); // スケールの設定

scene.add( mesh ); // シーンへメッシュの追加

レンダリング処理

レンダリング処理の関数を用意

DOMContentLoaded イベントの外に、レンダリング処理を記述します。

// レンダリング処理
function renderLoop () {

    // レンダリング処理を記述します。

}

メッシュの回転

var speed = 0.005; // 追加される値
// メッシュの回転
var meshRotaX = mesh.rotation.x + speed,
    meshRotaY = mesh.rotation.y + speed,
    meshRotaZ = mesh.rotation.z + speed;
mesh.rotation.set(meshRotaX, meshRotaY, meshRotaZ);

レンダリング

renderer.render( scene, camera ); // レンダリング

ループ処理

requestAnimationFrame( renderLoop ); // ループ処理

動作確認

170127_3d
https://hal-satoyuki.github.io/sample3d/

はじめのほうにも書きましたが、Chrome だとローカルフォルダ内で読み込んだ json ファイルの部分でエラーになっていまいますので、動作確認にはFirefoxを使って確認してみてください。

まとめ

Blenderで出力したものを ただ表示するだけですが、今回は簡単なやり方をまとめてみました。実際、あまりにも簡単だったのでびっくりしたほどです。読み込みに時間はかかるものの、もっと複雑な3Dのデータを表示することも可能です。

Blender の操作方法は今回紹介しませんでしたが、わりと Illustrator に近いのかなと思っています。ほかの3Dソフトも挑戦したことがありますが、独学では一番使いやすいイメージです。

Blender に興味が出た方は、ぜひ挑戦してみてはいかがでしょうか。