Πώς να φορτώσετε 3D μοντέλα σε Python

Πώς να φορτώσετε 3D μοντέλα σε Python

Aspose.3D FOSS for 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, left-hand vs right-hand). Ορίστε ObjLoadOptions.flip_coordinate_system = True ή εφαρμόστε μια περιστροφή στο Transform του ριζικού κόμβου μετά τη φόρτωση.

AttributeError: 'NoneType' object has no attribute 'polygons'

Η λίστα οντοτήτων ενός κόμβου μπορεί να περιέχει μη‑πλέγμα οντότητες (κάμερες, φωτισμούς). Πάντα να προστατεύετε με isinstance(entity, Mesh) πριν από τη μετατροπή.


Συχνές Ερωτήσεις (FAQ)

Ποια 3D μορφές μπορώ να φορτώσω;

OBJ (Wavefront), STL (binary and 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 μεταξύ των νημάτων χωρίς εξωτερικό κλείδωμα.

 Ελληνικά