Tutorial: Keyframe Animation
Author, preview, and export keyframe animations using the MC3 action/channel/keyframe system.
Animation Concepts
MeshCraft animations are organised into three levels:
- Action — a named clip with a duration and loop flag (e.g., "Walk", "Bounce").
- Channel — animates one scalar property of one named object (e.g.,
position.yof object"Ball"). - Keyframe — a (time, value) pair with an interpolation mode:
step,linear, orcubic.
All 23 animatable properties are scalars — you need three separate channels to animate full 3D position (one each for position.x, position.y, position.z).
Step 1 — Prepare a Scene
Start with a simple scene containing at least one named object. We will animate a sphere bouncing up and down.
Create bounce.mc3.xml:
<?xml version="1.0" encoding="UTF-8"?>
<mc3 version="0.3" model="BounceDemo">
<lights>
<ambient color="0.3 0.3 0.4" brightness="0.5"/>
<directional name="Sun" direction="-0.5 -1 -0.3" brightness="2.0"/>
</lights>
<materials>
<material id="red"><base_color>0.9 0.2 0.2 1.0</base_color></material>
<material id="grey"><base_color>0.5 0.5 0.5 1.0</base_color></material>
</materials>
<objects>
<plane name="Ground" size="10 10" axis="y" material="grey"/>
<sphere name="Ball" radius="0.5" position="0 0.5 0" material="red"/>
</objects>
</mc3>
Step 2 — Add an Action
Add the <actions> block after </objects> and before </mc3>:
<actions>
<action name="Bounce" duration="1.0" loop="true">
<channel target="Ball" property="position.y">
<keyframe time="0.0" value="0.5" interp="cubic">
<handle_left dt="-0.1" dv="0.0"/>
<handle_right dt=" 0.1" dv="3.0"/>
</keyframe>
<keyframe time="0.5" value="3.5" interp="cubic">
<handle_left dt="-0.1" dv="3.0"/>
<handle_right dt=" 0.1" dv="-3.0"/>
</keyframe>
<keyframe time="1.0" value="0.5" interp="linear"/>
</channel>
</action>
</actions>
This animates the Ball sphere's Y position from 0.5 → 3.5 → 0.5 over one second, looping indefinitely. The cubic interpolation with tangent handles gives a smooth ease-in/ease-out arc.
Step 3 — Open and Play
./cmake-build-debug/MeshCraft bounce.mc3.xml
- The scene opens. You should see the red sphere and grey ground plane.
- In the editor, find the Timeline panel (bottom area).
- Select the Bounce action from the drop-down.
- Press the Play button — the sphere animates up and down in the viewport.
- Drag the scrubber to a specific time to preview that pose.
Animation playback applies AnimOverride transforms to each object. This means keyframe transforms are independent of the static transform stored in the scene — the static transform is the base pose when no animation is playing. When a channel covers only one axis, the other two axes are read from the object's static transform.
Step 4 — Adding a Rotation Channel
Extend the same action with a spin channel. Add another <channel> inside the same <action>:
<channel target="Ball" property="rotation.y">
<keyframe time="0.0" value="0.0" interp="linear"/>
<keyframe time="1.0" value="360.0" interp="linear"/>
</channel>
Now the sphere bounces and spins simultaneously within the same clip.
Step 5 — Visibility Flash
The visible property (0.0 = hidden, ≥0.5 = visible) combined with step interpolation creates a strobe effect:
<action name="Flash" duration="0.4" loop="true">
<channel target="Ball" property="visible">
<keyframe time="0.0" value="1.0" interp="step"/>
<keyframe time="0.2" value="0.0" interp="step"/>
</channel>
</action>
Interpolation Modes Summary
| Mode | Attribute | Behaviour | Best for |
|---|---|---|---|
| Step | interp="step" | Value holds until next keyframe then jumps | Visibility, discrete states |
| Linear | interp="linear" | Straight-line lerp between keyframes | Constant-velocity motion, rotation |
| Cubic Bézier | interp="cubic" | Smooth curve using handle_left/handle_right tangents | Organic motion, bouncing, easing |
Exporting the Animation
Position, rotation (XYZ Euler → glTF quaternion), and scale channels are exported to glTF. See Export to glTF/GLB for the full pipeline.
./cmake-build-debug/mc3togltf/mc3togltf bounce.mc3.xml bounce.glb
Open bounce.glb in Blender or Godot — the "Bounce" animation clip will be importable directly.
Cubic Bézier channels are sampled at 30 fps and stored as LINEAR in the glTF output. The smooth curve is preserved visually, but the file size is larger than a pure 2-keyframe linear clip.
Animatable Properties Reference
See the complete list in the Animation Format Reference. All 23 properties are scalars — vector properties require one channel per component.