Rad sa grafom scene

Sav 3D sadržaj u Aspose.3D FOSS za TypeScript živi unutar Scene objekta organizovanog kao stablo Node objekata. Razumevanje ove hijerarhije je temelj za izgradnju, učitavanje i obradu bilo koje 3D datoteke.

Instalacija

Instalirajte paket sa npm pre pokretanja bilo kog koda u ovom vodiču:

npm install @aspose/3d

Osigurajte da vaš tsconfig.json uključuje "module": "commonjs" i "moduleResolution": "node" za pravilno rešavanje uvoza podputanje.

Koncepti grafova scene

Graf scene ima tri nivoa:

NivoKlasaUloga
ScenaSceneKontejner najvišeg nivoa. Sadrži rootNode, animationClips, i assetInfo.
ČvorNodeImenovani čvor stabla. Može imati podčvorove, entitet, transformaciju i materijale.
EntitetMesh, Camera, Light, …Sadržaj prikačen čvoru. Čvor nosi najviše jedan entitet.

Lanac nasleđivanja za glavne građevinske blokove je:

A3DObject
  └─ SceneObject
       ├─ Node          (tree structure)
       └─ Entity
            └─ Geometry
                 └─ Mesh   (polygon geometry)

scene.rootNode se kreira automatski. Ne kreirate ga ručno; vi kreirate podčvorove ispod njega.

Step 1: Create a 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 počinje sa praznim korenskim čvorom i bez animacionih klipova. Sadržaj gradite prikačivanjem podčvorova.

Korak 2: Dodajte čvorove-dece

Koristite createChildNode() za rast drveta. Metod vraća novi Node, tako da možete lančati dalja poziva sa bilo kog nivoa:

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šćenje smislenih imena olakšava debagovanje koda za traversiranje.

Korak 3: Kreirajte Mesh i postavite vertekse

Mesh je primarna klasa geometrije. Dodajte pozicije vrhova tako što ćete gurnuti Vector4 vrednosti u mesh.controlPoints, zatim pozovite createPolygon() da definišete površine 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 homogenе koordinate: komponenta w komponenta je 1 za pozicije i 0 za vektore pravca.

Step 4: Set Node Transforms

Svaki čvor ima transform svojstvo sa translation, rotation, i scaling. Postavi translation da pomeri čvor relativno u odnosu 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 u svetskom prostoru (samo za čitanje), izračunatu spajanjem svih transformacija pretka.

Korak 5: Prolazak kroz stablo

Napišite rekurzivnu funkciju koja posećuje svaki čvor. Proverite node.entity i node.childNodes na svakom nivou:

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]

Ime korenskog čvora je prazna niska jer Scene kreira ga bez argumenta za ime.

Uvek zaštitite pristup entitetu proverom na null pre kastovanja u određeni tip. Nije svaki čvor nosi entitet.

Korak 6: Sačuvajte u glTF ili GLB

Koristite GltfSaveOptions za kontrolu formata izlaza. Postavite binaryMode = true da proizvedete jedan samostalni .glb fajl; ostavite ga false za JSON .gltf + .bin sidecar par:

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

Prosledi GltfFormat.getInstance() kao argument formata kako biblioteka koristi ispravan enkoder bez obzira na ekstenziju fajla.

Saveti i najbolje prakse

  • Koristi createChildNode() umesto da konstrušeš Node direktno: createChildNode() automatski uspostavlja odnos roditelj-dete i registruje čvor u stablu.
  • Proveri node.entity pre nego što pristupiš svojstvima entiteta: mnogi čvorovi (grupni čvorovi, kosti, lokatori) nemaju entitet. Uvek proveravajte null vrednost ili instanceof test.
  • Postavi translation na podređene čvorove, a ne na vrhove mreže: modifikovanje transform.translation je nedestruktivan i može se kombinovati sa transformacijama roditelja.
  • Preferirajte binaryMode = true za GLB: jedan .glb datoteka je lakše distribuirati, učitavati u pregledačima i uvoziti u game engine‑ove nego podeljeni .gltf + .bin format.
  • Prođite putem for...of preko childNodes: izbegavajte numeričko indeksiranje; koristite iterable direktno za unapređenu kompatibilnost.

Uobičajeni problemi

SimptomVerovatni uzrokIspravi
child.entity = mesh nema efekta na izvozEntitet dodeljen pogrešnom nivou čvoraDodeli entity na list čvor, a ne na grupni čvor
node.entity je uvek nullSamo proverava rootNode samRekurzija u node.childNodes; rootNode obično nema entitet
Transformacija se ne odražava u GLB preglednikuglobalTransform nije ažuriranoglobalTransform se izračunava pri čuvanju; postavi transform.translation pre poziva scene.save()
GLB proizvodi zaseban .bin sidecarbinaryMode podrazumevano je falsePostavi saveOpts.binaryMode = true

Vidi takođe

 Српски