MENU

【Three.js】Blenderで作成したアニメーション付き3DモデルをWebページに表示する方法

こんにちは、もしくはこんばんは。シロです!

最近、Blenderを使用して3Dモデリングをする人が増えてきました。

3Dモデルはゲームやメタバース空間などで幅広く活用できます。しかし、Webコンテンツとしての活用方法はまだ情報が少なく、技術的に難しい思っている人も多いかと思います。

この記事では、3Dグラフィックスを描画するためのJavaScriptライブラリであるThree.jsを使って、3DモデルをWebページに表示する方法をご紹介します!

Three.jsについては以下の記事でも紹介しています。

目次

できるようになること

この記事を読むと、Webページにあなたが作成した3Dモデルを掲載できるようになります。

デモページを用意しました。マウス操作もできるようになっているので、ぜひ3Dモデルをぐるぐる操作してみてください。

前提条件

  • 3Dモデルをもっていること
  • Blenderの基本的な操作ができること
  • Javascript/CSSの基礎知識があること

ステップ1:3Dモデルの準備

初めに、Webページの表示に対応したデータ形式であるglTF形式で3Dモデルをエクスポートします。

Blenderを使ってglTF形式で3Dモデルをエクスポートする方法については、以下の記事をご覧ください。

また、3Dモデルのアップロードについては、各サーバやプラットフォームによって方法が異なります。

WordPressでのアップロード方法については、上記の記事に記載していますので、あわせてご覧ください。

ステップ2:Three.jsのインポート

Webページの<head>にThree.jsのインポート文を追記します。<head>内が推奨ですが、<body>内でも問題ありません。

このコードでは、importmapを使用してThree.jsのモジュールを読み込んでいます。

  <head>
    <script type="importmap">
      {
        "imports": {
          "three": "https://unpkg.com/three@v0.151.3/build/three.module.js",
          "three/addons/": "https://unpkg.com/three@v0.151.3/examples/jsm/"
        }
      }
    </script>
  </head>

ステップ3:3Dモデルの表示

Webページの<body>にGLTF形式の3Dモデルを表示するスクリプトを記載します。以下はスクリプトの全文です。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>three.jsでGLBファイルを表示する</title>
    <style>
      body {
        margin: 0;
        background-color: rgb(118, 120, 139);
      }
      canvas {
        display: block;
      }
    </style>
        <script type="importmap">
          {
            "imports": {
              "three": "https://unpkg.com/three@v0.151.3/build/three.module.js",
              "three/addons/": "https://unpkg.com/three@v0.151.3/examples/jsm/"
            }
          }
        </script>
  </head>
  <body>

    <script type="module">
        // 1. Three.jsライブラリの読み込み
        import * as THREE from 'three';
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
        import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
        import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

        // 2. シーンを作成する
        const scene = new THREE.Scene();

        // 2. カメラを作成する
        const camera = new THREE.PerspectiveCamera(
            75, // 視野角
            window.innerWidth / window.innerHeight, // アスペクト比
            0.1, // ニアクリップ面
            1000 // ファークリップ面
        );
        camera.position.z = 5; // カメラの位置を設定する

        // 4. レンダラーを作成する
        const renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xffffff, 0);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        const controls = new OrbitControls(camera, renderer.domElement);
        controls.zoomSpeed = 0.5;
        controls.update(); // 初期化時に一度だけ呼び出す

        // AmbientLightを追加する
        const ambientLight = new THREE.AmbientLight(0xffffff, 1);
        scene.add(ambientLight);

        // 5. GLTFLoaderを作成する
        const loader = new GLTFLoader();
        
        const dracoLoader = new DRACOLoader(); // DRACOLoaderのインスタンスを作成
        dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.1/');
        loader.setDRACOLoader(dracoLoader); // GLTFLoaderにDRACOLoaderのインスタンスを提供

        // 6. clockを作成する
        const clock = new THREE.Clock();

        // 7. 3Dモデルのロード&描画
        loader.load(
            "path/to/model.gltf",
            function (gltf) {
                // アニメーションを読み込む
                let mixer = new THREE.AnimationMixer(gltf.scene);
                gltf.animations.forEach((clip) => {
                    mixer.clipAction(clip).play();
                });

                scene.add(gltf.scene);

                // アニメーションを更新する関数を定義する
                function update() {
                    if (mixer) {
                        mixer.update(clock.getDelta());
                    }
                }

                // アニメーションを再生するイベントを設定する
                renderer.setAnimationLoop(() => {
                    update();
                    renderer.render(scene, camera);
                });
            },
            undefined,
            function (error) {
                console.error(error);
            }
        );
    </script>
  </body>
