วิธีสร้างเมช 3 มิติโดยเขียนโปรแกรมใน TypeScript

วิธีสร้างเมช 3 มิติโดยเขียนโปรแกรมใน TypeScript

Aspose.3D FOSS for TypeScript ให้คุณสร้างเรขาคณิต 3 มิติทั้งหมดด้วยโค้ดโดยไม่ต้องโหลดไฟล์ใด ๆ คุณกำหนดตำแหน่งเวอร์เท็กซ์เป็นจุดควบคุม ระบุหน้าพอลิกอนด้วยดัชนี และแนบองค์ประกอบเวอร์เท็กซ์เพิ่มเติมเช่นนอร์มัล, UV หรือสีเวอร์เท็กซ์ ผลลัพธ์สามารถบันทึกเป็นรูปแบบที่เขียนได้ทุกแบบ: glTF, GLB, STL, FBX หรือ COLLADA.

ข้อกำหนดเบื้องต้น

  • Node.js 18 หรือใหม่กว่า
  • TypeScript 5.0 หรือใหม่กว่า
  • @aspose/3d ติดตั้งแล้ว (ดูขั้นตอนที่ 1)

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

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

npm install @aspose/3d

ไม่จำเป็นต้องใช้แอดออนเนทีฟหรือไลบรารีระบบ. แพ็กเกจรวมการกำหนดประเภท TypeScript.

ขั้นต่ำ tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "strict": true
  }
}

ขั้นตอนที่ 2: สร้างฉากและโหนด

Scene คือคอนเทนเนอร์ระดับบนสุด เรขาคณิตทั้งหมดต้องถูกแนบไปยัง Node ภายในต้นไม้ฉาก:

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

const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');

createChildNode(name) สร้างโหนดที่มีชื่อและเชื่อมต่อเป็นลูกของโหนดปัจจุบัน วัตถุ Node ที่ส่งกลับมาคือที่คุณจะแนบเมชในขั้นตอนที่ 7.


ขั้นตอนที่ 3: สร้างอ็อบเจ็กต์ Mesh

Mesh เก็บตำแหน่งเวอร์เท็กซ์และคำนิยามของโพลิกอน สร้างหนึ่งโดยมีชื่อเป็นตัวเลือก:

import { Mesh } from '@aspose/3d/entities';

const mesh = new Mesh('triangle');

เมชเริ่มต้นเป็นค่าว่าง: ไม่มีจุดยอดและไม่มีหน้า. คุณเพิ่มพวกมันในขั้นตอนต่อไป.


ขั้นตอนที่ 4: เพิ่มจุดควบคุม (Vertices)

จุดควบคุมคือตำแหน่งเวอร์เท็กซ์ในพื้นที่ท้องถิ่น. ดันค่า Vector4 เข้าไปใน mesh.controlPoints. ส่วนประกอบที่สี่ (w) คือ 1 สำหรับตำแหน่ง:

import { Vector4 } from '@aspose/3d/utilities';

mesh.controlPoints.push(new Vector4(0.0, 0.0, 0.0, 1.0)); // index 0
mesh.controlPoints.push(new Vector4(1.0, 0.0, 0.0, 1.0)); // index 1
mesh.controlPoints.push(new Vector4(0.5, 1.0, 0.0, 1.0)); // index 2

คุณอ้างอิงตำแหน่งเหล่านี้โดยใช้ดัชนีเริ่มจากศูนย์เมื่อกำหนดหน้าโพลิกอน.


ขั้นตอนที่ 5: สร้างหน้าโพลิกอน

createPolygon() กำหนดหน้าตาโดยการระบุดัชนีของเวอร์เท็กซ์ตามลำดับ ดัชนีสามตัวทำให้เป็นสามเหลี่ยม:

mesh.createPolygon(0, 1, 2);

คุณยังสามารถกำหนดควอด (สี่ดัชนี) หรือรูปหลายเหลี่ยมใด ๆ สำหรับรูปแบบที่รองรับได้ สำหรับ glTF ไลบรารีจะทำการแปลงควอดและ n‑gon ให้เป็นสามเหลี่ยมโดยอัตโนมัติเมื่อส่งออก.


ขั้นตอนที่ 6: เพิ่มนอร์มัลของเวอร์เท็กซ์

Normal ช่วยปรับปรุงคุณภาพการเรนเดอร์ ใช้ mesh.createElement() เพื่อสร้าง VertexElementNormal, เก็บเวกเตอร์ปกติไว้ในอาเรย์, จากนั้นเรียก setData() เพื่อจัดเก็บมัน. ตัว getter data คืนค่ากลับเป็นสำเนาป้องกัน — การเพิ่มเข้าไปไม่มีผล. ใช้ FVector3 (float ความแม่นยำเดี่ยว) สำหรับข้อมูลปกติ, ไม่ใช่ Vector4.

import { VertexElementNormal } from '@aspose/3d/entities';
import { VertexElementType, MappingMode, ReferenceMode } from '@aspose/3d/entities';
import { FVector3 } from '@aspose/3d/utilities';

const normals = mesh.createElement(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
) as VertexElementNormal;

// Build the normal array, then call setData() — do NOT push to normals.data
normals.setData([
    new FVector3(0, 0, 1), // normal for vertex 0 (pointing +Z)
    new FVector3(0, 0, 1), // normal for vertex 1
    new FVector3(0, 0, 1), // normal for vertex 2
]);

MappingMode.CONTROL_POINT หมายถึงหนึ่งปกติต่อเวอร์เท็กซ์. ReferenceMode.DIRECT หมายถึงอาร์เรย์ข้อมูลถูกจัดทำดัชนีโดยตรงตามดัชนีเวอร์เท็กซ์ของโพลิกอน.


