Mit dem Scene Graph arbeiten

Alle 3D-Inhalte in Aspose.3D FOSS für TypeScript leben in einem Scene Ein Objekt, das als Baum von Node Verständnis dieser Hierarchie ist die Grundlage für die Erstellung, Laden und Verarbeitung von 3D-Dateien.

Installation

Installieren Sie das Paket von npm vor dem Lauf eines der Codes in diesem Leitfaden:

asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.

sichern Sie Ihre tsconfig.json Inbegriffen "module": "commonjs" und "moduleResolution": "node" für die korrekte Sub-Path-Import-Resolution.

Scene Graf

Das Scenogramm hat drei Drittel:

TierKlasseRolle
SchauspielSceneTop-Level Container - Halt rootNode, animationClips,und assetInfo.
NodeNodeName: Holzknoten. kann Kinderknoten, eine Einheit, eine Transformation und Materialien haben.
EntitätMesh, Camera, Light, …Inhalte, die an einen Knoten angeschlossen sind.Ein Knoten trägt auf höchstens eine Einheit.

Die Erbschaftskette für die Hauptgebäude ist:

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

scene.rootNode Sie erstellen es nicht manuell; Sie erstellen unter ihm Kindernoten.

Schritt 1: Erstellen eines 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)

Ein neuer Scene beginnt mit einem leeren Wurzeln und keine Animationsclips. Sie bauen Inhalte, indem Sie Kindernoten anheben.

Schritt 2: Erstellen von Kindernoten

Gebrauch createChildNode() die Baum zu wachsen. die Methode kehrt die neue Node, so können Sie weitere Anrufe von jedem Level verketten:

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)

Node-Namen sind willehafte Stränge.Namen müssen nicht einzigartig sein, aber mit sinnvollen Namen macht die Durchschnittscode leichter zu debugieren.

Schritt 3: Erstellen Sie einen Mesh und Set Vertikale

Mesh ist die primäre Geometrieklasse. Vertexpositionen hinzufügen, indem Sie Vector4 Werte in mesh.controlPoints,Dann rufen createPolygon() Die Anzahl der Gesichter durch den Vertex-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 die homogene Koordinaten verwendet: w Komponente ist 1 für Positionen und 0 für die Vektoren.

Schritt 4: Set Node Transforms

Jede Node hat eine transform Eigentum mit translation, rotation,und scaling.Set translation Um den Knoten in Bezug auf seinen Eltern zu bewegen:

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 bietet die Welt-Space-Transformationsmatrix (lesen nur), die durch Konkatenierung aller Vorfahren-Transformationen berechnet wird.

Schritt 5: Überqueren Sie den Baum

Schreiben Sie eine recursive Funktion, um jeden Knoten zu besuchen. node.entity und node.childNodes Auf jedem Niveau:

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

Für die hierarchisch erstellte hierarchie wird die ausgabe:

 [none]
  parent [none]
    child [Mesh]

Der Name der Wurzelnode ist eine leere String, weil Scene Er schafft es ohne Namen Argument.

Sie bewahren immer den Zugriff auf die Entität mit einem Null-Check vor dem Schießen auf einen bestimmten Typ.

Schritt 6: Sparen Sie auf GlTF oder GLB

Gebrauch GltfSaveOptions zum Steuerung des Ausgangsformats. Set binaryMode = true Erzeugen eines einzigen selbstverhaltenen .glb Datei; lassen Sie es false Für JSON .gltf + .bin Seite Paar :

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

Pass GltfFormat.getInstance() als Format Argument so die Bibliothek verwendet die richtige Codierung unabhängig von der Datei-Erweiterung.

Tipps und beste Praktiken

  • Gebrauch createChildNode() statt aufzubauen Node Direkt: createChildNode() automatisch die Eltern-Kind-Verhältnis anruft und registriert die Node im Baum.
  • Check node.entity Vor dem Zugriff auf Eigentumsvorteile: viele Knoten (Grupp Knoten, Knochen, Locatoren) tragen keine Einheit. instanceof Test zu machen.
  • Set translation auf Kindernoten, nicht auf Messervertikeln: Änderung transform.translation ist nicht zerstörbar und mit Elterntransformationen komposibel.
  • bevorzugt binaryMode = true für GLB: Ein Einzel .glb Dateien sind leichter zu verteilen, in Browsern zu laden und in Spielautomaten zu importieren als die .gltf + .bin Formate zu machen.
  • Durchgang durch for...of Über childNodes: Vermeiden Sie numerische Indexierung; verwenden Sie das Iterable direkt für die Kompatibilität im Vordergrund.

Gemeinsame Probleme

SymptomeWahrscheinlich UrsacheFix
child.entity = mesh Es hat keinen Einfluss auf den ExportEntität, die an falsche Node-Ebene zugeordnet istZugeordnet entity auf den Blattnode, nicht auf eine Gruppenode
node.entity ist immer nullNur überprüfen rootNode selbstZurück in node.childNodes; rootNode Normalerweise gibt es keine Einheit
Transformation nicht im GLB-Viewer reflektiertglobalTransform nicht aktualisiertglobalTransform ist auf Save berechnet; Set transform.translation Vor der Anrufe scene.save()
GLB produziert eine separate .bin SitzenbinaryMode Default zu falseSet saveOpts.binaryMode = true

Siehe auch

 Deutsch