기능 및 특성

Aspose.3D FOSS for Python은(는) 여러 산업 표준 포맷으로 3D 콘텐츠를 읽고, 구성하고, 쓰기 위한 완전한 씬 그래프 API를 제공합니다. 이 페이지에서는 실제 라이브러리 API를 사용하는 작동하는 Python 코드 예제와 함께 모든 주요 기능 영역을 문서화합니다.

설치 및 설정

단일 명령으로 PyPI에서 라이브러리를 설치합니다:

pip install aspose-3d-foss

추가 시스템 패키지, 네이티브 확장, 또는 컴파일러 툴체인이 필요하지 않습니다. 이 라이브러리는 순수 Python이며 Windows, macOS, Linux에서 Python 3.7부터 3.12까지를 지원합니다.

설치를 확인하려면:

from aspose.threed import Scene

scene = Scene()
print("Aspose.3D FOSS installed successfully")
print(f"Root node name: {scene.root_node.name}")

기능 및 특성

포맷 지원

Aspose.3D FOSS for Python은(는) 다음 포맷을 읽고 씁니다:

포맷확장자읽기쓰기비고
Wavefront OBJ.obj.mtl 재질 로드 지원
STL (바이너리).stl라운드트립 검증 (39 테스트)
STL (ASCII).stl라운드트립 검증
glTF 2.0.gltf전체 씬 그래프가 보존됩니다
GLB (바이너리 glTF).glb단일 파일 바이너리 컨테이너
COLLADA.dae씬 계층 구조 및 재질
3MF.3mf적층 제조 형식
FBX.fbx부분적아니오Tokenizer는 작동하지만 parser에는 알려진 버그가 있습니다

옵션을 사용한 OBJ 로드

ObjLoadOptions OBJ 파일이 파싱되는 방식을 제어합니다:

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

options = ObjLoadOptions()
options.enable_materials = True        # Load accompanying .mtl file
options.flip_coordinate_system = False # Preserve original handedness
options.normalize_normal = True        # Normalize vertex normals to unit length
options.scale = 1.0                    # Apply a uniform scale factor at load time

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

print(f"Loaded {len(scene.root_node.child_nodes)} top-level nodes")

STL 저장

StlSaveOptions 바이너리와 ASCII 출력 및 기타 STL 전용 설정을 제어합니다:

from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions

scene = Scene.from_file("model.obj")
options = StlSaveOptions()
scene.save("output.stl", options)

씬 그래프

모든 3D 콘텐츠는 트리 형태로 구성됩니다 Node 객체들. 트리의 루트는 scene.root_node. 모든 노드는 자식 노드를 포함할 수 있고, 그리고 Entity (mesh, camera, or light)와 Transform.

씬 계층 구조 탐색

from aspose.threed import Scene

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

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

traverse(scene.root_node)

프로그래밍 방식으로 씬 구축

from aspose.threed import Scene, Node, Entity
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3

scene = Scene()
root = scene.root_node

##Create a child node and position it
child = root.create_child_node("my_object")
child.transform.translation = Vector3(1.0, 0.0, 0.0)
child.transform.scaling = Vector3(2.0, 2.0, 2.0)

scene.save("constructed.glb")

GlobalTransform 검사

GlobalTransform 모든 조상 변환을 누적한 후 노드의 월드 공간 변환을 제공합니다:

from aspose.threed import Scene

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

for node in scene.root_node.child_nodes:
    gt = node.global_transform
    print(f"Node: {node.name}")
    print(f"  World translation: {gt.translation}")
    print(f"  World scale: {gt.scale}")

Mesh API

Mesh 엔터티는 제어점(버텍스), 폴리곤 및 노멀, UV, 색상용 버텍스 요소를 포함한 기하학 데이터에 대한 접근을 제공합니다.

Mesh 기하학 읽기

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

options = ObjLoadOptions()
options.enable_materials = True
options.flip_coordinate_system = False

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

for node in scene.root_node.child_nodes:
    if node.entity is None:
        continue
    mesh = node.entity
    print(f"Mesh: {node.name}")
    print(f"  Vertices: {len(mesh.control_points)}")
    print(f"  Polygons: {len(mesh.polygons)}")

