Jak ładować modele 3D w TypeScript

Jak ładować modele 3D w TypeScript

Ten @aspose/3d pakiet daje aplikacjom TypeScript i Node.js prosty interfejs API do otwierania plików scen 3D. Scene jest obiektem głównym: wywołaj scene.open() z ścieżką do pliku i opcjonalnymi opcjami ładowania specyficznymi dla formatu, a następnie przejdź scene.rootNode aby uzyskać dostęp do geometrii, materiałów i przekształceń.

Przewodnik krok po kroku

Krok 1: Zainstaluj @aspose/3d za pomocą npm

Dodaj pakiet do swojego projektu. Nie są wymagane natywne pliki binarne ani narzędzia budowania specyficzne dla platformy; wystarczy Node.js 18 lub nowszy.

npm install @aspose/3d

W projektach TypeScript definicje typów są dołączone do pakietu:

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

Krok 2: Importuj Scene oraz opcje specyficzne dla formatu

Każdy format udostępnia własną klasę ładowarki i obiekt opcji w podścieżce. Importuj tylko to, co jest potrzebne:

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

Dla innych formatów wzorzec jest identyczny:

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

Krok 3: Otwórz plik 3D przy użyciu scene.open()

Utwórz Scene instancję, a następnie wywołaj scene.open() z ścieżką do pliku i opcjonalnym obiektem opcji ładowania. Wywołanie jest synchroniczne.

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

Aby załadować z Buffer już w pamięci (przydatne w kontekstach serverless lub strumieniowych):

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());

Krok 4: Iteruj po węzłach sceny

Graf sceny jest drzewem z korzeniem w scene.rootNode. Każdy Node może zawierać węzły potomne i opcjonalny entity (siatka, kamera, światło, itp.).

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);

Krok 5: Uzyskaj dostęp do danych wierzchołków siatki poprzez controlPoints

Gdy encja węzła jest Mesh, możesz odczytać surowe punkty kontrolne (wierzchołki) z controlPoints tablicy. Każdy wpis jest Vector4 z x, y, z, oraz w komponenty.

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)}`);
        }
    }
}

Krok 6: Skonfiguruj ObjLoadOptions do ładowania materiałów

ObjLoadOptions udostępnia właściwości do kontrolowania, jak towarzyszące .mtl pliki materiałów i tekstury są rozwiązywane.

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.entity && node.entity.material) {
        console.log(`Material on "${node.name}": ${node.entity.material.constructor.name}`);
    }
}

Typowe problemy i rozwiązania

Błąd: Nie można znaleźć modułu ‘@aspose/3d/formats/obj’ Ścieżki podformatów wymagają eksportów pakietu Node.js 12.7+. Upewnij się, że używasz Node.js 18 lub nowszego. Jeśli używasz TypeScript, ustaw "moduleResolution": "node16" lub "bundler" w tsconfig.json.

scene.rootNode.childNodes jest pusty po wywołaniu open() Niektóre pliki OBJ używają niestandardowych zakończeń linii lub nie mają końcowego znaku nowej linii. Zweryfikuj, że plik jest prawidłowym OBJ, otwierając go w edytorze tekstu. Również potwierdź, że przekazałeś ObjLoadOptions i nie ogólny LoadOptions: opcje specyficzne dla formatu są wymagane do prawidłowego przekierowania.

tablica controlPoints ma zerową długość Siatka mogła zostać załadowana, ale nie zawiera geometrii (np. pustej grupy w OBJ). Użyj mesh.polygonCount aby sprawdzić przed iteracją wierzchołków.

Użycie pamięci jest wysokie dla dużych plików Ładowanie z bufora przy użyciu scene.openFromBuffer() nie zmniejsza szczytowego zużycia pamięci: cały plik musi być przetworzony. Dla dużych plików (> 100 MB) upewnij się, że proces Node.js ma wystarczający stos: node --max-old-space-size=4096 yourScript.js.

Błędy typów: ’entity’ jest typu ‘unknown’ Ten entity właściwość jest typowana szeroko. Rzutuj na any lub na konkretną klasę (Mesh, Camera, itp.) w zależności od tego, czego oczekujesz w swojej scenie.

Najczęściej zadawane pytania (FAQ)

Jakie formaty można załadować za pomocą scene.open()? OBJ, glTF 2.0 (.gltf + .bin), GLB, STL, 3MF, FBX i COLLADA (.dae) są wszystkie obsługiwane przy imporcie. Przekaż odpowiedni *LoadOptions klasę dla każdego formatu.

Czy mogę załadować plik bez podawania opcji? Tak. scene.open('model.glb') działa bez opcji dla formatów, które nie wymagają specjalnej konfiguracji. Przekazywanie opcji jest zalecane dla OBJ, ponieważ rozdzielczość materiału zależy od enableMaterials.

Czy ładowanie odbywa się asynchronicznie? Nie. scene.open() i scene.openFromBuffer() są synchroniczne. Owiń je w wątek roboczy lub setImmediate jeśli musisz utrzymać responsywną pętlę zdarzeń.

Czy eksport OBJ jest obsługiwany? Tak. Eksport OBJ jest obsługiwany przez scene.save('output.obj'). Ten .mtl plik materialny jest zapisywany automatycznie obok .obj pliku.

Gdzie oczekiwany jest plik .mtl podczas ładowania OBJ? Domyślnie parser szuka .mtl pliku odwołującego się wewnątrz OBJ (mtllib dyrektywy) względem katalogu pliku OBJ. Upewnij się, że oba pliki znajdują się w tym samym folderze.

Zobacz także

 Polski