ขั้นตอนที่ 7: แนบ Mesh และบันทึกเป็น glTF

กำหนดเมชให้กับโหนดผ่าน node.entity, จากนั้นบันทึกฉาก:

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

node.entity = mesh;

const saveOpts = new GltfSaveOptions();
scene.save('triangle.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Triangle mesh saved to triangle.gltf');

เพื่อสร้างไฟล์ .glb แบบอิสระเดียวแทน ให้ตั้งค่า saveOpts.binaryMode = true และเปลี่ยนส่วนขยายของไฟล์ผลลัพธ์เป็น .glb.

ตัวอย่างสมบูรณ์

ต่อไปนี้เป็นสคริปต์เต็มที่รวมขั้นตอนทั้งหมดข้างต้น:

import { Scene } from '@aspose/3d';
import { Mesh, VertexElementNormal } from '@aspose/3d/entities';
import { VertexElementType, MappingMode, ReferenceMode } from '@aspose/3d/entities';
import { Vector4, FVector3 } from '@aspose/3d/utilities';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');

const mesh = new Mesh('triangle');

mesh.controlPoints.push(new Vector4(0.0, 0.0, 0.0, 1.0));
mesh.controlPoints.push(new Vector4(1.0, 0.0, 0.0, 1.0));
mesh.controlPoints.push(new Vector4(0.5, 1.0, 0.0, 1.0));

mesh.createPolygon(0, 1, 2);

const normals = mesh.createElement(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
) as VertexElementNormal;

// setData() is the correct API — normals.data returns a defensive copy; pushing to it has no effect
normals.setData([
    new FVector3(0, 0, 1),
    new FVector3(0, 0, 1),
    new FVector3(0, 0, 1),
]);

node.entity = mesh;

const saveOpts = new GltfSaveOptions();
scene.save('triangle.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Triangle mesh saved to triangle.gltf');

เรียกใช้ด้วย ts-node:

npx ts-node triangle.ts

ปัญหาทั่วไป

IssueCauseFix
mesh.controlPoints.length เป็น 0 หลังจาก pushMesh ไม่ได้ถูกอ้างอิงโดย node ใดทำการ push ก่อนกำหนด node.entity; ลำดับไม่สำคัญ แต่ตรวจสอบการอ้างอิง
การส่งออกสร้าง geometry ว่างnode.entity ไม่ได้กำหนดตรวจสอบให้มี node.entity = mesh ก่อนเรียก scene.save()
จำนวน normal ไม่ตรงกันอาร์เรย์ที่ส่งให้ setData() สั้นกว่า controlPointsเพิ่มรายการ FVector3 หนึ่งรายการต่อ control point เมื่อใช้ MappingMode.CONTROL_POINT
ตัวดู glTF แสดง mesh สีดำNormals ชี้เข้าด้านในกลับลำดับ winding ใน createPolygon (เช่น 0, 2, 1) หรือทำให้เวกเตอร์ normal เป็นลบ
TypeScript: ไม่พบ property ’normals.data'เส้นทาง import ผิดนำเข้า VertexElementNormal จาก @aspose/3d/entities, ไม่ใช่จาก root @aspose/3d

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

ฉันสามารถสร้างควอดแทนที่จะเป็นสามเหลี่ยมได้หรือไม่? ใช่. ส่งดัชนีสี่ตัวไปยัง createPolygon(0, 1, 2, 3). ไลบรารีจะทำการแปลงควอดเป็นสามเหลี่ยมระหว่างการส่งออกไปยังรูปแบบที่ต้องการสามเหลี่ยม (glTF, STL).

ความแตกต่างระหว่าง MappingMode.CONTROL_POINT กับ MappingMode.POLYGON_VERTEX คืออะไร?
CONTROL_POINT เก็บค่าหนึ่งค่าต่อเวอร์เท็กซ์ที่ไม่ซ้ำกัน. POLYGON_VERTEX เก็บค่าหนึ่งค่าต่อคู่โพลิกอน‑เวอร์เท็กซ์, ซึ่งทำให้สามารถมีนอร์มอลที่แตกต่างกันที่เวอร์เท็กซ์เดียวกันเมื่อมันเป็นส่วนของหลายโพลิกอน (ขอบแข็ง).

ฉันต้องทำการแปลงเมชเป็นสามเหลี่ยมก่อนบันทึกเป็น STL หรือไม่? ไม่. ไลบรารีจัดการการแปลงเป็นสามเหลี่ยมโดยอัตโนมัติเมื่อส่งออกเป็นรูปแบบที่ต้องการสามเหลี่ยม คุณสามารถกำหนดควอดและ n‑gon ในเมชและบันทึกเป็น STL ได้โดยตรง.

ฉันจะเพิ่มพิกัด UV อย่างไร?
ใช้ mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) เพื่อสร้าง VertexElementUV แล้วเรียก setData([...]) พร้อมอาร์เรย์ของค่า FVector2 หรือ FVector3 — หนึ่งค่าต่อจุดควบคุม. ตัวรับค่า data จะคืนสำเนา; อย่าเพิ่มค่าโดยตรง.

ฉันสามารถสร้างหลายเมชในฉากเดียวได้หรือไม่?
ใช่. สร้างหลายโหนดภายใต้ scene.rootNode และกำหนด Mesh แยกต่างหากให้กับคุณสมบัติ entity ของแต่ละโหนด.

ดูเพิ่มเติม

 ภาษาไทย