버텍스 요소 접근

버텍스 요소는 버텍스당 또는 폴리곤당 데이터를 담고 있습니다. 가장 일반적인 요소는 노멀, UV 좌표, 버텍스 색상, 그리고 스무딩 그룹입니다:

from aspose.threed import Scene
from aspose.threed.entities import VertexElementNormal, VertexElementUV

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

for node in scene.root_node.child_nodes:
    if node.entity is None:
        continue
    mesh = node.entity

    # Iterate vertex elements to find normals and UVs
    for element in mesh.vertex_elements:
        if isinstance(element, VertexElementNormal):
            print(f"  Normals count: {len(element.data)}")
        elif isinstance(element, VertexElementUV):
            print(f"  UV count: {len(element.data)}")

Material System

Aspose.3D FOSS는 두 가지 재질 유형을 지원합니다: LambertMaterial (diffuse shading) 및 PhongMaterial (specular shading). 두 경우 모두 .mtl 파일에서 자동으로 로드됩니다, 사용할 때 ObjLoadOptionsenable_materials = True.

OBJ에서 머티리얼 읽기

from aspose.threed import Scene
from aspose.threed.shading import LambertMaterial, PhongMaterial
from aspose.threed.formats import ObjLoadOptions

options = ObjLoadOptions()
options.enable_materials = True

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

for node in scene.root_node.child_nodes:
    mat = node.material
    if mat is None:
        continue
    print(f"Node: {node.name}")
    if isinstance(mat, PhongMaterial):
        print(f"  Type: Phong")
        print(f"  Diffuse: {mat.diffuse_color}")
        print(f"  Specular: {mat.specular_color}")
    elif isinstance(mat, LambertMaterial):
        print(f"  Type: Lambert")
        print(f"  Diffuse: {mat.diffuse_color}")

프로그래밍 방식으로 머티리얼 할당

from aspose.threed import Scene, Node
from aspose.threed.shading import PhongMaterial
from aspose.threed.utilities import Vector3

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

material = PhongMaterial()
material.diffuse_color = Vector3(0.8, 0.2, 0.2)   # Red diffuse
material.specular_color = Vector3(1.0, 1.0, 1.0)  # White specular

##Apply to the first mesh node
for node in scene.root_node.child_nodes:
    if node.entity is not None:
        node.material = material
        break

scene.save("recolored.glb")

수학 유틸리티

aspose.threed.utilities 모듈은 씬 구성 및 검사를 위해 필요한 모든 기하학 수학 타입을 제공합니다.

클래스목적
Vector22D floating-point vector (UV coordinates)
Vector33D double-precision vector (positions, normals)
Vector44D double-precision vector (homogeneous coordinates)
FVector33D single-precision vector (compact storage)
Quaternion짐벌 락 없이 회전 표현
Matrix44×4 transformation matrix
BoundingBox최소/최대 코너를 갖는 축 정렬 경계 상자

변환 작업

from aspose.threed.utilities import Vector3, Quaternion, Matrix4
import math

##Build a rotation quaternion from axis-angle
axis = Vector3(0.0, 1.0, 0.0)          # Y-axis
angle_rad = math.radians(45.0)
q = Quaternion.from_angle_axis(angle_rad, axis)

print(f"Quaternion: x={q.x:.4f} y={q.y:.4f} z={q.z:.4f} w={q.w:.4f}")

##Convert to rotation matrix
mat = q.to_matrix()
print(f"Rotation matrix row 0: {mat[0, 0]:.4f} {mat[0, 1]:.4f} {mat[0, 2]:.4f}")

바운딩 박스 계산

from aspose.threed import Scene

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

# NOTE: mesh.get_bounding_box() is a stub — it always returns an empty BoundingBox()
# regardless of geometry. Compute bounds manually from control_points:
for node in scene.root_node.child_nodes:
    if node.entity is None:
        continue
    mesh = node.entity
    pts = mesh.control_points  # returns a copy of the vertex list
    if not pts:
        continue
    xs = [p.x for p in pts]
    ys = [p.y for p in pts]
    zs = [p.z for p in pts]
    print(f"Mesh: {node.name}")
    print(f"  Min: ({min(xs):.3f}, {min(ys):.3f}, {min(zs):.3f})")
    print(f"  Max: ({max(xs):.3f}, {max(ys):.3f}, {max(zs):.3f})")

