Come creare una mesh 3D programmaticamente in TypeScript
Aspose.3D FOSS per TypeScript ti consente di creare geometria 3D interamente in codice senza caricare alcun file. Definisci le posizioni dei vertici come punti di controllo, specifichi le facce dei poligoni per indice e alleghi elementi opzionali dei vertici come normali, UV o colori dei vertici. Il risultato può essere salvato in qualsiasi formato scrivibile: glTF, GLB, STL, FBX o COLLADA.
Prerequisiti
- Node.js 18 o versioni successive
- TypeScript 5.0 o versioni successive
@aspose/3dinstallato (vedi Passo 1)
Guida passo-passo
Passo 1: Installa @aspose/3d
npm install @aspose/3dNessun addon nativo o libreria di sistema è richiesto. Il pacchetto include le definizioni di tipo TypeScript.
Minimo tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Passo 2: Crea una scena e un nodo
Un Scene è il contenitore di livello superiore. Tutta la geometria deve essere collegata a un Node all’interno dell’albero della scena:
import { Scene } from '@aspose/3d';
const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');createChildNode(name) crea un nodo con nome e lo collega come figlio del nodo corrente. L’oggetto Node restituito è dove collegherai la mesh al Passo 7.
Passo 3: Crea un oggetto Mesh
Mesh contiene le posizioni dei vertici e le definizioni dei poligoni. Costruiscine uno con un nome opzionale:
import { Mesh } from '@aspose/3d/entities';
const mesh = new Mesh('triangle');La mesh parte vuota: nessun vertice e nessuna faccia. Li aggiungi nei passaggi successivi.
Passo 4: Aggiungi i punti di controllo (Vertici)
I punti di controllo sono le posizioni dei vertici nello spazio locale. Inserisci i valori Vector4 in mesh.controlPoints. Il quarto componente (w) è 1 per le posizioni:
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
Fai riferimento a queste posizioni tramite il loro indice a base zero quando definisci le facce del poligono.
Passo 5: Crea facce poligonali
createPolygon() definisce una faccia elencando gli indici dei vertici in ordine. Tre indici formano un triangolo:
mesh.createPolygon(0, 1, 2);È possibile definire anche quads (quattro indici) o poligoni arbitrari per i formati che li supportano. Per glTF, la libreria triangolerà automaticamente i quads e i n-gons all’esportazione.
Passo 6: Aggiungi le normali dei vertici
Le normali migliorano la qualità del rendering. Usa mesh.createElement() per creare un VertexElementNormal, raccogli i vettori normali in un array, quindi chiama setData() per memorizzarli. Il getter data restituisce una copia difensiva — aggiungere elementi non ha effetto. Usa FVector3 (float a precisione singola) per i dati delle normali, non 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 normale per vertice. ReferenceMode.DIRECT significa che l’array dei dati è indicizzato direttamente dall’indice del vertice del poligono.
Passo 7: Allega la Mesh e Salva in glTF
Assegna la mesh al nodo tramite node.entity, quindi salva la 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');Per produrre invece un unico file .glb autocontenuto, impostare saveOpts.binaryMode = true e modificare l’estensione del file di output in .glb.
Esempio completo
Il seguente è lo script completo che combina tutti i passaggi precedenti:
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');Esegui con ts-node:
npx ts-node triangle.tsProblemi comuni
| Problema | Causa | Correzione |
|---|---|---|
mesh.controlPoints.length è 0 dopo il push | Mesh non referenziato da alcun nodo | Eseguire il push prima di assegnare node.entity; l’ordine non è importante, ma verificare il riferimento |
| L’esportazione produce geometria vuota | node.entity non assegnato | Assicurarsi che node.entity = mesh sia impostato prima di chiamare scene.save() |
| Mancata corrispondenza del conteggio delle normali | L’array passato a setData() è più corto di controlPoints | Aggiungere una voce FVector3 per punto di controllo quando si utilizza MappingMode.CONTROL_POINT |
| Il visualizzatore glTF mostra una mesh nera | Normali orientate verso l’interno | Invertire l’ordine di winding in createPolygon (ad es., 0, 2, 1) o negare i vettori normali |
| TypeScript: proprietà ’normals.data’ non trovata | Percorso di importazione errato | Importare VertexElementNormal da @aspose/3d/entities, non dalla radice @aspose/3d |
Domande Frequenti
Posso creare quadrilateri invece di triangoli?
Sì. Passa quattro indici a createPolygon(0, 1, 2, 3). La libreria triangola i quadrilateri durante l’esportazione in formati che richiedono triangoli (glTF, STL).
Qual è la differenza tra MappingMode.CONTROL_POINT e MappingMode.POLYGON_VERTEX?CONTROL_POINT memorizza un valore per ogni vertice unico. POLYGON_VERTEX memorizza un valore per ogni coppia poligono‑vertice, il che consente normali diversi nello stesso vertice quando appartiene a più poligoni (spigoli netti).
Devo triangolare la mesh prima di salvarla in STL?
No. La libreria gestisce automaticamente la triangolazione quando si esporta in formati che richiedono triangoli. Puoi definire quad e n‑gon nella mesh e salvarla direttamente in STL.
Come aggiungere coordinate UV?
Usa mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) per creare un VertexElementUV, quindi chiama setData([...]) con un array di valori FVector2 o FVector3 — uno per punto di controllo. Il getter data restituisce una copia; non aggiungere elementi direttamente.
Posso creare più mesh in una singola scena?
Sì. Crea più nodi sotto scene.rootNode e assegna un Mesh separato alla proprietà entity di ciascun nodo.