blender Three.js

Three.jsにBlenderで作ったオブジェクトを読み込む

2020/07/11

※ 本ページはプロモーションが含まれています。

Three.jsにBlenderで作成したオブジェクトの読み込み方についての記事になります。
下記の前回で作ったものをベースに進めます。

Blenderでオブジェクトを書き出す。

Blenderで作成したオブジェクトを[ファイル > エクスポート > glTF2.0]でエクスポートします。
ミラーなどのモディファイアーは適応させておいた方が良いです。

Three.jsにglTFデータを読み込む

css

body {
  margin: 0;
  overflow: hidden;
  top: 0;
  left: 0;
}
#canvas {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}

html

<script src="js/threejs/three.min.js"></script>
<script src="js/threejs/GLTFLoader.js"></script>
<script src="js/sample01.js"></script>

</head>
<body>
<canvas id="canvas"></canvas>
</body>

javascript

window.addEventListener('load', init);

function init() {
    // レンダラーを作成
    const renderer = new THREE.WebGLRenderer({
        canvas: document.querySelector('#canvas'),
        antialias: true
    });
    // シーンを作成
    const scene = new THREE.Scene();

    // カメラを作成
    const camera = new THREE.PerspectiveCamera(45, 1);
    camera.fov = 60;
    camera.position.set(0, 0, 1000);

    // Load GLTF or GLB
    const loader = new THREE.GLTFLoader();
    const url = './img/Giraffe.glb';

    let model = null;
    loader.load(
        url,
        function (gltf) {
            model = gltf.scene;
            model.scale.set(100.0, 100.0, 100.0);
            model.position.set(0, -300, 0);
            //回転の調整
            model.rotation.y = THREE.Math.DEG2RAD * -45;
            scene.add(model);
        },
        function (error) {
            console.log('An error happened');
        }
    );
    //テクスチャをガンマ補正
    renderer.gammaOutput = true;
    renderer.gammaFactor = 2.2;


    // ライト追加
    hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x4169e1, 1.8);
    scene.add(hemisphereLight);

    // 初回実行
    tick();
    onResize();

    // リサイズイベント発生で実行
    window.addEventListener('resize', onResize);

    function onResize() {
        // サイズを取得
        const w = window.innerWidth;
        const h = window.innerHeight;
        // 描画サイズ
        renderer.setSize(w, h);
        // ピクセル比
        renderer.setPixelRatio(window.devicePixelRatio);
        // 空間の背景色 //0xから始まる16進数の色コード
        renderer.setClearColor(0xe4f8ec);

        // カメラのアスペクト比を正す
        camera.aspect = w / h;
        camera.updateProjectionMatrix();
        console.log('h' + h + 'h' + h);

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

    function tick() {
        requestAnimationFrame(tick);
        renderer.render(scene, camera);
    }

}

前回作成したものをベースにしています。
glTFデータを読み込むためにhtmlに[GLTFLoader.js]を読み込みます。jsファイルは、three.js-masterフォルダの[three.js-master/examples/js/loaders]にあります。

疑問点

meshデータ作成の部分を、glTFデータの読み込みに差し替えるだけのような気がするけど、なぜか、ちょっと回りくどいような[function tick()]みたいに、一つ噛まさないとglTFオブジェクトが表示されなかった。

【DEMO】

glTFオブジェクトをアニメーションさせる

window.addEventListener('load', init);

function init() {
    // レンダラーを作成
    const renderer = new THREE.WebGLRenderer({
        canvas: document.querySelector('#canvas'),
        antialias: true
    });
    // シーンを作成
    const scene = new THREE.Scene();

    // カメラを作成
    const camera = new THREE.PerspectiveCamera(45, 1);
    camera.fov = 60;
    camera.position.set(0, 0, 1000);

    // Load GLTF or GLB
    const loader = new THREE.GLTFLoader();
    const url = './img/Giraffe.glb';

    let model = null;
    loader.load(
        url,
        function (gltf) {
            model = gltf.scene;
            model.scale.set(100.0, 100.0, 100.0);
            model.position.set(0, -300, 0);
            //回転の調整
            //model.rotation.y = THREE.Math.DEG2RAD * -45;
            scene.add(model);
        },
        function (error) {
            console.log('An error happened');
        }
    );
    //テクスチャをガンマ補正
    renderer.gammaOutput = true;
    renderer.gammaFactor = 2.2;


    // ライト追加
    hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x4169e1, 1.8);
    scene.add(hemisphereLight);

    // 初回実行
    tick();
    onResize();

    // リサイズイベント発生で実行
    window.addEventListener('resize', onResize);

    function onResize() {
        // サイズを取得
        const w = window.innerWidth;
        const h = window.innerHeight;
        // 描画サイズ
        renderer.setSize(w, h);
        // ピクセル比
        renderer.setPixelRatio(window.devicePixelRatio);
        // 空間の背景色 //0xから始まる16進数の色コード
        renderer.setClearColor(0xe4f8ec);

        // カメラのアスペクト比を正す
        camera.aspect = w / h;
        camera.updateProjectionMatrix();
        console.log('h' + h + 'h' + h);

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

    function tick() {
        requestAnimationFrame(tick);
        //回転
        if (model) {
            model.rotation.y += 0.05;
        }
        renderer.render(scene, camera);
    }

}

function tick()関数に回転を付け加えただけです。ちょっとハマったのが、ここのif(model)部分で、このif文がないと挙動がおかしくなりました。どうやら『model(glTF)の読み込みが確認されてからアニメーション』っていうのがポイントのようです。

【DEMO】

【参考】

Three.js + Blender OrbitControls でカメラを動かす │ MUKOLOG

Three.jsにBlenderで作成したオブジェクトを読み込み、OrbitControls を使ってカメラを動かす


-blender, Three.js