This guide assumes you have already read/completed the previous tutorials.
File list
| File Link | Description |
|---|---|
| End Result | The end product of this tutorial for you to examine and compare. |
Introduction
On this page, we will take a look at how to create a basic animation, the process of getting it in-engine, and gain an understanding of the .model_animation_graph tag. The overall goal of the following tutorial is to add an animation to our platform scenery to make it move in-engine.
Animations in Blam!
Animation in the Blam! engine is quite a broad topic and not everything will be covered here, but the following basics should give you a good enough understanding such that you can create animations for any scenery or device machine object you wish. Unlike models, which all use the .JMS format for importing, animations use a multitude of formats that determine how tool handles them on import. You can see a list of all types here, but the main two we will focus on are .JMM and .JMO. Think of .JMM as the "base" type of animation - one that causes an object's bones to simply move. The most common use-case is for object idling animations. .JMO are overlay animations - these are additive meaning that the bone movement data is applied on top of any current base animation on the object. When talking about things that apply to all extension types, I will use .JMx to indicate any extension.
Some animations require specific numbers of frames, where certain actions happen on certain frames - this is not the case for basic scenery or device machine animations, but is something you should keep in mind in the future. For example, wheel-based vehicle (think Warthog) steering animations only consist of four frames: rest, full-right-turn, rest, full-left-turn.
Vertex weighting
Vertex weighting is a complex topic - it is the process of determining how the vertices in a 3D mesh are manipulated by the movement of bones in an armature. If you'd like to learn more, a good place to start is the official Blender documentation. Luckily, the weighting that we have to do for our model is extremely simple. As we only have one bone, and we want the entire model to follow the animation of that bone, we can simply weight all of the vertices in our model to that bone, with a value of 1.
- Open your Blender file from the last tutorial, or download the end result from the previous page.
- Select the
platformobject, then navigate to theObject Data(green) tab in thePropertieswindow. - At the top, locate the
Vertex Groupssection, and click the+symbol. This adds a new vertex group to the model. - Vertex groups rely on their name to determine which bone they are tied to. Put simply, rename the vertex group to
Boneto match the name of the bone in the armature.
Make sure you give the vertex group the same name as the bone.
- In the
3D Viewport, pressTabto enter intoEdit Mode. Set your selection mode toVertexwith the buttons to the right of the mode dropdown. You will notice that four new options have popped up underneath theVertex Groupssection -Assign,Remove,SelectandDeselect.Assigntakes any currently selected vertices, and assigns them to the currently selected vertex group.Removedoes the opposite.Selectwill highlight any vertices assigned to the currently selected vertex group.Deselectdoes the opposite. - Press A in the
3D Viewportto select all vertices in the model (they will turn orange). Then, in thePropertieswindow, hit theAssignbutton with theBonevertex group selected. - In the
Propertieswindow, switch to theModifiers(wrench icon) tab. We need to add anArmaturemodifier to our model, so that the newly added vertex group knows which armature to use (we only have one armature in the scene, but it needs the modifier regardless). - Click
Add Modifier, then chooseArmatureat the top of theDeformcolumn. - In the newly added
Armature Modifier, click inside theObjectfield, and chooseArmature. Ensure thatBind To Vertex Groupsis checked.
That's it! Our platform object will now correctly animate with the armature, once we have created an animation. If you wish to perform a check to make sure you have done these steps correctly, do the following:
- In the
3D Viewportwindow, click the mode select dropdown near the top left and choosePose Mode. Pose mode is a special object mode used to createkeyframesfor animation, but we will use this more in the next section. - Expand the Armature in the
Outlinerwindow, and select theBone. - Hover over the
3D Viewport, and press G to move the bone. As you move your mouse to move the bone around, theplatformobject should follow it. Don't worry that the physics object doesn't do the same - we will talk more about this later. - Right-click to stop moving the bone, or use Ctrl + Z to undo any changes if you accidentally made them. Then use the mode selection to return to
Object Mode.
Creating an animation
Our second goal is to make a simple animation to play on our .scenery object - a spinning animation will do nicely, and is easy to create with only a few keyframes.
If you are already comfortable with animating in Blender, you may wish to skip this sub-section and make an animation on your own - the types of animation we will be making in this tutorial do not need to follow any halo-specific rules.
- Ensure that you can see the
Timelinewindow (at the bottom of the screen in the default workspace). It is recommended to expand it vertically slightly for better visibility, as per the image below.
You need to have this window visible.
- In the
Timelinewindow, set theEndvalue to80. This number is the end frame - we start at 1, and the animation now ends at 80. Animations are played at 30 frames per second in-engine, so this animation will last roughly 2.67 seconds. - Select the
Armatureobject in your scene. - Use the
Modedrop-down menu in the top right of the 3D View to switch toPose Mode. - Select the bone in the armature (named
Bone). You can do this by zooming in and left-clicking the bone in the 3D View, or by expanding the dropdown on theArmatureobject in theOutlinerview on the right. - Make sure the currently active frame is
1. You can do this by dragging the blue slider in theTimelinewindow to the start, or by typing1into the box in the top right, next to theStartandEndframe boxes. - Hover your cursor over the
3D Viewportwindow, and press I. This will open the keyframe window - chooseRotation.
You will now notice an orange dot has appeared on the timeline. This is a keyframe - a keyframe, at its most basic, stores specific information about the keyframed object; in this case, the rotational data of our Bone in the Armature. It tells Blender that the specified frame, the rotation of the bone should be set to the keyframed value, regardless of what happens on previous or future frames. Let's add the rest of the necessary keyframes, and how they work should become much clearer:
- Use the timeline slider or the frame number box to set the current frame to
20. - In the
3D Viewport, press R, then Z, then type 90. Left-click or press Enter to confirm. This rotates the bone by 90 degrees, or one-quarter turn, and theplatformobject follows suit. - Hit I to open the keyframing menu, and select
Rotationto store the current rotational data into frame 20. - Move the timeline to frame
40. Once again press R, then Z, then type 90, followed by a left-click or the Enter key to apply. As before, use I to open the keyframe menu and keyframe theRotationdata. - Move the timeline to frame
60, and repeat the rest ofStep 11. - Move the timeline to frame
80, then repeatStep 11one final time.
On frame Spinning is a good trick.80, the bone and platform should now be back in their original rotation. You've done it - this is all that is required to make an anti-clockwise spinning animation! Press the play button in the top middle of the Timeline window to see your animation play on loop. You can use the other controls to skip to the start or end frame, or step through the animation one frame at a time. It should look like this: 
However, you may or may not have spotted an issue - the animation looks "jerky", as it slows down and speeds up slightly as it approaches each keyframe. We need to change blender's extrapolation mode to linear to make it nice and smooth:
- Click the
Editor Typedrop-down in the top left of theTimelinewindow (the clock icon). SelectGraph Editor. - Click the
Channelheading, theExtrapolation Mode, thenLinear Extrapolation. - Open the
Editor Typedrop-down again and set it back toTimeline. Play the animation again, and it will loop smoothly. - You can now leave
Pose Modeand return toObject Modein the3D Viewport.
Exporting animations from Blender
As you should already be familiar with exporting .JMS files from Blender with the Blender addon, the export process for animations should feel at least somewhat familiar.
As we have not directly edited the render model, physics model or armature since exporting them in previous tutorials, there is no need to re-export them now.
- Click
File->Exportand chooseHalo Jointed Model Animation (JMA). - Navigate to your the
custom_platform's data directory - that would be"H3EK\data\objects\scenery\custom_platform"if you have been following along exactly. - Create a new folder here (the
Create New Directorybutton to the left of the file path box), and name itanimations. As with therenderandphysicsfolders,tool.exelooks specifically for this folder name, so make sure it is named correctly. - Navigate inside the new
animationsfolder. - On the right side of the export menu, make sure the
Game Versionis set toHalo 3, and theExtensionis set toJMM. Leave everything else default. - At the bottom of the export menu, name the file
any idleexactly.
Naming animations correctly is important, as the name describes to tool.exe how the animation should be handled and where it gets put inside the .model_animation_graph tag. any idle specifies that this is an idle animation that should play under any circumstances.
- Hit the
Export Animationbutton, and wait for theExport completed successfullymessage to appear at the bottom of Blender.
Importing animations and the model animation graph
Animations are stored in .model_animation_graph tags once imported. This tag type is automatically generated on first import, similarly to how a .render_model tag is built automatically when you first import a .JMS. These tags can contain as many animations as needed, and are re-built whenever the animations folder is imported. This re-building process deletes any existing animations in the tag, and then adds those found in the animations folder back in. This means that if you no longer have the source .JMx files for some animations and attempt to import others, they will be removed.
Let's go through the process of importing our new any idle.JMM file:
- Open up
CMDin yourH3EKfolder. The command we will be using this time ismodel-animations. - Type
tool model-animations "path\to\your\scenery", wherepath\to\your\sceneryis the tags-relative path to your scenery's data folder. For example if you have been following along exactly, this will be"objects\scenery\custom_platform".
You should now see the following output from tool.exe output after running the "model-animations" command.tool, informing us that the .model_animation_graph tag has been successfully created (it will be alongside the other tags, e.g. in "H3EK\tags\objects\scenery\custom_platform"). The warning and error here can be ignored - they are simply informing us that a new tag is being made from scratch: 
.model_animation_graph tag in the object's tags folder. This isn't a necessary step, but it's a good idea to familiarise yourself with the tag regardless. There are three important sections of note - the Skeleton Nodes block, the Animations block, and the Mode-n-State Graph block.
The The Skeleton Nodes block.Skeleton Nodes block lists all of the bones used in this model and animation. In Blam!, bones are called nodes. We only have one node, and so there is only one entry in this block. The node list of a .model_animation_graph and the .render_model it is associated with must match exactly. You will get an error when importing animations if they do not. If you change something after the fact, such as editing the render model to add new bones but not updating the animation to reflect this, the node lists will no longer match, and the object will refuse to spawn at all. 
The The Animations block.Animations block is quite obvious - it lists all of the animations held in the tag, and their associated data. Here you can see our named animation. Note that spaces are replaced with colons in Guerilla, such that any idle.JMM becomes any:idle in the tag. One use of this block is to add sounds that play on certain frames of the animation - this is done in the Sound Events sub-block. 
The The Mode-n-State Graph block.Mode-n-State Graph block shows in what states the animations in the graph will play. As we named the animation any idle, tool recognised that it is to be played under any circumstance, and so it is already set up correctly in this block. This is why naming conventions for .JMx files are important, as it tells tool how to automatically handle them. Our idle animation will therefore play for any mode, in any weapon class, and in any weapon type. You can see the reference to the any:idle animation here in the Actions section. Actions are base animations, such as .JMA and .JMM, whereas the Overlays section is for .JMO animation types. 
Playing the animation in-engine
It's about time we saw that platform spinning in Sapien! We've already done 99% of the hard work, so let's do the final steps:
- In Guerilla, open the
.modeltag for the platform. - Right at the top, locate the
animationentry - it's in between the entries for the.render_modeland.physics_modelthat we have already added. - Click the
...next to the animation entry, and open the new.model_animation_graphtag. - Save the tag.

Add the animation graph reference like so.
- Open Sapien on a map of your choice, and add the platform scenery tag to the scenery palette if you haven't added it already. If you can't remember how to do this, refer to this section of the render importing guide
- Place the scenery down anywhere, and witness it spin!

Look at it go!
Once you've gotten to this point, you are ready to look at adding a second custom animation and a .device_machine tag, so that we can have the platform move us around! This next section is available here
Acknowledgements
Thanks to the following individuals for their research or contributions to this topic:
- PepperMan (Writing this guide)