ANI file specifications mostly decoded

The place to discuss scripting and game modifications for X4: Foundations.

Moderators: Moderators for English X Forum, Scripting / Modding Moderators

Aftershock_81
Posts: 28
Joined: Mon, 11. Dec 06, 21:03
x4

ANI file specifications mostly decoded

Post by Aftershock_81 »

I have been working with the .ANI files using a Hex editor, and have figured out almost all of the structure.

The first 16 bytes are a header. Bytes 0-3 are type INT and contain the number of animations. Bytes 4-7 are type INT and contain the offset of the first frame. Byte 8 is always 01. Bytes 9-15 are always 00.

This is an example from SHIP_ARG_S_FIGHTER_3_DATA.ANI:

Code: Select all

34 00 00 00 90 20 00 00 01 00 00 00 00 00 00 00
34 00 00 00 is 52 in decimal. There are 52 animation records in the file
90 20 00 00 is 8336 in decimal. The first frame record starts at offset 8336 (in decimal)

After the header are the animation records
These records are 160 bytes long.
Bytes 0-63 are an ASCII text string for the component to be animated. The first 00 byte terminates the string. Most of the entries have leftover garbage after this.
Bytes 64-127 are an ASCII text string for the animation name. As before the first 00 byte ends the string. The animation names are the same as is in the XML.
Bytes 128-131 are type INT for the number of position frames in the animation.
Bytes 132-135 are type INT for the number of rotation frames in the animation.
Bytes 136-139 are type INT for the number of scaling frames in the animation.
Bytes 140-147 are all 00 in all files that I have inspected.
Bytes 148-151 are type Float and contain a max time for the animation.
Bytes 152-159 are all 00 in all files that I have inspected.

Code: Select all

61 6E 69 6D 5F 6C 61 64 64 65 72 5F 62 6F 61 72 anim_ladder_boar
64 00 63 68 5F 30 32 00 00 00 00 00 00 00 00 00 d.ch_02.........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
63 6F 63 6B 70 69 74 5F 6F 70 65 6E 69 6E 67 00 cockpit_opening.
69 76 65 00 00 00 00 00 00 00 00 00 00 00 00 00 ive.............
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
03 00 00 00 03 00 00 00 03 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 ......€?........
This animation is for component "anim_ladder_board" and is called "cockpit_opening"
it contains three positioning frames, three rotation frames, and three scaling frames.
The max time is 00 00 80 3F which is 1.0 in decimal.

In ship_arg_s_fighter_03.xml, connection_45 with part anim_ladder_board does not have an animations entry. It can be found in the parent connection_44 with part anim_ladder:

Code: Select all

				<animations>
					<animation name="cockpit_closed" start="1" end="1"/>
					<animation name="cockpit_opening" start="1" end="30"/>
					<animation name="cockpit_open" start="30" end="30"/>
					<animation name="cockpit_closing" start="30" end="60"/>
				</animations>
Animations with start and ends with a difference of 30 seem to correspond with max time values of 1.0.

Starting immediately after the last animation definition record is the first frame record.
The offset of the first of these records corresponds with the value from the header.

These records are 128 bytes in length.
Bytes 0-3 are float. This is the X value.
Bytes 4-7 are float. This is the Y value.
Bytes 8-11 are float. This is the Z value.
Bytes 12-15, 16-19, and 20-23 appear to be INT. If this is the last frame in an animation group the value will be 1. If this is not the last frame, the value will be 2, or 5. I haven't determined the difference between 2 and 5. These three values are always the same.
Bytes 24-27 are float. This is the ending time for the frame. The time of the last frame in the group should match the max time value from the animation record.
Bytes 76-127 sometimes have data in them, but I have not been able to determine a meaning for them. In fact, I zeroed out these bytes from all the frame records in a copy of the Pulsar, and not only did it still work, but I could not see a difference in the animations.

Here is a position frame:

Code: Select all

7C A2 42 BF 70 89 1C BE 00 00 00 00 02 00 00 00 
02 00 00 00 02 00 00 00 AB AA 2A 3F 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 80 00 00 00 00 00 00 00 80 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7C A2 42 BF is -0.760291814804077 in decimal. 70 89 1C BE is 0.152868032455444 in decimal.
AB AA 2A 3F is 0.666666686534882 in decimal.

So, during this frame, the component will move to a relative position of -0.76, 0.153, 0.0 relative to the position in the XML file. This movement will end at two thirds of the full animation time of 1.0, and then the next frame will start.

