TypeScript에서 3D 모델 로드하는 방법

TypeScript에서 3D 모델 로드하는 방법

@aspose/3d 패키지는 TypeScript 및 Node.js 애플리케이션에 3D 씬 파일을 여는 간단한 API를 제공합니다. Scene는 루트 객체입니다: 파일 경로와 선택적인 형식별 로드 옵션을 사용하여 scene.open()을 호출하고, 그런 다음 scene.rootNode를 순회하여 기하학, 재료 및 변환에 접근합니다.

단계별 가이드

1단계: npm을 통해 @aspose/3d 설치

패키지를 프로젝트에 추가하십시오. 네이티브 바이너리나 플랫폼별 빌드 도구는 필요하지 않으며, Node.js 18 이상만 필요합니다.

npm install @aspose/3d

TypeScript 프로젝트의 경우, 타입 정의가 패키지에 포함됩니다:

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

Step 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';

Step 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(mesh, camera, light 등)를 포함할 수 있습니다.

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 배열에서 원시 제어점(정점)을 읽을 수 있습니다. 각 항목은 x, y, zw 구성 요소를 가진 Vector4입니다.

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 배열의 길이가 0입니다
메시가 로드되었지만 기하학이 포함되지 않았을 수 있습니다(예: OBJ의 빈 그룹). 정점 반복 전에 mesh.polygonCount를 사용하여 확인하십시오.

대용량 파일에서 메모리 사용량이 높음
Load-from-buffer with 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 파일을 OBJ 파일 디렉터리를 기준으로 찾습니다 (mtllib 지시문). 두 파일이 동일한 폴더에 있는지 확인하십시오.

관련 항목

 한국어