Closed kinshadow closed 1 year 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.
@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.
@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.
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.
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.
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
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.
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.
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.
Vanguard front landing gear. I think the armature is messed up. Branch for this is issue-65-ivo-datastream
.
0xD9EED421
is probably another Normals format (found between VertsUV and Tangents, size of 4 byte).
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
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.
@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. :(
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 😊).
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.