Πώς να περάσετε ένα 3D σκηνικό γραφικά στο Python

Πώς να περάσετε ένα 3D σκηνικό γραφικά στο Python

Το γραφικό σκηνής στο Aspose.3D FOSS είναι ένα δέντρο του Node αντικείμενα που ριζώνουν σε scene.root_node.Κάθε αρχείο 3D, είτε φορτώθηκε από OBJ, glTF, STL, COLLADA ή 3MF , παράγει την ίδια δομή δέντρου. Γνωρίζοντας πώς να περάσει το επιτρέπει να ελέγξετε τη γεωμετρία, να μετράτε πολυγόνες, τα αντικείμενα φιλτραρίσματος ανά τύπο και να επεξεργαστείτε συγκεκριμένα μέρη μιας σύνθετης σκηνής.

Βήμα προς βήμα οδηγός

Βήμα 1: Εγκατάσταση και εισαγωγή

Εισάγετε το Aspose.3D FOSS από την PyPI:

asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.

Εισαγωγή των τάξεων που χρειάζεστε:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

Όλες οι δημόσιες τάξεις ζουν κάτω από το aspose.threed και τα υποσυσκευαστικά του (aspose.threed.entities, aspose.threed.utilities).


Βήμα 2: Κατεβάστε μια σκηνή από ένα αρχείο

Χρησιμοποιήστε το στατικό Scene.from_file() Η μέθοδος για να ανοίξετε οποιαδήποτε υποστηριζόμενη μορφή.Η μορφοποίηση ανιχνεύεται αυτόματα από την επέκταση αρχείου:

scene = Scene.from_file("model.gltf")

Μπορείτε επίσης να ανοίξετε με τις επιλογές εκφραστικής φόρτωσης:

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

options = ObjLoadOptions()
options.enable_materials = True

scene = Scene()
scene.open("model.obj", options)

Μετά την φόρτιση, scene.root_node Όλα τα εισαγόμενα κόμβα είναι παιδιά ή απογόνους αυτού του κόμματος.


Βήμα 3: Γράψτε μια αναδρομική ταξιδιωτική λειτουργία

Η πιο απλή διαδρομή επισκέπτεται κάθε κόμβο σε πρώτη σειρά:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def traverse(node, depth=0):
    prefix = "  " * depth
    entity_name = type(node.entity).__name__ if node.entity else "-"
    print(f"{prefix}[{entity_name}] {node.name}")
    for child in node.child_nodes:
        traverse(child, depth + 1)

scene = Scene.from_file("model.gltf")
traverse(scene.root_node)

Παραδείγματα παραγωγής:

[-]
  [-] Armature
    [Mesh] Body
    [Mesh] Eyes
  [-] Ground
    [Mesh] Plane

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

Σημείωση : Το κενό έχει ένα άδειο όνομα (""1) Η πρώτη γραμμή δείχνει [-] χωρίς όνομα που ακολουθεί.

node.child_nodes επιστρέφει τα παιδιά σε εντολή εισαγωγής (η εντολής στην οποία ο εισαγγελέας ή ο χρήστης τους προσθέτει).


Βήμα 4: Πρόσβαση σε ιδιότητες οντότητας σε κάθε κόμβο

Χρησιμοποιήστε node.entity να λάβει την πρώτη οντότητα συνδεδεμένη σε ένα κόμβο, ή node.entities Για να τα ιταρίσετε όλα. ελέγξτε τον τύπο πριν από την πρόσβαση σε ιδιότητες που είναι ειδικές για μορφή:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def print_entity_details(node, depth=0):
    indent = "  " * depth
    for entity in node.entities:
        if isinstance(entity, Mesh):
            mesh = entity
            print(f"{indent}Mesh '{node.name}':")
            print(f"{indent}  vertices  : {len(mesh.control_points)}")
            print(f"{indent}  polygons  : {mesh.polygon_count}")
            print(f"{indent}  cast_shadows   : {mesh.cast_shadows}")
            print(f"{indent}  receive_shadows: {mesh.receive_shadows}")
    for child in node.child_nodes:
        print_entity_details(child, depth + 1)

scene = Scene.from_file("model.gltf")
print_entity_details(scene.root_node)

node.transform.translation, node.transform.rotation,και node.transform.scaling Να μεταμορφώσουμε τον τοπικό χώρο. node.global_transform δίνει το αξιολογημένο αποτέλεσμα του κόσμου (με global_transform.scale για την παγκόσμια κλίμακα).


Βήμα 5: Φιλτράρετε τα κενά ανά τύπο οντότητας

Για να λειτουργεί μόνο σε συγκεκριμένους τύπους οντοτήτων, προσθέστε ένα isinstance Η διαφύλαξη μέσα στο πέρασμα:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def find_mesh_nodes(node, results=None):
    if results is None:
        results = []
    for entity in node.entities:
        if isinstance(entity, Mesh):
            results.append(node)
            break   # One match per node is enough
    for child in node.child_nodes:
        find_mesh_nodes(child, results)
    return results

scene = Scene.from_file("model.gltf")
mesh_nodes = find_mesh_nodes(scene.root_node)
print(f"Found {len(mesh_nodes)} mesh node(s)")
for n in mesh_nodes:
    print(f"  {n.name}")

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


Βήμα 6: Συλλέξτε όλες τις μάζες και εκτυπώστε τα κέρματα Vertex

