Как да създадете 3D мрежа програмирано в TypeScript

Как да създадете 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‑гони при експортиране.


Стъпка 6: Добавяне на нормали на върховете

Нормалите подобряват качеството на рендерирането. Използвайте mesh.createElement(), за да създадете VertexElementNormal, събирайте нормалните вектори в масив, след което извикайте setData(), за да ги съхраните. Гетърът data връща защитно копие — добавянето към него няма ефект. Използвайте FVector3 (число с плаваща запетая с единична точност) за данни за нормали, а не 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

Чести проблеми

ПроблемПричинаПоправка
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

Често задавани въпроси

Мога ли да създавам quads вместо triangles?
Да. Предайте четири индекса на createPolygon(0, 1, 2, 3). Библиотеката триангулира quads при експортиране към формати, които изискват triangles (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 на всеки възел.

Вижте също

 Български