Kako programatski izgraditi 3D mrežu u TypeScriptu
Aspose.3D FOSS za TypeScript omogućuje izgradnju 3D geometrije u potpunosti u kodu bez učitavanja ikakve datoteke. Definirate položaje vrhova kao kontrolne točke, specificirate poligonalna lica po indeksu i dodajete opcionalne elemente vrhova poput normala, UV‑ova ili boja vrhova. Rezultat se može spremiti u bilo koji zapis koji se može pisati: glTF, GLB, STL, FBX ili COLLADA.
Preduvjeti
- Node.js 18 ili noviji
- TypeScript 5.0 ili noviji
@aspose/3dinstaliran (pogledajte Korak 1)
Vodič korak po korak
Korak 1: Instalirajte @aspose/3d
npm install @aspose/3dNisu potrebni nativni dodaci ili sistemske biblioteke. Paket uključuje TypeScript definicije tipova.
Minimum tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}Korak 2: Kreiraj scenu i čvor
A Scene je kontejner najviše razine. Sva geometrija mora biti pričvršćena na Node unutar stabla scene:
import { Scene } from '@aspose/3d';
const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');createChildNode(name) stvara imenovani čvor i povezuje ga kao dijete trenutnog čvora. Vraćeni Node objekt je mjesto gdje ćete u koraku 7 priložiti mrežu.
Korak 3: Stvori Mesh objekt
Mesh sadrži položaje vrhova i definicije poligona. Izradite jedan s opcionalnim imenom:
import { Mesh } from '@aspose/3d/entities';
const mesh = new Mesh('triangle');Mreža počinje prazna: nema vrhova i nema ploha. Dodajete ih u sljedećim koracima.
Korak 4: Dodaj kontrolne točke (vrhove)
Kontrolne točke su položaji vrhova u lokalnom prostoru. Gurnite Vector4 vrijednosti u mesh.controlPoints. Četvrta komponenta (w) je 1 za položaje:
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
Na ove položaje referencirate pomoću njihovog nultog indeksa prilikom definiranja poligonalnih lica.
Korak 5: Stvaranje poligonalnih lica
createPolygon() definira lice navodeći indekse vrhova redom. Tri indeksa čine trokut:
mesh.createPolygon(0, 1, 2);Također možete definirati kvadrate (četiri indeksa) ili proizvoljne poligone za formate koji ih podržavaju. Za glTF, biblioteka će automatski triangulirati kvadrate i n‑poligone pri izvozu.
Korak 6: Dodaj normale vrhova
Normalni vektori poboljšavaju kvalitetu renderiranja. Koristite mesh.createElement() za stvaranje VertexElementNormal, prikupite normalne vektore u polje, a zatim pozovite setData() da ih pohranite. Getter data vraća obrambenu kopiju — dodavanje u nju nema učinka. Koristite FVector3 (float jednostruke preciznosti) za normalne podatke, a ne 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 znači jedan normal po vrhu. ReferenceMode.DIRECT znači da je niz podataka indeksiran izravno prema indeksu vrha poligona.
Korak 7: Prikvači mrežu i spremi u glTF
Dodijelite mrežu čvoru putem node.entity, zatim spremite scenu:
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');Za proizvodnju jedne samostalne .glb datoteke umjesto toga, postavite saveOpts.binaryMode = true i promijenite ekstenziju izlazne datoteke u .glb.
Potpuni primjer
Sljedeći je potpuni skript koji kombinira sve prethodne korake:
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');Pokreni s ts-node:
npx ts-node triangle.tsUobičajeni problemi
| Problem | Uzrok | Rješenje |
|---|---|---|
mesh.controlPoints.length je 0 nakon push-a | Mreža nije referencirana ni od jednim čvorom | Push prije dodjele node.entity; redoslijed nije bitan, ali provjerite referencu |
| Izvoz generira praznu geometriju | node.entity nije dodijeljen | Osigurajte node.entity = mesh prije poziva scene.save() |
| Neusklađenost broja normala | Polje proslijeđeno setData() je kraće od controlPoints | Dodajte jedan FVector3 unos po kontrolnoj točki pri korištenju MappingMode.CONTROL_POINT |
| glTF preglednik prikazuje crnu mrežu | Normale usmjerene prema unutra | Obrnite redoslijed vrhova u createPolygon (npr., 0, 2, 1) ili negirajte vektore normala |
| TypeScript: svojstvo ’normals.data’ nije pronađeno | Pogrešna putanja uvoza | Uvezite VertexElementNormal iz @aspose/3d/entities, a ne iz korijena @aspose/3d |
Često postavljana pitanja
Mogu li kreirati četverokute umjesto trokuta?
Da. Proslijedite četiri indeksa u createPolygon(0, 1, 2, 3). Biblioteka triangulira četverokute tijekom izvoza u formate koji zahtijevaju trokute (glTF, STL).
Koja je razlika između MappingMode.CONTROL_POINT i MappingMode.POLYGON_VERTEX?
CONTROL_POINT pohranjuje jednu vrijednost po jedinstvenom vrhu. POLYGON_VERTEX pohranjuje jednu vrijednost po paru poligon‑vrh, što omogućuje različite normale na istom vrhu kada pripada više poligona (tvrdi rubovi).
Treba li triangulirati mrežu prije spremanja u STL?
Ne. Biblioteka automatski obrađuje triangulaciju prilikom izvoza u formate koji zahtijevaju trokute. Možete definirati kvadrate i n‑poligone u mreži i izravno spremiti u STL.
Kako dodati UV koordinate?
Koristite mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) za stvaranje VertexElementUV, zatim pozovite setData([...]) s nizom vrijednosti FVector2 ili FVector3 — po jednoj po kontrolnoj točki. Getter data vraća kopiju; nemojte ga izravno pushati.
Mogu li izgraditi više mreža u jednoj sceni?
Da. Stvorite više čvorova pod scene.rootNode i dodijelite zasebni Mesh svakom čvoru u svojstvu entity.