Εργασία με το Διάγραμμα Σκηνής
Όλο το 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 συνήθως δεν έχει οντότητα |
| Ο μετασχηματισμός δεν αντανακλάται στον προβολέα GLB | globalTransform δεν ενημερώθηκε | globalTransform υπολογίζεται κατά την αποθήκευση· ορίστε transform.translation πριν από την κλήση scene.save() |
Το GLB παράγει ένα ξεχωριστό .bin πρόσθετο | binaryMode προεπιλογή είναι false | Ορίστε saveOpts.binaryMode = true |
Δείτε επίσης
- Χαρακτηριστικά και Λειτουργίες: πλήρης αναφορά API για όλες τις περιοχές χαρακτηριστικών.
- Υποστήριξη Μορφών: υποστηριζόμενες 3D μορφές, δυνατότητα ανάγνωσης/εγγραφής και επιλογές μορφής.
- Πώς να δημιουργήσετε ένα 3D Mesh προγραμματιστικά