glTF形式の3DモデルをThree.jsを用いてブラウザに表示する方法

3Dモデル
目次

はじめに

最近、Blenderをちょいちょい触ることがあったので、それをブラウザで表示できないかと思い、その方法を調べてみた。

開発環境

  • Ruby on Rails 7.0.0
  • Blender 2.93.5

3Dモデルを用意

glTF形式の3Dモデルを用意。今回はBlenderを使って作成した。

  • BlenderでglTF形式でエクスポートをかける際に、Draco圧縮をかけてデータを圧縮をする

Draco圧縮とは?

DRACO(Dynamic Range Adaptive Compression Optimization)は、Googleが開発した、3Dモデルのデータ圧縮を目的としたオープンソースのライブラリ。DRACOは、3Dメッシュデータを非常に効率的に圧縮することができ、ファイルサイズを小さくし、モデルの読み込みや表示のパフォーマンスを向上させる。

出力したglTFは、GLTFLoaderで読み込むことができるが、Draco圧縮した場合は、DRACOLoaderを設定する必要有り。

https://www.pentacreation.com/blog/2020/02/200213.html

① ファイル → エクスポート → glTF形式ファイルを選択

② 次の画像のように設定(フォーマットはglTFバイナリで)

メニュー
メニュー

エクスポートしたglTFファイルは、publicディレクトリ内にmodelsというディレクトリを新たに作成し、そこに格納した。

HTMLの用意

今回は、HTMLファイルにスクリプトもCSSも記述した。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>gltf形式の3DモデルをThree.jsを用いてブラウザに表示する方法</title>

   // 外部モジュール
    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/three@0.151.3/build/three.module.js",
                "OrbitControls": "https://unpkg.com/three@0.151.3/examples/jsm/controls/OrbitControls.js",
                "GLTFLoader": "https://unpkg.com/three@0.151.3/examples/jsm/loaders/GLTFLoader.js",
                "DRACOLoader": "https://unpkg.com/three@0.151.3/examples/jsm/loaders/DRACOLoader.js",
                "lil-gui": "https://cdn.jsdelivr.net/npm/lil-gui@0.19/+esm"
            }
        }
    </script>
</head>

<body>
     <!-- // 3Dモデルを表示させるcanvas要素を作成 -->
    <canvas id="canvas"></canvas>
    <script type="module">
        import * as THREE from 'three';
        import { GLTFLoader } from "GLTFLoader";
        import { DRACOLoader } from 'DRACOLoader';
        import { OrbitControls } from "OrbitControls";
        import GUI from 'lil-gui';

        // 画面サイズの取得
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;

        // レンダラーの作成
        const canvas = document.getElementById('canvas')
        const renderer = new THREE.WebGLRenderer({ canvas: canvas });
        renderer.setSize(windowWidth, windowHeight);

        // シーンの作成
        const scene = new THREE.Scene();

        // 背景色の設定(黒)
        scene.background = new THREE.Color('#000000');

        // 見やすいようにヘルパー(網目)を設定
        let gridHelper = new THREE.GridHelper();
        scene.add(gridHelper);

        // カメラを作成
        const camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000);
        camera.position.set(0, 0.45, -1);
        camera.rotation.set(-2,1,3);
        camera.lookAt(camera.position);

        // ライトの作成
        const light = new THREE.PointLight(0xffffff, 2, 100);
        light.position.set(10, 20, 5);
        scene.add(light);

        // マウス制御
        const controls = new OrbitControls(camera, renderer.domElement);

        // DRACOLoaderを設定
        const dracoLoader = new DRACOLoader();
        dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.1/'); // デコーダーのパスを設定        
        
        // 3Dモデルの読み込み
        const loader = new GLTFLoader();
        loader.setDRACOLoader(dracoLoader);

        loader.load('../models/ファイル名', function (gltf) {
            const model = gltf.scene;
            model.scale.set(0.1, 0.1, 0.1);
            scene.add(model);
        }, undefined, function (error) {
            console.error(error);
        });

        // アニメーション
        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }

        //lil-GUI
        const gui = new GUI();
        const cameraFloder = gui.addFolder("camera_position");
        cameraFloder.add(camera.position,"x").min(-5).max(5).step(0.01);
        cameraFloder.add(camera.position,"y").min(-5).max(5).step(0.01);
        cameraFloder.add(camera.position,"z").min(-5).max(5).step(0.01);

        //ブラウザのリサイズに対応
        function onWindowResize(){
          renderer.setSize(window.innerWidth,window.innerHeight);
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix(); //カメラのアスペクト比を正したら必ず記述
        }
        window.addEventListener("resize",onWindowResize);


        // アニメーション実行
        animate();
    </script>
    <style>
        body{
            margin:0;
            width:100%;
            height:100%
        }
    </style>
</body>
</html>

今回読み込むのは、以下の4つ。

  • DRACOLoader:Draco圧縮したデータを読み込む。
  • OrbitControl:OrbitControlsを使用する事で空間内のカメラの動きをマウスで制御可能。
  • GLTFLoader:GLTFLoaderを使用することでglTF型式の3Dモデルを読み込む。
  • lil-GUI:パラメータを視覚的に操作できるUI。

JavaScript

・GridHelper: 地面がどこにあるのかを把握できる。

let gridHelper = new THREE.GridHelper();
scene.add(gridHelper);

・OrbitControls: canvas内での空間内のカメラをPCならマウス操作、モバイルならタッチ操作する事が可能。

const controls = new OrbitControls(camera, renderer.domElement);

参考

https://qiita.com/enumura1/items/c62f15c4fbeb541fa830
https://lil-gui.georgealways.com/#Guide#Installation

作品

https://syeimee.com/creations/tunnel.html

今回はここまで。

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