วิธีโหลดโมเดล 3 มิติใน TypeScript

วิธีโหลดโมเดล 3 มิติใน TypeScript

The @aspose/3d แพคเกจนี้ให้แอปพลิเคชัน TypeScript และ Node.js API ที่ตรงไปตรงมาสำหรับการเปิดไฟล์ฉาก 3D. Scene เป็นอ็อบเจ็กต์ราก: เรียก scene.open() ด้วยเส้นทางไฟล์และตัวเลือกการโหลดที่เฉพาะรูปแบบ (ถ้ามี), จากนั้นเดินทางผ่าน scene.rootNode เพื่อเข้าถึงเรขาคณิต, วัสดุ, และการแปลง.

คู่มือแบบขั้นตอนต่อขั้นตอน

ขั้นตอนที่ 1: ติดตั้ง @aspose/3d ผ่าน npm

เพิ่มแพคเกจนี้ลงในโปรเจกต์ของคุณ ไม่จำเป็นต้องมีไบนารีเนทีฟหรือเครื่องมือการสร้างที่เฉพาะแพลตฟอร์ม; เพียงแค่ Node.js เวอร์ชัน 18 ขึ้นไป.

npm install @aspose/3d

สำหรับโปรเจกต์ TypeScript, คำจำกัดความของประเภทจะถูกรวมอยู่ในแพคเกจ:

##tsconfig.json: minimum required settings
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true
  }
}

ขั้นตอนที่ 2: นำเข้า Scene และตัวเลือกที่เฉพาะรูปแบบ

แต่ละรูปแบบจะเปิดเผยคลาสโหลดเดอร์และอ็อบเจกต์ตัวเลือกของตนเองภายใต้เส้นทางย่อย ให้นำเข้าเฉพาะสิ่งที่คุณต้องการ:

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

สำหรับรูปแบบอื่น ๆ รูปแบบการใช้งานจะเหมือนกัน:

import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';

ขั้นตอนที่ 3: เปิดไฟล์ 3D ด้วยการใช้ scene.open()

สร้าง Scene อินสแตนซ์, จากนั้นเรียก scene.open() ด้วยเส้นทางไฟล์และอ็อบเจ็กต์ตัวเลือกการโหลด (ถ้ามี). การเรียกนี้เป็นแบบซิงโครนัส.

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

const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;

scene.open('model.obj', options);
console.log('Scene loaded successfully');

เพื่อโหลดจาก Buffer ที่อยู่ในหน่วยความจำแล้ว (มีประโยชน์ในบริบท serverless หรือการสตรีม):

import * as fs from 'fs';
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';

const buffer = fs.readFileSync('model.obj');
const scene = new Scene();
scene.openFromBuffer(buffer, new ObjLoadOptions());

ขั้นตอนที่ 4: วนลูปผ่านโหนดของฉาก

กราฟฉากเป็นต้นไม้ที่มีรากที่ scene.rootNode. Node แต่ละ entity สามารถมีโหนดลูกและอ็อบเจ็กต์เลือกได้.

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

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

function visitNode(node: any, depth: number = 0): void {
    const indent = '  '.repeat(depth);
    console.log(`${indent}Node: ${node.name}`);
    if (node.entity) {
        console.log(`${indent}  Entity type: ${node.entity.constructor.name}`);
    }
    for (const child of node.childNodes) {
        visitNode(child, depth + 1);
    }
}

visitNode(scene.rootNode);

ขั้นตอนที่ 5: เข้าถึงข้อมูลเวอร์เท็กซ์ของเมชผ่าน controlPoints

(เมช, กล้อง, แสง, ฯลฯ). Mesh,เมื่อเอนทิตี้ของโหนดเป็น คุณสามารถอ่านจุดควบคุมดิบ (เวอร์เท็กซ์) จาก controlPoints array. แต่ละรายการคือ Vector4 กับ x, y, z, และ w ส่วนประกอบ.

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

const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());

