Kako preći 3D Scene Graph u TypeScript-u

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/3d

Uvoz 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

SymptomCauseFix
childNodes has zero length on rootNodeModel not loadedEnsure scene.open() completed without error before traversing
node.entity instanceof Mesh never trueWrong Mesh import pathImport Mesh from @aspose/3d/entities, not from @aspose/3d root
Traversal misses nested meshesNot recursing into all childrenEnsure the recursive call covers every element in node.childNodes
mesh.controlPoints.length is 0Mesh loaded but contains no geometryCheck OBJ source for empty groups; use mesh.polygonCount as a secondary check
Stack overflow on deep hierarchiesVery 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
 Hrvatski