No problem... the comments basically store all the important information, that didn't find a home in milkshape.
So, call it "metadata", or whatever.... everything that is important for the files and the game, which can't be stored otherwise, is in the comments. In fact, some of it is redundant (e.g. equipment names shorter than 40 chars don't need that extra name in the comments, in theory, but it doesn't hurt). I need this information at least on export, to recreate what the game uses as data... of course, most of those settings can be changed to other values, e.g. shader parameters or attaching a drum on the back instead of the hips, etc.. Don't know how hardcoded the game is, you'll see when you play around with it.
About your text file - that is *exactly* what the extra-plugins do. It's manual, but I think cleaner for the following reasons:
- you can share "comments" across different files (e.g. all hats probably work the same, etc.)
- it's decoupled and reusable for other stuff you do in milkshape (there's many other plugins that depend on those comments, I noticed that while searching for something in the ms3d forums)
- you can preserve your own notes
- you don't get bugged on every export where that file is, etc..
- don't know what the exact ETW bone, that Primergy mentioned, was on the technical side, but I would bet that this approach might solve this as well (but maybe the author just hardcoded the ETW skeleton in the plugin, back then)
A typical workflow would look like:
1) load a .variant_part_mesh
2) export the comments to some file
3) export the ms3d scene to some other program, e.g. blender, 3dsmax, uu3d..., close milkshape
4) open blender, 3dsmax, uu3d, ... whatever, modify your data, then reexport to ms3d
5) open new unit mesh in ms3d
6) import the comments metadata stored in 2)
7) export back to .variant_part_mesh
About any bugs, etc. you come across - the file .variant_part_mesh format is very simple, and since I support it completely by now... no problem - just contact me if something needs to be changed or whenever something comes up. I'll be able to squeeze that in, somehow.
About the "many weeks" of fiddling around - in fact, like I said, I'm just super-busy at the moment and simply didn't get around working on it, a lot... if I count the evenings I spent on writing this, I might have spent 5 evenings, total, not more. I mean, I do pretty much exactly the same stuff at work every day, so it's not really a big mystery to me... and thanks to 'just', we didn't have to reverse engineer.
Everything is straightforward in those files, except for one detail in the type 1 models. The catch is type 1's "double position" and "double normal" storage, which is uncommon - however, after thinking about the reason for a few minutes, and knowing that there's a max bone influence count of 2 per vertex, it was pretty clear - it's simply precomputed, namely:
pos0 = originalPos * inverseGlobalBindPoseMatrixOfBoneInfluence0
pos1 = originalPos * inverseGlobalBindPoseMatrixOfBoneInfluence1
Same for the normals, IF the scale of the mesh is uniform (which seems to be the case for all the models).
This design saves 2 matrix computations per vertex per frame in the game, and (my guess) makes it probably easier to implement this component based unit system. This is probably a nice optimization, b/c the game deals with a lot of units. It's not commonly used in other games, as the drawbacks are decreased flexibility, in some ways, namely blending animations might be harder to do, inverse kinematics as well, and the file sizes increase. All this is not important for the game, though... There might be more reasons, but well... creative assembly would know best. I have not seen such a system applied somewhere else, so that's probably why other people trying to write loaders got stuck at this point - simply not knowing why this is stored that way.
I don't think there was anything else in the file format itself that kept me busy... The orientation issue turned out to be an issue with milkshape. Milkshape wants to have bone orientations as Euler angles, and there's 24 different possible combinations of specifying those... and well, Milkshape doesn't tell you which one. Furthermore it's not clear in which space they are applied, if it's degrees or radians, etc.. It turns out that Milkshape uses parent space, radians and XYZs order... the latter is a bit weird, as the gimbal lock problem tends to happen in a non-intuitive place, but well... we don't animate in milkshape. That took me a while to figure out, however, writing plugins for more advanced tools shouldn't be a problem, as most of them accept this data in alternative representations.
No really, that said, I guess there is really nothing fancy in the file format. The way data is stored is common, mainly to save space, sacrificing precision. 16 bit floating point numbers are possibly a bigger problem to implement, as most programming languages don't support them natively (and the hardware doesn't either, except for a lot of gfx cards). Especially in scripting languages, they might be a pain in the neck. Personally I had own code for that, already, so it wasn't a problem for me.
Maybe just post this? Might be interesting for others...