Decoding the Saints Row 3 mesh format.

Well I've managed to get the Morph file working on Shaundi. The startingpoint is indeed the npc_basehead model. I'm just having some trouble finding the right scales to use as it seems that the X, Y and Z scales are variables. I'm sure they are defined somewhere in the files, so I will be looking for that in the coming days. I've also ironed out some of the issues with other character files. The script is now able to import all character models! :) Check out the high-res head model!

Morphtest.png
Is the script available to download somewhere? I'd be interested in porting it to Blender/Python.
 
Sure, but they are still in development so things are going to change over time;
SRIII formatdescription and maxscripts

There is already quite some blender stuff available I think;
http://forum.xentax.com/viewtopic.php?f=16&t=10987
http://forum.xentax.com/viewtopic.php?f=16&t=9361

Ps, here's a new screenshot of the progress on shaundi. Corrected normalmaps and a nice high-res head model. Doesn't she look good?
SRIII_importer_V8.jpg


Next step is proper material parsing. I deleted the old stuff and need to re-write it properly. And I need to figure out how the materials are being constructed.
 
Last edited:
Sure, but they are still in development so things are going to change over time;
SRIII formatdescription and maxscripts

There is already quite some blender stuff available I think;
http://forum.xentax.com/viewtopic.php?f=16&t=10987
http://forum.xentax.com/viewtopic.php?f=16&t=9361

Ps, here's a new screenshot of the progress on shaundi. Corrected normalmaps and a nice high-res head model. Doesn't she look good?
SRIII_importer_V8.jpg


Next step is proper material parsing. I deleted the old stuff and need to re-write it properly. And I need to figure out how the materials are being constructed.


Give this man two bottles of rum, gentlemen!
Awesome work.
 
Fixed a small issue in the importer, so now we have Oleg!
Download new version here:

I still haven't figured out where the proper scales are referenced. They should be in the files somewhere. It seems very unlikely that they are hardcoded.
Also still have to write a proper material parser. These textures were all manually applied. The old material stuff I had was shit.

SRIII_Oleg.jpg
 
Here's what I figured out about the material format in SR4 so far by playing with the material cruncher:

matlib_pc format:

Code:
char[4] signature
uint64 strings_size
uint64 strings_count
align 16
char[strings_size] strings1 // zero terminated strings
align 16
uint8[56] unknown1
uint64 materials_count
uint8[32] unknown2
material[materials_count]
char[strings_count][] strings2 // No size, just keep reading strings until you have strings_count of them

Material for ir_at_bbsimple1. ir_at_bbsimple3 is similar, except it does not have unknown6 to unknown12.

Code:
uint64 size // size of the material entry
uint8[8] unknown1
uint32 flags
uint8[4] unknown2
uint8[36] unknown3
uint8[4] unknown4
uint8[4] unknown5
uint32 unknown6
uint8[4] unknown7
uint32 unknown8
uint32 unknown9
uint8[4] unknown10
uint32 unknown11
uint8[28] unknown12
uint8[12] unknown13
fxparam[] params
uint8[32] unknown32

fxparam is always 16 bytes and can be a single float or vector of 4. The amount and type is defined in each shaders .fxinfo_pc file. They are inside the shaders.vpp_pc file for the SRIV SDK.

Flags

Code:
Mat_Alpha_Mode 0x2
Mat_Glows 0x4
Mat_Distortion 0x8
Mat_Cull_Mode 0x10
Mat_Shadow_Cull_Mode 0x200
norender 0x1000

I used uint8 as the generic bytes type. The difference between uint8[4] and uint32 is that uint8[4] usually has values higher than 1 million, which is very uncommon for actual integers, I suspect they're hashes. Everything I wrote is mostly guessing, don't be confused if it doesn't match up with your files.

Here's a gist with my Python (3) code: https://gist.github.com/Yepoleb/ce56be1f52322ae69887c2ed0736983f
 
Thanks man! To be honest I've been spending some time investigating the rig_pc files for characters and have now got a proper rig parser. Next Item on the agenda is to figure out the vertex weights to rig the character to the bones. I think I already found out how to do that.
After this I will work on the materials and have a proper look at your findings ;)
 
