Kako preći 3D Scene Graph u TypeScript-u
Scenograf u Aspose.3D FOSS za TypeScript je drvo ‘Node’ objekata usmjerenih na ‘scene.rootNote’. Traversal je recursivna: svaki čvor izloži ‘childNodes’ iterabil i opcionalnu ’entity’ svojstvo.Ovaj vodič pokazuje kako hodati cijelo drvce, identificirati vrste entiteta, i prikupiti statistiku mesh.
Preduvjeti
- Node.js 18 ili kasnije
- Tipografski 5.0 ili noviji
- ‘@aspose/3d’ instalirano
Kratak korak vodič
1. korak: Ugradnja i uvoz
Instalirajte paket:
npm install @aspose/3dUvoz razreda koji se koriste u ovom vodiču:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';‘Scene’ i ‘Mesh’ su osnovne klase. ObjLoadOptions koristi se u uzorku za opterećenje; zamjenjuje razred prilagođavanja za druge formate.
2. korak: Preuzmite scenu iz datoteke
Stvorite ‘Scene’ i nazovite scene.open() s putom datoteke. detekcija formata je automatski iz binarnih magičnih brojeva, tako da ne morate odrediti format za GLB, STL ili 3MF datotekama:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
console.log(`Root node: "${scene.rootNode.name}"`);
console.log(`Top-level children: ${scene.rootNode.childNodes.length}`);Također možete preuzeti iz ‘Buffer’ u memoriju pomoću ‘scene.openFromBuffera(buffer, opcije)’, korisno u bez servera cijevi gdje disk I/O nije dostupan.
Korak 3: Napisati recursivnu funkciju putovanja
Recursion over ‘childNodes’ je standardni uzorak. funkcija posjećuje svaki stup dubine-prvi:
function traverse(node: any, depth = 0): void {
const indent = ' '.repeat(depth);
const entityType = node.entity ? node.entity.constructor.name : '-';
console.log(`${indent}[${entityType}] ${node.name}`);
for (const child of node.childNodes) {
traverse(child, depth + 1);
}
}
traverse(scene.rootNode);Za scenu s jednim mesom pod nazivom ‘Cube’, izlazak će izgledati kao:
[-] RootNode
[Mesh] Cube<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
’node.entity’ je ‘zero’ za grupne čvorove, kosti i lokatore. ‘constructor.name’ provjerava rad na bilo kojem vrsti subjekta: ‘Mesh’, ‘Kamera’, Light itd.
Korak 4: Pristup vrsti subjekta na svakom čvoru
Da biste poduzeli mjere na temelju vrste subjekta, koristite ‘instanceof’ provjeru nakon nula čuvar:
import { Mesh } from '@aspose/3d/entities';
function visitWithTypeCheck(node: any, depth = 0): void {
const indent = ' '.repeat(depth);
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
console.log(`${indent}MESH "${node.name}": ${mesh.controlPoints.length} vertices`);
} else if (node.entity) {
console.log(`${indent}${node.entity.constructor.name} "${node.name}"`);
} else {
console.log(`${indent}GROUP "${node.name}"`);
}
for (const child of node.childNodes) {
visitWithTypeCheck(child, depth + 1);
}
}
visitWithTypeCheck(scene.rootNode);‘instanceof Mesh’ je najsigurniji način da se potvrdi entitet je poligonski mesh prije pristupa ‘kontrolnim točkama’, ‘poligonsko-kontinentalnim’ ili vertikalnim elementima.
Korak 5: Filter ugla po vrsti entiteta
Da biste prikupili samo čvorove bez tiskanja cijelog drveta, koristite recursivni akumulator:
import { Mesh } from '@aspose/3d/entities';
function collectMeshes(
node: any,
results: Array<{ name: string; mesh: Mesh }> = []
): Array<{ name: string; mesh: Mesh }> {
if (node.entity instanceof Mesh) {
results.push({ name: node.name, mesh: node.entity as Mesh });
}
for (const child of node.childNodes) {
collectMeshes(child, results);
}
return results;
}
const meshNodes = collectMeshes(scene.rootNode);
console.log(`Found ${meshNodes.length} mesh node(s)`);Funkcija prihvaća opcionalni ‘resultati’ red tako da ga pozivači mogu unaprijed popularizirati za spajanje rezultata preko više poddruga.
Korak 6: Prikupite sve Mesh i tiskanje Vertex računova
Proširite kolektor za tiskanje statističkih podataka:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';
function collectMeshes(node: any, results: Array<{name: string, mesh: Mesh}> = []) {
if (node.entity instanceof Mesh) {
results.push({ name: node.name, mesh: node.entity as Mesh });
}
for (const child of node.childNodes) {
collectMeshes(child, results);
}
return results;
}
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
const meshes = collectMeshes(scene.rootNode);
for (const { name, mesh } of meshes) {
console.log(`${name}: ${mesh.controlPoints.length} vertices, ${mesh.polygonCount} polygons`);
}Primjer izlaska za dvomjesečnu scenu:
Cube: 8 vertices, 6 polygons
Sphere: 482 vertices, 480 polygons<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
Savjeti i najbolje prakse
- Uvijek null-check ’node.entity’ prije pristupa entitet specifičnim svojstvima. mnogi čvorovi su čiste grupne čvore koje ne nose entiteta.
- Koristite ‘instanceof’ preko ‘constructor.name’ za tipove provjere u logskim putovima. ’ instanceoff’ je refactor-safe; red usporedba na ‘Constructors.nam’ prekida s minifikacijom.
- Prekrijte preko ‘za’ na ‘ChildNodes’: iterabilni upravlja svim veličinama rasporeda sigurno. izbjegavajte brojno indeksiranje za naprednu kompatibilnost.
- Izbjegavajte mutaciju drveta tijekom prolaza: ne dodajte ili uklanjajte čvorove unutar recursivnog poziva. Prvo prikupite rezultate, a zatim izmijenite.
- Prođite rezultatni red kao parametar: to izbjegava dodjelu novog redova na svakom ponovnom pozivu i olakšava spajanje rezultata poddrvnog drveta.
Zajednički problemi
| Symptom | Cause | Fix |
|---|---|---|
childNodes has zero length on rootNode | Model not loaded | Ensure scene.open() completed without error before traversing |
node.entity instanceof Mesh never true | Wrong Mesh import path | Import Mesh from @aspose/3d/entities, not from @aspose/3d root |
| Traversal misses nested meshes | Not recursing into all children | Ensure the recursive call covers every element in node.childNodes |
mesh.controlPoints.length is 0 | Mesh loaded but contains no geometry | Check OBJ source for empty groups; use mesh.polygonCount as a secondary check |
| Stack overflow on deep hierarchies | Very deep scene tree (hundreds of levels) | Replace recursion with an explicit stack using Array.push / Array.pop |
Često postavljana pitanja
Ne. Korištenje korijena je kontejner koji automatski stvara knjižnica. nema entiteta. vaša geometrija i drugi objekti scene žive na dječjim čvorovima jedan ili više razina ispod ‘korištaja’.
Koja je razlika između ’node.entity’ i ‘Node-entities’? ’ node, entity` drži jedinstvenu primarnu entitet (običan slučaj). Neki stariji FBX i COLLADA datoteke mogu proizvesti čvorove s više povezanih entiteta; u tom slučaju ’noode (plural) pruža pun popis.
Da, koristite kutiju umjesto recursivnog poziva: pritisnite ‘scene.rootNode’ u redoslijed, a zatim promijenite i obrađujete čvorove dok priti ‘childNodes’ svakog čvora u kućni vrat.
‘scene.open()’ je sinhroniziran? da. scena.op() i `cene .openFromBuffer()’ oboje blokiraju pozivni vijek sve dok datoteka ne bude potpuno parsed.
Kako dobijem svjetsko-svemirske pozicije iz čvorova? pročitajte ’node.globalTransform’; vraća samo čitanje ‘GlobalTransforma’ s svjetskim prostorom, sastojom od svih predaka transformacija. za eksplicitnu matričnu matematiku nazovite ‘Node .evaluateGlobalna transforma (false)’.
Koje su vrste subjekata moguće osim ‘Mesh’? ‘Kamera’, ‘Light’ i prilagođene skeletonske/bone entitete. provjerite ’node.entity.constructor.name’ ili koristite `instanceof’ s određenom klasom uvezenom iz ‘@aspose/3d’.
Vidjeti također
- Kako preuzeti 3D modela u tipografiji
- Kako napraviti 3D Mesh programski u TypeScript-u
- Tagovi: Scene Graph
- Sljedeći članak: @aspose/3d