モデルの読み込み【drei,fiber】

React

モデルの読み込みはfiberだけでもできますが、dreiを使うとさらに簡単に読み込めます。

ファイルの場所

publicファイル・・・静的ファイルとしてアクセスしたいとき
srcファイル・・・Webpackの管理下でファイルを扱いたいとき

publicフォルダに置く場合

  • アクセス方法: publicフォルダ内のファイルはURL経由で直接アクセスできます。例えば、public/models/model.gltfにファイルがある場合は、Reactのコードで/models/model.gltfのようにURLとして参照します。
  • ファイル処理: publicに置かれたファイルはWebpackのビルドプロセスに含まれず、そのままのパスで出力されます。つまり、ビルド後の構造が変わらず、ファイルが「そのままの形」で保持されます。
const { scene } = useGLTF('/models/model.gltf'); // publicフォルダにあるファイル

srcフォルダに置く場合

  • アクセス方法: srcフォルダに置く場合は、importを使ってモデルファイルをWebpackによって管理されたモジュールとしてインポートする必要があります。これはWebpackがファイルをバンドルしてくれるためで、ファイルを直接URLで参照することはできません。
  • ファイル処理: srcに置いたファイルはWebpackのビルドプロセスで処理され、依存関係としてバンドルされます。これにより、ファイルが効率的にパッケージ化され、必要なときに利用されます。つまり、publicフォルダに置いた場合と違い、ファイルのサイズ最適化やキャッシングなどのWebpackの機能が有効になります。
import modelUrl from './assets/model.gltf'; // srcフォルダにあるファイル 
const { scene } = useGLTF(modelUrl);

GLTFファイル形式

gltfとglbの二種類があります。

  • .gltf:
    テキストファイル(JSON)で、別のバイナリファイル(.bin)やテクスチャファイルを参照します。
  • .glb:
    全てのデータが1つのバイナリファイルにまとめられています。この形式は、配布や管理が簡単で、特にWebベースのアプリケーションで好まれます。

.gltf形式とその構成要素

  1. JSON形式のデータ(.gltf):
    JSON形式でモデルの構成情報(メッシュ、マテリアル、アニメーション、カメラなど)を記述します。(.binファイルへのuri情報が書いてあるので、名前を変えるときはこれも変える必要有)
  "buffers": [
    {
      "byteLength": 1840512,
      "uri": "earth.bin"//.binファイルの名前が書いてある
    }
  ],
  1. バイナリデータ(.bin):
    モデルのジオメトリ(頂点情報、インデックス、法線、テクスチャ座標など)のバイナリデータを別のファイル(通常は.binファイル)に格納します。.binファイルには、モデルのメッシュデータやアニメーションデータが含まれています。
  2. テクスチャファイル:
    テクスチャは、.gltfファイル内に直接含めず、外部の画像ファイル(PNGやJPEG形式)として管理することが一般的です。これにより、テクスチャのサイズや圧縮方式を最適化でき、異なるテクスチャを簡単に差し替えたり、再利用したりすることができます。

モデルをjsxコンポーネントに変換する

モデルをドラッグ&ドロップでコンポーネントに一発変換してくれるサイト↓

コマンドもあります

cd public //gltfやglbがあるフォルダまで移動
npx gltfjsx model.gltf //ファイル名を指定して実行

●ちなみにリンクはpublicからのリンクになってしまうので、フォルダに入れてたりするときはリンクを直す必要があります。
●export の default はついてないのでimport形式に注意。

import React from "react";
import { useGLTF } from "@react-three/drei";

export function Earth(props) {
  const { nodes, materials } = useGLTF("/earth.gltf");
  return (
    <group {...props} dispose={null}>
      <mesh
        geometry={nodes.Object_4.geometry}
        material={materials["Scene_-_Root"]}
        scale={1.128}
      />
    </group>
  );
}

useGLTF.preload("/earth.gltf");

上記のように、自動でuseGLTFを使ってnodeやmaterial情報を読み取り、geometryとmaterialにセットしてくれてます。素晴らしいです。

Suspense

useGLTFを使うと、reactのSuspenseコンポーネント使用時に、ローディング中にフォールバックを表示することができます。

import { Suspense } from "react";

function App() {
  return (
    <Canvas>
      <Suspense fallback={<Html>Loading...</Html>}>
        <Earth />
      </Suspense>
    </Canvas>
  );
}

fallbackの内容は直接HTML要素はおけないので、dreiのコンポーネント<Html>で挟む必要があります。(挟んだらdivとかも使えます)