RX3 file format research thread

Dmitri

Youth Team
Okay, trying to understand how bones are sorted in these tables.
I'm checking hair model with 23 "used bones".
First table:
upload_2020-6-8_16-8-19.png

You can see local IDs here, from 0 to 22 (0x16).

Second table:
upload_2020-6-8_16-9-54.png

Second table contains 23 bone IDs (real IDs) which are used on the mesh (0x91 = 145 - neck bone).

So we need to understand what are these local IDs. Why bones are sorted in such order?

0x91 - Neck [145]
upload_2020-6-8_16-18-54.png


0xA1 - Right_Throat_Helper [161]
upload_2020-6-8_16-19-24.png


0x92 - Neck1 [146]
upload_2020-6-8_16-20-19.png


0x93 - Head [147]
upload_2020-6-8_16-21-4.png


0xA5 - Jaw [165]
upload_2020-6-8_16-21-57.png


0xA3 - NeckBack_Helper [163]
upload_2020-6-8_16-22-26.png


...

This is not the order how they are placed in the skeleton.

Maybe they were used only for offline job (to connect with EA's modelling software)?
Or maybe they somehow used in the game?
 
Last edited:

tokke001

Senior Squad
Okay, trying to understand how bones are sorted in these tables.
I'm checking hair model with 23 "used bones".
First table:
View attachment 41971
You can see local IDs here, from 0 to 22 (0x16).

Second table:
View attachment 41972
Second table contains 23 bone IDs (real IDs) which are used on the mesh (0x91 = 145 - neck bone).

So we need to understand what are these local IDs. Why bones are sorted in such order?

0x91 - Neck [145]
View attachment 41973

0xA1 - Right_Throat_Helper [161]
View attachment 41974

0x92 - Neck1 [146]
View attachment 41975

0x93 - Head [147]
View attachment 41976

0xA5 - Jaw [165]
View attachment 41977

0xA3 - NeckBack_Helper [163]
View attachment 41978

...

This is not the order how they are placed in the skeleton.

Maybe they were used only for offline job (to connect with EA's modelling software)?
Or maybe they somehow used in the game?

from what i noticed,
it may be a noobish remark :) :
at the vertex data u ll find the BlendIndices
those are, for each vertex, 4 BlendIndices (4 unsigned bytes)
now,
those BlendIndices can be found in the section "RX3_SECTION_SKELETON" (1881640942)

it helped me to check a block with 1 bone in use :
at the head file,
block 2 is used for the eyes only:
* according to the vertex data (of all block2 vertexes) use 1 BlendIndice
* this BlendIndice can be found in RX3_SECTION_SKELETON (block 2), wich has only 1 bone


edit:
there s also the shader files?
data\fifarna\shader.big
data\fifarna\shader_boot.big
 

Dmitri

Youth Team
BlendIndices in Vertex Buffer are "real" bone IDs.

edit:
there s also the shader files?
data\fifarna\shader.big
data\fifarna\shader_boot.big
Probably. But I doubt they are stored in rx3 files. Maybe just compiled binaries.
 
Last edited:

tokke001

Senior Squad
BlendIndices in Vertex Buffer are "real" bone IDs.


Probably. But I doubt they are stored in rx3 files. Maybe just compiled binaries.

And in file skeleton.rx3 there are the boneids defined ?
Because not all games have that file i think

Let s say u want change the boneids (at a head model),
And the game has no skeleton file
Would it work with only editing that head model, or u guess other files (skeleton data) would be needed to edit
 

Dmitri

Youth Team
Maybe FIFA 14 skeleton is hardcoded in the executable. I don't know yet.
For head model editing skeleton is not necessary (until you want to move bones and see how mesh react on this).

I have some progress on research.
Sections IDs in RX3 files are actually hashes.
They were generated with this hashing function:
C++:
unsigned int FifaRX3Hash(std::string const &str) {
    unsigned int result = 5321;
    for (auto c : str)
        result = c + result * 33;
    return result;
}

Here's a list with original section names:
Code:
HASH       SUGGESTED NAME                   ORIGINAL NAME
1808827868 RX3_SECTION_TEXTURES_HEADER      texturebatch
2047566042 RX3_SECTION_TEXTURE              texture
5798561    RX3_SECTION_VERTEX_BUFFER        vb
582139446  RX3_SECTION_INDEX_BUFFERS_HEADER ibbatch
5798132    RX3_SECTION_INDEX_BUFFER         ib
255353250  RX3_SECTION_PARTIAL_SKELETON     boneremap
3751472158 RX3_SECTION_BONE_MATRICES        animationskin
1843792843 -                                edgemesh
3566041216 RX3_SECTION_PRIMITIVE_TYPE       simplemesh
3263271920 RX3_SECTION_VERTEX_DECLARATION   vertexformat
1285267122 RX3_SECTION_NAMES                nametable
685399266  RX3_SECTION_PROP                 location
4116388378 RX3_SECTION_HOTSPOT              hotspot
123459928  RX3_SECTION_MATERIAL             material
4185470741 -                                collision
4034198449 RX3_SECTION_COLLISION            collisiontrimesh
2116321516 RX3_SECTION_NODE                 sceneinstance
230948820  RX3_SECTION_NODE_NAME            scenelayer
2360999927 RX3_SECTION_2360999927           sceneanimation
3247952176 RX3_SECTION_MORPH                morphindexed
1881640942 RX3_SECTION_SKELETON             skeleton

Simple models

VertexFormat
Represents vertex declaration - vertex elements
Code:
struct Rx3SectionVertexFormat {
    unsigned int totalSize; // total size of this section
    unsigned int vertexFormatSize; // size of vertex format string, including null-terminator
    unsigned int padding[2]; // { 0, 0 }
    char vertexFormat[vertexFormatSize]; // vertexFormat, with null-terminator
    char[] align16;
};

Format string example:
Code:
p0:00:00:0001:4f16 n0:08:00:0001:3s10n g0:0C:00:0001:3s10n t0:10:00:0001:2f16 t1:14:00:0001:2f16 i0:18:00:0001:4u8 w0:1C:00:0001:4u8n
Elements are separated with space (" "), element attributes are separated with semi-colon (":") or double semi-colon ("::").
Possible string format:
Code:
%c%X:%02X:%02X:%04X:%s - usage, usageIndex, offset, unk0, unk1, dataType
%c%X:%02X:%02X:%s - usage, usageIndex, offset, unk0, dataType
%c%d:%X:%s - usage, usageIndex, offset, dataType
%c%d::%s - usage, usageIndex, dataType
usage (single character):
Code:
b - binormal
c - color
g - tangent
i - blendindices
n - normal
p - position
t - texcoord
w - boneweights
usageIndex - might be used for colors or texcoords (first UV set, second UV set etc.)
offset - offset in the stream (starts with 0)
unk0 - unknown, maybe stream index. Usually 0
unk1 - unknown. Usually 1
dataType:
Code:
name       elements  total size  element size
----------------------------------------------
void           0          0          0
1f32           1          4          4
1s32           1          4          4
1s16           1          2          2
1s8            1          1          1
2f32           2          8          4
2s32           2          8          4
2s16           2          4          2
2s8            2          2          1
3f32           3          12         4
3s32           3          12         4
3s16           3          6          2
3s8            3          3          1
4f32           4          16         4
4s32           4          16         4
4s16           4          8          2
4s8            4          4          1
4u8            4          4          1
4u8n           4          4          1
4u8n           4          4          1
4u8endianswapp 4          4          1
4u8nendianswap 4          4          1
2s16n          2          4          2
4s16n          4          8          2
3u10           3          4          4
3s10n          3          4          4
3s11n          3          4          4
2f16           2          4          2
4f16           4          8          2
2s16s          2          4          2
3s16s          3          6          2
1u16rgb565     1          2          2
3u8rgb8        3          3          1
4u8rgbx8       4          4          1
1u16rgba4      1          2          2
3u8rgba6       3          3          1
4u8rgba8       4          4          1
2u16           2          4          2
4u16           4          8          2
2u16n          2          4          2
4u16n          4          8          2
custom         4          0          0

VertexBuffer
Represents vertex data
Code:
struct Rx3SectionVertexBuffer {
    unsigned int totalSize; // total size of this section
    unsigned int numVertices;
    unsigned int vertexStride;
    unsigned char unknown1; // 0 or 1
    char padding[3];
    unsigned char vertexData[numVertices * vertexStride]; // vertices, format is defined by VertexFormat section
    char[] align16;
};

IndexBuffer
Represents index data
Code:
struct Rx3SectionIndexBuffer {
    unsigned int totalSize; // total size of this section
    unsigned int numIndices;
    unsigned char indexSize; // usually 2
    char padding[7]; // 0
    unsigned char indexData[numIndices * indexStride]; // indices
    char align16[];
};

Complex models

RX3_SECTION_NODE
Node is a part of scene hierarchy. Each node has its own transform space. A node consists of meshes.
Code:
struct Rx3NodeHeader { // sizeof() = 120 bytes
    unsigned int size; // size of the whole section - with header, data and padding
    unsigned int status; // 1 if used, 0 if unused (according to FIFA 15 3D importer/exporter; I didn't see files with '0' yet)
    int unknown1; // always -1
    int unknown2; // always 0
    Matrix4x4 transform; // sizeof() = 0x40, usually an identity matrix
    BBox bbox; // sizeof() = 0x20, 2x Vector4 (min, max)
    unsigned int numMeshes;
    int unknown3; // always -1
}
The header is followed by Mesh descriptors:
Code:
struct Rx3NodeMeshDescriptor { // sizeof() = 40 bytes
    BBox bbox; // bounding box of the mesh
    unsigned int meshIndex; // starts with 0, index for vertex buffer and index buffer
    unsigned int materialIndex; // starts with 0, index for material
};

RX3_SECTION_NODE_NAME
Name for the node. It's also used for collision part.
Code:
struct Rx3NodeNameHeader { // sizeof() = 16 bytes
    unsigned int size; // size of the whole section - with header, data and padding
    unsigned int type; // 0 for collision name, 1 for regular node name
    unsigned int unknown1[2]; // always 0? maybe padding
};
This header is followed by null-terminated string (the name).
The struct is then followed with 4-byte or 2-byte (can't be figured out at the moment) value:
Code:
struct Rx3NodeNameNodeIndex { // sizeof() = 4 bytes (or 2 bytes)
    unsigned int nodeIndex; // index of the node this name corresponds to - starts with 0 (it's usually 0 if name is related to collision - might be collision part index)
};

RX3_SECTION_PROP
Represents point and rotation in the scene.
Code:
struct Rx3Prop { // sizeof() = 32 bytes
    unsigned int size; // size of the whole section (32)
    Vector3 position;
    Vector3 rotation;
    unsigned int unknown1; // always 0? maybe padding
};
Prop names are stored in RX3_SECTION_NAMES section, with RX3_SECTION_PROP ID.

RX3_SECTION_MATERIAL
Represents a material.
Code:
struct Rx3MaterialHeader {
    unsigned int size; // size of the whole section - with header, data and padding
    unsigned int numTexMaps; // number of texture maps
    unsigned int unknown1[2]; // always 0? maybe padding
};
The header is followed by shader name (null-terminated string).
The name is followed by texture maps descriptors. Each descriptor consists of texture type name ("diffuseTexture", "normalMap", etc.) and texture index in textrure names from model's names section (32-bit integer).
Code:
Rx3MaterialHeader header
for numTexMaps
    string texTypeName (null-terminated string)
    unsigned int texId

RX3_SECTION_COLLISION
Represents collision mesh for some stadium parts.
Code:
struct Rx3CollisionHeader {
    unsigned int size; // size of the whole section - with header, data and padding
    unsigned int unknown1; // always 1?
    unsigned int unknown2[2]; // always 0? maybe padding
};
The header is followed by collision name (null-terminated string), unknown 32-bit integer (always 1?), number of collision triangles (32-bit integer) and an array of triangles (each triangle is represented with Vector3 struct for 3 vertices).
 
Last edited:

tokke001

Senior Squad
VertexBuffer
Represents vertex data
Code:
struct Rx3SectionVertexBuffer {
    unsigned int totalSize; // total size of this section
    unsigned int numVertices;
    unsigned int vertexStride;
    unsigned int padding; // 0
    unsigned char vertexData[numVertices * vertexStride]; // vertices, format is defined by VertexFormat section
    char[] align16;
};

for the vertexbuffer,
i notice the padding is sometimes a 1 value, not sure what this value is
also could be it is a integer (like u say), or maybe a byte and 3 paddings?

maybe this is an indicator if the vertex data is big or little endian format:
at fifa 11 (big endian), this is 0
newer fifas (little endian) is 1

i have had rx3 files wich had a rx3b header (big endian file),
but only the vertex data was in little endian format: and the (unknown) value i mention was 1
 

Dmitri

Youth Team
Indeed, "local" bone IDs from BoneRemap section (previously PARTIAL_SKELETON) are written into VertexBuffer, so they replace original "real" bone IDs in BlendIndices.

I think I won't be able to explain it until I make a working FBX>RX3 converter and try different combinations in-game.
Maybe order in local bone IDs doesn't matter.

at fifa 11 (big endian), this is 0
newer fifas (little endian) is 1
Could be one byte + 3 bytes padding. When the game reads this section, for big-endian case it swaps only first 3 integers (totalSize,
numVertices, vertexStride).

.
 

tokke001

Senior Squad
Possible string format:
Code:
%c%X:%02X:%02X:%04X:%s - usage, usageIndex, offset, unk0, unk1, dataType
%c%X:%02X:%02X:%s - usage, usageIndex, offset, unk0, dataType
%c%d:%X:%s - usage, usageIndex, offset, dataType
%c%d::%s - usage, usageIndex, dataType

it could be unk0 is the DeclarationMethod, wich is usually 0 :
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb322869(v=vs.85)
or streamindex like u say, but small detail this is...

(DeclarationMethod is at fifa 11 also always 0 i notice)
 
Last edited:

ramzidz15

Club Supporter
Indeed, "local" bone IDs from BoneRemap section (previously PARTIAL_SKELETON) are written into VertexBuffer, so they replace original "real" bone IDs in BlendIndices.

I think I won't be able to explain it until I make a working FBX>RX3 converter and try different combinations in-game.
Maybe order in local bone IDs doesn't matter.


Could be one byte + 3 bytes padding. When the game reads this section, for big-endian case it swaps only first 3 integers (totalSize,
numVertices, vertexStride).

.
Dmitri How do I know the skeleton of my FIFA 19 Ps3 game Because I only find a file skeleton_player On FIFA 20 switch
But on the old FIFA does not exist
 

Attachments

  • uoKwdP7.png
    uoKwdP7.png
    959.6 KB · Views: 101
Last edited:

Dmitri

Youth Team
I made some additional tests in FIFA 14 on BlendIndices, BlendWeights and BoneRemap section.

1. There are no "empty" bone indices. Even if weight value is zero, it is attached to some existing bone.
Normally it should be first used bone of the vertex, or last used bone.
Code:
BlendIndices 93 00 00 00 - wrong
BlendIndices 93 93 93 93 - correct

2. Bone weights are normalized and their sum is equal to 255.
Code:
BlendWeights E0 1E 00 00 - wrong (sum FE)
BlendWeights E1 1E 00 00 - correct (sum FF)

3. Order in BoneRemap is related to vertices order (forward) and bone indices order in the vertex (reverse).
Taking these 3 vertices as example:
Code:
Vertex1 BlendIndices 01 02 03 04
Vertex2 BlendIndices 05 03 04 06
Vertex3 BlendIndices 03 05 07 08
BoneRemap order will be:
Code:
04 03 02 01 06 05 08 07

4. I'm currently facing some unknown problem with newly-created models.
When I'm using all 64 bones, with 4 bones per vertex and with all vertex weights set, the mesh is deformed wrongly.
fifa14 11840.png
Reducing the total number of bones in the mesh just to 3 solves this, but there are no facial animations (I left only Head, Neck and Spine bones)
fifa14 11844.png
Reducing the number of bones per vertex to 2 makes deformations less noticable.
fifa14 11846.png
Reducing the number of bones per vertex just to 1 also completely solves it, but facial animations are not precise.
fifa14 11847.png

It might be some another limit.
My guess:
a) a limit of vertices which can be affected by 4, 3 or 2 bones (similar to old-gen (FIFA10 era) limits)
b) incorrect vertex sorting in the mesh
Probably it's something else what I can't even imagine at the moment.

