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/3dVarmista, että tsconfig.json sisältää "module": "commonjs" ja "moduleResolution": "node" oikean alipolkujen tuonnin ratkaisemiseksi.
Scene Graph -käsitteet
Scene graphilla on kolme tasoa:
| Taso | Luokka | Rooli |
|---|---|---|
| Kohtaus | Scene | Ylätason säiliö. Sisältää rootNode, animationClips, ja assetInfo. |
| Solmu | Node | Nimetty puusolmu. Voi sisältää alisolmuja, entiteetin, muunnoksen ja materiaaleja. |
| Entiteetti | Mesh, 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ä rakentaisitNodesuoraan:createChildNode()kytkee automaattisesti vanhempi‑lapsi-suhteen ja rekisteröi solmun puuhun. - Tarkista
node.entityennen kuin käytät entiteetin ominaisuuksia: useat solmut (group nodes, bones, locators) eivät sisällä entiteettiä. Suojaa aina null checkillä taiinstanceoftestillä. - Aseta
translationlapsisolmuilla, ei mesh vertices: muokkaaminentransform.translationon ei-destruktiivinen ja yhdistettävissä vanhempien muunnosten kanssa. - Suosi
binaryMode = trueGLB:lle: yksi.glbtiedosto on helpompi jakaa, ladata selaimissa ja tuoda pelimoottoreihin kuin jaettu.gltf+.binformaatti. - Kulje kautta
for...ofylichildNodes: vältä numeerista indeksointia; käytä iteroitavaa suoraan etukäteisyhteensopivuuden vuoksi.
Yleisiä ongelmia
| Oire | Todennäköinen syy | Korjaus |
|---|---|---|
child.entity = mesh ei vaikuta vientiin | Entiteetti määritetty väärälle solmutasolle | Määritä entity lehtisolmuun, ei ryhmäsolmuun |
node.entity on aina null | Vain tarkistetaan rootNode itse | Käy läpi rekursiivisesti node.childNodes; rootNode tyypillisesti ei sisällä entiteettiä |
| Muutosta ei näytetä GLB-katselijassa | globalTransform ei päivitetty | globalTransform lasketaan tallennettaessa; aseta transform.translation ennen kutsua scene.save() |
GLB tuottaa erillisen .bin sivutiedoston | binaryMode oletusarvo on false | Aseta saveOpts.binaryMode = true |
Katso myös
- Ominaisuudet ja toiminnot: täydellinen API-viite kaikille ominaisuusalueille.
- Formaattituki: tuetut 3D-formaatit, luku-/kirjoituskapasiteetti ja formaattivalinnat.
- Kuinka rakentaa 3D Mesh ohjelmallisesti