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:
| Tier | Klasse | Rolle |
|---|---|---|
| Schauspiel | Scene | Top-Level Container - Halt rootNode, animationClips,und assetInfo. |
| Node | Node | Name: Holzknoten. kann Kinderknoten, eine Einheit, eine Transformation und Materialien haben. |
| Entität | Mesh, 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 aufzubauenNodeDirekt:createChildNode()automatisch die Eltern-Kind-Verhältnis anruft und registriert die Node im Baum. - Check
node.entityVor dem Zugriff auf Eigentumsvorteile: viele Knoten (Grupp Knoten, Knochen, Locatoren) tragen keine Einheit.instanceofTest zu machen. - Set
translationauf Kindernoten, nicht auf Messervertikeln: Änderungtransform.translationist nicht zerstörbar und mit Elterntransformationen komposibel. - bevorzugt
binaryMode = truefür GLB: Ein Einzel.glbDateien sind leichter zu verteilen, in Browsern zu laden und in Spielautomaten zu importieren als die.gltf+.binFormate zu machen. - Durchgang durch
for...ofÜberchildNodes: Vermeiden Sie numerische Indexierung; verwenden Sie das Iterable direkt für die Kompatibilität im Vordergrund.
Gemeinsame Probleme
| Symptome | Wahrscheinlich Ursache | Fix |
|---|---|---|
child.entity = mesh Es hat keinen Einfluss auf den Export | Entität, die an falsche Node-Ebene zugeordnet ist | Zugeordnet entity auf den Blattnode, nicht auf eine Gruppenode |
node.entity ist immer null | Nur überprüfen rootNode selbst | Zurück in node.childNodes; rootNode Normalerweise gibt es keine Einheit |
| Transformation nicht im GLB-Viewer reflektiert | globalTransform nicht aktualisiert | globalTransform ist auf Save berechnet; Set transform.translation Vor der Anrufe scene.save() |
GLB produziert eine separate .bin Sitzen | binaryMode Default zu false | Set saveOpts.binaryMode = true |
Siehe auch
- Eigenschaften und Funktionen: Vollständige API-Referenz für alle Funktionsbereiche.
- Format Unterstützung: unterstützte 3D-Formate, Les- und Schreibfähigkeit und Formatoptionen.
- Wie man ein 3D-Mesh programmatisch baut