Dmitri How do I know the skeleton of my FIFA 19 Ps3
I know nothing about ps3 game.
 

ramzidz15

Club Supporter
I made some additional tests in FIFA 14 on BlendIndices, BlendWeights and BoneRemap section.

1. There are no "empty" bone indices. Even if weight value is zero, it is attached to some existing bone.
Normally it should be first used bone of the vertex, or last used bone.
Code:
BlendIndices 93 00 00 00 - wrong
BlendIndices 93 93 93 93 - correct

2. Bone weights are normalized and their sum is equal to 255.
Code:
BlendWeights E0 1E 00 00 - wrong (sum FE)
BlendWeights E1 1E 00 00 - correct (sum FF)

3. Order in BoneRemap is related to vertices order (forward) and bone indices order in the vertex (reverse).
Taking these 3 vertices as example:
Code:
Vertex1 BlendIndices 01 02 03 04
Vertex2 BlendIndices 05 03 04 06
Vertex3 BlendIndices 03 05 07 08
BoneRemap order will be:
Code:
04 03 02 01 06 05 08 07

4. I'm currently facing some unknown problem with newly-created models.
When I'm using all 64 bones, with 4 bones per vertex and with all vertex weights set, the mesh is deformed wrongly.
View attachment 42579
Reducing the total number of bones in the mesh just to 3 solves this, but there are no facial animations (I left only Head, Neck and Spine bones)
View attachment 42580
Reducing the number of bones per vertex to 2 makes deformations less noticable.
View attachment 42581
Reducing the number of bones per vertex just to 1 also completely solves it, but facial animations are not precise.
View attachment 42582

