Työskentely Scene Graphin kanssa

Työskentely Scene Graphin kanssa

Kaikki 3D-sisältö Aspose.3D FOSS TypeScriptille sijaitsee sisällä Scene objektina, joka on järjestetty puuksi Node objekteja. Tämän hierarkian ymmärtäminen on perusta minkä tahansa 3D-tiedoston rakentamiselle, lataamiselle ja käsittelylle.

Installation

Asenna paketti npm:stä ennen kuin suoritat oppaan minkä tahansa koodin:

npm install @aspose/3d

Varmista, että tsconfig.json sisältää "module": "commonjs" ja "moduleResolution": "node" oikean alipolkujen tuonnin ratkaisemiseksi.

Scene Graph -käsitteet

Scene graphilla on kolme tasoa:

TasoLuokkaRooli
KohtausSceneYlätason säiliö. Sisältää rootNode, animationClips, ja assetInfo.
SolmuNodeNimetty puusolmu. Voi sisältää alisolmuja, entiteetin, muunnoksen ja materiaaleja.
EntiteettiMesh, Camera, Light, …Sisältö, joka on liitetty solmuun. Solmu kantaa enintään yhtä entiteettiä.

Pääasiallisten rakennuspalikoiden periytymisketju on:

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

scene.rootNode luodaan automaattisesti. Et luo sitä manuaalisesti; sen alle luodaan lapsisolmuja.

Vaihe 1: Luo kohtaus

import { Scene } from '@aspose/3d';

const scene = new Scene();
console.log(scene.rootNode.name); // '' (empty string — the root node is created with no name)

Uusi Scene alkaa tyhjällä juurisolmulla eikä sisällä animaatioklippejä. Rakennat sisällön liittämällä lapsisolmuja.

Vaihe 2: Lisää lapsisolmuja

Käytä createChildNode() kasvattaaksesi puuta. Metodi palauttaa uuden Node, joten voit ketjuttaa lisäkutsuja mistä tahansa tasosta:

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)

Solmujen nimet ovat mielivaltaisia merkkijonoja. Nimien ei tarvitse olla uniikkeja, mutta merkityksellisten nimien käyttö tekee läpikäyntikoodin virheenkorjauksesta helpompaa.

Vaihe 3: Luo Mesh ja aseta vertexit

Mesh on ensisijainen geometria-luokka. Lisää kärkipisteet työntämällä Vector4 arvoja mesh.controlPoints, sitten kutsua createPolygon() määrittääksesi pinnat kärkinumeroinnin perusteella:

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 käyttää homogeenisia koordinaatteja: w komponentti on 1 sijainneille ja 0 suuntavektoreille.

Vaihe 4: Aseta solmun transformit

Jokaisella solmulla on transform ominaisuus, jossa on translation, rotation, ja scaling. Aseta translation siirtääksesi solmua suhteessa sen vanhempaan:

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 tarjoaa maailmanavaruuden muunnosmatriisin (vain luku), joka on laskettu yhdistämällä kaikki vanhempien muunnokset.

Vaihe 5: Käy puu läpi

Kirjoita rekursiivinen funktio, joka käy läpi jokaisen solmun. Tarkista node.entity ja node.childNodes kussakin tasossa:

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

Yllä luodulle hierarkialle tuloste on:

 [none]
  parent [none]
    child [Mesh]

Juurisolmun nimi on tyhjä merkkijono, koska Scene luo sen ilman nimeä argumenttina.

Suojaa entiteettipääsy aina null‑tarkistuksella ennen muuntamista tiettyyn tyyppiin. Kaikilla solmuilla ei ole entiteettiä.

Vaihe 6: Tallenna glTF- tai GLB-muotoon

Käytä GltfSaveOptions ohjaamaan tulostusmuotoa. Aseta binaryMode = true tuottamaan yksi itsenäinen .glb tiedosto; jätä se false JSON:lle .gltf + .bin sivukappalepariksi:

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

Anna GltfFormat.getInstance() muotoargumenttina, jotta kirjasto käyttää oikeaa enkooderia tiedostopäätteen riippumatta.

Vinkkejä ja parhaita käytäntöjä

  • Käytä createChildNode() sen sijaan, että rakentaisit Node suoraan: createChildNode() kytkee automaattisesti vanhempi‑lapsi-suhteen ja rekisteröi solmun puuhun.
  • Tarkista node.entity ennen kuin käytät entiteetin ominaisuuksia: useat solmut (group nodes, bones, locators) eivät sisällä entiteettiä. Suojaa aina null checkillä tai instanceof testillä.
  • Aseta translation lapsisolmuilla, ei mesh vertices: muokkaaminen transform.translation on ei-destruktiivinen ja yhdistettävissä vanhempien muunnosten kanssa.
  • Suosi binaryMode = true GLB:lle: yksi .glb tiedosto on helpompi jakaa, ladata selaimissa ja tuoda pelimoottoreihin kuin jaettu .gltf + .bin formaatti.
  • Kulje kautta for...of yli childNodes: vältä numeerista indeksointia; käytä iteroitavaa suoraan etukäteisyhteensopivuuden vuoksi.

Yleisiä ongelmia

OireTodennäköinen syyKorjaus
child.entity = mesh ei vaikuta vientiinEntiteetti määritetty väärälle solmutasolleMääritä entity lehtisolmuun, ei ryhmäsolmuun
node.entity on aina nullVain tarkistetaan rootNode itseKäy läpi rekursiivisesti node.childNodes; rootNode tyypillisesti ei sisällä entiteettiä
Muutosta ei näytetä GLB-katselijassaglobalTransform ei päivitettyglobalTransform lasketaan tallennettaessa; aseta transform.translation ennen kutsua scene.save()
GLB tuottaa erillisen .bin sivutiedostonbinaryMode oletusarvo on falseAseta saveOpts.binaryMode = true

Katso myös

 Suomi