TypeScriptで3Dモデルをロードする方法

TypeScriptで3Dモデルをロードする方法

@aspose/3d パッケージは、TypeScript および Node.js アプリケーションに 3D シーン ファイルを開くためのシンプルな API を提供します。Scene はルートオブジェクトです。scene.open() をファイルパスとオプションのフォーマット固有のロードオプションで呼び出し、次に scene.rootNode をたどってジオメトリ、マテリアル、トランスフォームにアクセスします。

ステップバイステップガイド

ステップ 1: npm 経由で @aspose/3d をインストール

パッケージをプロジェクトに追加してください。ネイティブバイナリやプラットフォーム固有のビルドツールは不要です; Node.js 18以降のみ必要です。

git clone https://github.com/aspose-3d-foss/Aspose.3D-FOSS-for-TypeScript.git
cd Aspose.3D-FOSS-for-TypeScript
npm install
npm run build

TypeScript プロジェクトの場合、型定義はパッケージに同梱されています:

##tsconfig.json: minimum required settings
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true
  }
}

ステップ 2: シーンのインポートとフォーマット固有のオプション

各フォーマットは、サブパスの下に独自のローダークラスとオプションオブジェクトを公開します。必要なものだけをインポートしてください:

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

他の形式ではパターンは同じです:

import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';

ステップ 3: scene.open() を使用して 3D ファイルを開く

Scene インスタンスを作成し、次にファイルパスとオプションの load‑options オブジェクトを使用して scene.open() を呼び出します。この呼び出しは同期です。

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;

scene.open('model.obj', options);
console.log('Scene loaded successfully');

メモリ内にすでにある Buffer からロードする(サーバーレスやストリーミングのコンテキストで便利です):

import * as fs from 'fs';
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const buffer = fs.readFileSync('model.obj');
const scene = new Scene();
scene.openFromBuffer(buffer, new ObjLoadOptions());

ステップ 4: シーンノードを反復処理

シーングラフは scene.rootNode を根とするツリーです。各 Node は子ノードとオプションの entity(メッシュ、カメラ、ライトなど)を含むことができます。

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

function visitNode(node: any, depth: number = 0): void {
    const indent = '  '.repeat(depth);
    console.log(`${indent}Node: ${node.name}`);
    if (node.entity) {
        console.log(`${indent}  Entity type: ${node.entity.constructor.name}`);
    }
    for (const child of node.childNodes) {
        visitNode(child, depth + 1);
    }
}

visitNode(scene.rootNode);

ステップ5: controlPoints を介してメッシュの頂点データにアクセス

ノードのエンティティがMeshの場合、controlPoints配列から生の制御点(頂点)を読み取ることができます。各エントリはVector4で、x、y、z、およびwコンポーネントを持ちます。

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

for (const node of scene.rootNode.childNodes) {
    if (!node.entity) continue;
    const entity = node.entity;
    // Check if the entity is a Mesh by duck-typing controlPoints
    if ('controlPoints' in entity) {
        const mesh = entity as any;
        console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices`);
        // Print first three vertices
        for (let i = 0; i < Math.min(3, mesh.controlPoints.length); i++) {
            const v = mesh.controlPoints[i];
            console.log(`  v[${i}]: x=${v.x.toFixed(4)}, y=${v.y.toFixed(4)}, z=${v.z.toFixed(4)}`);
        }
    }
}

ステップ 6: マテリアル読み込みのために ObjLoadOptions を構成する

ObjLoadOptions は、付随する .mtl マテリアルファイルとテクスチャの解決方法を制御するプロパティを公開します。

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const options = new ObjLoadOptions();
options.enableMaterials = true;   // parse .mtl file if present

const scene = new Scene();
scene.open('model.obj', options);

// Inspect materials attached to nodes
for (const node of scene.rootNode.childNodes) {
    if (node.material) {
        console.log(`Material on "${node.name}": ${node.material.constructor.name}`);
    }
}

一般的な問題と対処法

エラー: モジュール ‘@aspose/3d/formats/obj’ が見つかりません
フォーマットのサブパスは Node.js 12.7+ パッケージエクスポートが必要です。Node.js 18 以降を使用していることを確認してください。TypeScript を使用している場合は、"moduleResolution": "node16" または "bundler" を tsconfig.json に設定してください。

scene.rootNode.childNodes が open() 後に空です
一部の OBJ ファイルは非標準の改行コードを使用しているか、末尾の改行がありません。テキストエディタで開いて、ファイルが有効な OBJ であることを確認してください。また、汎用の LoadOptions ではなく ObjLoadOptions を渡したことを確認してください。フォーマット固有のオプションは正しいディスパッチに必要です。

controlPoints 配列の長さがゼロです
メッシュはロードされたがジオメトリが含まれていない可能性があります(例: OBJ の空のグループ)。頂点を反復処理する前に mesh.polygonCount を使用して確認してください。

大きなファイルでメモリ使用量が高くなる
scene.openFromBuffer() を使用したバッファからのロードでは、ピークメモリは削減されません。ファイル全体を解析する必要があります。100 MB を超える大きなファイルの場合、Node.js プロセスに十分なヒープが確保されていることを確認してください: node --max-old-space-size=4096 yourScript.js.

タイプエラー: ’entity’ は型 ‘unknown’ です
entity プロパティは広く型付けされています。any にキャストするか、特定のクラス(Mesh、Camera など)にキャストしてください。シーンで期待するものに応じて選択します。

よくある質問 (FAQ)

scene.open()で読み込めるフォーマットはどれですか?
OBJ、glTF 2.0(.gltf + .bin)、GLB、STL、3MF、FBX、そして COLLADA(.dae)はすべてインポートがサポートされています。各フォーマットに対応する *LoadOptions クラスを渡してください。

オプションを指定せずにファイルをロードできますか? はい。 scene.open('model.glb') は、特別な設定を必要としないフォーマットではオプションなしで動作します。OBJ では、マテリアルの解像度が enableMaterials に依存するため、オプションを渡すことが推奨されます。

ロードは非同期で実行されますか?
いいえ。 scene.open() と scene.openFromBuffer() は同期的です。イベントループを応答可能に保つ必要がある場合は、ワーカースレッドまたは setImmediate にラップしてください。

OBJ エクスポートはサポートされていますか? はい。OBJ エクスポートは scene.save('output.obj') を介してサポートされています。.mtl マテリアルファイルは .obj ファイルと同時に自動的に書き込まれます。

OBJ をロードするときに .mtl ファイルはどこにあることが期待されますか?
デフォルトでは、パーサは OBJ 内で参照されている .mtl ファイル(mtllib ディレクティブ)を OBJ ファイルのディレクトリを基準に探します。両方のファイルが同じフォルダーにあることを確認してください。

関連項目

 日本語