</html>

1. Three.jsライブラリの読み込み

        import * as THREE from 'three';
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
        import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
        import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

このコードは、Three.jsを使用して3Dモデルを表示するための準備をするためのものです。

import文は、Three.jsのライブラリから必要な機能をインポートします。ここでは、THREEオブジェクト全体をインポートし、OrbitControlsGLTFLoaderDRACOLoaderの各機能をインポートしています。

OrbitControlsは、カメラをマウスで制御するためのユーティリティであり、GLTFLoaderDRACOLoaderは、それぞれGLTF形式の3Dモデルと、その圧縮バージョンであるDRACO形式の3Dモデルを読み込むためのユーティリティです。

2. シーンを作成する

        const scene = new THREE.Scene();

このコードは、Three.jsのSceneオブジェクトを作成するコードです。

Sceneオブジェクトは、3Dオブジェクトを保持するコンテナのようなもので、3Dオブジェクトを配置するための基盤となります。

Sceneオブジェクトを作成したら、この中に3Dオブジェクトを追加していきます。例えば、立方体や球体、テキストなどが3Dオブジェクトにあたりますが、今回はGLTF形式の3Dデータを追加します。

3. カメラを作成する

        const camera = new THREE.PerspectiveCamera(
            75, // 視野角
            window.innerWidth / window.innerHeight, // アスペクト比
            0.1, // ニアクリップ面
            1000 // ファークリップ面
        );
        camera.position.z = 5; // カメラの位置を設定する

これはthree.jsのカメラオブジェクトを作成し、適切な位置を設定するコードです。

具体的には、PerspectiveCameraを作成しています。

第1引数は視野角、第2引数はアスペクト比、第3引数はニアクリップ面、第4引数はファークリップ面を指定します。

  • 視野角:この角度で描画範囲を調整します。
  • アスペクト比: カメラが描画する領域です。一般的に、ディスプレイの縦横比と同じ値を指定します。
  • ニアクリップ面:カメラが描画する最も近い距離です。この距離よりも近いオブジェクトは描画されません。
  • ファークリップ面:カメラが描画する最も遠い距離です。この距離よりも遠いオブジェクトは描画されません。

また、カメラの位置をz方向に5に設定しています。

4. レンダラーを作成する

        const renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xffffff, 0);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        const controls = new OrbitControls(camera, renderer.domElement);
        controls.zoomSpeed = 0.5;
        controls.update(); // 初期化時に一度だけ呼び出す

        // AmbientLightを追加する
        const ambientLight = new THREE.AmbientLight(0xffffff, 1);
        scene.add(ambientLight);

このコードは、レンダラーとカメラコントロールを設定し、シーンにAmbientLightを追加している部分です。

rendererは、Three.jsが提供するWebGLRendererオブジェクトです。setSize()を使用して、描画領域のサイズを指定し、domElementをdocumentに追加することで、シーンをレンダリングするためのキャンバスをHTMLに挿入します。

OrbitControlsは、Three.jsが提供するカメラコントロールオブジェクトです。この例では、OrbitControlsを使用してカメラを制御し、マウスでシーンをズーム、回転、平行移動することができます。

AmbientLightは、環境光源を表すThree.jsのライトオブジェクトです。この例では、白色光を1.0の強度でシーンに追加しています。環境光源は、影を落とすことはできませんが、3Dモデルをより自然に見せるために使用されます。

