Як програмно створити 3D‑меш у TypeScript
Aspose.3D FOSS for TypeScript дозволяє створювати 3D‑геометрію повністю в коді без завантаження будь‑якого файлу. Ви визначаєте позиції вершин як контрольні точки, вказуєте полігональні грані за індексом і додаєте необов’язкові елементи вершин, такі як нормалі, 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 Object
Mesh містить позиції вершин та визначення полігонів. Створіть один з необов’язковою назвою:
import { Mesh } from '@aspose/3d/entities';
const mesh = new Mesh('triangle');Мережа починає порожньою: немає вершин і граней. Ви додаєте їх у наступних кроках.
Крок 4: Додати контрольні точки (вершини)
Контрольні точки — це позиції вершин у локальному просторі. Перенесіть значення 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-gons під час експорту.
Крок 6: Додати нормалі вершин
Нормалі покращують якість рендерингу. Використайте mesh.createElement() для створення VertexElementNormal, зберіть вектори нормалей у масив, а потім викличте setData() для їх збереження. Геттер 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: Прикріпити сітку та зберегти у 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Типові проблеми
| Issue | Cause | Fix |
|---|---|---|
mesh.controlPoints.length дорівнює 0 після push | Сітка не використовується жодним вузлом | Виконайте push перед присвоєнням node.entity; порядок не має значення, але перевірте посилання |
| Експорт створює порожню геометрію | node.entity не присвоєно | Переконайтеся, що node.entity = mesh виконано перед викликом scene.save() |
| Несумісність кількості нормалей | Масив, переданий у setData(), коротший за controlPoints | Додайте один запис FVector3 на кожну контрольну точку при використанні MappingMode.CONTROL_POINT |
| glTF‑переглядач показує чорну сітку | Нормалі спрямовані всередину | Змініть порядок обходу у createPolygon (наприклад, 0, 2, 1) або інвертуйте вектори нормалей |
| TypeScript: властивість ’normals.data’ не знайдена | Неправильний шлях імпорту | Імпортуйте VertexElementNormal з @aspose/3d/entities, а не з кореня @aspose/3d |
Часті запитання
Чи можу я створювати квадрати замість трикутників?
Так. Передайте чотири індекси до createPolygon(0, 1, 2, 3). Бібліотека триангуляє квадрати під час експорту у формати, які вимагають трикутників (glTF, STL).
Яка різниця між MappingMode.CONTROL_POINT та MappingMode.POLYGON_VERTEX?CONTROL_POINT зберігає одне значення для кожної унікальної вершини. POLYGON_VERTEX зберігає одне значення для кожної пари полігон‑вершина, що дозволяє мати різні нормалі в одній і тій же вершині, коли вона належить кільком полігонам (жорсткі краї).
Чи потрібно триангуляти сітку перед збереженням у STL?
Ні. Бібліотека автоматично виконує триангуляцію під час експорту у формати, які вимагають трикутники. Ви можете визначати чотирикутники та n‑багатокутники у сітці та зберігати безпосередньо у STL.
Як додати UV‑координати?
Використовуйте mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) для створення VertexElementUV, потім викличте setData([...]) з масивом значень FVector2 або FVector3 — по одному на контрольну точку. Геттер data повертає копію; не додавайте до нього безпосередньо.
Чи можу я створювати кілька сіток в одній сцені?
Так. Створіть кілька вузлів під scene.rootNode і призначте окремий Mesh для властивості entity кожного вузла.