Markemp / Cryengine-Converter

A c# program to convert Crytek files to Collada (XML) format
https://www.heffaypresents.com/GitHub/
GNU General Public License v2.0
209 stars 53 forks source link

Unknown IVO Chunk Type in some Star Citizen .skin files #65

Closed kinshadow closed 1 year ago

kinshadow commented 2 years ago

I am working with the new Star Citizen game armors (notably the grin folder / Grey Cat armor from the 3.14 PTU). In the last release (1.2.0), the support of these IVO files is a mixed bag. For instance, the GRIN Helmet LOD2 works (m_grin_utility_medium_helmet_01_lod2.skin), but the full geometry file fails (m_grin_utility_medium_helmet_01.skin) with a invalid object error.

I have also tried the most recent master and branches (I'm eager to get these files converted). Changes to the chunk handling code show these files (both of the ones mentioned above and all of the GRIN) have an unhandled chunk type (type 20), which causes the ChunkIvoSkin to go into an infinite loop in the case statement as there is no default.

Markemp commented 2 years ago

Yup, working on these right now. I'm releasing a 1.3.0 version Soon(TM), hopefully in the next few days, that should address these issues.

Markemp commented 2 years ago

@kinshadow , can you test this against the 1.3 version? Let me know if it doesn't work. I don't have the 3.14 files yet, so hopefully they haven't made any more changes to the #ivo file format.

kinshadow commented 2 years ago

@Markemp It seems to fix more of the GRIN files, but doesn't finish on the helmet files I mentioned above. I haven't run it in debug yet, so I don't know if it is the exact same loop error. I'll try and run it in debug later today.

vmxeo commented 2 years ago

Interesting. From my testing It chews through most assets, and then will just get stuck. One example is:

\Objects\Spaceships\Ships\CRUS\Starlifter\Exterior\CRUS_Starlifter_Rear_L_LandingGear_SKIN.skin

I'm going to try again with debugging output.

Markemp commented 2 years ago

The #ivo files have some really weird boundary checking stuff going on. Unlike previous datastream chunks, there is no indication on how big a chunk is, or where the end point of that chunk is. So I have to calculate it by taking the number of elements in the datastream with the size of the elements (given info). However, sometimes there is padding to make sure the next datastream chunk starts at a word boundary.

For the indices datastream, the boundary can have either no padding (next datastream starts at the next byte), 2 bytes, or 4 bytes. I thought at first it was based on odd vs even number of elements, but I found 2 examples (landing gear and mobiglass) where one had no padding and the other had 1 word of padding. So now for indices, I peek at the next character. If it's 0x0, then I assume it's padding and skip those next for bytes. Otherwise, it goes to the next datastream.

Other datastream types probably have similar boundary issues, so I will need to check a few different files to see where those are failing. That is where the endless looping is happening too, btw.

Finally, the face morph stuff isn't implemented yet for ivo files, so... yeah. That will happen down the road a bit. I'm not sure if that includes helmets or not.

kinshadow commented 2 years ago

I checked out the helmet and compared it to the chunk order in the other GRIN files. The GRIN ARMS show an order of IVOINDICES, IVOVERTSUVS, IVOTANGENTS, IVOBONEMAP. The Helmet shows the same order, but the code reports a chunk in the middle: IVOINDICES, IVOVERTSUVS, 0xd9eed421, IVOTANGENTS, IVOBONEMAP (I wrote a quick default case to skim ahead to the next recognizable chunk value).

I thought perhaps this is an issue with the NumElements in the chunk for IVOVERTSUV, but I tried the helmet primary and the LOD2 version and they both have the same issue with the same extra chunk value. Note, the LOD2 version works fine with the previous 1.2.0 cgf-converter. IVOVERTSUVS: b.BaseStream.Position = 0x0000000000021038 0xd9eed421: b.BaseStream.Position = 0x00000000000694a8 IVOTANGENTS: b.BaseStream.Position = 0x0000000000077bf8

Markemp commented 2 years ago

m_grin_utility_medium_helmet_01.skin has a new chunk type (BShapesGPU (57A3BEFDh)) that I haven't run across yet. Blend shapes? Will need to sort out what that is doing. I think I've processed blend shapes previously, so maybe it won't be too bad?

Narrator: It'll probably be that bad.

kinshadow commented 2 years ago

The cgf-converter 1.2.0 version would output visually valid geometry LOD2 version of the helmet and it seems like that file also includes the new chunk type. Perhaps the geometry is still usable if the new chunk is skipped? I tried adding that in myself, but I seem to be missing something as I always hit a bad object pointer in the UV translation code.

Markemp commented 2 years ago

I think you're right; the geometry will be valid. Calculating the end of that chunk needs to be solved though. It's probably similar logic to indices, but will need to test a few different files to make sure. It's only a 4 byte chunk, so not really sure what it is. The last byte looks like it is always FF though. It's the branch I'm currently working on, so hopefully I'll have an answer soon.

Markemp commented 2 years ago

image

Vanguard front landing gear. I think the armature is messed up. Branch for this is issue-65-ivo-datastream.

Markemp commented 2 years ago

0xD9EED421 is probably another Normals format (found between VertsUV and Tangents, size of 4 byte).

vmxeo commented 2 years ago

Compiled 1.3.1 yesterday and ran it on a number of test files. On the armor and landing gear assets I tested on, some assets now successfully convert that didn't before, though other assets that did now don't. One example is CRUS_Starlifter_Front_LandingGear_SKIN.skin - this worked in 1.3 but doesn't in 1.3.1

kinshadow commented 2 years ago

The helmet now seems to work! Thanks! You've saved my cosplay :)

If I get a chance, I'll see if I can do a survey of which were fixed and which were broken by 1.3.1.

Markemp commented 2 years ago

@ventorvar , I think you provided the Load_IVOChrSkin.cpp file, which looks like a Ghidra analysis. If so, there is some code in there that need to sort out:

if (num_chunks == 0x9293b9d8) {
        if (chunk_hdr_offset[-1] != 0x900) {
          FUN_14012fe30();
        }
        *(char **)(skin_struct? + 0x62) = in_buffer + *chunk_hdr_offset;
      }

~0x9293b9d8 is the datastream stuff for Ivo files. That function FUN_14012fe30... I think I need that to sus out the remaining pieces of skin info. Any chance you can get the Ghidra output of that for me?~

Scratch that... that is the error output function. Whatever the other branch is what I need to figure out. :(

Markemp commented 1 year ago

Ok, this model file is working now, complete with the armature and proper mapping between bones and geometry (v1.5.0, coming Soon™).

The material file is relative to the base of the game, so using -objectdir is important (as always 😊).