Rad s grafom scene
Sav 3D sadržaj u Aspose.3D FOSS za TypeScript nalazi se unutar Scene objekt organiziran kao stablo Node objekata. Razumijevanje ove hijerarhije temelj je za izgradnju, učitavanje i obradu bilo koje 3D datoteke.
Instalacija
Instalirajte paket s npm-a prije pokretanja bilo kojeg koda u ovom vodiču:
npm install @aspose/3dOsigurajte da vaš tsconfig.json uključuje "module": "commonjs" i "moduleResolution": "node" za ispravno rješavanje podputeva uvoza.
Pojmovi grafova scene
Graf scene ima tri razine:
| Razina | Klasa | Uloga |
|---|---|---|
| Scena | Scene | Kontejner najviše razine. Sadrži rootNode, animationClips, i assetInfo. |
| Čvor | Node | Imenovani čvor stabla. Može imati podčvorove, entitet, transformaciju i materijale. |
| Entitet | Mesh, Camera, Light, … | Sadržaj priložen čvoru. Čvor nosi najviše jedan entitet. |
Lanac nasljeđivanja za glavne građevne blokove je:
A3DObject
└─ SceneObject
├─ Node (tree structure)
└─ Entity
└─ Geometry
└─ Mesh (polygon geometry)scene.rootNode se automatski stvara. Ne stvarate ga ručno; stvarate podčvorove pod njim.
Korak 1: Stvaranje scene
import { Scene } from '@aspose/3d';
const scene = new Scene();
console.log(scene.rootNode.name); // '' (empty string — the root node is created with no name)
Novi Scene započinje s praznim korijenskim čvorom i bez animacijskih isječaka. Sadržaj gradite spajanjem podčvorova.
Korak 2: Dodajte čvorove djece
Koristite createChildNode() za rast stabla. Metoda vraća novi Node, tako da možete lančati daljnje pozive s bilo koje razine:
import { Scene } from '@aspose/3d';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('parent');
const child = parent.createChildNode('child');
console.log(scene.rootNode.childNodes.length); // 1 (parent)
console.log(parent.childNodes.length); // 1 (child)
Imena čvorova su proizvoljni stringovi. Imena ne moraju biti jedinstvena, ali korištenje smislenih imena olakšava otklanjanje grešaka u kodu za traversiranje.
Korak 3: Stvorite mrežu i postavite vrhove
Mesh je primarna geometrijska klasa. Dodajte položaje vrhova gurajući Vector4 vrijednosti u mesh.controlPoints, zatim pozovite createPolygon() za definiranje površina po indeksu vrha:
import { Scene } from '@aspose/3d';
import { Mesh } from '@aspose/3d/entities';
import { Vector4 } from '@aspose/3d/utilities';
const scene = new Scene();
const child = scene.rootNode.createChildNode('parent').createChildNode('child');
const mesh = new Mesh('cube');
mesh.controlPoints.push(new Vector4(0, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 1, 0, 1));
mesh.controlPoints.push(new Vector4(0, 1, 0, 1));
mesh.createPolygon(0, 1, 2, 3); // quad face using all four vertices
child.entity = mesh;
console.log(mesh.controlPoints.length); // 4
console.log(mesh.polygonCount); // 1
Vector4 koristi homogenog koordinatni sustav: the w komponenta je 1 za položaje i 0 za vektore smjera.
Korak 4: Postavite transformacije čvora
Svaki čvor ima transform svojstvo s translation, rotation, i scaling. Postavite translation za pomicanje čvora relativno na njegovog roditelja:
import { Scene } from '@aspose/3d';
import { Mesh } from '@aspose/3d/entities';
import { Vector4, Vector3 } from '@aspose/3d/utilities';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('parent');
const child = parent.createChildNode('child');
const mesh = new Mesh('cube');
mesh.controlPoints.push(new Vector4(0, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 1, 0, 1));
mesh.controlPoints.push(new Vector4(0, 1, 0, 1));
mesh.createPolygon(0, 1, 2, 3);
child.entity = mesh;
child.transform.translation = new Vector3(2.0, 0.0, 0.0);globalTransform pruža matricu transformacije svjetskog prostora (samo za čitanje), izračunatu spajanjem svih transformacija pretka.
Korak 5: Prolazak kroz stablo
Napišite rekurzivnu funkciju koja posjećuje svaki čvor. Provjerite node.entity i node.childNodes na svakoj razini:
function traverse(node: any, depth = 0): void {
const indent = ' '.repeat(depth);
const entityType = node.entity ? node.entity.constructor.name : 'none';
console.log(`${indent}${node.name} [${entityType}]`);
for (const child of node.childNodes) {
traverse(child, depth + 1);
}
}
traverse(scene.rootNode);Za hijerarhiju kreiranu iznad, izlaz će biti:
[none]
parent [none]
child [Mesh]Naziv korijenskog čvora je prazan niz jer Scene ga stvara bez argumenta za ime.
Uvijek zaštitite pristup entitetu provjerom na null prije kastanja u određeni tip. Nije svaki čvor nositelj entiteta.
Korak 6: Spremi u glTF ili GLB
Koristite GltfSaveOptions za kontrolu izlaznog formata. Postavite binaryMode = true za stvaranje jedne samostalne .glb datoteke; ostavite ga false za JSON .gltf + .bin par bočnog dodatka:
import { Scene } from '@aspose/3d';
import { Mesh } from '@aspose/3d/entities';
import { Vector4, Vector3 } from '@aspose/3d/utilities';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';
const scene = new Scene();
const parent = scene.rootNode.createChildNode('parent');
const child = parent.createChildNode('child');
const mesh = new Mesh('cube');
mesh.controlPoints.push(new Vector4(0, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 0, 0, 1));
mesh.controlPoints.push(new Vector4(1, 1, 0, 1));
mesh.controlPoints.push(new Vector4(0, 1, 0, 1));
mesh.createPolygon(0, 1, 2, 3);
child.entity = mesh;
child.transform.translation = new Vector3(2.0, 0.0, 0.0);
const saveOpts = new GltfSaveOptions();
saveOpts.binaryMode = true; // write a single .glb file
scene.save('scene.glb', GltfFormat.getInstance(), saveOpts);
console.log('Scene saved to scene.glb');Proslijedite GltfFormat.getInstance() kao argument formata kako bi biblioteka koristila ispravan enkoder neovisno o ekstenziji datoteke.
Savjeti i najbolje prakse
- Koristite
createChildNode()umjesto izgradnjeNodeizravno:createChildNode()automatski uspostavlja odnos roditelj-dijete i registrira čvor u stablu. - Provjerite
node.entityprije pristupa svojstvima entiteta: mnogo čvorova (grupni čvorovi, kosti, lokatori) ne nosi entitet. Uvijek zaštitite provjerom null vrijednosti iliinstanceoftest. - Postavi
translationna podređenim čvorovima, a ne na vrhovima mreže: modificiranjetransform.translationje nedestruktivan i sastavljiv s roditeljskim transformacijama. - Preferiraj
binaryMode = trueza GLB: jedan.glbdatoteka je lakša za distribuciju, učitavanje u preglednicima i uvoz u game engineove od podijeljenog.gltf+.binformat. - Prođi putem
for...ofprekochildNodes: izbjegavaj numeričko indeksiranje; koristi iterable izravno za buduću kompatibilnost.
Uobičajeni problemi
| Simptom | Vjerojatni uzrok | Popravi |
|---|---|---|
child.entity = mesh nema učinka na izvoz | Entitet dodijeljen na pogrešnoj razini čvora | Dodijeli entity do listnog čvora, a ne do grupnog čvora |
node.entity je uvijek null | Samo provjeravanje rootNode sam | Rekurzija u node.childNodes; rootNode obično nema entitet |
| Transformacija nije prikazana u GLB pregledniku | globalTransform nije ažurirano | globalTransform se izračunava pri spremanju; postavi transform.translation prije poziva scene.save() |
GLB generira zasebni .bin sidecar | binaryMode zadano je false | Postavi saveOpts.binaryMode = true |
Vidi također
- Značajke i funkcionalnosti: potpuna API referenca za sva područja značajki.
- Podrška formata: podržani 3D formati, mogućnost čitanja/pisanja i opcije formata.
- Kako izgraditi 3D Mesh programatski