Darbas su scenos grafu
Visas 3D turinys Aspose.3D FOSS TypeScript kalbai yra viduje vieno Scene objektas, organizuotas kaip medžio Node objektų. Šios hierarchijos supratimas yra pagrindas bet kokio 3D failo kūrimui, įkėlimui ir apdorojimui.
Įdiegimas
Įdiekite paketą iš npm prieš paleisdami bet kurį šio vadovo kodą:
npm install @aspose/3dĮsitikinkite, kad jūsų tsconfig.json įtraukia "module": "commonjs" ir "moduleResolution": "node" teisingam subkelio importų sprendimui.
Scenos grafo koncepcijos
Scenos grafas turi tris lygius:
| Lygmuo | Klasė | Vaidmuo |
|---|---|---|
| Scena | Scene | Aukščiausio lygio konteineris. Laiko rootNode, animationClips, ir assetInfo. |
| Mazgas | Node | Pavadintas medžio mazgas. Gali turėti vaikų mazgus, entitetą, transformaciją ir medžiagas. |
| Entitetas | Mesh, Camera, Light, … | Turinis, prisegtas prie mazgo. Mazgas nešioja ne daugiau kaip vieną objektą. |
Paveldėjimo grandinė pagrindiniams statybiniams blokams yra:
A3DObject
└─ SceneObject
├─ Node (tree structure)
└─ Entity
└─ Geometry
└─ Mesh (polygon geometry)scene.rootNode sukuriamas automatiškai. Jūs jo nesukuriate rankiniu būdu; jūs kuriate vaikų mazgus po jo.
Žingsnis 1: Sukurti sceną
import { Scene } from '@aspose/3d';
const scene = new Scene();
console.log(scene.rootNode.name); // '' (empty string — the root node is created with no name)
Naujas Scene prasideda su tuščiu šakniniu mazgu ir be animacijos klipų. Jūs kuriate turinį prisegdami vaikų mazgus.
Žingsnis 2: Pridėti vaikų mazgus
Naudokite createChildNode() auginti medį. Metodas grąžina naują Node, todėl galite grandinti tolesnius kvietimus iš bet kurio lygio:
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)
Mazgo pavadinimai yra bet kokios eilutės. Pavadinimai neturi būti unikalūs, tačiau prasmingų pavadinimų naudojimas palengvina keliaujančio kodo derinimą.
Žingsnis 3: Sukurti Mesh ir nustatyti viršūnes
Mesh yra pagrindinė geometrijos klasė. Pridėkite viršūnių pozicijas stumdami Vector4 reikšmes į mesh.controlPoints, tada iškvieskite createPolygon() apibrėžti paviršius pagal viršūnių indeksą:
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 naudoja homogenines koordinates: šio w komponentas yra 1 pozicijoms ir 0 krypties vektoriams.
Žingsnis 4: Nustatyti mazgo transformacijas
Kiekvienas mazgas turi transform savybę su translation, rotation, ir scaling. Nustatyti translation perkelti mazgą santykinai su jo tėvu:
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 pateikia pasaulio erdvės transformacijos matricą (tik skaitymui), apskaičiuotą sujungiant visas tėvų transformacijas.
Žingsnis 5: Pereiti medį
Parašykite rekursinę funkciją, kuri aplankytų kiekvieną mazgą. Patikrinkite node.entity ir node.childNodes kiekviename lygyje:
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);Aukščiau sukurtai hierarchijai išvestis bus:
[none]
parent [none]
child [Mesh]Šaknies mazgo pavadinimas yra tuščia eilutė, nes Scene jį sukuria be pavadinimo argumento.
Visada apsaugokite prieigą prie entiteto patikrinimu, ar jis nėra null, prieš konvertuojant į konkretų tipą. Ne kiekvienas mazgas turi entitetą.
Žingsnis 6: Išsaugoti į glTF arba GLB
Naudokite GltfSaveOptions norėdami valdyti išvesties formatą. Nustatykite binaryMode = true kad sukurtumėte vieną savarankišką .glb failą; palikite jį false JSON .gltf + .bin sidecar pora:
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');Paduokite GltfFormat.getInstance() kaip formato argumentą, kad biblioteka naudotų teisingą koduotuvą, nepriklausomai nuo failo plėtinio.
Patarimai ir geriausia praktika
- Naudokite
createChildNode()vietoj konstruojimoNodetiesiogiai:createChildNode()automatiškai sukuria tėvo-vaiko ryšį ir registruoja mazgą medyje. - Patikrinkite
node.entityprieš prieinant prie objekto savybių: daugelis mazgų (grupės mazgai, kaulai, lokatoriai) neturi jokio objekto. Visada apsaugokite naudodami null patikrinimą arbainstanceoftestą. - Nustatyti
translationvaikų mazguose, o ne tinklelio viršūnėse:modifikavimastransform.translationyra nekenksmingas ir suderinamas su tėvų transformacijomis. - Pirmenybę teikite
binaryMode = trueGLB formatui: vienas.glbfailas yra lengviau platinti, įkelti į naršykles ir importuoti į žaidimų variklius nei suskaidytas.gltf+.binformatas. - Naršyti per
for...ofviršchildNodes: venkite skaitmeninio indeksavimo; naudokite iteruojamąjį tiesiogiai, kad išlaikytumėte suderinamumą ateityje.
Dažnos problemos
| Simptomas | Tikėtina priežastis | Pataisa |
|---|---|---|
child.entity = mesh neturi įtakos eksporto | Entitetas priskirtas neteisingam mazgo lygiui | Priskirti entity į lapo mazgą, o ne į grupės mazgą |
node.entity visada null | Tik tikrinama rootNode pats | Rekursuoti į node.childNodes; rootNode paprastai neturi objekto |
| Transformacija neatsispindi GLB peržiūros programoje | globalTransform neatnaujinta | globalTransform apskaičiuojama išsaugojant; nustatyti transform.translation prieš iškviečiant scene.save() |
GLB sukuria atskirą .bin šoninis failas | binaryMode numatytasis yra false | Nustatyti saveOpts.binaryMode = true |
Žr. taip pat
- Savybės ir funkcionalumas: pilna API nuoroda visoms funkcijų sritims.
- Formato palaikymas: palaikomi 3D formatai, skaitymo/rašymo galimybės ir formato parinktys.
- Kaip programiškai sukurti 3D Mesh.