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/3dinstalat (vezi Pasul 1)
Ghid pas cu pas
Pasul 1: Instalați @aspose/3d
npm install @aspose/3dNu 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.tsProbleme comune
| Problem | Cauză | Soluție |
|---|---|---|
mesh.controlPoints.length este 0 după push | Mesh-ul nu este referențiat de niciun nod | Efectuați push înainte de a atribui node.entity; ordinea nu contează, dar verificați referința |
| Exportul produce geometrie goală | node.entity nu este atribuit | Asigurați node.entity = mesh înainte de a apela scene.save() |
| Număr de normale nepotrivit | Matricea transmisă la setData() este mai scurtă decât controlPoints | Adăugați o intrare FVector3 pentru fiecare punct de control când utilizați MappingMode.CONTROL_POINT |
| Vizualizatorul glTF afișează mesh negru | Normalele sunt orientate spre interior | Inversaț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.