It might be some another limit.
My guess:
a) a limit of vertices which can be affected by 4, 3 or 2 bones (similar to old-gen (FIFA10 era) limits)
b) incorrect vertex sorting in the mesh
Probably it's something else what I can't even imagine at the moment.


I know nothing about ps3 game.
Dmitri
I follow your research
Playstation has the same structure as Nintendo and PC
Just some differences in texture and size.
 

tokke001

Senior Squad
i think i dont know too much about bones,
but it may help trying some things (for testing) maybe with the eyes of headfiles (wich only uses 1 bone type)
block 2 of head files are used for the eyes only

1. There are no "empty" bone indices. Even if weight value is zero, it is attached to some existing bone.
Normally it should be first used bone of the vertex, or last used bone.
Code:
BlendIndices 93 00 00 00 - wrong
BlendIndices 93 93 93 93 - correct

u are sure option 1 is wrong?
i know at fifa 11 these boneindices (at vertexdatas) are used for the eyes:
Code:
00 00 00 33
but maybe this is only fifa 11...
 

Dmitri

Youth Team
I figured it out.
fifa14 11849.png

It was this:
2. Bone weights are normalized and their sum is equal to 255.
Bone weights should be normalized and their sum must be equal to 255.
If you don't do so, you will have problems like shown on previous screens.