for (const node of scene.rootNode.childNodes) {
    if (!node.entity) continue;
    const entity = node.entity;
    // Check if the entity is a Mesh by duck-typing controlPoints
    if ('controlPoints' in entity) {
        const mesh = entity as any;
        console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices`);
        // Print first three vertices
        for (let i = 0; i < Math.min(3, mesh.controlPoints.length); i++) {
            const v = mesh.controlPoints[i];
            console.log(`  v[${i}]: x=${v.x.toFixed(4)}, y=${v.y.toFixed(4)}, z=${v.z.toFixed(4)}`);
        }
    }
}

ขั้นตอนที่ 6: กำหนดค่า ObjLoadOptions สำหรับการโหลดวัสดุ

ObjLoadOptions เปิดเผยคุณสมบัติเพื่อควบคุมวิธีการที่ไฟล์แนบ .mtl ไฟล์วัสดุและเทกเจอร์ถูกกำหนดค่า.

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

const options = new ObjLoadOptions();
options.enableMaterials = true;   // parse .mtl file if present

const scene = new Scene();
scene.open('model.obj', options);

// Inspect materials attached to nodes
for (const node of scene.rootNode.childNodes) {
    if (node.entity && node.entity.material) {
        console.log(`Material on "${node.name}": ${node.entity.material.constructor.name}`);
    }
}

ปัญหาทั่วไปและวิธีแก้ไข

ข้อผิดพลาด: ไม่พบโมดูล ‘@aspose/3d/formats/obj’ เส้นทางย่อยของรูปแบบต้องการการส่งออกแพ็กเกจของ Node.js 12.7+ ตรวจสอบว่าคุณใช้ Node.js 18 หรือใหม่กว่า หากใช้ TypeScript ให้ตั้งค่า "moduleResolution": "node16" หรือ "bundler" ใน tsconfig.json.

scene.rootNode.childNodes ว่างเปล่าหลังจาก open() ไฟล์ OBJ บางไฟล์ใช้การขึ้นบรรทัดที่ไม่เป็นมาตรฐานหรือไม่มี newline สุดท้าย ตรวจสอบว่าไฟล์เป็น OBJ ที่ถูกต้องโดยเปิดในโปรแกรมแก้ไขข้อความ นอกจากนี้ยังยืนยันว่าคุณได้ส่ง ObjLoadOptions และไม่ใช่แบบทั่วไป LoadOptions: ตัวเลือกเฉพาะรูปแบบจำเป็นสำหรับการส่งที่ถูกต้อง.

อาร์เรย์ controlPoints มีความยาวเป็นศูนย์ เมชอาจถูกโหลดแล้วแต่ไม่มีเรขาคณิต (เช่น กลุ่มว่างใน OBJ) ใช้ mesh.polygonCount เพื่อตรวจสอบก่อนทำการวนลูปเวอร์เทกซ์.

การใช้หน่วยความจำสูงสำหรับไฟล์ขนาดใหญ่ โหลดจากบัฟเฟอร์ด้วย scene.openFromBuffer() ไม่ลดการใช้หน่วยความจำสูงสุด: ต้องทำการพาร์สไฟล์ทั้งหมด สำหรับไฟล์ขนาดใหญ่ (> 100 MB) ให้แน่ใจว่ากระบวนการ Node.js ของคุณมี heap เพียงพอ: node --max-old-space-size=4096 yourScript.js.

ข้อผิดพลาดประเภท: ’entity’ มีประเภทเป็น ‘unknown’ The entity คุณสมบัติมีการกำหนดประเภทอย่างกว้างขวาง. แคสต์เป็น any หรือเป็นคลาสเฉพาะ (Mesh, Camera, ฯลฯ) ขึ้นอยู่กับสิ่งที่คุณคาดหวังในฉากของคุณ.

คำถามที่พบบ่อย (FAQ)

รูปแบบใดบ้างที่สามารถโหลดด้วย scene.open()? OBJ, glTF 2.0 (.gltf + .bin), GLB, STL, 3MF, FBX และ COLLADA (.dae) ทั้งหมดได้รับการสนับสนุนสำหรับการนำเข้า ส่งผ่านคลาสที่สอดคล้องกัน *LoadOptions คลาสสำหรับแต่ละรูปแบบ.

ฉันสามารถโหลดไฟล์โดยไม่ระบุตัวเลือกได้หรือไม่? ได้. scene.open('model.glb') ทำงานได้โดยไม่ต้องระบุตัวเลือกสำหรับรูปแบบที่ไม่ต้องการการกำหนดค่าพิเศษ การส่งผ่านตัวเลือกแนะนำสำหรับ OBJ เนื่องจากการแก้ไขวัสดุขึ้นอยู่กับ enableMaterials.

การโหลดทำงานแบบอะซิงโครนัสหรือไม่? ไม่. scene.open() และ scene.openFromBuffer() ทำงานแบบซิงโครนัส. ห่อหุ้มไว้ในเธรดทำงานหรือ setImmediate หากคุณต้องการให้ลูปเหตุการณ์ตอบสนองได้.

รองรับการส่งออก OBJ หรือไม่? ได้. การส่งออก OBJ ได้รับการสนับสนุนผ่าน scene.save('output.obj'). ตัว .mtl ไฟล์วัสดุจะถูกเขียนโดยอัตโนมัติข้างเคียงกับ the .obj ไฟล์.

ไฟล์ .mtl คาดว่าจะอยู่ที่ไหนเมื่อโหลด OBJ? โดยค่าเริ่มต้น parser จะมองหา .mtl ไฟล์ที่อ้างอิงภายใน OBJ (mtllib directive) สัมพันธ์กับไดเรกทอรีของไฟล์ OBJ. ตรวจสอบให้แน่ใจว่าไฟล์ทั้งสองอยู่ในโฟลเดอร์เดียวกัน.

ดูเพิ่มเติม

 ภาษาไทย