Exporting skinned meshes
by Portitor · in Torque Game Engine · 01/23/2003 (1:22 pm) · 1 replies
Hi all. I was having problems to export my mesh with a non-standard-bone-hierarchy (my character is a squid), until I manage to discover what was going on, and here I'm posting what I discovered:
First of all, I think that the max2dts documentation is not clear about what are the exact requirements for all the different types of export that someone could want to do. All in all, how to export an unskinned mesh, with all the details and collision stuff is reasonably well explained. As well as the explanation about exporting sequences, provided that your skeleton is "player.max-compatible". And there laid the problem (in my opinion). I made a skeleton (not importing it from Biped or other plugin), bone by bone, and then I skinned my mesh. Unfortunately I was unable to export it as a DTS. (For details look at: www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=8881 )
After that failure, I started a more analytical approach. I exported player.max (the one that comes in the torque_max_filepack.zip ), and compared the dump file with the one generated when trying to export my mesh. One line in the player.max dump file contained "Vicon node found", which was absent in the other dump file. Then I searched in the max2dts code for "vicon" and found a function named isVicon() , (SceneEnum.cc, line 81) that controls if the name of a node is "VICON" or "Bip01" (return true if the node's name is any of those two). Guess what? "Player.max" root-bone is named "Bip01" (coincidence? I don't believe so...). After I added a root-bone named "Bip01", my creature exported successfully !!!
But that didn't look like the "clean" way to export skinned creatures (or at least I couldn't believe that THAT could be the case...). Then I continued experimenting and looking at the code.
I noticed that the consequence of isVicon() being successful was that the node was added to the 'subTrees' array. I noticed that the other way that a node was added to that array was if the function isSubtree() succeeded on the node. This function succeeds if it's a root-node (a root-bone node is a root node) and if the function hasMesh() failed. Then, the only reason for my original skeleton not being exported was because hasMesh() retuned 'true' when evaluating my skinned-creature's root-bone node.
Looking at hasMesh() (maxUtil.cc, line 178), you can see:
In the case of my SquidRoot bone, the CanConvert... call was successful (I guess because the bone has a mesh representation in the scene), and the ClassId comparison (the ==) was failing, and as everybody knows, (TRUE AND NOT FALSE) = TRUE, hence hasMesh() returns true for my SquidRoot bone. Therefore isSubtree() failed, and then this node was not being added to the subTree array (confused? follow the code...). That explained why my skeleton wasn't being exported.
Playing a bit with MaxScript I discovered the ClassId of my bones (a Max 4.0 bone). Checking in the sdk headers, I found it:
BONE_OBJ_CLASSID.
Then, I though that's what was missing. I changed hasMesh() to
(hence checking that it's not a BipedBone (I guess that's the first ClassId comparison), nor a Max 4.0 Bone).
Guess what happened then? I didn't need anymore to have a "Bip01" root-bone node to export successfully, because even if isVicon() didn't succeed, now isSubtree() finds (correctly) that "SquidRoot" is a subTree node, hence the export works ok.
Then, the problem I had could be attributed to:
1. Uncompleted docs (they should say that "For a skinned mesh the top bone should be named 'Bip01' ". and clarify the "You don't require Biped" sentence.)
or
2. It was a max2dts bug. The hasMesh() function should be checking for the other type of bone (not just the Biped one) from the start, given that the plugin is supposed to work with Max 4.0
or
3. ???
I'm not entirely convinced on 1. or 2. because then (I think) many more people would have the same problems than I had, and I didn't have that impression from what I read in the forums. Well, at least supposing there IS people trying to do skinned objects-creatures without using the bones hierarchies with the infamous "Bip01" as the name of the root node ( I don't WANT to believe that that naming convention is just "common wisdom" to export successfully ;-)
So, if somebody sees what is that mysterious third option, I will be really grateful...
Thanks in advance!
Rod
First of all, I think that the max2dts documentation is not clear about what are the exact requirements for all the different types of export that someone could want to do. All in all, how to export an unskinned mesh, with all the details and collision stuff is reasonably well explained. As well as the explanation about exporting sequences, provided that your skeleton is "player.max-compatible". And there laid the problem (in my opinion). I made a skeleton (not importing it from Biped or other plugin), bone by bone, and then I skinned my mesh. Unfortunately I was unable to export it as a DTS. (For details look at: www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=8881 )
After that failure, I started a more analytical approach. I exported player.max (the one that comes in the torque_max_filepack.zip ), and compared the dump file with the one generated when trying to export my mesh. One line in the player.max dump file contained "Vicon node found", which was absent in the other dump file. Then I searched in the max2dts code for "vicon" and found a function named isVicon() , (SceneEnum.cc, line 81) that controls if the name of a node is "VICON" or "Bip01" (return true if the node's name is any of those two). Guess what? "Player.max" root-bone is named "Bip01" (coincidence? I don't believe so...). After I added a root-bone named "Bip01", my creature exported successfully !!!
But that didn't look like the "clean" way to export skinned creatures (or at least I couldn't believe that THAT could be the case...). Then I continued experimenting and looking at the code.
I noticed that the consequence of isVicon() being successful was that the node was added to the 'subTrees' array. I noticed that the other way that a node was added to that array was if the function isSubtree() succeeded on the node. This function succeeds if it's a root-node (a root-bone node is a root node) and if the function hasMesh() failed. Then, the only reason for my original skeleton not being exported was because hasMesh() retuned 'true' when evaluating my skinned-creature's root-bone node.
Looking at hasMesh() (maxUtil.cc, line 178), you can see:
bool hasMesh(INode * pNode)
{
ObjectState os = pNode->EvalWorldState(0);
return( os.obj->CanConvertToType(triObjectClassID) && !(os.obj->ClassID() == BipedObjectClassID));
}In the case of my SquidRoot bone, the CanConvert... call was successful (I guess because the bone has a mesh representation in the scene), and the ClassId comparison (the ==) was failing, and as everybody knows, (TRUE AND NOT FALSE) = TRUE, hence hasMesh() returns true for my SquidRoot bone. Therefore isSubtree() failed, and then this node was not being added to the subTree array (confused? follow the code...). That explained why my skeleton wasn't being exported.
Playing a bit with MaxScript I discovered the ClassId of my bones (a Max 4.0 bone). Checking in the sdk headers, I found it:
BONE_OBJ_CLASSID.
Then, I though that's what was missing. I changed hasMesh() to
bool hasMesh(INode * pNode)
{
ObjectState os = pNode->EvalWorldState(0);
return( os.obj->CanConvertToType(triObjectClassID)
&& !(os.obj->ClassID() == BipedObjectClassID)
&& !(os.obj->ClassID() == BONE_OBJ_CLASSID));
}(hence checking that it's not a BipedBone (I guess that's the first ClassId comparison), nor a Max 4.0 Bone).
Guess what happened then? I didn't need anymore to have a "Bip01" root-bone node to export successfully, because even if isVicon() didn't succeed, now isSubtree() finds (correctly) that "SquidRoot" is a subTree node, hence the export works ok.
Then, the problem I had could be attributed to:
1. Uncompleted docs (they should say that "For a skinned mesh the top bone should be named 'Bip01' ". and clarify the "You don't require Biped" sentence.)
or
2. It was a max2dts bug. The hasMesh() function should be checking for the other type of bone (not just the Biped one) from the start, given that the plugin is supposed to work with Max 4.0
or
3. ???
I'm not entirely convinced on 1. or 2. because then (I think) many more people would have the same problems than I had, and I didn't have that impression from what I read in the forums. Well, at least supposing there IS people trying to do skinned objects-creatures without using the bones hierarchies with the infamous "Bip01" as the name of the root node ( I don't WANT to believe that that naming convention is just "common wisdom" to export successfully ;-)
So, if somebody sees what is that mysterious third option, I will be really grateful...
Thanks in advance!
Rod
Torque Owner Jared Schnelle
Change the detail2 to Details2
Notice the plural Details. Link bounds to the "root" node.
Take a look at this, and see if it makes more sense.
www.rykos.net/schematic.jpg
-----------------------
You can choose to export your animations as .dsq or inside the .dts file
If you want to export the sequences as .dsq, you'll need to delete the mesh, but NOT the Details2 marker.
If you want to export the .dts with all the animations within the shape. You need to create several sequence helpers. Go to "Helpers" then click the down arrows, and pick DTS Scene Object.
You name these whatever you want. SquidDance SquidMove SquidDie
Then, go to TrackView(next to the schematic view), and look over on the left. You should see a list of objects in your scene. You'll see SquidDancer, SquidMove SquidDie, etc
www.rykos.net/track.jpg
There's a track view of my Idle animation. You can have as many of these sequence helpers you want. Mine goes from frame 0->32, but you could have one go from 1->5, then another from 4->30.
If you have any other questions, lemme know.
-Jared