Как экспортировать 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;Дополнительные параметры, которые вы можете установить:
| Свойство | Тип | По умолчанию | Эффект |
|---|---|---|---|
binaryMode | boolean | false | true → GLB, false → glTF JSON |
flipTexCoordV | boolean | true | Перевернуть вертикальную ось UV для совместимости с движком |
Шаг 5: Сохранить с помощью scene.save()
Передайте путь вывода, дескриптор GltfFormat и настроенные параметры:
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 material file not found after export
При сохранении в 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) упаковывает всё в один бинарный контейнер. Установите binaryMode = true для GLB, false для JSON glTF.
Могу ли я экспортировать сцену, полностью построенную в коде (без исходного файла)?
Да. Создайте Scene, добавьте объекты Node, присоедините Mesh или другие сущности, затем вызовите scene.save(). Сцена не обязана исходить из загруженного файла.
Экспорт glTF без потерь?
Для геометрии и трансформаций — да. Материалы по возможности сопоставляются со свойствами PBR‑материалов glTF. Собственные расширения материалов 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() синхронен. Оберните его в рабочий поток, если нужно избежать блокировки цикла событий при больших экспортных операциях.
Какие версии Node.js поддерживаются? Node.js 18, 20 и 22+. Node.js 16 и более ранние версии не поддерживаются.