Εργασία με το Διάγραμμα Σκηνής

Εργασία με το Διάγραμμα Σκηνής

Όλο το 3D περιεχόμενο στο Aspose.3D FOSS για TypeScript βρίσκεται μέσα σε ένα Scene αντικείμενο οργανωμένο ως δέντρο από Node αντικείμενα. Η κατανόηση αυτής της ιεραρχίας είναι το θεμέλιο για την κατασκευή, τη φόρτωση και την επεξεργασία οποιουδήποτε 3D αρχείου.

Installation

Εγκαταστήστε το πακέτο από το npm πριν εκτελέσετε οποιονδήποτε κώδικα σε αυτόν τον οδηγό:

npm install @aspose/3d

Βεβαιωθείτε ότι το tsconfig.json περιλαμβάνει "module": "commonjs" και "moduleResolution": "node" για σωστή επίλυση εισαγωγών υπο-διαδρομών.

Έννοιες Διάγραμμα Σκηνής

Το διάγραμμα σκηνής έχει τρία επίπεδα:

ΕπίπεδοΚλάσηΡόλος
ΣκηνήSceneΚοντέινερ ανώτερου επιπέδου. Περιέχει rootNode, animationClips, και assetInfo.
ΚόμβοςNodeΟνομασμένος κόμβος δέντρου. Μπορεί να έχει υποκόμβους, μια οντότητα, έναν μετασχηματισμό και υλικά.
ΟντότηταMesh, Camera, Light, …Περιεχόμενο προσαρτημένο σε έναν κόμβο. Ένας κόμβος μεταφέρει το πολύ μία οντότητα.

Η αλυσίδα κληρονομικότητας για τα κύρια δομικά στοιχεία είναι:

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

scene.rootNode Δημιουργείται αυτόματα. Δεν το δημιουργείτε χειροκίνητα· δημιουργείτε υποκόμβους κάτω από αυτό.

Βήμα 1: Δημιουργία Σκηνής

import { Scene } from '@aspose/3d';

const scene = new Scene();
console.log(scene.rootNode.name); // '' (empty string — the root node is created with no name)

Ένα νέο Scene ξεκινά με έναν κενό ριζικό κόμβο και χωρίς κλιπ κίνησης. Δημιουργείτε περιεχόμενο προσαρτώντας υποκόμβους.

Βήμα 2: Προσθήκη Κόμβων-Παιδιών

Χρησιμοποιήστε createChildNode() για να μεγαλώσετε το δέντρο. Η μέθοδος επιστρέφει το νέο Node, ώστε να μπορείτε να αλυσίσετε περαιτέρω κλήσεις από οποιοδήποτε επίπεδο:

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)

Τα ονόματα των κόμβων είναι αυθαίρετες συμβολοσειρές. Δεν χρειάζεται να είναι μοναδικά, αλλά η χρήση σημασιολογικών ονομάτων κάνει τον κώδικα διάσχισης πιο εύκολο στην αποσφαλμάτωση.

Βήμα 3: Δημιουργία Mesh και Ορισμός Κορυφών

Mesh είναι η κύρια κλάση γεωμετρίας. Προσθέστε θέσεις κορυφών σπρώχνοντας Vector4 τιμές στο mesh.controlPoints, στη συνέχεια καλέστε createPolygon() για να ορίσετε faces με δείκτη κορυφής:

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 χρησιμοποιεί ομογενείς συντεταγμένες: η w συστατικό είναι 1 για θέσεις και 0 για διανύσματα κατεύθυνσης.

Βήμα 4: Ορισμός Μετασχηματισμών Κόμβου

Κάθε κόμβος έχει ένα transform ιδιότητα με translation, rotation, και scaling. translation για να μετακινήσετε τον κόμβο σε σχέση με τον γονέα του:

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 παρέχει τον πίνακα μετασχηματισμού του παγκόσμιου χώρου (μόνο για ανάγνωση), υπολογιζόμενο με τη συνένωση όλων των μετασχηματισμών προγόνων.

