Python에서 3D 장면 그래픽을 통과하는 방법

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 결과를 반환합니다 충전된 STLSTL 파일은 일반적으로 한 개의 메시 센티브를 가진 단일 평면 노드를 직접 아래로 생성합니다. 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에서 보여준 것처럼.

 한국어