Kā pārlūkot 3D ainas grafu Python

Kā pārlūkot 3D ainas grafu Python

Ainas grafiks Aspose.3D FOSS ir koks no Node objektu, kura sakne ir scene.root_node. Katrs 3D fails, neatliekot to no OBJ, glTF, STL, COLLADA vai 3MF, izveido vienu un to pašu koka struktūru. Zinot, kā to pārlūkot, ļauj pārbaudīt ģeometriju, saskaitīt daudzstūrus, filtrēt objektus pēc tipa un apstrādāt konkrētas sarežģītas ainas daļas.

Solī pa solim rokasgrāmata

1. solis: Instalēšana un importēšana

Instalējiet Aspose.3D FOSS no PyPI:

pip install aspose-3d-foss

Importējiet vajadzīgās klases:

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

Visas publiskās klases atrodas zem aspose.threed vai tās apakšpakotnēs (aspose.threed.entities, aspose.threed.utilities).


2. solis: Ielādēt scēnu no faila

Izmantojiet statisko Scene.from_file() metodi, lai atvērtu jebkuru atbalstītu formātu. Formāts tiek automātiski noteikts no faila paplašinājuma:

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

Varat arī atvērt, norādot konkrētas ielādes opcijas:

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

options = ObjLoadOptions()
options.enable_materials = True

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

Pēc ielādes, scene.root_node ir koka sakne. Visi importētie mezgli ir šī mezgla bērni vai pēcnācēji.


3. solis: Uzrakstīt rekursīvu pārlūkošanas funkciju

Visvienkāršākā pārlūkošana apmeklē katru mezglu dziļuma pirmās kārtas secībā:

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)

Piemēra izvada rezultāts:

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

Piezīme: Saknes mezglam ir tukšs nosaukums (""), tāpēc pirmajā rindā tiek parādīts [-] bez nosaukuma pēc tam.

node.child_nodes atgriež bērnus ievietošanas secībā (secībā, kādā importētājs vai lietotājs tos pievienoja).


4. solis: Piekļūt entītiju īpašībām katrā mezglā

Izmantojiet node.entity lai iegūtu pirmo vienību, kas pievienota mezglam, vai node.entities lai iterētu visus tos. Pārbaudiet tipu pirms piekļuves formāta specifiskām īpašībām:

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, un node.transform.scaling dod lokālo telpas transformāciju. node.global_transform sniedz novērtēto pasaules telpas rezultātu (ar global_transform.scale pasaules telpas mērogam).


5. solis: Filtrēt mezglus pēc vienības tipa

Lai darbinātu tikai uz konkrētiem entītiju tipiem, pievienojiet isinstance aizsargu traversēšanas laikā:

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}")

Šis modelis ir noderīgs masveida operācijām: transformācijas piemērošanai katram Mesh mezglam, materiālu aizstāšanai vai apakškoku eksportēšanai.


6. solis: Savākt visus Mesh un izdrukāt virsotņu skaitus

Apkopot Mesh statistiku vienā gājienā:

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

Biežāk sastopamās problēmas

ProblēmaRisinājums
AttributeError: 'NoneType' object has no attribute 'polygons'Aizsargāt ar if node.entity is not None vai isinstance(node.entity, Mesh) pirms piekļūšanas režģa īpašībām. Mezgli bez entītijām atgriež None.
Traversēšana apstājas agriPārliecinieties, ka rekursija sasniedz node.child_nodes. Ja iterējat tikai scene.root_node.child_nodes (ne rekursīvi), jūs izlaidīsiet visus pēcnācējus.
Režģis trūkst savāktajos rezultātosPārbaudiet, vai faila formāts saglabā hierarhiju. OBJ izlīdzina visu ģeometriju vienā mezgla līmenī. Izmantojiet glTF vai COLLADA dziļām hierarhijām.
node.entity atgriež tikai pirmo vienībuIzmantojiet node.entities (pilns saraksts), ja mezgls satur vairākas vienības. node.entity ir saīsinājums priekš node.entities[0] kad entities nav tukšs.
collect_meshes atgriež 0 rezultātus ielādētam STLSTL faili parasti izveido vienu plakanu mezglu ar vienu režģa vienību tieši zem root_node. Pārbaudiet root_node.child_nodes[0].entity tieši.
Mezglu nosaukumi ir tukši virknesDaži formāti (binārais STL, daži OBJ faili) nesaglabā objektu nosaukumus. Mezgliem būs tukši name virknes; tā vietā izmantojiet indeksu identificēšanai.

Biežāk uzdotie jautājumi

Cik dziļa var būt ainas grafiks?

Nav stingra ierobežojuma. Python noklusējuma rekursijas limits (1000 kadri) attiecas uz rekursīvajām pārvietošanas funkcijām. Ļoti dziļām hierarhijām pārvērtiet rekursiju par skaidri definētu steku:

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

Vai varu modificēt koku, kamēr to pārvietoju?

Neievietojiet vai noņemiet mezglus no child_nodes tā iterējot. Savāciet mezglus, kurus modificēt, pirmajā caurgriezumā, pēc tam veiciet izmaiņas otrajā caurgriezumā.

Kā atrast konkrētu mezglu pēc nosaukuma?

Izmantojiet node.get_child(name) lai atrastu tiešu bērnu pēc nosaukuma. Lai veiktu dziļu meklēšanu, pārlūkojiet koku ar nosaukuma filtru:

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

Vai node.entity vienmēr atgriež Mesh?

Nē. Mezgls var saturēt jebkuru vienības veidu: Mesh, Camera, Light, vai pielāgotas vienības. Vienmēr pārbaudiet ar isinstance(node.entity, Mesh) pirms izmantot mesh-specifiskas īpašības.

Kā iegūt mezgla pozīciju pasaules telpā?

Lasīt node.global_transform.translation. Šī ir aprēķinātā pozīcija pasaules telpā, ņemot vērā visus priekšgājēju transformācijas. Tā ir tikai lasāma; modificējiet node.transform.translation lai pārvietotu mezglu.

Vai es varu saskaitīt kopējo daudzstūru skaitu ainas, nepievienojot traversēšanas rakstīšanas?

Ne tieši caur API; nav scene.total_polygon_count īpašības. Izmantojiet collect_meshes un saskaitiet mesh.polygon_count visā rezultātos, kā parādīts 6. solī.

 Latviešu