Βήμα 5: Διέλευση του Δέντρου

Γράψτε μια αναδρομική συνάρτηση για να επισκεφθείτε κάθε κόμβο. Ελέγξτε node.entity και node.childNodes σε κάθε επίπεδο:

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

Για την ιεραρχία που δημιουργήθηκε παραπάνω, η έξοδος θα είναι:

 [none]
  parent [none]
    child [Mesh]

Το όνομα του ριζικού κόμβου είναι μια κενή συμβολοσειρά επειδή Scene το δημιουργεί χωρίς όρισμα ονόματος.

Πάντα προστατεύετε την πρόσβαση στην οντότητα με έλεγχο null πριν κάνετε μετατροπή σε συγκεκριμένο τύπο. Δεν φέρει οντότητα κάθε κόμβος.

Βήμα 6: Αποθήκευση σε glTF ή GLB

Χρησιμοποιήστε GltfSaveOptions για να ελέγξετε τη μορφή εξόδου. Ορίστε binaryMode = true για να παράγει ένα ενιαίο αυτοσυμπεριλαμβανόμενο .glb αρχείο· αφήστε το false για το JSON .gltf + .bin ζεύγος 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');

Περάστε GltfFormat.getInstance() ως το όρισμα format ώστε η βιβλιοθήκη να χρησιμοποιεί τον σωστό κωδικοποιητή ανεξάρτητα από την επέκταση του αρχείου.

Συμβουλές και Καλές Πρακτικές

  • Χρησιμοποιήστε createChildNode() αντί για την κατασκευή Node απευθείας: createChildNode() συνδέει αυτόματα τη σχέση γονέα-παιδιού και καταχωρεί τον κόμβο στο δέντρο.
  • Ελέγξτε node.entity πριν προσπελάσετε τις ιδιότητες της οντότητας: πολλοί κόμβοι (κόμβοι ομάδας, οστά, εντοπιστές) δεν έχουν οντότητα. Πάντα να προστατεύετε με έλεγχο null ή instanceof δοκιμή.
  • Ορίστε translation σε κόμβους-παιδιά, όχι σε κορυφές του πλέγματος:τροποποίηση transform.translation είναι μη καταστροφική και συνθέσιμη με τους γονικούς μετασχηματισμούς.
  • Προτιμήστε binaryMode = true για GLB: ένα ενιαίο .glb το αρχείο είναι πιο εύκολο στη διανομή, τη φόρτωση σε προγράμματα περιήγησης και την εισαγωγή σε μηχανές παιχνιδιών από το διαχωρισμένο .gltf + .bin μορφή.
  • Διασχίστε μέσω for...of πάνω childNodes: αποφύγετε την αριθμητική δεικτοδότηση· χρησιμοποιήστε το iterable απευθείας για προοπτική συμβατότητα.

Κοινά Προβλήματα

ΣύμπτωμαΠιθανή ΑιτίαΔιόρθωση
child.entity = mesh δεν έχει καμία επίδραση στην εξαγωγήΗ οντότητα έχει εκχωρηθεί σε λανθασμένο επίπεδο κόμβουΑντιστοίχισε entity στο φύλλο κόμβο, όχι σε κόμβο ομάδας
node.entity είναι πάντα nullΜόνο έλεγχος rootNode αυτόΕπανάληψη σε node.childNodes; rootNode συνήθως δεν έχει οντότητα
Ο μετασχηματισμός δεν αντανακλάται στον προβολέα GLBglobalTransform δεν ενημερώθηκεglobalTransform υπολογίζεται κατά την αποθήκευση· ορίστε transform.translation πριν από την κλήση scene.save()
Το GLB παράγει ένα ξεχωριστό .bin πρόσθετοbinaryMode προεπιλογή είναι falseΟρίστε saveOpts.binaryMode = true

Δείτε επίσης

 Ελληνικά