Python에서 3D 장면 그래픽을 통과하는 방법
Aspose.3D FOSS의 장면 그래픽은 나무의 Node 뿌리 잡힌 물체들에 대하여 scene.root_node.모든 3D 파일, OBJ, glTF, STL, COLLADA 또는 3MF에서 충전되든 동일한 나무 구조를 생성합니다.이를 통과하는 방법을 아는 것은 지질학을 검사하고, 폴리곤을 계산하고 , 유형에 따라 개체를 필터링하고 복잡한 장면의 특정 부분을 처리 할 수 있습니다.
단계별 가이드
단계 1 : 설치 및 수입
PyPI에서 Aspose.3D FOSS를 설치하십시오 :
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 팩스 하드웨어 (Subpackage)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 직접적으로 니다. |
| 노드 이름은 빈 스트립입니다. | 일부 형식 (비나리 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 언제나 메시지를 반환하나요?
No. 노드는 어떤 유형의 단체를 보유할 수 있습니다 : 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에서 보여준 것처럼.