Как экспортировать 3D‑сцены в glTF/GLB в TypeScript

Как экспортировать 3D‑сцены в glTF/GLB в TypeScript

Aspose.3D FOSS поддерживает glTF 2.0 как формат импорта, так и экспорта. То же Scene объект может быть заполнен из OBJ, FBX, STL или другого исходного файла, а затем записан в .gltf (JSON + внешнее бинарное) или .glb (единственный бинарный контейнер), установив один флаг на GltfSaveOptions.

Пошаговое руководство

Шаг 1: Установите @aspose/3d

npm install @aspose/3d

Убедитесь, что активна Node.js 18 или более новая версия:

node --version   # must be >= 16.0.0

Шаг 2: Импортировать Scene, GltfSaveOptions и GltfFormat

import { Scene } from '@aspose/3d';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

GltfFormat является дескриптором формата, передаваемым в scene.save(). GltfSaveOptions содержит всю конфигурацию экспорта.

Если вы также загружаете исходный файл (например, OBJ), импортируйте соответствующие параметры загрузки:

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

Шаг 3: Создать или загрузить сцену

Вариант A: Загрузка из существующего файла (конверсия 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());

Вариант B: Программно построить минимальную сцену:

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

Шаг 4: Настроить GltfSaveOptions

GltfSaveOptions управляет форматом вывода и деталями кодирования.

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;

Дополнительные параметры, которые можно задать:

СвойствоТипПо умолчаниюЭффект
binaryModebooleanfalsetrue → GLB, false → glTF JSON
flipTexCoordVbooleantrueОтразить вертикальную ось UV для совместимости с движком

Шаг 5: Сохранить с помощью scene.save()

Передайте путь вывода, GltfFormat descriptor, а также настроенные параметры:

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

Для создания JSON .gltf файл вместо этого:

saveOpts.binaryMode = false;
scene.save('output.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Exported to glTF JSON successfully');

Шаг 6: Проверьте выходной файл

Убедитесь, что выходной файл существует и имеет ненулевой размер:

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

Для проверки обратного пути перезагрузите GLB и проверьте количество узлов:

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

Распространённые проблемы и их решения

Файл материала OBJ не найден после экспорта При сохранении в OBJ через scene.save('output.obj'), .mtl файл материалов записывается рядом с .obj файлом автоматически. Убедитесь, что каталог вывода доступен для записи и оба файла находятся вместе.

Выходной .glb меньше, чем ожидалось / сетки отсутствуют Если загруженная сцена содержит узлы без сущностей (например, пустые группы из OBJ), GLB не будет содержать геометрию этих узлов. Убедитесь, что ваш входной файл содержит реальные полигональные данные, используя mesh.controlPoints.length > 0 перед сохранением.

Не удалось найти модуль ‘@aspose/3d/formats/gltf’ Убедитесь, что вы используете Node.js 18+ и что @aspose/3d установлен в том же node_modules как ваша точка входа. Запустите npm ls @aspose/3d чтобы подтвердить, что версия 24.12.0 или новее.

GltfFormat.getInstance() возвращает undefined Это указывает на несоответствие версий между основным @aspose/3d пакетом и кэшированной более старой версией. Удалите node_modules и package-lock.json, затем выполните npm install снова.

Текстуры отсутствуют в выходном GLB Убедитесь binaryMode = true установлен для создания самодостаточного GLB. Для вывода glTF JSON файлы изображений текстур должны присутствовать рядом с выходным файлом, поскольку они указаны относительным путём.

Ошибка типа: аргумент типа ‘GltfSaveOptions’ не может быть присвоен Убедитесь, что оба Scene и GltfSaveOptions импортируются из одного и того же установленного экземпляра пакета. Смешанные установки (глобальные + локальные) могут вызвать несоответствия интерфейсов.

Часто задаваемые вопросы (FAQ)

В чём разница между glTF и GLB? glTF 2.0 JSON (.gltf) сохраняет граф сцены в виде читаемого человеком JSON‑файла с отдельными .bin буферами и файловыми изображениями. GLB (.glb) упаковывает всё в один бинарный контейнер. Set binaryMode = true для GLB, false для JSON glTF.

Могу ли я экспортировать сцену, построенную полностью в коде (без исходного файла)? Да. Создайте Scene, добавьте Node объекты, присоедините Mesh или другие сущности, затем вызвать scene.save().Сцена не обязана исходить из загруженного файла.

Экспорт glTF без потерь? Для геометрии и трансформаций — да. Материалы по возможности сопоставляются со свойствами материалов glTF PBR. Проприетарные расширения материалов FBX могут не проходить обратный процесс без потерь.

Могу ли я экспортировать в STL или 3MF вместо этого? Да. Схема идентична; импортируйте соответствующий формат. *SaveOptions и *Format.getInstance():

import { StlSaveOptions, StlFormat } from '@aspose/3d/formats/stl';
const opts = new StlSaveOptions();
scene.save('output.stl', StlFormat.getInstance(), opts);

Выполняется ли scene.save() асинхронно? Нет. scene.save() является синхронным. Оберните его в worker thread, если вам нужно избежать блокировки event loop при больших экспортах.

Какие версии Node.js поддерживаются? Node.js 18, 20 и 22+. Node.js 16 и более ранние версии не поддерживаются.

См. также

 Русский