Page 2 of 2

Re: Boiling Point: Road to Hell *.RF2

Posted: Wed Feb 09, 2022 10:50 pm
by E3245
grandshot wrote: Wed Feb 09, 2022 8:39 pm Trying to research bone anim format. By reverse engineering the verender2.dll file with included *.pdb, managed to get bone structures. Turned out what they having the following format:

Code: Select all

struct BONE {
    char name[20];
    byte parentID;
    byte groupID;
    byte rootGroupID;
    uint32 packedAnimSize;
    if( packedAnimSize )
    {
        PACKED_ANIM packedVectors;
        PACKED_ANIM packedQuats;
    };

};
PACKED_ANIM structure is next:

Code: Select all

struct PACKED_ANIM( int itemType ) {
    uint32 numPackedItems;
    PACKED_VECTOR3 item[numPackedItems]; //Vectors or Quats packed to 3x uint16 per item. Unpacking functions is included.
    ARRAY packedIDs;
    ARRAY originalIDs;
    uint16 numFrames; //total frame count for bone. Often same value as in header. Useful for determine structure ending.
};
Array structure in turn:

Code: Select all

struct ARRAY {
    uint16 numItems;
    uint16 numBits; //per item
    
    uint64 item : numBits  // in the count of numItems. uint64 because numBits can be 48. Bitfield padding off
    ubyte numBitsKey : 8;
    uint64 mask : numBits; //not used?
};
Main problem here is how to allocate correct size of items in array. No matter how I tried, I cant figure out. Obvious things such as numItems mul to numBits and align to ceil bytes dont fit here.
This is the last frontier in the fully research of the format. In attch I privide my 010 editor template for parsing bones and verender2.dll & pdb.

ve_boneanim_research.zip
From what I gathered in BipedBones section of the RF2 file, each bone has the following properties:

Code: Select all

 
char* name (Always 0x15)
byte parent;
byte group;
byte rootGroupID (I think this is supposed to be for special bone names);
uint32 MemoryCommitSize;
uint32 array_count
packed3DVector* v
packedQuat* q
The animation format is a series of Vector3 half floats (x, y, z) followed by a series of Quaternions shorts (x, y, z, w), so they're 1-to-1 with each other. There's always at least 2 array_count even for objects that assumingly have no animations to them (ded-ak47-low).

I still have not figured out the operations needed to turn it into a standard animation format, but I think it requires using Slerp(quat) and Lerp(vector), several unknown math operations, then converting the resultant 4x3 Matrix into a TAnimKey structure.

That's all I know so far. I've been busy writing tools to decompress the *.dt textures in the cache folder, parsing the map format, and documenting (and eventually writing tools to decompile) the LV2 file structure. I'm still trying to figure out the layer masks and the detail object layer but it's coming along.

EDIT: Upon further inspection, I was looking at the wrong place for this. I see that the sequence of data where i assumed the Quats were is actually a TShrinkedArray of elements or struct ARRAY in the quoted data structure.

According to IDA Pro, allocating a TShrinkedArray may look like this:

Code: Select all

 void __usercall TShrinkedArray::Allocate(TShrinkedArray *this@<esi>, int s@<ebx>)
{
  __int64 v2; // rax
  int v3; // ecx
  unsigned int *element; // edi
  unsigned int *v5; // eax
  size_t v6; // [esp-8h] [ebp-Ch]

  v2 = s * this->nBits + 31;
  v3 = ((BYTE4(v2) & 0x1F) + (int)v2) >> 5;
  if ( v3 != (this->nBits * this->array_size + 31) / 32 )
  {
    element = this->element;
    this->array_size = s;
    v5 = (unsigned int *)operator new(4 * v3);
    v6 = 4 * ((this->nBits * this->num + 31) / 32);
    this->element = v5;
    memmove(v5, element, v6);
    if ( element )
      operator delete(element);
  }
}

Re: Boiling Point: Road to Hell *.RF2

Posted: Mon Feb 21, 2022 1:29 am
by E3245
Animations support is almost done, just got to figure out how to sync the frames together.

Image

I wrote up a long post explaining my findings but it got wiped before I got a chance to post it :[

In short, I had to look around in the dlls and the RF2_Export.dlu that came with pdb symbols to figure out some information, from the Shrinked Array stuff, to the Vector3s and Packed Quats to Quats conversion. Shrinked Arrays are still a bit of a mystery with how they're structured but it's essential to get the proper key timings.

I'm not sure if I'll support movement vectors since it's a bit more complicated than it seems. We'll see though.

Re: Boiling Point: Road to Hell *.RF2

Posted: Mon Feb 21, 2022 10:18 pm
by grandshot
I'm also can't find a way how to allocate a proper size of these shrinked arrays. They should contain a 'Pack Indexes' which i'm imagine as ids of packed vectors & quats, and 'Original Indexes' which may pointing to frame positions on timeline.
2022-02-21.png
Anims in Vital Engine 2.0 should be framerate independent because they speed in fps sets in model settings.

Image

Movement Vectors it's just a positions of root bone per each frame on timeline.