Okay, after some fiddling I figured out the structure at least. There are still a lot of unknowns though
Code:
int Align(int length){
    local int val = FTell();
    while (val > length) {
        val = val-length;
    }
    val = length-val;
    return val;
}

struct TEXTURENAME {
    char Name[];
};

struct TEXTURENAME2 {
    char Name[];
    byte zero1;
    byte spacing[Align(2)];
};

struct SUBMAT {
    int bitmapnamestart;  
    byte crc[4];  
    int matindex;
};

struct MATERIAL {  
    int64 matsize;
    byte unknown1[8];
    int flags;
    byte bitmap_count;
    byte unknown2;
    byte chunk_count;
    byte unknown3;
    byte unknown4[32];//0
    SUBMAT submats[bitmap_count];
    int unknown6[chunk_count];
    byte spacing1[Align(16)];
    float transforms[unknown3*4];
};

int CRC;
int textures_size;
int null1;
int textures_count;
int null2;
byte spacing1[Align(16)];
TEXTURENAME TextureNames[textures_count] <optimize=false> ;
byte spacing2[Align(16)];
int unknown1[6];
int materials_count;
int unknown2;
int materialslength; //the part between both texturename entries
int unknown3[5];
int entrycount;
int unknown4;
int matstartpositions[entrycount];
byte spacing3[Align(16)];
int64 matlenghtorsomething[entrycount];
byte spacing4[Align(16)];
MATERIAL Materials[materials_count] <optimize=false>;
TEXTURENAME2 TextureNames2[textures_count] <optimize=false> ;
byte spacing5[Align(16)];

This is a part of a script I made for 010 Editor. I find it to be a pretty useful application for file format checking because it is very easy to make scripts that can parse the files and you can quickly see your errors.
Anyway, still working on this at a slow pace. Hopefully the material parser will prove to be useful.

EDIT: smal update with proper parsing right now. Still a lot of unknowns though ;)
 
Last edited:
I have done some work on this again. I figured out the ccmesh_pc file has identical information as the matlib_pc file, but it refers to the low-res materials that are default for the characters. All at the end of the file. I've managed to create a proper material parser, and I managed to use scanti's SR3Unpacktextures tool in combination with the maxscript to automatically unpack the textures. So now we have automatic material creation! :) Many models now successfully import, apart from a little few. So there is still a little tweaking that needs to be done. Other than that, things are starting to get somewhere! :)

2017-08-20_11h55_48.png


2017-08-20_12h59_45.png
2017-08-20_13h04_10.png
 
I have done some work on this again. I figured out the ccmesh_pc file has identical information as the matlib_pc file, but it refers to the low-res materials that are default for the characters. All at the end of the file. I've managed to create a proper material parser, and I managed to use scanti's SR3Unpacktextures tool in combination with the maxscript to automatically unpack the textures. So now we have automatic material creation! :) Many models now successfully import, apart from a little few. So there is still a little tweaking that needs to be done. Other than that, things are starting to get somewhere! :)

2017-08-20_11h55_48.png


2017-08-20_12h59_45.png
2017-08-20_13h04_10.png
Unfortunately you can only like a post once, so I needed to comment to show that extra bit of appreciation :)
 
We are in luck! For the heads I have investigated so far, one of the vertices for the eyes is always the same index. That means I was able to determine where the morph should end up and from there I could calculate the scale values needed for the morph file to start working! So now we have automatic high head model import! yeay! I still wonder where the scales can be found without my dirty trick, because this won't work on morph files that are used for other items such as clothing and accessories I'm afraid...
The screen below shows the LOD head and the HIGH head on top of each other. They fit perfectly :)

2017-08-29_20h44_42.png


From now on I will focus on cleaning up the script and making it more robust. Also I would like to be able to import ALL models without issues, so that will be the focus for the coming time. After that I will try to get that white hair to have the right color. Hopefully I don't have to go all the way into the shaders for that... I'm hoping there is a diffuse color in the matlib_pc file somewhere. After that I will focus on getting the rig files to work. I can already import them, but I am running into an issue where max crashes upon skinning the rig with the model. But all in good time... ;)
 
Last edited:
Back
Top