Cara Membuat Mesh 3D Secara Programatis dengan TypeScript

Cara Membuat Mesh 3D Secara Programatis dengan TypeScript

Aspose.3D FOSS untuk TypeScript memungkinkan Anda membangun geometri 3D sepenuhnya dalam kode tanpa memuat file apa pun. Anda mendefinisikan posisi vertex sebagai titik kontrol, menentukan wajah poligon dengan indeks, dan melampirkan elemen vertex opsional seperti normal, UV, atau warna vertex. Hasilnya dapat disimpan ke format yang dapat ditulis apa pun: glTF, GLB, STL, FBX, atau COLLADA.

Prasyarat

  • Node.js 18 atau lebih baru
  • TypeScript 5.0 atau lebih baru
  • @aspose/3d terpasang (lihat Langkah 1)

Panduan Langkah-demi-Langkah

Langkah 1: Instal @aspose/3d

npm install @aspose/3d

Tidak diperlukan addon native atau pustaka sistem. Paket ini menyertakan definisi tipe TypeScript.

Minimum tsconfig.json:

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

Langkah 2: Buat Scene dan Node

Sebuah Scene adalah kontainer tingkat atas. Semua geometri harus dilampirkan ke Node di dalam pohon adegan:

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

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

createChildNode(name) membuat node bernama dan menghubungkannya sebagai anak dari node saat ini. Objek Node yang dikembalikan adalah tempat Anda akan melampirkan mesh pada Langkah 7.


Langkah 3: Buat Objek Mesh

Mesh menyimpan posisi vertex dan definisi poligon. Buat satu dengan nama opsional:

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

const mesh = new Mesh('triangle');

Mesh dimulai kosong: tidak ada vertices dan tidak ada faces. Anda menambahkannya pada langkah selanjutnya.


Langkah 4: Tambahkan Titik Kontrol (Vertices)

Control points adalah posisi vertex dalam ruang lokal. Dorong nilai Vector4 ke dalam mesh.controlPoints. Komponen keempat (w) adalah 1 untuk posisi:

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

Anda merujuk posisi-posisi ini dengan indeks berbasis nol saat mendefinisikan wajah poligon.


Step 5: Buat Wajah Poligon

createPolygon() mendefinisikan sebuah face dengan mencantumkan indeks vertex secara berurutan. Tiga indeks membentuk segitiga:

mesh.createPolygon(0, 1, 2);

Anda juga dapat mendefinisikan kuad (empat indeks) atau poligon arbitrer untuk format yang mendukungnya. Untuk glTF, perpustakaan akan secara otomatis melakukan triangulasi kuad dan n‑gon saat ekspor.


Langkah 6: Tambahkan Normal Vertex

Normal meningkatkan kualitas rendering. Gunakan mesh.createElement() untuk membuat VertexElementNormal, kumpulkan vektor normal ke dalam array, lalu panggil setData() untuk menyimpannya. Getter data mengembalikan salinan defensif — menambahkan ke dalamnya tidak berpengaruh. Gunakan FVector3 (float presisi tunggal) untuk data normal, bukan 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 berarti satu normal per vertex. ReferenceMode.DIRECT berarti array data diindeks langsung oleh indeks vertex poligon.


Langkah 7: Lampirkan Mesh dan Simpan ke glTF

Tetapkan mesh ke node melalui node.entity, lalu simpan adegan:

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');

Untuk menghasilkan satu file .glb yang berdiri sendiri, atur saveOpts.binaryMode = true dan ubah ekstensi file output menjadi .glb.

Contoh Lengkap

Berikut adalah skrip lengkap yang menggabungkan semua langkah di atas:

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');

Jalankan dengan ts-node:

npx ts-node triangle.ts

Masalah Umum

MasalahPenyebabPerbaikan
mesh.controlPoints.length adalah 0 setelah pushMesh tidak direferensikan oleh node mana punPush sebelum menetapkan node.entity; urutan tidak penting, tetapi verifikasi referensinya
Ekspor menghasilkan geometri kosongnode.entity tidak ditetapkanPastikan node.entity = mesh sebelum memanggil scene.save()
Jumlah normal tidak cocokArray yang diberikan ke setData() lebih pendek daripada controlPointsTambahkan satu entri FVector3 per titik kontrol saat menggunakan MappingMode.CONTROL_POINT
Penampil glTF menampilkan mesh hitamNormal mengarah ke dalamBalikkan urutan winding di createPolygon (mis., 0, 2, 1) atau negasikan vektor normal
TypeScript: properti ’normals.data’ tidak ditemukanJalur impor salahImpor VertexElementNormal dari @aspose/3d/entities, bukan dari akar @aspose/3d

Pertanyaan yang Sering Diajukan

Bisakah saya membuat kuad alih-alih segitiga?
Ya. Berikan empat indeks ke createPolygon(0, 1, 2, 3). Perpustakaan melakukan triangulasi kuad saat mengekspor ke format yang memerlukan segitiga (glTF, STL).

Apa perbedaan antara MappingMode.CONTROL_POINT dan MappingMode.POLYGON_VERTEX?
CONTROL_POINT menyimpan satu nilai per vertex unik. POLYGON_VERTEX menyimpan satu nilai per pasangan polygon‑vertex, yang memungkinkan normal yang berbeda pada vertex yang sama ketika termasuk dalam beberapa polygon (tepi keras).

Apakah saya perlu melakukan triangulasi mesh sebelum menyimpan ke STL?
Tidak. Perpustakaan menangani triangulasi secara otomatis saat mengekspor ke format yang memerlukan segitiga. Anda dapat mendefinisikan kuad dan n‑gon dalam mesh dan menyimpan langsung ke STL.

Bagaimana cara menambahkan koordinat UV?
Gunakan mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) untuk membuat VertexElementUV, kemudian panggil setData([...]) dengan array nilai FVector2 atau FVector3 — satu per titik kontrol. Getter data mengembalikan salinan; jangan menambahkan langsung ke dalamnya.

Bisakah saya membangun beberapa mesh dalam satu adegan?
Ya. Buat beberapa node di bawah scene.rootNode dan tetapkan Mesh terpisah ke properti entity masing‑masing node.

Lihat Juga

 Bahasa Indonesia