5. GLTFLoaderを作成する

        const loader = new GLTFLoader();
        
        const dracoLoader = new DRACOLoader(); // DRACOLoaderのインスタンスを作成
        dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.1/');
        loader.setDRACOLoader(dracoLoader); // GLTFLoaderにDRACOLoaderのインスタンスを提供

このコードは、GLTFファイルを読み込むためのローダを設定しています。

GLTFファイルを読み込むためには、GLTFLoaderを使用します。GLTFLoaderは内部的に、バイナリファイルの解析やテクスチャの読み込みを行います。

DRACOLoaderは、3Dモデルのファイルサイズを小さくするための圧縮技術であるDracoのデコーダを提供します。DRACOLoaderを使用するには、DRACOのデコードに必要なファイルをロードして、GLTFLoaderに渡す必要があります。

dracoLoader変数は、DRACOLoaderのインスタンスを作成し、setDecoderPath()メソッドを使用してDRACOデコーダのパスを設定します。そして、setDRACOLoader()メソッドを使用して、GLTFLoaderにDRACOLoaderのインスタンスを提供します。

6. clockを作成する

        const clock = new THREE.Clock();

このコードは、Three.jsで時間を追跡するために使用するClockオブジェクトを作成しています。

Clockオブジェクトは、Three.jsのアニメーションに欠かせないもので、アニメーションにおいて経過した時間を管理するために使用します。

具体的には、各アニメーションフレーム間で経過した時間を計測し、アニメーションに必要な変更を正確な速度で行うために使用されます。例えば、オブジェクトを回転させるアニメーションを作成する場合、Clockオブジェクトを使用して、オブジェクトが回転する速度を設定できます。

7. 3Dモデルのロード&描画

        loader.load(
            "path/to/model.gltf",
            function (gltf) {
                // アニメーションを読み込む
                let mixer = new THREE.AnimationMixer(gltf.scene);
                gltf.animations.forEach((clip) => {
                    mixer.clipAction(clip).play();
                });

                scene.add(gltf.scene);

                // アニメーションを更新する関数を定義する
                function update() {
                    if (mixer) {
                        mixer.update(clock.getDelta());
                    }
                }

                // アニメーションを再生するイベントを設定する
                renderer.setAnimationLoop(() => {
                    update();
                    renderer.render(scene, camera);
                });
            },
            undefined,
            function (error) {
                console.error(error);
            }
        );

このコードは、Three.jsを使用してGLTF形式の3Dモデルを読み込んで、アニメーションを再生する方法を示しています。

最初にGLTFLoaderを使用して、3Dモデルを読み込みます。読み込みが完了すると、アニメーションを再生するための準備が整います。

アニメーションを再生するためには、THREE.AnimationMixerを使用して、アニメーションクリップをミキサーに追加し、再生する必要があります。

そして、アニメーションを更新するために、アニメーションを再生するイベントをrenderer.setAnimationLoop()メソッドで設定します。

renderer.setAnimationLoop()メソッドは、フレームごとにupdate()関数を呼び出して、アニメーションを進め、シーンをレンダリングします。

この方法を使用すると、シームレスなアニメーションを実現することができます。

まとめ

この記事では、Thess.jsを使ってWebページ上にアニメーション付きの3Dモデルを表示する方法について解説しました。

過去の記事でご紹介したmodel-viewerではより簡単にアニメーションの再生が可能ですが、残念ながら複数アニメーションの再生に対応していません
(この記事でご紹介した振り子のデモでいうと、1つの振り子しか動かない状態になります。)

一方で、Three.jsでは3Dモデルデータに含まれる全てのアニメーションをシームレスに再生可能です。

ぜひこの記事を参考にして、より魅力的なコンテンツを自分のウェブサイトやブログに追加してみてください!

以上、「【Three.js】Blenderで作成したアニメーション付き3DモデルをWebページに表示する方法」についての紹介でした。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
目次