애니메이션

Aspose.3D FOSS는 기반의 애니메이션 모델을 제공합니다 AnimationClip, AnimationNode, KeyFrame, 및 KeyframeSequence. 로드된 파일(glTF, COLLADA)에 저장된 애니메이션 데이터는 이러한 객체를 통해 접근할 수 있습니다.

애니메이션 클립 읽기

from aspose.threed import Scene

scene = Scene.from_file("animated.glb")

for clip in scene.animation_clips:
    print(f"Clip: {clip.name}  ({clip.start:.2f}s – {clip.stop:.2f}s)")
    for anim_node in clip.animations:
        print(f"  Animation node: {anim_node.name}")
        for sub in anim_node.sub_animations:
            print(f"    Sub-animation: {sub.name}")
        for bp in anim_node.bind_points:
            print(f"    Bind point: {bp.name}")

로드 및 저장 옵션

지원되는 모든 포맷은 파싱 및 직렬화 동작을 제어하는 해당 옵션 클래스를 가지고 있습니다.

클래스포맷핵심 속성
ObjLoadOptionsOBJenable_materials, flip_coordinate_system, normalize_normal, scale
StlSaveOptionsSTL바이너리 vs. ASCII 출력 모드
(glTF는 기본값을 사용합니다)glTF / GLB장면 그래프와 재질이 자동으로 보존됩니다.

사용 예시

예제 1: OBJ를 STL 포맷으로 변환

OBJ 파일(재질 포함)을 바이너리 STL로 변환하고, 진행 중에 메시 통계를 출력합니다:

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

##Load OBJ with material support
load_opts = ObjLoadOptions()
load_opts.enable_materials = True
load_opts.flip_coordinate_system = False
load_opts.normalize_normal = True

scene = Scene()
scene.open("input.obj", load_opts)

##Report what was loaded
total_vertices = 0
total_polygons = 0
for node in scene.root_node.child_nodes:
    if node.entity is not None:
        mesh = node.entity
        total_vertices += len(mesh.control_points)
        total_polygons += len(mesh.polygons)
        print(f"  {node.name}: {len(mesh.control_points)} vertices, {len(mesh.polygons)} polygons")

print(f"Total: {total_vertices} vertices, {total_polygons} polygons")

##Save as STL
save_opts = StlSaveOptions()
scene.save("output.stl", save_opts)
print("Saved output.stl")

예제 2: 배치 glTF를 GLB로 패킹

별도의 glTF + 텍스처 파일이 있는 디렉터리를 자체 포함된 GLB 바이너리로 다시 저장합니다:

import os
from aspose.threed import Scene

input_dir = "gltf_files"
output_dir = "glb_files"
os.makedirs(output_dir, exist_ok=True)

for filename in os.listdir(input_dir):
    if not filename.endswith(".gltf"):
        continue
    src = os.path.join(input_dir, filename)
    dst = os.path.join(output_dir, filename.replace(".gltf", ".glb"))
    scene = Scene.from_file(src)
    scene.save(dst)
    print(f"Packed {filename} -> {os.path.basename(dst)}")

예제 3: 씬 그래프 검사 및 내보내기 보고서

COLLADA 파일의 씬 그래프를 순회하고, 메쉬별 통계를 수집한 뒤 구조화된 보고서를 출력합니다:

from aspose.threed import Scene

scene = Scene.from_file("assembly.dae")

report = []

def collect(node, path=""):
    full_path = f"{path}/{node.name}" if node.name else path
    if node.entity is not None:
        mesh = node.entity
        gt = node.global_transform
        report.append({
            "path": full_path,
            "vertices": len(mesh.control_points),
            "polygons": len(mesh.polygons),
            "world_x": gt.translation.x,
            "world_y": gt.translation.y,
            "world_z": gt.translation.z,
        })
    for child in node.child_nodes:
        collect(child, full_path)

collect(scene.root_node)

