Πώς να φορτώσετε 3D μοντέλα στο Python
Aspose.3D FOSS για Python παρέχει ένα απλό API για το άνοιγμα 3D αρχείων χωρίς καμία εγγενή εξάρτηση. Μετά τη φόρτωση ενός αρχείου σε ένα Scene αντικείμενο, μπορείτε να περιηγηθείτε στην ιεραρχία των κόμβων και να διαβάσετε ακατέργαστα δεδομένα γεωμετρίας για κάθε πλέγμα στη σκηνή.
Οδηγός βήμα προς βήμα
Βήμα 1: Εγκατάσταση του πακέτου
Εγκαταστήστε το Aspose.3D FOSS από το PyPI. Δεν απαιτούνται πρόσθετες βιβλιοθήκες συστήματος.
pip install aspose-3d-fossΥποστηριζόμενες εκδόσεις του Python: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12.
Βήμα 2: Εισαγωγή της κλάσης Scene
Η Scene κλάση είναι το κορυφαίο κοντέινερ για όλα τα 3D δεδομένα. Εισάγετε την μαζί με οποιεσδήποτε κλάσεις επιλογών φόρτωσης χρειάζεστε.
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptionsΌλες οι δημόσιες κλάσεις βρίσκονται κάτω από aspose.threed ή τα υπο-πακέτα της (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).
Βήμα 3: Φόρτωση αρχείου
Χρησιμοποιήστε τη στατική Scene.from_file() μέθοδο για να ανοίξετε οποιαδήποτε υποστηριζόμενη μορφή. Η βιβλιοθήκη εντοπίζει τη μορφή αυτόματα από την επέκταση του αρχείου.
##Automatic format detection
scene = Scene.from_file("model.obj")Εναλλακτικά, δημιουργήστε ένα Scene αντίγραφο και καλέστε open(); χρήσιμο όταν θέλετε να περάσετε επιλογές φόρτωσης ή να διαχειριστείτε σφάλματα ρητά:
scene = Scene()
scene.open("model.obj")Και οι δύο μέθοδοι υποστηρίζουν αρχεία OBJ, STL (δυαδικά και ASCII), glTF 2.0 / GLB, COLLADA (DAE) και 3MF.
Βήμα 4: Διάσχιση κόμβων της σκηνής
Μια φορτωμένη σκηνή είναι ένα δέντρο από Node αντικείμενα με ρίζα στο scene.root_node. Επαναλάβετε αναδρομικά για να βρείτε όλους τους κόμβους:
from aspose.threed import Scene, Node
scene = Scene.from_file("model.obj")
def walk(node: Node, depth: int = 0) -> None:
indent = " " * depth
print(f"{indent}Node: {node.name!r}")
for child in node.child_nodes:
walk(child, depth + 1)
walk(scene.root_node)Κάθε Node μπορεί να μεταφέρει μηδέν ή περισσότερα Entity αντικείμενα (πλέγματα, κάμερες, φωτισμοί). Έλεγχος node.entities για να δείτε τι είναι συνδεδεμένο.
Βήμα 5: Πρόσβαση σε δεδομένα κορυφών και πολυγώνων
Μετατρέψτε την οντότητα ενός κόμβου σε Mesh και διαβάστε τα σημεία ελέγχου του (θέσεις κορυφών) και τα πολύγωνα (λίστες δεικτών προσώπων):
from aspose.threed import Scene
from aspose.threed.entities import Mesh
scene = Scene.from_file("model.obj")
for node in scene.root_node.child_nodes:
for entity in node.entities:
if isinstance(entity, Mesh):
mesh: Mesh = entity
print(f"Mesh '{node.name}': "
f"{len(mesh.control_points)} vertices, "
f"{len(mesh.polygons)} polygons")
# First vertex position
if mesh.control_points:
v = mesh.control_points[0]
print(f" First vertex: ({v.x:.4f}, {v.y:.4f}, {v.z:.4f})")
# First polygon face (list of control-point indices)
if mesh.polygons:
print(f" First polygon: {mesh.polygons[0]}")mesh.control_points είναι μια λίστα των Vector4 αντικείμενα; x, y, z μεταφέρουν τη θέση και w είναι η ομογενής συντεταγμένη (συνήθως 1.0).
mesh.polygons είναι μια λίστα λιστών ακεραίων, όπου κάθε εσωτερική λίστα είναι το διατεταγμένο σύνολο δεικτών σημείων ελέγχου για ένα πρόσωπο.
Βήμα 6: Εφαρμογή επιλογών φόρτωσης ειδικών για μορφή
Για λεπτομερή έλεγχο του τρόπου ερμηνείας ενός αρχείου OBJ, περάστε ένα ObjLoadOptions αντίγραφο σε scene.open():
from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions
options = ObjLoadOptions()
options.flip_coordinate_system = True # Convert right-hand Y-up to Z-up
options.scale = 0.01 # Convert centimetres to metres
options.enable_materials = True # Load .mtl material file
options.normalize_normal = True # Normalize all normals to unit length
scene = Scene()
scene.open("model.obj", options)Για αρχεία STL, η ισοδύναμη κλάση είναι StlLoadOptions. Για glTF, χρησιμοποιήστε GltfLoadOptions. Δείτε το αναφορά API για μια πλήρη λίστα.
Κοινά προβλήματα και διορθώσεις
FileNotFoundError κατά την κλήση Scene.from_file()
Η διαδρομή πρέπει να είναι απόλυτη ή σωστή σχετική με τον τρέχοντα φάκελο κατά την εκτέλεση. Χρησιμοποιήστε pathlib.Path για τη δημιουργία αξιόπιστων διαδρομών:
from pathlib import Path
from aspose.threed import Scene
path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))mesh.polygons είναι κενό μετά τη φόρτωση ενός αρχείου STL
Τα αρχεία STL αποθηκεύουν τρίγωνα ως ακατέργαστες όψεις, όχι ως ευρετηριακό πλέγμα. Μετά τη φόρτωση, τα πολύγωνα συντίθενται από αυτές τις όψεις. Αν polygons εμφανίζεται κενό, ελέγξτε len(mesh.control_points); εάν ο αριθμός είναι πολλαπλάσιο του 3, η γεωμετρία αποθηκεύεται σε μη ευρετηριακή μορφή και κάθε διαδοχικό τρίπτυχο κορυφών σχηματίζει ένα τρίγωνο.
Ασυμφωνία συστήματος συντεταγμένων (το μοντέλο φαίνεται περιστραμμένο ή κατοπτρισμένο)
Διαφορετικά εργαλεία χρησιμοποιούν διαφορετικές συμβάσεις (Y-up vs Z-up, αριστερόχειρο vs δεξιόχειρο). Ορίστε ObjLoadOptions.flip_coordinate_system = True ή εφαρμόστε μια περιστροφή στο ριζικό κόμβου Transform μετά τη φόρτωση.
AttributeError: 'NoneType' object has no attribute 'polygons'
Η λίστα οντοτήτων ενός κόμβου μπορεί να περιέχει οντότητες που δεν είναι πλέγμα (κάμερες, φωτισμοί). Πάντα προστατεύστε με isinstance(entity, Mesh) πριν από τη μετατροπή τύπου.
Συχνές Ερωτήσεις (FAQ)
Ποια 3D φορμάτ μπορώ να φορτώσω;?
OBJ (Wavefront), STL (δυαδικό και ASCII), glTF 2.0 / GLB, COLLADA (DAE) και 3MF. Η τοκενικοποίηση αρχείων FBX υποστηρίζεται μερικώς, αλλά η πλήρης ανάλυση δεν είναι ακόμη ολοκληρωμένη.
Φορτώνει η φόρτωση ενός αρχείου OBJ επίσης το .mtl υλικό;?
Ναι, όταν ObjLoadOptions.enable_materials = True (η προεπιλογή). Η βιβλιοθήκη ψάχνει για το .mtl αρχείο στον ίδιο φάκελο με το .obj αρχείο. Εάν το .mtl λείπει, η γεωμετρία φορτώνεται ακόμη και εκδίδεται μια προειδοποίηση.
Μπορώ να φορτώσω ένα αρχείο από ροή byte αντί για διαδρομή;?
Ναι. scene.open() δέχεται οποιοδήποτε αντικείμενο τύπου αρχείου με ένα .read() μέθοδο εκτός από μια συμβολοσειρά διαδρομής αρχείου. Περνάτε ένα ανοιχτό δυαδικό ρεύμα (π.χ., io.BytesIO) απευθείας. Scene.from_file() αποδέχεται μόνο μια συμβολοσειρά διαδρομής αρχείου.
Πώς μπορώ να λάβω τις κανονικές επιφάνειας;?
Μετά τη φόρτωση, ελέγξτε mesh.get_element(VertexElementType.NORMAL). Αυτό επιστρέφει ένα VertexElementNormal του οποίου data η λίστα περιέχει ένα κανονικό διάνυσμα ανά αναφορά, χαρτογραφημένο σύμφωνα με mapping_mode και reference_mode.
from aspose.threed.entities import Mesh, VertexElementType
normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
print(normals.data[0]) # First normal vectorΕίναι η βιβλιοθήκη thread-safe για τη φόρτωση πολλαπλών αρχείων ταυτόχρονα;?
Κάθε Scene το αντικείμενο είναι ανεξάρτητο. Φόρτωση ξεχωριστών αρχείων σε ξεχωριστά Scene αντιπροσωπείες από ξεχωριστά νήματα είναι ασφαλείς εφόσον δεν μοιράζεστε ένα μόνο Scene μεταξύ νημάτων χωρίς εξωτερικό κλείδωμα.