This is a rotation frame:

Code: Select all

DB 0F C9 3F 00 00 00 80 00 00 00 00 01 00 00 00 
01 00 00 00 01 00 00 00 00 00 00 40 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
DB 0F C9 3F is 1.57079637050629 in decimal. 00 00 00 80 is -0 in decimal. 00 00 00 40 is 2.0 in decimal.
The rotations appear to be in a three axis quaternion system. There is no W value in the record, which makes the effect of the value difficult for me to calculate. The component will rotate to a quaternion of 1.57,0,0 with an ending time of 2.0. This is the last rotation frame of this animation due to the 01 00 00 00 values.

The format of the scaling frame is the same:

Code: Select all

56 55 55 40 00 00 80 3F 00 00 80 3F 05 00 00 00 
05 00 00 00 05 00 00 00 AB AA 2A 3F 2A 15 47 3F 
48 9A AA 40 6C 75 1C 3F B8 65 15 40 2A 15 47 3F
00 00 80 3F 6C 75 1C 3F 00 00 80 3F 2A 15 47 3F 
00 00 80 3F 6C 75 1C 3F 00 00 80 3F 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
56 55 55 40 is 3.33333349227905 in decimal. 00 00 80 3F is 1.0 in decimal. AB AA 2A 3F is 0.666666686534882 in decimal.
During this frame, the component will scale to 3.3 times original size in the X axis while maintaining scale in the Y and Z axes. This frame ends at time 0.66 of 1.0

-----------

So far, I have done all my animation editing in a hex editor, using a spreadsheet I put together to calculate the frame offsets for each animation. There is a lot of trial and error, especially for rotation values, but it works.
------------------------
Aftershock_81
Cg089
Posts: 80
Joined: Fri, 18. Jan 19, 19:25
x4

Re: ANI file specifications mostly decoded

Post by Cg089 »

Oh jeez, I wish I had known you had been working on this too, I could have saved you a lot of headache... been meaning to clean up and post the info I got. I asked the devs nicely if there was any info we could get a while back and got a response back. The devs want us modders to be able do things, it's just a matter of how much time they can devote to making tools and stuff. CBJ & lino were kind enough to send me a pretty detailed specification a month or so ago. I've been working on tool support for it, but I've been pretty busy with school and while I've mentioned what I've been up to on Discord and in some threads, hadn't gotten around to making a dedicated thread since I keep thinking I'm almost ready to release something. Sorry about that :( I feel bad.

I'm impressed as hell you got so far. Again, sorry I didn't post this info sooner. I'll run thru some quick info here until I have time to post more.

Bytes 8 - 11 are the version number, hence always 0x01 0x00 0x00 0x00 since it's version 1 of their file format & endianness. the last byte is padding.

Bytes 140-147 are the number of pre- and post- scale keys, these keys are used very very rarely (a handful of all ANI files, I have a test that runs over all of the ANI files and matches them against what I expect to see).
Pretty everything else is interpolation related and the hardest to work out, and is where I was pretty stuck without info from the devs. You got a bit further than I did before getting stuck, again, great work. And it's pretty difficult to work them out from viewing the animations since it affects the shape of the curve, not where things arrive. I'm not awake enough yet to coherently explain all the fields in a forum post. 1 is step interpolation, or hold a constant value, hence why it usually is the last frame in the group. 2 is linear interpolation. 5 is bezier interpolation. There are other values but they're far far far less common.

Please please please come chat on the unofficial Discord, it's where a lot of ideas get bounced around and info gets shared faster that way https://discord.gg/RzAGhcY. I'd love to collaborate if you're interested, I could definitely use a hand with this whole project. I'll clean up and post the full info tonight & answer any questions I can. I'll also share my codebase (including stuff to mostly make the files human readable & get stuff into blender) happily, I'm going to open source it once it's a bit more polished.
Cg089
Posts: 80
Joined: Fri, 18. Jan 19, 19:25
x4

Re: ANI file specifications mostly decoded

Post by Cg089 »

I'll be putting my info here later: viewtopic.php?f=181&t=416852. Not trying to steal your thunder, just been meaning to put the info together for a while so that this didn't happen and I feel guilty you put lots of time into reverse engineering this, so I finally got around to making the thread I said I'd make months ago.

Return to “X4: Foundations - Scripts and Modding”