Hoe een 3D-mesh programmatisch te bouwen in TypeScript

Hoe een 3D-mesh programmatisch te bouwen in TypeScript

Aspose.3D FOSS for TypeScript stelt je in staat om 3D‑geometrie volledig in code te bouwen zonder een bestand te laden. Je definieert vertexposities als controlepunten, specificeert polygonvlakken door index en voeg je optionele vertexelementen toe, zoals normalen, UV’s of vertexkleuren. Het resultaat kan worden opgeslagen in elk schrijfbaar formaat: glTF, GLB, STL, FBX of COLLADA.

Vereisten

  • Node.js 18 of hoger
  • TypeScript 5.0 of hoger
  • @aspose/3d geïnstalleerd (zie Stap 1)

Stapsgewijze gids

Stap 1: Installeer @aspose/3d

npm install @aspose/3d

Geen native add‑ons of systeembibliotheken zijn vereist. Het pakket bevat TypeScript‑typedefinities.

Minimum tsconfig.json:

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

Stap 2: Maak een Scene en Node

Een Scene is de bovenste container. Alle geometrie moet worden gekoppeld aan een Node binnen de sceneboom:

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

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

createChildNode(name) maakt een benoemde node aan en koppelt deze als kind van de huidige node. Het geretourneerde Node‑object is waar je het mesh in Stap 7 aanhecht.


Stap 3: Maak een Mesh Object

Mesh bevat vertexposities en polygoondefinities. Construeer er één met een optionele naam:

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

const mesh = new Mesh('triangle');

De mesh start leeg: geen vertices en geen faces. Je voegt ze toe in de volgende stappen.


Stap 4: Controlepunten toevoegen (Vertices)

Controlepunten zijn de vertexposities in lokale ruimte. Duw Vector4-waarden in mesh.controlPoints. Het vierde component (w) is 1 voor posities:

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

U verwijst naar deze posities met hun nulgebaseerde index bij het definiëren van polygonvlakken.


Stap 5: Polygonvlakken maken

createPolygon() definieert een vlak door de vertex-indexen in volgorde te vermelden. Drie indexen vormen een driehoek:

mesh.createPolygon(0, 1, 2);

U kunt ook quads (vier indexen) of willekeurige polygonen definiëren voor formaten die deze ondersteunen. Voor glTF zal de bibliotheek bij export automatisch quads en n-gons trianguleren.


Stap 6: Vertexnormals toevoegen

Normaalvectoren verbeteren de renderkwaliteit. Gebruik mesh.createElement() om een VertexElementNormal te maken, verzamel normaalvectoren in een array en roep vervolgens setData() aan om ze op te slaan. De data getter retourneert een defensieve kopie — er iets aan toevoegen heeft geen effect. Gebruik FVector3 (single-precision float) voor normaaldata, niet 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 betekent één normaal per vertex. ReferenceMode.DIRECT betekent dat de gegevensarray direct wordt geïndexeerd door de polygon-vertex-index.


Stap 7: Mesh koppelen en opslaan als glTF

Wijs het mesh toe aan de node via node.entity, sla vervolgens de scène op:

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

Om in plaats daarvan een enkel zelfvoorzienend .glb-bestand te produceren, stel saveOpts.binaryMode = true in en wijzig de extensie van het uitvoerbestand naar .glb.

Volledig voorbeeld

Het volgende is het volledige script dat alle bovenstaande stappen combineert:

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

Uitvoeren met ts-node:

npx ts-node triangle.ts

Veelvoorkomende problemen

IssueCauseFix
mesh.controlPoints.length is 0 na pushMesh niet door een node gerefereerdPush vóór het toewijzen van node.entity; volgorde maakt niet uit, maar controleer de referentie
Export genereert lege geometrienode.entity niet toegewezenZorg ervoor dat node.entity = mesh vóór het aanroepen van scene.save()
Aantal normalen komt niet overeenArray die aan setData() wordt doorgegeven is korter dan controlPointsVoeg één FVector3-item toe per controlepunt bij gebruik van MappingMode.CONTROL_POINT
glTF-viewer toont zwart meshNormalen wijzen naar binnenKeer windingvolgorde om in createPolygon (bijv. 0, 2, 1) of negeer de normaalvectoren
TypeScript: eigenschap ’normals.data’ niet gevondenVerkeerd importpadImporteer VertexElementNormal vanuit @aspose/3d/entities, niet vanuit de @aspose/3d-root

Veelgestelde vragen

Kan ik quads maken in plaats van driehoeken? Ja. Geef vier indexen door aan createPolygon(0, 1, 2, 3). De bibliotheek trianguleert quads tijdens het exporteren naar formaten die driehoeken vereisen (glTF, STL).

Wat is het verschil tussen MappingMode.CONTROL_POINT en MappingMode.POLYGON_VERTEX?
CONTROL_POINT slaat één waarde per unieke vertex op. POLYGON_VERTEX slaat één waarde per polygon-vertex-paar op, waardoor verschillende normals op dezelfde vertex mogelijk zijn wanneer deze tot meerdere polygonen behoort (hard edges).

Moet ik het mesh trianguleren voordat ik het opsla naar STL?
Nee. De bibliotheek handelt triangulatie automatisch af bij het exporteren naar formaten die driehoeken vereisen. Je kunt quads en n-gons definiëren in het mesh en direct naar STL opslaan.

Hoe voeg ik UV-coördinaten toe?
Gebruik mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) om een VertexElementUV te maken, roep vervolgens setData([...]) aan met een array van FVector2 of FVector3 waarden — één per controlepunt. De data getter geeft een kopie terug; duw er niet direct op.

Kan ik meerdere meshes in één scène bouwen?
Ja. Maak meerdere knooppunten onder scene.rootNode en wijs een aparte Mesh toe aan de entity‑eigenschap van elk knooppunt.

Zie ook

 Nederlands