วิธีส่งออกฉาก 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 มีขนาดเล็กกว่าที่คาดไว้ / mesh หายไป
หากฉากที่โหลดมีโหนดที่ไม่มีเอนทิตี (เช่น กลุ่มว่างจาก 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 ไฟล์รูปภาพเท็กซ์เจอร์ต้องอยู่เคียงข้างไฟล์ผลลัพธ์ เนื่องจากถูกอ้างอิงด้วยเส้นทางสัมพันธ์.

Type error: Argument of type ‘GltfSaveOptions’ is not assignable
ตรวจสอบให้แน่ใจว่า Scene และ GltfSaveOptions ถูกนำเข้าจากอินสแตนซ์แพ็กเกจที่ติดตั้งเดียวกัน การติดตั้งแบบผสม (global + local) อาจทำให้เกิดความไม่ตรงกันของอินเทอร์เฟซ.

คำถามที่พบบ่อย (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 ที่เป็นกรรมสิทธิ์อาจไม่ทำการ round‑trip อย่างสมบูรณ์.

ฉันสามารถส่งออกเป็น 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 และก่อนหน้านั้นไม่ได้รับการสนับสนุน.

ดูเพิ่มเติม

 ภาษาไทย