なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

Three.js で ArrayBuffer から 3D モデルを表示したい

Three.js 系列 (three / @react-three/fiber) で、例えば直接サポートされていない圧縮形式のリモートファイルをダウンロードして表示したい、みたいなケースがある。 そういうときは、 ArrayBuffer を経由して以下のようにすると、 3D モデルを上手いこと表示出来る。 以下は @react-three/fiber を使って、 Polygon File Format (PLY) ファイルを表示する例:

// @react-three/fiber を使った例
import { OrbitControls, PerspectiveCamera } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { useEffect, useState } from "react";

import { type BufferGeometry, DoubleSide} from "three";
import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";

const Renderer = () => {
  const [model, setModel] = useState<BufferGeometry>();
  useEffect(() => {
    fetch("~~~")
      .then(w => .../* なんらかの解凍処理など */)
      .then(w => w.arrayBuffer()) // ArrayBuffer にできればなんでも良い
      .then(buffer => {
        const loader = new PLYLoader();
        const geometry = loader.parse(buffer);
        geometry.computeVertexNormals();

        setModel(geometry);
      });
  }, []);

  if (!model) {
    return null;
  }

  return <Canvas>
    <OrbitControls />
    <PerspectiveCamera makeDefault fov={50} aspect={1/1} />
    <mesh>
      <primitive object={model} />
    </mesh>
  </Canvas>
};

実際には Suspense 出来るようにしてあげると良いが、ポイントとしては loader.parse() を呼ぶこと、必要に応じて computeVertexNormals() などの追加計算処理を走らせること、の2つ。 そこまでできれば、あとは得られた Geometry を Primitive を用いて描画してあげれば良い。

ということで、メモでした。