Com crear una malla 3D programàticament amb TypeScript
Aspose.3D FOSS per a TypeScript et permet crear geometria 3D completament en codi sense carregar cap fitxer. Definixes les posicions dels vèrtexs com a punts de control, especifiques les cares dels polígons per índex i adjuntes elements opcionals del vèrtex com ara normals, UVs o colors del vèrtex. El resultat es pot desar a qualsevol format d’escriptura: glTF, GLB, STL, FBX o COLLADA.
Requisits previs
- Node.js 18 o posterior
- TypeScript 5.0 o posterior
@aspose/3dinstal·lat (vegeu el Pas 1)
Guia pas a pas
Pas 1: Instal·la @aspose/3d
npm install @aspose/3dNo es requereixen complements natius ni biblioteques del sistema. El paquet inclou definicions de tipus TypeScript.
Mínim tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Pas 2: Crea una Escena i un Node
Un Scene és el contenidor de nivell superior. Tota la geometria ha d’estar adjunta a un Node dins de l’arbre d’escena:
import { Scene } from '@aspose/3d';
const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');createChildNode(name) crea un node anomenat i el connecta com a fill del node actual. L’objecte Node retornat és on adjuntareu la malla al pas 7.
Pas 3: Crea un objecte Mesh
Mesh conté posicions de vèrtex i definicions de polígons. Construeix-ne un amb un nom opcional:
import { Mesh } from '@aspose/3d/entities';
const mesh = new Mesh('triangle');La malla comença buida: sense vèrtexs i sense cares. Els afegeixes en els passos següents.
Pas 4: Afegeix punts de control (Vèrtexs)
Els punts de control són les posicions dels vèrtexs en l’espai local. Empenyeu els valors Vector4 a mesh.controlPoints. El quart component (w) és 1 per a les posicions:
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
Feu referència a aquestes posicions pel seu índex basat en zero en definir les cares del polígon.
Pas 5: Crear cares de polígon
createPolygon() defineix una cara enumerant els índexs dels vèrtexs en ordre. Tres índexs formen un triangle:
mesh.createPolygon(0, 1, 2);També podeu definir quads (quatre índexs) o polígons arbitràris per a formats que els admeten. Per a glTF, la biblioteca triangul·larà automàticament els quads i els n‑gons en exportar.
Pas 6: Afegir normals de vèrtex
Les normals milloren la qualitat del renderitzat. Utilitzeu mesh.createElement() per crear una VertexElementNormal, recolliu vectors normals en una matriu i, a continuació, crideu setData() per emmagatzemar‑los. El getter data retorna una còpia defensiva — afegir elements a ella no té cap efecte. Utilitzeu FVector3 (float de precisió simple) per a les dades normals, no 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 significa una normal per vèrtex. ReferenceMode.DIRECT significa que la matriu de dades està indexada directament per l’índex del vèrtex del polígon.
Pas 7: Adjunta la malla i desa a glTF
Assigna la malla al node mitjançant node.entity, i després desa l’escena:
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');Per generar un únic fitxer .glb autocontingut, estableix saveOpts.binaryMode = true i canvia l’extensió del fitxer de sortida a .glb.
Exemple complet
El següent és l’script complet que combina tots els passos anteriors:
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');Executa amb ts-node:
npx ts-node triangle.tsProblemes comuns
| Issue | Cause | Fix |
|---|---|---|
mesh.controlPoints.length és 0 després del push | Malla no referenciada per cap node | Fes el push abans d’assignar node.entity; l’ordre no importa, però verifica la referència |
| L’exportació produeix geometria buida | node.entity no assignat | Assegura’t que node.entity = mesh estigui present abans de cridar scene.save() |
| Desajust del recompte de normals | L’array passat a setData() és més curt que controlPoints | Afegeix una entrada FVector3 per punt de control quan s’utilitza MappingMode.CONTROL_POINT |
| El visualitzador glTF mostra una malla negra | Normals apuntant cap a l’interior | Inverteix l’ordre de winding a createPolygon (p. ex., 0, 2, 1) o nega els vectors normals |
| TypeScript: propietat ’normals.data’ no trobada | Camí d’importació incorrecte | Importa VertexElementNormal des de @aspose/3d/entities, no des de l’arrel @aspose/3d |
Preguntes freqüents
Puc crear quads en lloc de triangles?
Sí. Passeu quatre índexs a createPolygon(0, 1, 2, 3). La biblioteca triangula els quads durant l’exportació a formats que requereixen triangles (glTF, STL).
Quina és la diferència entre MappingMode.CONTROL_POINT i MappingMode.POLYGON_VERTEX?CONTROL_POINT emmagatzema un valor per vèrtex únic. POLYGON_VERTEX emmagatzema un valor per parella polígon‑vèrtex, la qual cosa permet normals diferents al mateix vèrtex quan pertany a diversos polígons (vores dures).
Cal que trianguli la malla abans de desar a STL?
No. La biblioteca gestiona la triangulació automàticament quan s’exporta a formats que requereixen triangles. Podeu definir quads i n-gons a la malla i desar a STL directament.
Com afegir coordenades UV?
Utilitzeu mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) per crear un VertexElementUV, després crideu setData([...]) amb una matriu de valors FVector2 o FVector3 — un per punt de control. El getter data retorna una còpia; no hi afegiu elements directament.
Puc crear diverses malles en una escena?
Sí. Creeu diversos nodes sota scene.rootNode i assigneu un Mesh separat a la propietat entity de cada node.