I am currently porting Noesis' Bayonetta plugin for the PC version of the game (with Rich permission). You can find the work in progress here:https://github.com/Kerilk/noesis_bayonetta_pc
Models load correctly and most of them are more or less textured correctly. Lightmaps are missing, and some texture have transformation that are not applied.
As improving material support would require knowledge I don't have for now (and that must be buried in the binary) I am trying to add animation support.
Animations are stored in .mot files. I have more or less decoded the format but there are still things I don't understand and though that maybe some of you would have some insight about it.
The layout of the file is the following:
- supplementary data
The header looks like this
typedef struct bayoMOTHdr_s
short int unknownA;
short int frameCount;
id is "mot\0". As far as i know unknownA is always 0 or 1. ofsMotion is always 0x10 and is the start of the entries data.
frameCount is self explanatory.
typedef union bayoMotField_u
typedef struct bayoMotItem_s
short int boneIndex;
short int elem_number;
short int unknown;
the value is an union and can be either a float or an offset in the file. This is decided based on the value of the flag. if the flag is 0x00 then value is a float (and elem_number seems to be ignored). Here is an example (generated with this version of the plugin https://github.com/Kerilk/noesis_bayone ... d66e8efe7a
this model has 4 bones
value of index 0,1,2 could be position offset and value 3,4,5 could be Euler angles. Or something else I don't really know.
Sometimes you can find index 7, 8 and 9. (coud be scaling values ?)
The last record is always (as far as I can tell): 32767 -1 0xff 0 0 +0.000000
If the flag is 6 then the union is an offset into the file where you will find a 12 byte header (6 half float?) and numEntrie records. those records contain 4 bytes: one index and 3 coefficients. The index is a duration between key frames for this value (I think), thus their sum is usually frameCount - 1. I have no idea what kind of interpolation method is used here that would require 6 fixed values and 3 variable coefficient per frame.
Here is an example from the same model (as I am not entirely sure about the half floats I put the corresponding hex string below):
If the flag is 4 then the union is an offset into the file where you will find a 24 byte header (6 float?) and numEntrie records. those records contain 8 bytes: one index and 3 coefficients. The index is the key frame index for this value. Seems like a more precise version of the method above with twice as much data.
Here is an example from another model with 38 bones:
Flag 7 can also be found, in that case the header is 12 bytes (6 half floats) and 6 bytes per record. 2 bytes are a short int for frame index (as in flag 4) and it leaves 4 bytes for coefficient. As it is seldom found and in huge models I will not put an example here, the post is already very long.
Any Idea what those coefficients can be?
After doing some reading on motion compression techniques for skeletal animation I think the floats and integral parameters are used for quantization.
what leads me to believe that is:
- odd floats are always positive, while even floats can be any sign => odd floats are ranges, even floats a reference values
- integer parameters always explore the complete range between 0xff and 0x00 or 0xffff and 0x0000 => normalized values
so a possible formula would be:
float0 + float1 * integer0 / integer_max
float2 + float3 * integer1 / integer_max
float4 + float5 * integer2 / integer_max
but it could also be something like that:
float0 + float1 * (integer0 - integer_max/2) / (integer_max/2)
float2 + float3 * (integer1 - integer_max/2) / (integer_max/2)
float4 + float5 * (integer2 - integer_max/2) / (integer_max/2)
Summing the obtained values doesn't really make sense as the cost for storing the 3 integers is 0.75 of 1.5times the cost of a float. At this rate storing a float would have been easier for similar storage cost and good enough accuracy.
So the question that remains is why is there 3 values per key-frame. For interpolation purposes?
If anyone has an idea, I'd gladly hear it.
PS: I added the resulting log (see: bayo.log) when applying the first formula for the example with flag 6, if it can help someone make sense of the obtained values.