An animated GLB or GLTF model stores geometry and animation data rather than a folder of ready-made images. To create thumbnails or a frame sequence, you need to evaluate the model’s animation at particular timestamps and render each resulting scene into an image. This tutorial explains how to render GLB animation frames in Python using Aspose.3D for Python via .NET. You’ll load an animated model, select a clip, sample its timeline, and save each frame as a numbered PNG image. You can use the resulting images as model previews or as input to a separate image-sequence workflow.
Install Aspose.3D for Python via .NET
Install the package using pip:
pip install aspose-3d
You’ll also need:
- An animated
.glbfile or a.gltffile with its accompanying buffers and textures. - A rendering environment compatible with Aspose.3D’s hardware requirements. See the system requirements.
- A camera position that keeps the animated object in view across the sampled timeline.
Render an animation clip as PNG frames
Save the following code as render_glb_animation_frames.py and run it from the folder containing 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()
Run it with:
python render_glb_animation_frames.py
Expected output: a frames directory containing images such as frame_0000.png, frame_0001.png, and frame_0002.png. When the renderer captures the applied animation states correctly, the images show the model at successive points in its animation.
How the frame-rendering code works
Load the scene and select an animation clip
The Scene.from_file() method opens the model, while scene.animation_clips provides access to the animation clips it contains. The example uses the first clip and reads its start and stop properties to determine the time range. A model without animation clips cannot generate an animated sequence by this method.
For more detail about clip selection and node transformations, see Load and Evaluate GLB/GLTF Animations in Python.
Sample the timeline at regular intervals
The script uses five samples per second. If the clip lasts two seconds, it requests ten frames at timestamps from 0.0 to 1.8 seconds when the clip starts at zero. Excluding the exact endpoint avoids generating a redundant final frame for animations that loop back to the starting pose.
The clip.apply_to(timestamp) method applies the selected animation clip at each timestamp. Unlike evaluating a single keyframe sequence, this step is intended to update the animated scene before the image is rendered.
Render the updated scene from one camera
The example adds a camera at a fixed position and calls scene.render() for each frame. It also sets an 800 × 600 pixel image size and a PNG output format. Keeping the camera fixed makes frame-to-frame differences easier to inspect.
The Aspose.3D scene-rendering guide shows how to save a 3D view as an image. For animation sequences, verify that each image reflects the intended timestamp. If successive frames show the same pose, check whether the rendering path is using the current animated state.
Name each PNG frame consistently
The frame_0000.png pattern keeps images in order when sorted by filename. It is suitable for generating preview thumbnails or passing the output to a separate image-sequence or video workflow. The script does not create a video or an animated GIF.
The script also compares file hashes to warn when all output files are byte-identical. Different hashes do not by themselves prove that the animation is rendered correctly; inspect representative frames side by side.
Get a Free Temporary License
You can request a free 30-day temporary license to render GLB and GLTF animation frames using Aspose.3D for Python via .NET without evaluation limitations. To apply the license in your Python application, follow the Aspose.3D licensing guide.
Free Learning Resources
Explore the following resources to learn more about loading animated 3D models, working with animation clips, and rendering 3D scenes using Aspose.3D for Python via .NET:
- Aspose.3D for Python Developer Guide – Learn how to load, modify, animate, and render 3D models in Python.
- Render 3D Scenes to Images – Learn how to configure a camera and render 3D scenes as image files.
- Aspose.3D Python API Reference – Explore classes and methods for animation clips, scene rendering, cameras, and 3D file processing.
- Free Online 3D Applications – View, convert, and process supported 3D models directly in your browser.
- Aspose.3D Tutorials and Articles – Find practical Python tutorials covering GLB/GLTF animations, keyframe evaluation, and other 3D processing tasks.
Conclusion
You can generate frame images by sampling an animation timeline and rendering the scene at each selected timestamp. Use the numbered PNGs to build thumbnails, compare poses, or prepare an image sequence for another tool. If you need numeric animation values rather than images, see the keyframe evaluation tutorial. For rendering issues, visit the Aspose.3D support forum.
