[Astro] #121 3D Model Viewer — assimpjs WASM による40+フォーマット対応ブラウザ完結型3Dモデルビューア

[Astro] #121 3D Model Viewer — assimpjs WASM による40+フォーマット対応ブラウザ完結型3Dモデルビューア

概要

Open Asset Import Library(assimp)のWASMビルド「assimpjs」を使い、FBX・OBJ・DAE・3DS・STL・PLY・DXF・X3D・IFC・STEP等 40以上の3Dファイルフォーマットをブラウザ内でGLBに変換し、Three.jsで3D表示するユニバーサル3Dモデルビューアを構築した。

サーバーへのファイルアップロードは一切不要で、すべてブラウザ内で完結する。変換後のGLBファイルはそのままダウンロードでき、3Dフォーマットコンバーターとしても機能する。

スクリーンショット

3D Model Viewer スクリーンショット 3D Model Viewer スクリーンショット

動画 (GIF)

3D Model Viewer スクリーンショット

今回の実装内容

機能・モジュール概要
assimpjs統合assimp C++ライブラリのWASMビルドをブラウザに組み込み
40+フォーマット変換FileList API → ConvertFileList(‘glb2’) → GLBバイナリ
Three.js 3D表示GLTFLoaderでGLBを表示、OrbitControlsでカメラ操作
ネイティブローダーフォールバックassimpjs初期化失敗時にFBX/OBJ/STL/PLY/3DS/DAEをThree.jsネイティブローダーで処理
ZIP対応ZIP内のモデル+テクスチャ+MTLを自動展開しassimpjsに渡す
アニメーション再生GLB変換後のアニメーションクリップを検出、再生/停止
GLBエクスポートassimpjs変換後のGLBバイナリをそのままダウンロード
ファイル情報表示三角形数、頂点数、メッシュ数、アニメーション数、変換前後のサイズ
変換ログassimpjs処理の各ステップをログパネルにリアルタイム表示

背景

3Dモデルのファイルフォーマットは歴史的に乱立している。FBX(Autodesk)、OBJ(Wavefront)、DAE(Collada)、3DS(3ds Max)、STL(3Dプリント)、PLY(点群)、DXF(AutoCAD)、IFC(建築BIM)、STEP(CAD)、X3D(Web3D)等、用途ごとに異なるフォーマットが使われている。

これらを個別のローダーで対応するとコードが膨大になる。assimp(Open Asset Import Library)はC++で書かれた3Dファイル読み込みライブラリで、40以上のフォーマットを統一的なデータ構造に変換できる。assimpjsはこのassimpをEmscriptenでWASMビルドしたもので、ブラウザ内で同じ変換が可能になる。

技術実装の詳細

1. アーキテクチャ

[ ブラウザ ]
│  ファイルドロップ / ZIP展開 (JSZip)
│  → fileEntries: { name, data }[]

[ assimpjs WASM ]
│  FileList.AddFile() でファイル群を登録
│  ConvertFileList(fileList, 'glb2') → GLBバイナリ

[ Three.js GLTFLoader ]
│  GLBバイナリをparse → Scene + Animations

[ WebGL描画 ]
   OrbitControls, AmbientLight, DirectionalLight, HemisphereLight

2. assimpjsの組み込み

assimpjsはEmscriptenビルドのWASMモジュール。assimpjs.js(グルーコード)とassimpjs.wasmの2ファイルで構成される。

CDNからの読み込みではlocateFileによるWASMパス解決が不安定なため、public/libs/にローカル配置して読み込む。

<script src="/libs/assimpjs.js" is:inline></script>
const assimpPromise = assimpjs({
  locateFile: (path) => '/libs/' + path
});

3. 変換パイプライン

assimpjsのAPIは3ステップ:

const ajs = await assimpPromise;
const fileList = new ajs.FileList();

// メインファイル + テクスチャ/MTL等を全て追加
fileList.AddFile(fileName, new Uint8Array(arrayBuffer));

// GLB2形式に変換
const result = ajs.ConvertFileList(fileList, 'glb2');

if (result.IsSuccess() && result.FileCount() > 0) {
  const glbData = new Uint8Array(result.GetFile(0).GetContent());
}

ZIP内のテクスチャやMTLファイルもFileListに追加することで、assimpが内部で参照を解決する。

4. フォールバック設計

assimpjsのWASM初期化が失敗した場合(ネットワーク問題、ブラウザ互換性等)、Three.jsのネイティブローダーにフォールバックする二重の安全網を設計。

ファイルドロップ
├─ GLB/GLTF → GLTFLoader(直接表示)
└─ その他
   ├─ assimpjs成功 → GLB変換 → GLTFLoader
   └─ assimpjs失敗
      ├─ FBX → FBXLoader
      ├─ OBJ → OBJLoader + MTLLoader
      ├─ STL → STLLoader
      ├─ PLY → PLYLoader
      ├─ 3DS → TDSLoader
      ├─ DAE → ColladaLoader
      └─ その他 → エラー表示

5. カメラ自動フレーミング

モデルのバウンディングボックスからサイズと中心を算出し、カメラ位置・OrbitControlsターゲット・near/farクリッピングを自動調整。ミリメートル単位の小さなモデルから100メートル級の建築モデルまで対応。

const box = new THREE.Box3().setFromObject(obj);
const maxDim = Math.max(size.x, size.y, size.z);
camera.position.set(center.x, center.y + size.y * 0.15, center.z + maxDim * 2.2);
camera.near = Math.max(0.001, maxDim * 0.001);
camera.far = Math.max(100, maxDim * 20);

対応フォーマット一覧(assimpjs経由)

CAD・交換フォーマット: FBX, DAE/Collada, OBJ, 3DS, STL, PLY, DXF, STP/STEP, IFC-STEP, 3MF, X3D, glTF/GLB

ゲーム・エンジン系: MDL, MD2, MD3, MD5, B3D, SMD, VTA, ASE, X, OGEX, OFF, NDO

DCC・モデリングツール系: AC/AC3D, LWO, LWS, LXO, COB, MS3D, NFF, CSM, BVH, IRR/IRRMESH

その他: HMP, RAW, TER, SCN, PMX, XGL, ZGL, M3D, USD 等

技術スタック

  • Astro — ページ構築
  • assimpjs — assimp C++ライブラリのEmscripten WASMビルド(40+フォーマット→GLB変換)
  • Three.js r160 — GLTFLoader, OrbitControls, WebGL描画
  • JSZip — ZIP展開(モデル+テクスチャの一括読み込み)
  • vanilla JavaScript — DOM操作、ドラッグ&ドロップ、ファイル処理

更新履歴

  • [v1.0]: assimpjs統合、40+フォーマット対応、GLBエクスポート、ネイティブローダーフォールバック、アニメーション再生、ZIP対応。公開。