Πώς να περάσετε ένα 3D σκηνικό γραφικά σε TypeScript
Το γραφικό σκηνής στο Aspose.3D FOSS για το TypeScript είναι ένα δέντρο Node αντικείμενα που ριζώνουν σε scene.rootNode.Ο ταξιδιωτικός είναι επαναλαμβανόμενος: κάθε κόμβος εκθέτει ένα childNodes Ανεκτίμητο και ελεγχόμενο entity Ο οδηγός αυτός δείχνει πώς να περπατάτε ολόκληρο το δέντρο, εντοπίζοντας τύπους οντοτήτων και συλλέγοντας στατιστικά στοιχεία για τα μασά.
Προϋποθέσεις
- Node.js 18 ή αργότερα
- TypeScript 5.0 ή νεότερη
@aspose/3dεγκατεστημένο
Βήμα προς βήμα οδηγός
Βήμα 1: Εγκατάσταση και εισαγωγή
Εγκαταστήστε το πακέτο:
npm install @aspose/3dΕισαγωγή των τάξεων που χρησιμοποιούνται σε αυτόν τον οδηγό:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';Scene και Mesh Είναι οι κεντρικές τάξεις. ObjLoadOptions χρησιμοποιείται στο παράδειγμα φόρτωσης. αντικαθιστά την κατηγορία επιλογών ίσης για άλλες μορφές.
Βήμα 2: Κατεβάστε μια σκηνή από ένα αρχείο
Δημιουργία A Scene και καλεί scene.open() Η ανίχνευση μορφών είναι αυτόματη από τα δυαδικά μαγικά αριθμούς, οπότε δεν χρειάζεται να προσδιορίσετε τη μορφή για τα αρχεία GLB, STL ή 3MF:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
console.log(`Root node: "${scene.rootNode.name}"`);
console.log(`Top-level children: ${scene.rootNode.childNodes.length}`);Μπορείτε επίσης να φορτώσετε από το A Buffer στη μνήμη χρησιμοποιώντας scene.openFromBuffer(buffer, options);· Χρήσιμο σε μη διακομιστικά σωλήνες όπου το δίσκο I/O δεν είναι διαθέσιμο.
Βήμα 3: Γράψτε μια αναδρομική ταξιδιωτική λειτουργία
ΕΠΙΣΚΕΨΗ ΠΡΟΣ childNodes Η λειτουργία επισκέπτεται κάθε κόμβο βάθος-πρώτα:
function traverse(node: any, depth = 0): void {
const indent = ' '.repeat(depth);
const entityType = node.entity ? node.entity.constructor.name : '-';
console.log(`${indent}[${entityType}] ${node.name}`);
for (const child of node.childNodes) {
traverse(child, depth + 1);
}
}
traverse(scene.rootNode);Για μια σκηνή με ένα μασχ που ονομάζεται Cube,Η παραγωγή θα μοιάζει με:
[-] RootNode
[Mesh] Cube<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
node.entity Είναι null για τους κόμβους, τα οστά και τους εντομοκτόνους. constructor.name Ελέγξτε τις εργασίες για οποιοδήποτε είδος οντότητας: Mesh, Camera, Light,κλπ.
Βήμα 4: Πρόσβαση στον τύπο οντότητας σε κάθε κόμβο
Για να λάβετε δράση βάσει του τύπου οντότητας, χρησιμοποιήστε ένα instanceof Ελέγξτε μετά την μηδενική φρουρά:
import { Mesh } from '@aspose/3d/entities';
function visitWithTypeCheck(node: any, depth = 0): void {
const indent = ' '.repeat(depth);
if (node.entity instanceof Mesh) {
const mesh = node.entity as Mesh;
console.log(`${indent}MESH "${node.name}": ${mesh.controlPoints.length} vertices`);
} else if (node.entity) {
console.log(`${indent}${node.entity.constructor.name} "${node.name}"`);
} else {
console.log(`${indent}GROUP "${node.name}"`);
}
for (const child of node.childNodes) {
visitWithTypeCheck(child, depth + 1);
}
}
visitWithTypeCheck(scene.rootNode);instanceof Mesh είναι ο ασφαλέστερος τρόπος για να επιβεβαιωθεί η οντότητα είναι ένα πολυγόνο μασχί πριν από την πρόσβαση controlPoints, polygonCount,ή των στοιχείων του Vertex.
Βήμα 5: Φιλτράρετε τα κενά ανά τύπο οντότητας
Για να συλλέξετε μόνο κόμβους με μασχ χωρίς να εκτυπώσετε το πλήρες δέντρο, χρησιμοποιήστε μια επαναλαμβανόμενη μπαταρία:
import { Mesh } from '@aspose/3d/entities';
function collectMeshes(
node: any,
results: Array<{ name: string; mesh: Mesh }> = []
): Array<{ name: string; mesh: Mesh }> {
if (node.entity instanceof Mesh) {
results.push({ name: node.name, mesh: node.entity as Mesh });
}
for (const child of node.childNodes) {
collectMeshes(child, results);
}
return results;
}
const meshNodes = collectMeshes(scene.rootNode);
console.log(`Found ${meshNodes.length} mesh node(s)`);Η λειτουργία αποδέχεται μια επιλεκτική results συσκευασία έτσι οι καλεστές μπορούν να προ-παραδοτήσουν για τη συγχώνευση των αποτελεσμών σε πολλαπλές υποδένες.
Βήμα 6: Συλλέξτε όλες τις μάζες και εκτυπώστε τα κέρματα Vertex
Επέκταση του συλλέκτη για να εκτυπώσετε στατιστικά στοιχεία per-mesh:
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
import { Mesh } from '@aspose/3d/entities';
function collectMeshes(node: any, results: Array<{name: string, mesh: Mesh}> = []) {
if (node.entity instanceof Mesh) {
results.push({ name: node.name, mesh: node.entity as Mesh });
}
for (const child of node.childNodes) {
collectMeshes(child, results);
}
return results;
}
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
const meshes = collectMeshes(scene.rootNode);
for (const { name, mesh } of meshes) {
console.log(`${name}: ${mesh.controlPoints.length} vertices, ${mesh.polygonCount} polygons`);
}Εικόνα για μια σκηνή δύο μεσημέρι:
Cube: 8 vertices, 6 polygons
Sphere: 482 vertices, 480 polygons<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
Συμβουλές και βέλτιστες πρακτικές
- Πάντα μηδενική επιθεώρηση
node.entityΠριν από την πρόσβαση σε ιδιότητες ειδικά για τον όμιλο.Πολλοί κόμβοι είναι καθαρά ομίλους που δεν φέρουν οντότητα. - Χρησιμοποιήστε
instanceofΠάνω απόconstructor.nameΓια τους τύπους ελέγχων σε λογικά μονοπάτια.instanceofείναι αναστρέψιμο-σφάλαιο· σύγκριση σιδήρου σεconstructor.nameΔιακόπτει με μίνι. - Περνάμε μέσω
for...ofΠάνω απόchildNodes: το μη διατηρημένο χειρίζεται όλα τα μεγέθη του ράγματος με ασφάλεια. αποφύγετε την αριθμητική ενσωμάτωση για προοδευτική συμβατότητα. - Αποφύγετε την μεταμόσχευση του δέντρου κατά τη διάρκεια της διαδρομής: μην προσθέτετε ή αφαιρέστε κόντρα μέσα στο επανειλημμένο κλήση. συλλέξτε τα αποτελέσματα πρώτα, στη συνέχεια τροποποιήστε.
- Πάρτε ένα αποτέλεσμα ως παράμετρο:Αυτό αποφεύγει την κατανομή μιας νέας σειράς σε κάθε επανειλημμένη κλήση και καθιστά εύκολο να συγχωνευθούν τα αποτελέσματα του υποδένου.
κοινά ζητήματα
| Συμπτώματα | Αιτία | ΦΙΛΕΞΗ |
|---|---|---|
childNodes Έχει μηδενικό μήκος rootNode | Μοντέλο που δεν φορτίζεται | Ασφάλεια scene.open() Εξέτασης χωρίς λάθος πριν από την διείσδυση |
node.entity instanceof Mesh Ποτέ αλήθεια | λάθος Mesh Ο δρόμος εισαγωγής | εισαγωγών Mesh Από την @aspose/3d/entities,Όχι από @aspose/3d ρίζα |
| Ο ταξιδιώτης λείπει από τα σκουπίδια | Δεν αναζητάμε όλα τα παιδιά | Βεβαιωθείτε ότι η επανειλημμένη κλήση καλύπτει κάθε στοιχείο στο node.childNodes |
mesh.controlPoints.length 0 είναι | Το Mesh φορτίζεται αλλά δεν περιέχει γεωμετρία | Ελέγξτε την πηγή OBJ για κενές ομάδες. χρησιμοποιήστε mesh.polygonCount ως δευτερογενής έλεγχος |
| Στενάει το πέρασμα σε βαθιές ιεραρχίες | Πολύ βαθιά σκηνή δέντρο (σε εκατοντάδες επίπεδα) | Αντικαταστήστε την αναδρομή με μια ρητή σκάκι χρησιμοποιώντας Array.push / Array.pop |
Συχνές ερωτήσεις
Η ΚΕ scene.rootNode Εχει μια οντότητα;? Ο κόμβος ρίζας είναι ένα δοχείο που δημιουργείται αυτόματα από τη βιβλιοθήκη. δεν έχει οντότητα. η γεωμετρία σας και άλλα αντικείμενα σκηνής ζουν σε παιδικά κόμπια ενός ή περισσότερων επιπέδων κάτω από το rootNode.
Ποια είναι η διαφορά μεταξύ node.entity και node.entities? node.entity Κάποια παλαιότερα αρχεία FBX και COLLADA μπορεί να παράγουν κόμβους με πολλαπλές συνδεδεμένες οντότητες. node.entities (Πολύ) παρέχει την πλήρη λίστα.
Μπορώ να περάσω με ευρύτατη πρώτη σειρά αντί για βάθος πρώτος;? Χρησιμοποιήστε ένα κουτί αντί για μια επανεκκλητική κλήση: push scene.rootNode σε μια σειρά, στη συνέχεια μετακινεί και επεξεργάζεται κόμβους ενώ πιέζει κάθε κόμμα childNodes Στον κατώτατο χείλος.
Είναι scene.open() Συνομολογημένη ? Ναι . scene.open() και scene.openFromBuffer() και τα δύο μπλοκάρουν το καλώδιο μέχρι να διαλυθεί πλήρως το αρχείο. Βάλε τους σε ένα εργοδότη, εάν χρειάζεται να κρατήσει την ροή των γεγονότων ανταποκριτική.
Πώς μπορώ να πάρω θέσεις διαστήματος από ένα κόμβο;? Διαβάστε node.globalTransform;Επέστρεψε μια ανάγνωση μόνο GlobalTransform με τη ματρίκα του κόσμου-διαστήματος, που αποτελείται από όλες τις μετασχηματιστικές προγόνες. για την εκφραστική Ματριάκη Μαθηματικά, καλέστε node.evaluateGlobalTransform(false).
Ποια είδη οντοτήτων είναι δυνατά εκτός από Mesh? Camera, Light, και προσαρμοσμένες οντότητες σκληρότητας / κόλπου. ελέγξτε node.entity.constructor.name ή χρησιμοποιώντας instanceof Η συγκεκριμένη κατηγορία που εισάγεται από την @aspose/3d.