(1) Where's the data stored?
In Milkshape the group name, type, and flag are stored in the group
comments and the bounding sphere data is stored in the model comment.
In 3ds Max and Gmax the name of a given mesh is the group name and
the group type and flag are stored in user defined properties. To see them
select the mesh with the Select Objects dialog, then under the edit menu
item select Object Properties, then select the User Defined tab to see
the group name and flag. The bounding sphere is stored in the root bone:
bone_pelvis for humanoids, bone_H_Saddle for horses, bone_camel_root
for camels, bone_E_platform for elephants, and USUALLY bone_body for
siege engines. The bounding sphere is stored as ASCII floats joined by
% signs. (Oddity of Gmax, maybe of 3ds Max, you can store strings with
spaces in User Properties and see them there, but only the first whole
word comes back out, hence the need to make strings with no spaces.)
When dealing with animated files, the .cas header, hierarchy, and footer
strings are stored in the first three joint comments in Milkshape.
In 3ds Max and Gmax they are stored in the root bone as well and you
can see them in User Properties. They also are ASCII format numbers
joined by percent signs. Underscores would have looked better but
texture paths for siege engines have underscores so I couldn't use
them because I tokenize the string based on the chosen delimeter.
Naturally for siege engines, the three texture paths are stored here,
it's just that their keywords are: animheader, animhierarchy, and
animfooter. This may change if I get animation utilities to work with
siege engines.
(2) Known Deficiencies:
The script works on unanimated regular units converted by GrumpyOldMan's
converter and unanimated mounts and siege engines converted by my
Python converter. It also works for animated regular units and mounts.
It WON'T work for animated siege engines because I store the three
texture paths for siege engines in the joints comments but I also
store the .cas file animation headers, hierarchy, and footers in the joints comments. Haven't worked through this conflict yet.
Not a deficiency of this script but if people are going to start using the
Python animation utilities (version 1_1 uploaded June 18, 2007) there are
three known bugs.
1 - on line 1092 in the animextract function there's this extraneous entry
float_vec3.fromfile( fidcas, 7 )
I can't fathom how it got there, it wasn't there when I tested everything.
Just comment it out with a pound sign like
# float_vec3.fromfile( fidcas, 7 )
2 - Converttxttocas doesn't convert the degrees back to radians. Oops,
it's fixed just have to post an updated copy.
3 - I didn't check for uppercase extensions so some cas files that look like
name.CAS
don't get exported to. Bwian found this one in the exportskeleton function. Also fixed just not released.
(3) Modifier Stack:
The export only works if the skin is at the top of the modifier stack for
each mesh in the model. You can do this manually by clicking and holding
the modifier and moving it. A "feature" of Gmax at least is that if you do
this to the skin modifier to move it to the top of the stack it loses all
its information about bone assignments and weighting. On the other hand,
if you manually move all other modifiers below the skin modifier, the
information is retained and the export works. I've duplicated this procedure
in the script so that if the skin modifier is NOT at the top of the stack,
I make full copies of all the modifiers above the skin modifier, delete
the originals so that the skin modifier is at the top, and then recreate
the other modifiers, in order, below the skin modifier. The script will
stop and ask if you want it to do this procedure or to terminate.
(4) Trying to reconstruct the basepose on exporting an animated model:
Having used Milkshape first I expected animated files to look the same way
in Gmax, that is, be in the basepose and only change to animations when
you hit the animate button. Bwian explained this isn't the way it works,
animations are just done differently between the two. If I simply exported
the same way I did a regular model I get the vertex positions of whatever
frame happens to be displayed at the time. If you opened this is Milkshape
you'd see the bones in the basepose and a distorted mesh. The animations
are perfectly good and you can run animextract to make a perfectly good
.cas file but this is still unsightly.
So to get an approximation to the basepose mesh I followed this procedure.
For each vertex get its primary bone assignment. In that bone's coordinate
system get the vertex position, i.e., relative to the pivot point. Now get
the relative bone positions all the way up the hierarchy to the root bone
and add them up. This SHOULD be the vertex position in world or object
or whatever the outside coordinate system is. (bone_pelvis is hard coded
to be at (0, 0, 0) since its position got overridden by the animation data.)
For armored_sergeants this was good to about a percent, too large to be
round-off error but too small to detect in Milkshape. So the warning is:
don't reimport a previously exported animated model, it's akin to making
a xerox of a xerox. Again, this is just for aesthetics, you only want the
animation data from an exported animated model, you never backconvert
these to meshes.
(5) Bone Assignments:
Mesh files always have two bone assignments, a primary and a secondary,
even if the vertex weighting on the secondary is zero. Gmax ignores an
assignment with a zero weight so to preserve these two bones I weight
the secondary one with 0.00001 and the primary with 0.99999. This
satisfies Gmax to keep two assignments but on conversion back to
Milkshape format it rounds back to 100 percent on the primary and
0 percent on the secondary and everybody's happy. Custom made models
in Milkshape frequently have only a single bone assignment so the
secondary Id is -1. To be safe and ensure that there are always two
bone assignments I arbitrarily made the secondary assignment to the
root bone with a weight of 0.00001.
Bookmarks