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-fossImportējiet vajadzīgās klases:
from aspose.threed import Scene
from aspose.threed.entities import MeshVisas 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ēma | Risinā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 agri | Pā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ātos | Pā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ību | Izmantojiet 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 STL | STL 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 virknes | Daž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ī.