Comment créer un maillage 3D de manière programmatique en TypeScript
Aspose.3D FOSS for TypeScript vous permet de créer une géométrie 3D entièrement en code sans charger de fichier. Vous définissez les positions des sommets comme points de contrôle, spécifiez les faces polygonales par indice, et ajoutez des éléments de sommet optionnels tels que les normales, les UV ou les couleurs de sommet. Le résultat peut être enregistré dans n’importe quel format pouvant être écrit : glTF, GLB, STL, FBX ou COLLADA.
Prérequis
- Node.js 18 ou version ultérieure
- TypeScript 5.0 ou version ultérieure
@aspose/3dinstallé (voir l’étape 1)
Guide étape par étape
Étape 1 : Installer @aspose/3d
npm install @aspose/3dAucun module natif ni bibliothèque système n’est requis. Le package inclut les définitions de types TypeScript.
Minimum tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Étape 2 : Créer une scène et un nœud
Un Scene est le conteneur de niveau supérieur. Toute la géométrie doit être attachée à un Node dans l’arbre de scène :
import { Scene } from '@aspose/3d';
const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');createChildNode(name) crée un nœud nommé et le branche comme enfant du nœud actuel. L’objet Node retourné est l’endroit où vous attacherez le maillage à l’étape 7.
Étape 3 : Créer un Mesh Object
Mesh contient les positions des sommets et les définitions des polygones. Créez‑en un avec un nom facultatif :
import { Mesh } from '@aspose/3d/entities';
const mesh = new Mesh('triangle');Le maillage commence vide : aucun sommet et aucune face. Vous les ajoutez dans les étapes suivantes.
Étape 4 : Ajouter des points de contrôle (sommets)
Les points de contrôle sont les positions des sommets dans l’espace local. Poussez les valeurs Vector4 dans mesh.controlPoints. Le quatrième composant (w) est 1 pour les positions :
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
Vous faites référence à ces positions par leur indice basé sur zéro lors de la définition des faces du polygone.
Étape 5 : Créer des faces de polygone
createPolygon() définit une face en listant les indices des sommets dans l’ordre. Trois indices forment un triangle :
mesh.createPolygon(0, 1, 2);Vous pouvez également définir des quads (quatre indices) ou des polygones arbitraires pour les formats qui les prennent en charge. Pour glTF, la bibliothèque triangulera automatiquement les quads et les n-gons lors de l’exportation.
Étape 6 : Ajouter les normales des sommets
Les normales améliorent la qualité du rendu. Utilisez mesh.createElement() pour créer un VertexElementNormal, collectez les vecteurs normaux dans un tableau, puis appelez setData() pour les stocker. Le getter data renvoie une copie défensive — y pousser des éléments n’a aucun effet. Utilisez FVector3 (float à simple précision) pour les données de normales, pas 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 signifie une normale par sommet. ReferenceMode.DIRECT signifie que le tableau de données est indexé directement par l’indice du sommet du polygone.
Étape 7 : Attacher le maillage et enregistrer au format glTF
Attribuez le maillage au nœud via node.entity, puis enregistrez la scène :
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');Pour produire un fichier .glb autonome unique à la place, définissez saveOpts.binaryMode = true et changez l’extension du fichier de sortie en .glb.
Exemple complet
Le script complet combinant toutes les étapes ci‑dessus :
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');Exécuter avec ts-node:
npx ts-node triangle.tsProblèmes courants
| Issue | Cause | Fix |
|---|---|---|
mesh.controlPoints.length vaut 0 après le push | Maillage non référencé par aucun nœud | Effectuer le push avant d’assigner node.entity ; l’ordre n’a pas d’importance, mais vérifiez la référence |
| L’exportation produit une géométrie vide | node.entity non assigné | Assurez-vous que node.entity = mesh est présent avant d’appeler scene.save() |
| Mauvaise correspondance du nombre de normales | Le tableau passé à setData() est plus court que controlPoints | Ajoutez une entrée FVector3 par point de contrôle lors de l’utilisation de MappingMode.CONTROL_POINT |
| Le visualiseur glTF affiche un maillage noir | Normales pointant vers l’intérieur | Inversez l’ordre de winding dans createPolygon (par ex., 0, 2, 1) ou inversez les vecteurs normaux |
| TypeScript : propriété ’normals.data’ introuvable | Chemin d’importation incorrect | Importez VertexElementNormal depuis @aspose/3d/entities, pas depuis la racine @aspose/3d |
Foire aux questions
Puis-je créer des quadrilatères au lieu de triangles ?
Oui. Passez quatre indices à createPolygon(0, 1, 2, 3). La bibliothèque triangule les quadrilatères lors de l’exportation vers des formats qui nécessitent des triangles (glTF, STL).
Quelle est la différence entre MappingMode.CONTROL_POINT et MappingMode.POLYGON_VERTEX ?CONTROL_POINT stocke une valeur par sommet unique. POLYGON_VERTEX stocke une valeur par paire polygone‑sommet, ce qui permet d’avoir des normales différentes au même sommet lorsqu’il appartient à plusieurs polygones (arêtes dures).
Dois-je trianguler le maillage avant de l’enregistrer au format STL ?
Non. La bibliothèque gère automatiquement la triangulation lors de l’exportation vers des formats qui nécessitent des triangles. Vous pouvez définir des quadrilatères et des n-gons dans le maillage et enregistrer directement au format STL.
Comment ajouter des coordonnées UV ?
Utilisez mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) pour créer un VertexElementUV, puis appelez setData([...]) avec un tableau de valeurs FVector2 ou FVector3 — une par point de contrôle. Le getter data renvoie une copie ; ne poussez pas directement dedans.
Puis-je créer plusieurs maillages dans une même scène ?
Oui. Créez plusieurs nœuds sous scene.rootNode et attribuez un Mesh distinct à la propriété entity de chaque nœud.