Jak projít 3D scénový graf v TypeScript

Jak projít 3D scénový graf v TypeScript

Scénový graf v Aspose.3D FOSS pro TypeScript je stromem Node objekty zakořeněné v scene.rootNode.Procházka je rekurzivní: každý uzel vystavuje childNodes iterovatelné a volitelné. entity Tento průvodce ukazuje, jak projít celým stromem, identifikovat typy subjektů a shromažďovat statistické údaje o síti.

Předpoklady

  • Node.js 18 or later
  • TypScript 5.0 nebo novější
  • @aspose/3d nainstalované

Krok za krokem

Krok 1: Instalace a import

Nainstalujte balíček:

asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.

Import tříd používaných v této příručce:

import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';

Scene a) Mesh jsou základní třídy. ObjLoadOptions je použit v příkladu zatížení; za jiné formáty nahraďte třídu možností shodování.


Krok 2: Nahrát scénu z souboru

Vytvořit Scene a zavolat. scene.open() Sdělovací systém je automaticky detekován z binárních magických čísel, takže nemusíte specifikovat formát pro soubory GLB, STL nebo 3MF:

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}`);

Můžete také načítat z Buffer v paměti pomocí scene.openFromBuffer(buffer, options); užitečné v bezserverových potrubích, kde není k dispozici vstup/výstup na disku.


Krok 3: Napište rekurzivní průchodovou funkci

Recursion over (Překročení) childNodes funkce navštíví každý uzel nejprve:

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

Pro scénu s jedním jménem. Cube, výstup bude vypadat takto:

[-] 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=“Zkopírovat kód”

<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: null pro skupinové uzly, kosti a lokátory. constructor.name ověřování práce pro jakýkoli typ subjektu: Mesh, Camera, Light, atd.


Krok 4: Přístup k typu entity na každém uzlu

Pro provedení opatření na základě typu subjektu použijte položku “Přístupné údaje” (Elementary Information) a položky “Zájemní informace”. instanceof kontrola po nulové ochraně:

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 nejbezpečnější způsob, jak potvrdit, že entita je polygonová síť před přístupem k této stránce. controlPoints, polygonCount, nebo vrcholovými prvky.


Krok 5: Filtrovat uzly podle typu entity

Pro sběr pouze uzlů s okovy bez tisknutí celého stromu použijte rekurzivní akumulátor:

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

Funkce přijímá volitelné: results Array, takže volání může předem vyplnit pro sloučení výsledků přes více podstromy.


Krok 6: Sbírá všechny mísy a tisknout počty vrcholů

Rozšířit kolektor na tisk statistických údajů pro každý okruh:

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`);
}

Příklad výstupu pro scénu s dvěma okami:

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=“Zkopírovat kód”

<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>

Tipy a nejlepší postupy

  • Vždy nulový check. node.entity Mnoho uzlů jsou čisté skupinové uzly, které nesou žádnou entitu.
  • Použití: instanceof Přesně. constructor.name pro kontroly typu v logických cestách. instanceof je refaktorově bezpečný; srovnání řetězců na constructor.name přerušuje minifikaci.
  • Procházet přes for...of Přesně. childNodes: iterovatelná manipulace se všemi velikostmi souborů bezpečně. Vyhněte se číselnému indexování pro budoucí kompatibilitu.
  • Vyhněte se mutování stromu během průchodu.: nepřidávejte ani neodstraňujte uzly uvnitř rekurzivního volání. Nejprve shromažďujte výsledky a pak je upravte.
  • Přenést soubor výsledků jako parametr: tím se vyhýbá přidělování nového řetězce na každý rekurzivní hovor a usnadňuje spojení výsledků podstromu.

Obvyklé problémy

Příznak:Příčina:Opravy
childNodes má nulovou délku na rootNodeModel není nabitý.Zajištění: scene.open() bezchybně dokončeno před přejezdem.
node.entity instanceof Mesh Nikdy pravda.- Nepravdivé. Mesh vstupní cestaDovoz Mesh od: @aspose/3d/entities, ne z @aspose/3d kořen
Vzdáleně od křížových ok.Nevykazuje se u všech dětí.Zajistit rekurzivní volání pokrývá každý prvek v node.childNodes
mesh.controlPoints.length je 0Ošivka s zabitím, ale bez geometrieZkontrolujte zdroj OBJ pro prázdné skupiny; použít mesh.polygonCount jako sekundární kontrola
Přeplavení stacků v hlubokých hierarchiíchVelmi hluboký strom scén (stovky úrovní)Náhraďte rekurzi explicitním stackem pomocí: Array.push / Array.pop

Časté otázky

- Ano. scene.rootNode Sama sebou nesou entitu? Rootový uzel je kontejner vytvořený automaticky knihovnou. Nemá žádnou entitu. Vaše geometrie a další objekty scény žijí na dětských uzlech jeden nebo více úrovní pod ním. rootNode.

Jaký je rozdíl mezi node.entity a) node.entities? node.entity Některé starší soubory FBX a COLLADA mohou vytvářet uzly s více připojenými subjekty; v tomto případě je možné vytvořit jednotlivé primární entity. node.entities (plural) poskytuje úplný seznam.

Můžu projít podle šířky, ne podle hloubky? Ano, místo rekurzivního volání použijte fronty: “push” (potlačte) scene.rootNode do řady, pak posunout a zpracovat uzly při tlačení každý uzel je childNodes do řady.

Je to … scene.open() Synchronní? - Ano, jsem. scene.open() a) scene.openFromBuffer() Obě blokovat volání nití, dokud soubor je plně analyzovaný. Obalte je do pracovní nit, pokud potřebujete udržet event smyčku reaktivní.

Jak se dostaneme do světové pozice z uzlu? Čtěte. node.globalTransform; vrací pouze pro čtení GlobalTransform Pro explicitní matrixovou matematiku, nazývejte node.evaluateGlobalTransform(false).

Jaké druhy subjektů jsou možné kromě: Mesh? Camera, Light, a vlastní entity kostní/skeletální. node.entity.constructor.name nebo použití instanceof s konkrétní třídou dovezenou z: @aspose/3d.

Viz také:

 Čeština