Hacking The Movies Game Animation Files
There are tools available to extract 3d models from The Movies Game and import them into Blender. These models include sets, buildings, terrain, props, and characters, all rigged and ready to be animated. One could conceivably use these assets to make animated videos in Blender that would go beyond the capabilities of The Movies Game.
On the other hand, one can use Blender to modify or create 3D assets which can then be injected into the game, extending its capabilities.
One of valuable goodies hidden in the game are animation files; there are about 8002 animation files, most of them for human figures, but there are also animation files for animals such as horses, dogs, and birds. Creating animations for use in Blender is labor intensive work, and if we could recover those assets from the Movies game, they could save a lot of time developing scenes in Blender.
On the other hand, some times when creating a movie in the game, you can't quite get the scene that you would like from the available options. This is where a program like flmreaderzero comes in handy because it allows you to create new and swap out the existing animations for others. If we had a way to create new animations, we could replace the existing animations with new ones.
The goal of this project is to be able to edit animation (anm) files from the movies game by importing them into Blender, changing the poses, then exporting the changes out as new animation files which can then be used in new scenes which we can create in The Movies Game.
1.0 The Coordinate System In The Game
The goal of section is to understand the coordinate system used internally by animations in The Movies Game. The method was to edit existing animation files, change the data, and observe the effects when the editted animation was played in the game.
I created a new scene from "close up head" on the blue screen set and then opened the "flm" file in flmreaderzero. I saw that the main animation used was "idle_male.anm." I used the code from Gleem's importanm.py script to write a program which would print out a map of the file showing the location of all of the frame data for each bone. Using this map and a hex editor, I tried modifying the rotation data for the arm_r bone and then observing how the animation changed when played back in the game while in the "advanced script writing facility."
The screen grabs below illustrate the effects observed in the game due to various changes.
Figure 1: Effect of Changing Rotation Data for arm bone as observed in the game
No. 1: This screen capture shows the original "idle male" animation as it appears in the game. The rotation angles for the right arm (arm_r) are approximately: x = -165.58, y = 81.62, z = -101.47 No. 2: The next image shows what happens if you zero the X rotation data for the right arm. As you can see, the arm rotates around the long axis. The animation file rotation data is in a compressed format, such that #7FFF corresponds to a rotation angle of zero. No. 3: The third image shows the effect of nulling the Y rotation data (X data restored to orginal values) No. 4: Setting the Z rotation data for the arm to zero causes it to point straight down. No. 5: Setting all 3 axes, X,Y, and Z to zero rotation causes the arm to point straight out in front of the Figure
These results show that simple modifications to the anm files are possible using a hex editor and viewing the effects of changes in the game. It should not be difficult to tweak the "idle male" animation into an animation of a fascist salute. That might be useful, especially in these interesting times in which we live.
One thing I discovered was that the game program appears to be "caching" the animation files, although not the "flm" files which describe the contents of a scene. When viewing a scene in the advanced scriptwriting facility, if you return to the initial screen where roles are default costumes are selected, then return to the scene, any changes in the flm file for that scene will immediately be reflected in the display. If you modify the animation file, however, the display will not change. I believe this is because the animation files are cached once loaded. The only way to clear the cache appears to be exiting from the game entirely and restarting it. As a work around, I adopted a practice of adding a version number to each new anm file introduced during then session. Since the new name is not in the cache, the program loads the file from the hard drive.
I decided to experiment with the data in the anm file in order to understand the coordinate system used by the game. I wrote a set of python scripts to help manipulate the data in the anm file and used those to make changes and view the results in the game. In the following sequence I tried changing the rotation angles for the arms to see the change in the position of the arm as viewed in the game.
Figure 2: Position of right arm bone for various yaw, pitch, roll angles
Starting from a T pose, I tried moving the right arm from the all zero position to various setting by increments of 45 degrees.
Figure 3: Effect of moving control2_arm_r to various yaw, pitch, and roll angles.
The parent bone of the right arm is called 'control2_arm_r.' When arm_r is set to zero rotation, it points in the same direction as control2_arm_r. When we move control2_arm_r through various angles around different axes, the arm moves with it.
Figure 4: Effect of moving the legs to different yaw, pitch, and roll angles.
In this series, I moved the legs around to see how they responded.
1.0 The X axis in the movies game points to stage right.
2.0 The Y axis points upstage (toward the back of the set)
3.0 The Z axis points upward.
4.0 With all angles set to zero, the bone axes are aligned with the stage axes.
5.0 The x axis of the bone is along the axis of the bone.
All of this was done using python scripts to modify the data in the animation file and observing the effects in the game. This is slow going and a graphical tool would be very helpful if we could display the data outside the game and modify the pose with instant visual feedback before exporting the data back to the game and observing the results there. The easiest way to provide a tool for this purpose seemed to be using blender, but we need to figure out how to make the bones in blender move in the same way in blender as they did in the game.
2.0 Converting Rotation Data From Movies Game Coordinates to Blender
If we set all of the rotation angles in an anm file to zero, the model assumes its "rest position."
Figure 6: Effect of zeroing rotation angles for all bones as seen in game
If we construct an armature in blender and layout the bones so that they match the rest position in the above image, we get something like the following:
Figure 7: My approximation of movies game armature
In the movies game, the x axis is along the bone, but in Blender, the y axis is along the bone. The rotation data in the movies game are euler angles expressed relative to the Movies game coordinate system. Rotate first around the Z axis, then the Y axis, then the X axis, a yaw, pitch, roll Euler sequence. These rotations do not work in Blender. To make the Blender bone follow the rotation of the Movies game bone, you still rotate around Z first by the yaw angle, but then around the X axis through the pitch angle, then around the Y axis through the roll angle. Since the X axis in Blender is in the opposite direction to the Y axis in The Movies Game, the X angle of rotation in blender will be the negative of the pitch angle rotation in the game.
This is complicated and it is hard to hold it in your head for very long, but we can capture it if we write it down in terms of Blender Python code. The following Blender python function will convert a set of Movies Game euler angles to a quaternion that will position the bones of our armature correctly.
def tm_to_blender(x,y,z): ea = Blender.Mathutils.Euler(0.0,0.0,z) mz = ea.toMatrix() ea = Blender.Mathutils.Euler(-y,0.0,0.0) mx = ea.toMatrix() ea = Blender.Mathutils.Euler(0.0,x,0.0) my = ea.toMatrix() m = my*mx*mz quat = m.toQuat() return quat
The inputs are the x,y,z rotation angles from the anm files (converted to degrees) and the output quat is a quaternion which can be used to pose an armature in blender. If you setup the armature so that the rest positions match the ones in the movies game anm data, it works.
Here are some test videos made using the method described above.
This is enough to verify that the transformations are being correctly performed and we can display animations from the game in blender as an animated armature.
3.0 Applying Movies Game Rotation Data to a Costume Imported to Blender
In the previous section we have seen how we can use the concocted armature shown in figure 7 and replicate the animations in the movies game using the movies game animation data extracted from anm files, which is great, but all you see are bones. What we would like to do is figure out how to make the imported costumes duplicate the poses imported from the game. The problem is that the rest postion of a costume armature is not the same as the rest position of the armature show in figure 7.
The rotational data for a pose can be represented as a quaternion which moves a bone from its rest position to the correct pose position. Let's call this quaternion q. The tm_to_blender python function above computes a quaternion which moves a bone from the movies game rest position to the desired pose in blender. Let's call this quaternion qanm. Suppose we have a quaternion, qbr, which moves a bone from the costume rest position to the movies game rest postion. We can multiply qbr by qanm to get q.
q = qbr*qanm
The problem now is to find qbr. Well, there is a way to compute qbr. There is a movies game animation file, sm_pose.anm, and from this we can compute qsm which takes us from the movies game rest position to the costume rest position. This is just the opposite of qbr, so:
qbr = qsm.conjugate()
There is one more little detail to take care of, however. If we apply qsm, we get following result:
Figure 8: sm_pose applied to armature in figure 7.
Let us now look at the costume armature in the rest position.
Figure 9: Rest pose for the costume armature
Looking closely at these last two figures, we see that the axes are not quite right. The reason is that the costume armature bones have a bone roll angle set to -90 degrees. We can fix this by going back to our original armature and changing the bone roll angle in edit mode for each bone to -90 degrees. To be consistent, we have to modify the tm_to_blender function to the following:
def tm_to_blender(x,y,z): ea = Blender.Mathutils.Euler(0.0,0.0,y) mz = ea.toMatrix() ea = Blender.Mathutils.Euler(z,0.0,0.0) mx = ea.toMatrix() ea = Blender.Mathutils.Euler(0.0,x,0.0) my = ea.toMatrix() m = my*mz*mx quat = m.toQuat() return quat
When we do this, all the axes line up the way they should and we can now use this pose to calculate our offset quaternions to convert movies game rotations to blender rotations.
Figure 10: Corrected sm_pose with -90 roll on bones.
Here is a short video showing three different animations applied to a costume in blender: