Evaluating animations in a GLB or GLTF file lets you inspect how 3D objects move, rotate, and scale over time without rendering the scene. You can use this approach to analyze animation data, verify movements, or export transformations for further processing. In this tutorial, you will load an animated GLB model, inspect its clips, evaluate five timestamps, and export node transformations to CSV.
Load and evaluate GLB animations in Python
An animation clip contains animation data associated with a scene. Its start and stop times define the period you can evaluate. The workflow is to load a model, select an animation clip, apply it at specific times, inspect the scene nodes, and export their transformations.
Install Aspose.3D for Python via .NET
Install Aspose.3D for Python via .NET, which provides the animation evaluation API used here:
pip install aspose-3d==26.10.0
See the installation documentation for more details.
Evaluate animation and export node transformations
The following code example evaluates the first animation clip at five evenly spaced timestamps and saves each node’s local translation, rotation, and scaling in animation_transforms.csv.
import csv
import aspose.threed as a3d
INPUT_FILE = "animated_model.glb"
OUTPUT_FILE = "animation_transforms.csv"
FRAME_COUNT = 5
def get_nodes(root):
"""Recursively collect all nodes in the scene."""
nodes = [root]
for child in root.child_nodes:
nodes.extend(get_nodes(child))
return nodes
# Load the animated model
scene = a3d.Scene.from_file(INPUT_FILE)
# Retrieve animation clips
clips = list(scene.animation_clips)
if not clips:
raise RuntimeError("No animation clips found.")
print(f"Found {len(clips)} animation clip(s).")
for i, item in enumerate(clips):
print(
f"{i}: {item.name} "
f"({item.start:.3f} to {item.stop:.3f} seconds)"
)
# Select the first clip and collect scene nodes
clip = clips[0]
nodes = get_nodes(scene.root_node)
print(f"\nEvaluating: {clip.name}")
print(f"Scene nodes: {len(nodes)}")
records = []
for i in range(FRAME_COUNT):
time = float(
clip.start +
(clip.stop - clip.start) * i / (FRAME_COUNT - 1)
)
# Apply animation at the requested time
clip.apply_to(time)
print(f"\nTimestamp: {time:.3f}s")
for index, node in enumerate(nodes):
transform = node.transform
translation = str(transform.translation)
rotation = str(transform.rotation)
scaling = str(transform.scaling)
records.append([
time,
index,
node.name or "(unnamed)",
translation,
rotation,
scaling
])
print(
f" {node.name or '(unnamed)'}: "
f"position={translation}, "
f"rotation={rotation}"
)
# Write evaluated transformations to CSV
with open(
OUTPUT_FILE, "w", newline="", encoding="utf-8"
) as file:
writer = csv.writer(file)
writer.writerow([
"Time",
"Node Index",
"Node Name",
"Translation",
"Rotation",
"Scaling"
])
writer.writerows(records)
print(f"\nSaved animation data to {OUTPUT_FILE}")
How the animation evaluation works
Load the GLB scene and retrieve its clips
Scene.from_file() loads the GLB or GLTF model. The scene.animation_clips collection provides the available clips:
scene = a3d.Scene.from_file("animated_model.glb")
clips = list(scene.animation_clips)
Each clip exposes a name and a time range in seconds through name, start, and stop. See the AnimationClip API reference.
Apply the animation at specific timestamps
The central operation is clip.apply_to(time). For the sample clip, whose duration is approximately 3.708 seconds, the five timestamps are:
| Sample | Time (seconds) |
|---|---|
| 1 | 0.000 |
| 2 | 0.927 |
| 3 | 1.854 |
| 4 | 2.781 |
| 5 | 3.708 |
You can change FRAME_COUNT to collect more samples. These samples are evaluated animation states, not rendered image frames.
Read translation, rotation, and scaling
After applying the clip, the script traverses all scene nodes and reads:
transform.translation: the node’s local position.transform.rotation: the node’s local rotation.transform.scaling: the node’s local scale.
These are local transformations, not necessarily world-space coordinates. Parent node transformations also affect a node’s final position in the scene. Nodes without animation can retain the same values at every timestamp.
CSV output from the animation
The script creates animation_transforms.csv. For the supplied sample, the console begins with:
Found 1 animation clip(s).
0: Animation_1 (0.000 to 3.708 seconds)
Evaluating: Animation_1
The CSV contains one row per scene node at each sampled timestamp and these columns:
| Column | Description |
|---|---|
| Time | Evaluation timestamp in seconds |
| Node Index | Node’s index in the recursive traversal |
| Node Name | Name of the scene node |
| Translation | Local position at the timestamp |
| Rotation | Local rotation at the timestamp |
| Scaling | Local scale at the timestamp |
You can open the CSV in a spreadsheet application or analyze it with Python to compare transformations across the clip.
What to check when evaluating animations
Multiple clips. This example evaluates clips[0]. To evaluate another animation, choose a different index or retrieve a clip by name using scene.get_animation_clip(name).
Sampling resolution. Five timestamps provide a basic overview, but might miss fast motion. Increase FRAME_COUNT or choose specific times to inspect more detail.
Skeletons and morph targets. Not all animation effects appear as changes in a node’s local translation, rotation, or scaling. This CSV workflow does not capture every kind of skeletal or morph-target deformation.
GLTF dependencies. Text-based .gltf files may reference external buffers and textures. Keep those files at their expected relative paths.
Does evaluating GLB animations require a GPU?
This example does not invoke Scene.render() or the Vulkan rendering backend. It evaluates animation properties and writes CSV data instead of generating images. Aspose.3D rendering has separate Vulkan hardware requirements, which do not apply to this example’s CSV-only workflow.
Get a Free Temporary License
You can request a free 30-day temporary license to evaluate 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 working with 3D models, animations, and supported file formats using Aspose.3D for Python via .NET:
- Aspose.3D for Python Developer Guide – Learn how to create, load, modify, and process 3D files.
- Free Online 3D Applications – View, convert, and process 3D models directly in your browser.
- Aspose.3D Python API Reference – Explore available classes, methods, and properties.
- Aspose.3D Tutorials and Articles – Find practical examples and guides for working with 3D file formats.
Conclusion
Aspose.3D for Python via .NET 26.10 lets you evaluate GLB and GLTF animation clips at selected times with AnimationClip.apply_to(). By reading node transformations after each evaluation, you can inspect movement and export structured animation data without rendering the model. Adapt the example to evaluate additional clips, increase sampling frequency, or analyze selected nodes.