Συγκεντρώστε τα στατιστικά στοιχεία με ένα μόνο πέρασμα:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def collect_meshes(node, results=None):
    if results is None:
        results = []
    if isinstance(node.entity, Mesh):
        results.append((node.name, node.entity))
    for child in node.child_nodes:
        collect_meshes(child, results)
    return results

scene = Scene.from_file("model.gltf")
meshes = collect_meshes(scene.root_node)

print(f"Total meshes: {len(meshes)}")
total_verts = 0
total_polys = 0

for name, mesh in meshes:
    verts = len(mesh.control_points)
    polys = mesh.polygon_count
    total_verts += verts
    total_polys += polys
    print(f"  {name}: {verts} vertices, {polys} polygons")

print(f"Scene totals: {total_verts} vertices, {total_polys} polygons")

κοινά ζητήματα

ΘέμαΨήφισμα
AttributeError: 'NoneType' object has no attribute 'polygons'Φύλαξη με if node.entity is not None ή isinstance(node.entity, Mesh) πριν από την πρόσβαση σε ιδιότητες μασχ. Σημεία χωρίς οντότητες επιστροφή None.
Ταξιδεύουν νωρίςΝα διασφαλιστεί ότι η αναδρομή φτάνει στο node.child_nodes.Αν το απλώς ερμηνεύεις scene.root_node.child_nodes (Δεν επαναλαμβάνετε), λείπουν όλοι οι απογόνες σας.
Απαλλαγή από τα συλλεχθέντα αποτελέσματαΒεβαιωθείτε ότι η μορφή αρχείου διατηρεί την ιεραρχία. OBJ στρέφει όλη τη γεωμετρία σε ένα επίπεδο κόμβου. Χρησιμοποιήστε glTF ή COLLADA για βαθιές ιοραξίες.
node.entity Επέστρεψε μόνο την πρώτη οντότητα.Χρησιμοποιήστε node.entities (η πλήρης λίστα) όταν ένα κόμβο φέρει πολλαπλές οντότητες. node.entity Είναι ένα μικρό χέρι για node.entities[0] Όταν entities Είναι άδικο.
collect_meshes Επιστρέφει 0 αποτελέσματα για ένα φορτισμένο STLΤα αρχεία STL συνήθως παράγουν ένα ενιαίο επίπεδη κόμβο με μία οντότητα μασής απευθείας κάτω από το root_node.Ελέγξτε root_node.child_nodes[0].entity απευθείας .
Τα ονόματα των κόμβων είναι άδειες γραμμέςΟρισμένες μορφές (binary STL, ορισμένα αρχεία OBJ) δεν αποθηκεύουν ονόματα αντικειμένων. name Σημειώνεται ότι χρησιμοποιεί τον δείκτη για την αναγνώριση.

Συχνές ερωτήσεις

Πόσο βαθιά μπορεί να είναι ένα γραφείο σκηνής;?

Δεν υπάρχει σκληρός όρος. ο προεπιλεγμένος όγκος αναδρομίας του Python (1000 πλαίσια) ισχύει για τις αναδυόμενες διασταυρωτικές λειτουργίες. Για πολύ βαθιές ιεραρχίες, μετατρέψτε την ανακάλυψη σε μια σαφή γραμμή:

from collections import deque
from aspose.threed import Scene

scene = Scene.from_file("deep.gltf")
queue = deque([(scene.root_node, 0)])

while queue:
    node, depth = queue.popleft()
    print("  " * depth + node.name)
    for child in node.child_nodes:
        queue.append((child, depth + 1))

Μπορώ να αλλάξω το δέντρο ενώ περνάω;?

Μην προσθέτετε ή αφαιρέστε κόντρα από το child_nodes Συλλέξτε τα κόμβα για να τροποποιήσετε σε ένα πρώτο πέρασμα, στη συνέχεια εφαρμόστε αλλαγές σε μια δεύτερη πέρασή.

Πώς μπορώ να βρω ένα συγκεκριμένο κόμβο με το όνομα;?

Χρησιμοποιήστε node.get_child(name) Για μια βαθιά αναζήτηση, διασχίστε το δέντρο με ένα φίλτρο ονόματος:

def find_by_name(root, name):
    if root.name == name:
        return root
    for child in root.child_nodes:
        result = find_by_name(child, name)
        if result:
            return result
    return None

target = find_by_name(scene.root_node, "Wheel_FL")

Η ΚΕ node.entity Πάντα επιστρέφει ένα μαστίκι;?

Ένα κόμβο μπορεί να έχει οποιοδήποτε είδος οντότητας: Mesh, Camera, Light,ΕΝΑ ΠΟΛΙΤΙΚΟ ΑΡΘΡΟ.Πάντα ελέγξτε με isinstance(node.entity, Mesh) πριν από τη χρήση ειδικών ιδιότητες.

Πώς μπορώ να πάρω τη θέση του κόσμου-διαστημικού ενός κόμβου;?

Διαβάστε node.global_transform.translation.Αυτή είναι η αξιολογημένη θέση στο παγκόσμιο διάστημα, με βάση όλες τις μετασχηματιστικές προγόνες. node.transform.translation Να επαναφέρει το κόμβο.

Μπορώ να μετρήσω τα πλήρη πολυγόνους σε μια σκηνή χωρίς να γράψω ένα διασταύρωση;?

Όχι απευθείας μέσω της API, δεν υπάρχει scene.total_polygon_count Ιδιοκτησία - Χρήση collect_meshes και το sum mesh.polygon_count Τα αποτελέσματα, όπως δείχνουν στο βήμα 6.

 Ελληνικά