Práca so scénovým grafom
Všetok 3D obsah v Aspose.3D FOSS pre TypeScript sa nachádza v Scene objekte usporiadanom ako strom Node objektov. Pochopenie tejto hierarchie je základom pre tvorbu, načítanie a spracovanie akéhokoľvek 3D súboru.
Inštalácia
Nainštalujte balík z npm pred spustením akéhokoľvek kódu v tomto sprievodcovi:
npm install @aspose/3dUistite sa, že váš tsconfig.json obsahuje "module": "commonjs" a "moduleResolution": "node" pre správne riešenie importu podcesty.
Koncepty scénového grafu
Scénový graf má tri úrovne:
| Úroveň | Trieda | Úloha |
|---|---|---|
| Scéna | Scene | Kontajner najvyššej úrovne. Obsahuje rootNode, animationClips, a assetInfo. |
| Uzol | Node | Pomenovaný uzol stromu. Môže mať podriadené uzly, entitu, transformáciu a materiály. |
| Entita | Mesh, Camera, Light, … | Obsah pripojený k uzlu. Uzol nesie najviac jednu entitu. |
Dedičný reťazec pre hlavné stavebné bloky je:
A3DObject
└─ SceneObject
├─ Node (tree structure)
└─ Entity
└─ Geometry
└─ Mesh (polygon geometry)scene.rootNode sa vytvára automaticky. Nevytvárate ho ručne; vytvárate pod ním podriadené uzly.
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)
Nový Scene začína s prázdnym koreňovým uzlom a žiadnymi animačnými klipmi. Obsah vytvárate pripojovaním podriadených uzlov.
Krok 2: Pridať podriadené uzly
Použiť createChildNode() na rast stromu. Metóda vracia nový Node, takže môžete reťaziť ďalšie volania z akejkoľvek úrovne:
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)
Názvy uzlov sú ľubovoľné reťazce. Názvy nemusia byť jedinečné, ale použitie zmysluplných názvov uľahčuje ladenie kódu prechádzajúceho stromom.
Krok 3: Vytvoriť sieť (Mesh) a nastaviť vrcholy
Mesh je primárna trieda geometrie. Pridajte pozície vrcholov pomocou vkladania Vector4 hodnôt do mesh.controlPoints, potom zavolajte createPolygon() na definovanie plôch podľa indexu vrchola:
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 používa homogénne súradnice: w komponent je 1 pre pozície a 0 pre smerové vektory.
Step 4: Set Node Transforms
Každý uzol má transform vlastnosť s translation, rotation, a scaling. Nastavte translation na presunutie uzla relatívne k jeho rodičovi:
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 poskytuje maticu transformácie vo svetovom priestore (iba na čítanie), vypočítanú zreťazení všetkých transformácií predkov.
Krok 5: Prejdi strom
Napíšte rekurzívnu funkciu na prechádzanie každého uzla. Skontrolujte node.entity a node.childNodes na každej úrovni:
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);Pre hierarchiu vytvorenú vyššie bude výstup:
[none]
parent [none]
child [Mesh]Názov koreňového uzla je prázdny reťazec, pretože Scene vytvára ho bez argumentu názvu.
Vždy chráňte prístup k entite kontrolou na null pred pretypovaním na konkrétny typ. Nie každý uzol nesie entitu.
Krok 6: Uložiť do glTF alebo GLB
Použite GltfSaveOptions na ovládanie výstupného formátu. Nastavte binaryMode = true na vytvorenie jedného samostatného .glb súboru; ponechajte ho false pre JSON .gltf + .bin párový sidecar:
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');Prejdite GltfFormat.getInstance() ako argument formátu, aby knižnica použila správny enkóder bez ohľadu na príponu súboru.
Tipy a osvedčené postupy
- Použite
createChildNode()namiesto konštruovaniaNodepriamo:createChildNode()automaticky prepojí vzťah rodič-dieťa a zaregistruje uzol v strome. - Skontrolujte
node.entitypred prístupom k vlastnostiam entity.: mnoho uzlov (skupinové uzly, kosti, lokátory) neobsahuje žiadny objekt. Vždy ich chráňte kontrolou na null aleboinstanceoftestom. - Nastaviť
translationna podriadených uzloch, nie na vrcholoch siete: modifikáciatransform.translationje nedestruktívny a skladateľný s rodičovskými transformáciami. - Preferovať
binaryMode = truepre GLB: jediný.glbsúbor je jednoduchší na distribúciu, načítanie v prehliadačoch a import do herných enginov než rozdelený.gltf+.binformát. - Prechádzať cez
for...ofnadchildNodes: vyhnite sa číselnému indexovaniu; použite iterovateľ priamo pre budúcu kompatibilitu.
Bežné problémy
| Symptóm | Pravdepodobná príčina | Oprava |
|---|---|---|
child.entity = mesh nemá žiadny vplyv na export | Entita priradená na nesprávnu úroveň uzla | Priradiť entity na listový uzol, nie na skupinový uzol |
node.entity je vždy null | Iba kontrola rootNode samo | Rekurzívne do node.childNodes; rootNode zvyčajne nemá entitu |
| Transformácia sa neodráža v prehliadači GLB | globalTransform neaktualizované | globalTransform sa vypočíta pri uložení; nastaviť transform.translation pred volaním scene.save() |
GLB vytvára samostatný .bin sidecar | binaryMode predvolene je false | Nastaviť saveOpts.binaryMode = true |
Pozri tiež
- Funkcie a funkcionalita: úplná referenčná dokumentácia API pre všetky oblasti funkcií.
- Podpora formátov: podporované 3D formáty, možnosť čítania/zápisu a možnosti formátu.
- Ako programovo zostaviť 3D mesh.