애니메이션 GLB 또는 GLTF 모델은 준비된 이미지 폴더가 아니라 기하학 및 애니메이션 데이터를 저장합니다. 썸네일이나 프레임 시퀀스를 만들려면 특정 타임스탬프에서 모델의 애니메이션을 평가하고 각 결과 장면을 이미지로 렌더링해야 합니다. 이 튜토리얼에서는 Aspose.3D for Python via .NET을 사용하여 Python에서 GLB 애니메이션 프레임을 렌더링하는 방법을 설명합니다. 애니메이션 모델을 로드하고, 클립을 선택하고, 타임라인을 샘플링한 다음 각 프레임을 번호가 매겨진 PNG 이미지로 저장합니다. 결과 이미지를 모델 미리보기로 사용하거나 별도의 이미지 시퀀스 워크플로에 입력으로 사용할 수 있습니다.

Aspose.3D for Python via .NET 설치

pip을 사용하여 패키지를 설치합니다:

pip install aspose-3d

또한 다음이 필요합니다:

  • 애니메이션 .glb 파일 또는 해당 버퍼와 텍스처가 포함된 .gltf 파일.
  • Aspose.3D의 하드웨어 요구 사항과 호환되는 렌더링 환경. 시스템 요구 사항을 확인하십시오.
  • 샘플링된 타임라인 전체에 걸쳐 애니메이션 객체가 보이도록 유지하는 카메라 위치.

애니메이션 클립을 PNG 프레임으로 렌더링

다음 코드를 render_glb_animation_frames.py 파일로 저장하고 animated_model.glb 파일이 있는 폴더에서 실행하십시오.

import hashlib
import math
from pathlib import Path

import aspose.threed as a3d
from aspose.pydrawing import Color, Size
from aspose.pydrawing.imaging import ImageFormat
from aspose.threed.entities import Camera
from aspose.threed.utilities import Vector3

INPUT_FILE = Path("animated_model.glb")
OUTPUT_DIR = Path("frames")
FRAMES_PER_SECOND = 5
IMAGE_WIDTH = 800
IMAGE_HEIGHT = 600

def main():
    if not INPUT_FILE.is_file():
        raise FileNotFoundError(f"Input model not found: {INPUT_FILE}")

scene = a3d.Scene.from_file(str(INPUT_FILE))
    clips = list(scene.animation_clips)
    if not clips:
        raise RuntimeError("The input model has no animation clips.")

clip = clips[0]
    duration = float(clip.stop - clip.start)
    if duration <= 0:
        raise ValueError("The selected animation has no positive time range.")

# Use the same camera position for every frame.
    camera = Camera()
    camera_node = scene.root_node.create_child_node("PreviewCamera", camera)
    camera_node.transform.translation = Vector3(3, 2, 6)
    camera.look_at = Vector3.ORIGIN

options = a3d.ImageRenderOptions()
    options.background_color = Color.white
    options.asset_directories.append(str(INPUT_FILE.resolve().parent))

OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    frame_count = max(1, math.ceil(duration * FRAMES_PER_SECOND))
    hashes = set()

for frame_index in range(frame_count):
        timestamp = float(clip.start) + frame_index / FRAMES_PER_SECOND
        clip.apply_to(timestamp)

frame_path = OUTPUT_DIR / f"frame_{frame_index:04d}.png"
        scene.render(
            camera,
            str(frame_path),
            Size(IMAGE_WIDTH, IMAGE_HEIGHT),
            ImageFormat.png,
            options,
        )

if not frame_path.is_file() or frame_path.stat().st_size == 0:
            raise RuntimeError(f"Rendering did not create a usable PNG: {frame_path}")

hashes.add(hashlib.sha256(frame_path.read_bytes()).digest())
        print(f"Frame {frame_index + 1}/{frame_count}: {frame_path} at {timestamp:.3f}s")

if frame_count > 1 and len(hashes) == 1:
        print("WARNING: All PNG files are byte-identical. Check animation state and camera view.")

print(f"Created {frame_count} PNG file(s) in {OUTPUT_DIR}/")

if __name__ == "__main__":
    main()

다음으로 실행:

python render_glb_animation_frames.py