print(f"{'Path':<40} {'Verts':>6} {'Polys':>6} {'X':>8} {'Y':>8} {'Z':>8}")
print("-" * 78)
for entry in report:
    print(
        f"{entry['path']:<40} "
        f"{entry['vertices']:>6} "
        f"{entry['polygons']:>6} "
        f"{entry['world_x']:>8.3f} "
        f"{entry['world_y']:>8.3f} "
        f"{entry['world_z']:>8.3f}"
    )

팁 및 모범 사례

포맷 선택

  • glTF 2.0 / GLB 재질, 애니메이션 및 복잡한 계층 구조를 포함하는 장면에 권장되는 교환 형식입니다. 이식성을 위해 glTF(텍스트 + 외부 파일)보다 GLB(바이너리)를 선호하십시오.
  • STL 다운스트림 사용자가 슬라이서, CAD 도구 또는 기하학만 필요한 도구인 경우 올바른 선택입니다. STL은 재질이나 애니메이션 데이터를 포함하지 않습니다.
  • OBJ 광범위하게 지원되며 재질 데이터를 오래된 도구와 교환해야 할 때 좋은 선택입니다. .obj 파일과 함께 .mtl 파일을 항상 보관하십시오.

좌표계

  • 다양한 애플리케이션이 서로 다른 손잡이 규칙을 사용합니다. 설정하십시오 ObjLoadOptions.flip_coordinate_system = True 파이프라인이 왼손 좌표계를 기대하는 경우 오른손 좌표계를 사용하는 도구에서 OBJ 파일을 가져올 때 설정하고, 그 반대의 경우에도 마찬가지입니다.
  • 플립을 적용하기 전에 원본 에셋의 축 규칙을 확인하세요. 두 번 플립하면 잘못된 기하학이 생성됩니다.

정규화

  • 항상 설정하십시오 ObjLoadOptions.normalize_normal = True 다운스트림 파이프라인이 단위 법선을 기대할 때(예: 법선을 셰이더에 전달하거나 내적 조명 계산을 수행할 때). 형식이 잘못된 OBJ 파일의 정규화되지 않은 법선은 조명 아티팩트를 일으킵니다.

성능

  • 파일을 한 번만 로드하고 메모리 내 장면 그래프를 변환하십시오. 각 출력 형식마다 디스크에서 다시 로드하는 대신. 단일 Scene.from_file() 호출에 이어 여러 scene.save() 호출이 반복 로드보다 더 효율적입니다.
  • 대량 배치를 처리할 때, 단일 ObjLoadOptions 또는 StlSaveOptions 인스턴스를 생성하고 파일마다 새로운 옵션 객체를 만드는 대신 모든 파일에 재사용하십시오.

오류 처리

  • 감싸기 scene.open()scene.save() 호출을 try/except 신뢰할 수 없거나 사용자 제공 파일을 처리할 때 블록합니다. 예외 메시지에 파일 이름을 보고하여 배치 파이프라인에서 디버깅을 단순화합니다.

일반적인 문제

문제원인해결책
로드 후 메시가 좌우 반전된 것처럼 보임좌표계 손잡이 불일치전환 ObjLoadOptions.flip_coordinate_system
노멀 벡터가 길이 0임원본 파일에 정규화되지 않은 노멀 존재설정 ObjLoadOptions.normalize_normal = True
OBJ에서 재질이 로드되지 않음enable_materialsFalse (기본값)설정 ObjLoadOptions.enable_materials = True
씬은 로드되지만 모든 노드가 비어 있음파일이 FBX 형식을 사용함FBX 파서는 현재 개발 중이며, 대신 OBJ, STL 또는 glTF를 사용하십시오
모델이 매우 작거나 큽니다소스 파일이 비미터법 단위를 사용합니다적용 ObjLoadOptions.scale 대상 단위로 변환하려면
AttributeError 켜짐 mesh.polygons노드 엔터티가 메시가 아닙니다.다음으로 보호 if node.entity is not None 엔터티 속성에 접근하기 전에
GLB 파일이 뷰어에 의해 거부되었습니다.다음으로 저장됨 .gltf 확장자사용 .glb 호출 시 확장자 scene.save() 바이너리 컨테이너를 트리거하려면

자주 묻는 질문

