Як експортувати 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 та налаштовані параметри:

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 без втрат?
Для геометрії та трансформацій — так. Матеріали, де можливо, відображаються у властивості матеріалів 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() є синхронним. Обгорніть його у робочий потік, якщо потрібно уникнути блокування циклу подій під час великих експортів.

Які версії Node.js підтримуються? Node.js 18, 20 і 22+. Node.js 16 та раніше не підтримуються.

Див. також

 Українська