예상 출력: frames 디렉터리에는 frame_0000.png, frame_0001.png, frame_0002.png와 같은 이미지가 포함됩니다. 렌더러가 적용된 애니메이션 상태를 올바르게 캡처하면, 이미지들은 애니메이션에서 모델이 연속적인 시점에 있는 모습을 보여줍니다.

프레임 렌더링 코드가 작동하는 방식

씬을 로드하고 애니메이션 클립을 선택

Scene.from_file() 메서드는 모델을 열고, scene.animation_clips는 포함된 애니메이션 클립에 접근할 수 있게 합니다. 예제에서는 첫 번째 클립을 사용하고 해당 클립의 start 및 stop 속성을 읽어 시간 범위를 결정합니다. 애니메이션 클립이 없는 모델은 이 메서드로 애니메이션 시퀀스를 생성할 수 없습니다.

자세한 클립 선택 및 노드 변환에 대해서는 Python에서 GLB/GLTF 애니메이션 로드 및 평가를 참조하십시오.

타임라인을 정규 간격으로 샘플링

스크립트는 초당 5개의 샘플을 사용합니다. 클립이 2초 동안 지속되면, 클립이 0에서 시작할 때 0.0초부터 1.8초까지의 타임스탬프에서 총 10개의 프레임을 요청합니다. 정확한 끝점을 제외함으로써 시작 자세로 되돌아가는 루프 애니메이션에서 중복된 마지막 프레임이 생성되는 것을 방지합니다.

clip.apply_to(timestamp) 메서드는 각 타임스탬프에서 선택된 애니메이션 클립을 적용합니다. 단일 키프레임 시퀀스를 평가하는 것과 달리, 이 단계는 이미지가 렌더링되기 전에 애니메이션 씬을 업데이트하기 위한 것입니다.

하나의 카메라에서 업데이트된 장면을 렌더링

예제는 고정된 위치에 카메라를 추가하고 각 프레임마다 scene.render()를 호출합니다. 또한 800 × 600 픽셀 이미지 크기와 PNG 출력 형식을 설정합니다. 카메라를 고정해 두면 프레임 간 차이를 더 쉽게 검사할 수 있습니다.

Aspose.3D 씬 렌더링 가이드는 3D 뷰를 이미지로 저장하는 방법을 보여줍니다. 애니메이션 시퀀스의 경우 각 이미지가 의도한 타임스탬프를 반영하는지 확인하십시오. 연속 프레임이 동일한 포즈를 표시하면 렌더링 경로가 현재 애니메이션 상태를 사용하고 있는지 확인하세요.

각 PNG 프레임을 일관되게 이름 지정

frame_0000.png 패턴은 파일 이름으로 정렬할 때 이미지 순서를 유지합니다. 미리 보기 썸네일을 생성하거나 출력을 별도의 이미지 시퀀스 또는 비디오 워크플로에 전달하는 데 적합합니다. 스크립트는 비디오나 애니메이션 GIF를 만들지 않습니다.

스크립트는 또한 파일 해시를 비교하여 모든 출력 파일이 바이트 단위로 동일한 경우 경고합니다. 해시가 다르다고 해서 애니메이션이 올바르게 렌더링되었다는 것을 증명하는 것은 아니므로, 대표 프레임을 나란히 검사하십시오.

무료 임시 라이선스 받기

무료 30일 임시 라이선스 요청하기를 통해 Aspose.3D for Python via .NET를 사용해 평가 제한 없이 GLB 및 GLTF 애니메이션 프레임을 렌더링할 수 있습니다. Python 애플리케이션에 라이선스를 적용하려면 Aspose.3D 라이선스 가이드를 따르세요.

무료 학습 자료

다음 리소스를 탐색하여 애니메이션 3D 모델 로드, 애니메이션 클립 작업 및 Aspose.3D for Python via .NET를 사용한 3D 씬 렌더링에 대해 자세히 알아보세요:

결론

애니메이션 타임라인을 샘플링하고 각 선택된 타임스탬프에서 장면을 렌더링하여 프레임 이미지를 생성할 수 있습니다. 번호가 매겨진 PNG를 사용하여 썸네일을 만들고, 포즈를 비교하거나 다른 도구용 이미지 시퀀스를 준비하세요. 이미지 대신 숫자 애니메이션 값이 필요하면 키프레임 평가 튜토리얼을 참조하십시오. 렌더링 문제에 대해서는 Aspose.3D 지원 포럼을 방문하세요.