지원되는 Python 버전은 무엇입니까? Python 3.7, 3.8, 3.9, 3.10, 3.11, 및 3.12 모두 지원됩니다. 이 라이브러리는 순수 Python이며 네이티브 확장이 없으므로 CPython이 실행되는 모든 플랫폼에서 작동합니다.

이 라이브러리는 외부 의존성이 있습니까? 아니요. Aspose.3D FOSS for Python는 Python 표준 라이브러리만 사용합니다. 단일 pip install aspose-3d-foss 명령이며 추가 단계가 없습니다.

FBX가 지원됩니까? FBX 토크나이저가 구현되어 바이너리 FBX 토큰 스트림을 파싱할 수 있지만, 토크나이저 위에 있는 씬 그래프 빌더에는 알려진 버그가 있으며 프로덕션에 사용할 수 없습니다. 신뢰할 수 있는 프로덕션 사용을 위해 OBJ, STL, glTF, COLLADA 또는 3MF를 사용하십시오.

상업용 제품에서 Aspose.3D FOSS를 사용할 수 있나요? 예. 이 라이브러리는 MIT 라이선스로 배포되며, 라이선스 고지를 포함하는 한 로열티 없이 독점 및 상업 소프트웨어에 사용할 수 있습니다.

버그를 보고하거나 포맷을 요청하려면 어떻게 해야 하나요? 저장소에 이슈를 열어 주세요. 최소 재현 파일과 Python 버전, 운영 체제, 그리고 라이브러리 버전을 포함하십시오. pip show aspose-3d-foss.


API 레퍼런스 요약

핵심 클래스

  • Scene: 3D 씬을 위한 최상위 컨테이너. 진입점은 open(), from_file(), 및 save().
  • Node: 장면 그래프의 트리 노드. 다음을 포함합니다 entity, transform, global_transform, material, child_nodes, 및 name.
  • Entity: 노드에 부착된 객체(Mesh, Camera, Light)의 기본 클래스.
  • Transform: 노드의 로컬 공간 위치, 회전(Quaternion), 및 스케일.
  • GlobalTransform: 모든 조상 변환을 누적하여 계산된 읽기 전용 월드 공간 변환.

기하학

  • Mesh: 다음과 같은 폴리곤 메시 control_points (버텍스 리스트) 및 polygons.
  • VertexElementNormal: 버텍스당 또는 폴리곤당 법선 벡터.
  • VertexElementUV: 버텍스당 UV 텍스처 좌표.
  • VertexElementVertexColor: 버텍스당 색상 데이터.
  • VertexElementSmoothingGroup: 폴리곤 스무딩 그룹 할당.

재질

  • LambertMaterial: 다음과 함께하는 디퓨즈 셰이딩 모델 diffuse_coloremissive_color.
  • PhongMaterial: Specular shading 모델 추가 specular_colorshininess.

수학 유틸리티 (aspose.threed.utilities)

  • Vector2: 2D 벡터.
  • Vector3: 3D 이중 정밀도 벡터.
  • Vector4: 4D 이중 정밀도 벡터.
  • FVector3: 3D 단일 정밀도 벡터.
  • Quaternion: 다음과 함께 회전 쿼터니언 from_angle_axis() : 및 to_matrix().
  • Matrix4: 4×4 변환 행렬.
  • BoundingBox: 축 정렬 경계 상자 (다음과 함께) minimum : 및 maximum : 코너들.

애니메이션

  • AnimationClip: 애니메이션 채널 집합 및 해당 키프레임을 위한 명명된 컨테이너.
  • AnimationNode: 클립 내 각 노드별 애니메이션 데이터.
  • KeyFrame: 시간과 값을 가진 단일 키프레임.
  • KeyframeSequence: 단일 애니메이션 속성을 위한 정렬된 키프레임 시퀀스.

로드 / 저장 옵션

  • ObjLoadOptions: OBJ 전용 로드 설정: enable_materials, flip_coordinate_system, normalize_normal, scale.
  • StlSaveOptions: STL 전용 저장 설정 (바이너리 vs. ASCII 모드).

카메라 및 조명

  • Camera: 다음에 부착 가능한 카메라 엔티티. Node.
  • Light: 라이트 소스 엔티티, a에 부착 가능 Node.
 한국어