block 2 of head files are used for the eyes only
What is block 2?

Another thing I found, bone matrices (AnimationSkin section) might be different, even in head files.
Not sure if it's important, maybe each head might have its own skeleton.
 

Dmitri

Youth Team
I need file samples (rx3 models&textures) from FIFA 12/ FIFA 13/ FIFA 15/ FIFA 16:
heads, hairs, body, balls, boots, gloves, kits, stadiums, trophies
If someone have these games, please extract/decrypt files for me.

How about boots mate? Does all this theory apply to them as well?
Yes, I think it's same for all skinned meshes.
 

Dmitri

Youth Team
Sections added in FIFA 15:
Code:
1881640942 skeleton
283785394  clothdef

Sections added in FIFA 16:
Code:
341785025  quadibbatch
191347397  qib
137740398  bonename
899336811  adjacency
 

mita996

Youth Team
I need file samples (rx3 models&textures) from FIFA 12/ FIFA 13/ FIFA 15/ FIFA 16:
heads, hairs, body, balls, boots, gloves, kits, stadiums, trophies
If someone have these games, please extract/decrypt files for me.


Yes, I think it's same for all skinned meshes.
@Wujek
 

pao4ever

Starting XI
I need file samples (rx3 models&textures) from FIFA 12/ FIFA 13/ FIFA 15/ FIFA 16:
heads, hairs, body, balls, boots, gloves, kits, stadiums, trophies
If someone have these games, please extract/decrypt files for me.


Yes, I think it's same for all skinned meshes.
That's excelent! Could you try this, as well please?
 

V.K

Starting XI
I need file samples (rx3 models&textures) from FIFA 12/ FIFA 13/ FIFA 15/ FIFA 16:
heads, hairs, body, balls, boots, gloves, kits, stadiums, trophies
If someone have these games, please extract/decrypt files for me.


Yes, I think it's same for all skinned meshes.
@pe pe @Re_coded maybe you guys have some of those files
 

Dmitri

Youth Team
I've checked FIFA 13 face files.
They are very similar to FIFA 14.
Files which I checked are big-endian (RX3b). I think FIFA engine can load both big/low endian (at least, FIFA 14 can).
Other than this, I saw only 2 differences:
- skeleton. There are more bones in FIFA 14 (255) than in FIFA 13 (252).
- texture mapping. Placement of ears, teeth and some other parts is different (image is taken from FIFA forum):


That's excelent! Could you try this, as well please?
Try what?
 


Top