Jak wyeksportować sceny 3D do glTF/GLB w TypeScript
Aspose.3D FOSS obsługuje glTF 2.0 zarówno jako format importu, jak i eksportu. Ten sam Scene obiekt może być wypełniony z pliku OBJ, FBX, STL lub innego pliku źródłowego, a następnie zapisany do .gltf (JSON + zewnętrzny plik binarny) lub .glb (pojedynczy kontener binarny) poprzez ustawienie jednej flagi w GltfSaveOptions.
Przewodnik krok po kroku
Krok 1: Zainstaluj @aspose/3d
npm install @aspose/3dUpewnij się, że Node.js 18 lub nowszy jest aktywny:
node --version # must be >= 16.0.0Krok 2: Importuj Scene, GltfSaveOptions i GltfFormat
import { Scene } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';GltfFormat jest deskryptorem formatu przekazywanym do scene.save(). GltfSaveOptions zawiera całą konfigurację eksportu.
Jeśli również ładujesz plik źródłowy (np. OBJ), zaimportuj odpowiadające opcje ładowania:
import { ObjLoadOptions } from '@aspose/3d/formats/obj';Krok 3: Utwórz lub wczytaj scenę
Opcja A: Ładowanie z istniejącego pliku (konwersja OBJ → GLB):
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());Opcja B: Zbuduj minimalną scenę programowo:
import { Scene, Node, Mesh } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const childNode = new Node('cube');
scene.rootNode.addChildNode(childNode);
// Attach geometry to childNode as needed
Krok 4: Skonfiguruj GltfSaveOptions
GltfSaveOptions kontroluje format wyjściowy i szczegóły kodowania.
const saveOpts = new GltfSaveOptions();
// Set to true for a single binary .glb file
// Set to false (default) for JSON .gltf + separate .bin
saveOpts.binaryMode = true;Dodatkowe opcje, które możesz ustawić:
| Właściwość | Typ | Domyślne | Efekt |
|---|---|---|---|
binaryMode | boolean | false | true → GLB, false → glTF JSON |
flipTexCoordV | boolean | true | Odwróć pionową oś UV dla zgodności z silnikiem |
Krok 5: Zapisz przy użyciu scene.save()
Przekaż ścieżkę wyjściową, deskryptor GltfFormat oraz skonfigurowane opcje:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true; // produce .glb
scene.save('output.glb', GltfFormat.getInstance(), saveOpts);
console.log('Converted to GLB successfully');Aby zamiast tego utworzyć plik JSON .gltf:
saveOpts.binaryMode = false;
scene.save('output.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Exported to glTF JSON successfully');Krok 6: Zweryfikuj plik wyjściowy
Sprawdź, czy plik wyjściowy istnieje i ma niezerowy rozmiar:
import * as fs from 'fs';
const outputPath = 'output.glb';
const stats = fs.statSync(outputPath);
console.log(`Output file size: ${stats.size} bytes`);
if (stats.size === 0) {
throw new Error('Export produced an empty file: check scene content');
}Aby zweryfikować pełny cykl, ponownie załaduj plik GLB i sprawdź liczbę węzłów:
import { Scene } from '@aspose/3d';
import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
const verify = new Scene();
verify.open('output.glb', new GltfLoadOptions());
let nodeCount = 0;
function countNodes(node: any): void {
nodeCount++;
for (const child of node.childNodes) countNodes(child);
}
countNodes(verify.rootNode);
console.log(`Round-trip verification: ${nodeCount} node(s) in output`);Typowe problemy i rozwiązania
Plik materiałowy OBJ nie został znaleziony po eksporcie
Podczas zapisywania do OBJ za pomocą scene.save('output.obj'), plik materiałowy .mtl jest zapisywany automatycznie obok pliku .obj. Upewnij się, że katalog wyjściowy jest zapisywalny i że oba pliki są przechowywane razem.
Wyjściowy plik .glb jest mniejszy niż oczekiwano / brak niektórych siatek
Jeśli załadowana scena zawiera węzły bez encji (np. puste grupy z pliku OBJ), plik GLB nie będzie zawierał geometrii tych węzłów. Upewnij się, że Twój plik wejściowy zawiera rzeczywiste dane wielokątów, używając mesh.controlPoints.length > 0 przed zapisaniem.
Nie można znaleźć modułu ‘@aspose/3d/formats/gltf’
Upewnij się, że używasz Node.js 18+ i że @aspose/3d jest zainstalowany w tym samym node_modules co Twój punkt wejścia. Uruchom npm ls @aspose/3d, aby potwierdzić, że wersja to 24.12.0 lub nowsza.
GltfFormat.getInstance() zwraca undefined
Wskazuje to na niezgodność wersji pomiędzy głównym pakietem @aspose/3d a zbuforowaną starszą wersją. Usuń node_modules i package-lock.json, a następnie uruchom ponownie npm install.
Tekstury brakują w wyjściowym pliku GLB
Upewnij się, że binaryMode = true jest ustawiony tak, aby generować samodzielny plik GLB. Dla wyjścia JSON glTF pliki obrazów tekstur muszą znajdować się obok pliku wyjściowego, ponieważ są odwoływane za pomocą ścieżki względnej.
Błąd typu: Argument typu ‘GltfSaveOptions’ nie jest przypisywalny
Upewnij się, że zarówno Scene, jak i GltfSaveOptions są importowane z tej samej zainstalowanej instancji pakietu. Mieszane instalacje (globalne + lokalne) mogą powodować niezgodności interfejsów.
Najczęściej zadawane pytania (FAQ)
Jaka jest różnica między glTF a GLB?
glTF 2.0 JSON (.gltf) przechowuje graf sceny jako czytelny dla człowieka plik JSON z oddzielnymi .bin buforami i plikami obrazów. GLB (.glb) pakuje wszystko w pojedynczy binarny kontener. Ustaw binaryMode = true dla GLB, false dla JSON glTF.
Czy mogę wyeksportować scenę, która została zbudowana całkowicie w kodzie (bez pliku źródłowego)?
Tak. Utwórz Scene, dodaj Node obiekty, dołącz Mesh lub inne jednostki, a następnie wywołaj scene.save(). Scena nie musi pochodzić z załadowanego pliku.
Czy eksport do glTF jest bezstratny? Jeśli chodzi o geometrię i przekształcenia, tak. Materiały są mapowane na właściwości materiałów PBR glTF, gdzie to możliwe. Własne rozszerzenia materiałów FBX mogą nie zachować się idealnie przy ponownym imporcie.
Czy mogę wyeksportować do STL lub 3MF zamiast tego?
Tak. Wzorzec jest identyczny; zaimportuj odpowiednie formaty *SaveOptions i *Format.getInstance():
import { StlSaveOptions, StlFormat } from '@aspose/3d/formats/stl';
const opts = new StlSaveOptions();
scene.save('output.stl', StlFormat.getInstance(), opts);Czy scene.save() działa asynchronicznie?
Nie. scene.save() jest synchroniczny. Owiń to w wątek roboczy, jeśli musisz uniknąć blokowania pętli zdarzeń podczas dużych eksportów.
Jakie wersje Node.js są obsługiwane? Node.js 18, 20 i 22+. Node.js 16 i wcześniejsze nie są obsługiwane.