Cum să construiești o rețea 3D programatic în TypeScript

Cum să construiești o rețea 3D programatic în TypeScript

Aspose.3D FOSS pentru TypeScript vă permite să construiți geometrie 3D în întregime în cod, fără a încărca niciun fișier. Definiți pozițiile vârfurilor ca puncte de control, specificați fețele poligonale prin index și atașați elemente opționale ale vârfului, cum ar fi normale, UV-uri sau culori ale vârfului. Rezultatul poate fi salvat în orice format scriabil: glTF, GLB, STL, FBX sau COLLADA.

Precondiții

  • Node.js 18 sau o versiune ulterioară
  • TypeScript 5.0 sau o versiune ulterioară
  • @aspose/3d instalat (vezi Pasul 1)

Ghid pas cu pas

Pasul 1: Instalați @aspose/3d

npm install @aspose/3d

Nu sunt necesare addon-uri native sau biblioteci de sistem. Pachetul include definiții de tip TypeScript.

Minim tsconfig.json:

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

Pasul 2: Crearea unei scene și a unui nod

Un Scene este containerul de nivel superior. Toată geometria trebuie să fie atașată unui Node în interiorul arborelui de scenă:

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

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

createChildNode(name) creează un nod denumit și îl conectează ca un copil al nodului curent. Obiectul Node returnat este locul în care veţi ataşa mesh‑ul în Pasul 7.


Pasul 3: Crează un obiect Mesh

Mesh conține pozițiile vârfurilor și definițiile poligoanelor. Construiți unul cu un nume opțional:

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

const mesh = new Mesh('triangle');

Mesh-ul începe gol: fără vertices și fără faces. Le adaugi în pașii următori.


Pasul 4: Adăugați puncte de control (vârfuri)

Punctele de control sunt pozițiile vârfurilor în spațiul local. Împinge valorile Vector4 în mesh.controlPoints. A patra componentă (w) este 1 pentru poziții:

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

Faceţi referire la aceste poziţii prin indicele lor bazat pe zero atunci când definiţi feţele poligonului.


Pasul 5: Crearea fețelor poligonale

createPolygon() definește o față prin listarea indicilor vârfurilor în ordine. Trei indici formează un triunghi:

mesh.createPolygon(0, 1, 2);

De asemenea, puteți defini cvadrilaturi (patru indici) sau poligoane arbitrare pentru formatele care le acceptă. Pentru glTF, biblioteca va triangula automat cvadrilaturile și n-gonii la export.


Pasul 6: Adăugați normalele de vârf

Normalele îmbunătățesc calitatea redării. Folosește mesh.createElement() pentru a crea un VertexElementNormal, colectează vectorii normali într-un tablou, apoi apelează setData() pentru a-i stoca. Getter-ul data returnează o copie defensivă — adăugarea de elemente în ea nu are niciun efect. Folosește FVector3 (float cu precizie simplă) pentru datele de normale, nu 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 înseamnă un normal pe fiecare vârf. ReferenceMode.DIRECT înseamnă că matricea de date este indexată direct prin indicele vârfului poligonului.


Pasul 7: Atașează Mesh-ul și Salvează în glTF

Atribuiți mesh-ul nodului prin node.entity, apoi salvați scena:

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

Pentru a produce un singur fișier .glb autocontinut în schimb, setați saveOpts.binaryMode = true și schimbați extensia fișierului de ieșire la .glb.

Exemplu complet

Mai jos este scriptul complet care combină toți pașii de mai sus:

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

Rulați cu ts-node:

npx ts-node triangle.ts

Probleme comune

ProblemCauzăSoluție
mesh.controlPoints.length este 0 după pushMesh-ul nu este referențiat de niciun nodEfectuați push înainte de a atribui node.entity; ordinea nu contează, dar verificați referința
Exportul produce geometrie goalănode.entity nu este atribuitAsigurați node.entity = mesh înainte de a apela scene.save()
Număr de normale nepotrivitMatricea transmisă la setData() este mai scurtă decât controlPointsAdăugați o intrare FVector3 pentru fiecare punct de control când utilizați MappingMode.CONTROL_POINT
Vizualizatorul glTF afișează mesh negruNormalele sunt orientate spre interiorInversați ordinea de înfășurare în createPolygon (de ex., 0, 2, 1) sau negați vectorii normali
TypeScript: proprietatea ’normals.data’ nu a fost găsităCale de import greșităImportați VertexElementNormal din @aspose/3d/entities, nu din rădăcina @aspose/3d

Întrebări frecvente

Pot crea quads în loc de triunghiuri?
Da. Transmite patru indici la createPolygon(0, 1, 2, 3). Biblioteca triangulează quads în timpul exportului către formate care necesită triunghiuri (glTF, STL).

Care este diferența dintre MappingMode.CONTROL_POINT și MappingMode.POLYGON_VERTEX?
CONTROL_POINT stochează o valoare pentru fiecare vârf unic. POLYGON_VERTEX stochează o valoare pentru fiecare pereche poligon‑vârf, ceea ce permite normale diferite la același vârf când aparține mai multor poligoane (muchii dure).

Trebuie să triangulez mesh-ul înainte de a salva în STL?
Nu. Biblioteca gestionează triangularea automat când exportă în formate care necesită triunghiuri. Poți defini cvadrilaturi și n‑goni în mesh și să salvezi direct în STL.

Cum adaug coordonate UV?
Folosiți mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) pentru a crea un VertexElementUV, apoi apelați setData([...]) cu un tablou de valori FVector2 sau FVector3 — una pentru fiecare punct de control. Getter‑ul data returnează o copie; nu adăugați elemente direct în el.

Pot să construiesc mai multe mesh-uri într-o singură scenă?
Da. Creează mai multe noduri sub scene.rootNode și atribuie un Mesh separat proprietății entity a fiecărui nod.

Vezi și

 Română