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/3dterpasang (lihat Langkah 1)
Panduan Langkah-demi-Langkah
Langkah 1: Instal @aspose/3d
npm install @aspose/3dTidak 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.tsMasalah Umum
| Masalah | Penyebab | Perbaikan |
|---|---|---|
mesh.controlPoints.length adalah 0 setelah push | Mesh tidak direferensikan oleh node mana pun | Push sebelum menetapkan node.entity; urutan tidak penting, tetapi verifikasi referensinya |
| Ekspor menghasilkan geometri kosong | node.entity tidak ditetapkan | Pastikan node.entity = mesh sebelum memanggil scene.save() |
| Jumlah normal tidak cocok | Array yang diberikan ke setData() lebih pendek daripada controlPoints | Tambahkan satu entri FVector3 per titik kontrol saat menggunakan MappingMode.CONTROL_POINT |
| Penampil glTF menampilkan mesh hitam | Normal mengarah ke dalam | Balikkan urutan winding di createPolygon (mis., 0, 2, 1) atau negasikan vektor normal |
| TypeScript: properti ’normals.data’ tidak ditemukan | Jalur impor salah | Impor 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.