PDA

View Full Version : More efficient skin weights tool?


StephG
05-17-2006, 08:01 PM
I remember reading about a suggestion here to use something like:

setAttr ($skinCluserName + ".wl["+$vertexIndex+"].w["+ $jointIndex +"]") $weightValue;

instead of using the skinPercent command, to speed up scripts.

I can't for the life of me figure out how to get the vertex and joint indices for a skin cluster name. In other words, I'd like to be able to take say "skinCluster155" and get a list of the indices, and which joint and vertex they're referring to.

What I'm looking to do is speed up a working tool I wrote to take the weight values of joints I created as spokes sticking out of joint (which are named differently), and add them onto the parent joint (allowing me to delete the spokes). Using skinPercent, this script takes a long time to run (at least 2 minutes).

Anyone got any clues? Thanks in advance.

Robert Bateman
05-18-2006, 11:05 AM
use skinPercent to get the joint names and num verts, then use setAttr in the way you described. It's the multiple calls to skinPercent for each vertex weight that slows things down.

StephG
05-18-2006, 07:28 PM
use skinPercent to get the joint names and num verts, then use setAttr in the way you described. It's the multiple calls to skinPercent for each vertex weight that slows things down.

Robert, I know I'm gonna go "DUH!" when I finally get the secret decoder ring for this info, but I can't for the life of me figure out how to get the information you get by querying skinPercent to match the information you get from from querying the skinCluster by using getAttr.

Let's just take one CV.

if I use: skinPercent -q -v skinCluster179 EyeR.cv[0][0];
I get: 0 0 0.0135774 0.285971 0.653093 0.0327955 0.0145636 0 0
If I use: skinPercent -q -t skinCluster179 EyeR.cv[0][0];
I get: Sternum_J NeckA_J NeckB_J NeckC_J HeadA_J HeadB_J JawA_J JawB_J R_Clavicle_J

(This shotgun weight assignment is just a sample, not the way I actually assign weights: those bones other than the head bones would be joint spokes)

OK, so you'd think that EyeR.cv[0][0] would have a vertex index of 0.
And you'd think HeadA_J would have a joint index of 4. The coincident value of 0 and 4 should yield the value of 0.653093 if I query the attributes of skinCluster179.

So next I try: getAttr skinCluster179.wl[0].w[4];
And I get: 0

In fact, it isn't until I get to: getAttr skinCluster179.wl[0].w[9];
That I get the correct value: 0.653093

This implies, to me, that the joint indices are a fixed name/value for all the joints in the scene, since in this case the correct values start being returned arount wl.[0].w[5] (which in the above is "Sternum").

On other parts of the body I've tested, the offset between the index and the order listed for influence objects varies.

So how do I get an accurate list of joint indices that will always be the correct number when used in the skinClusterX.wl[].w[] attribute? I'd like to be able to get a list in the form (as a result):

//skinCluster179.wl[0].w[9]0.653093

And haven't even figured that out.

Even better would be a list that gives values like this:
skinCluster179.wl[0] EyeR.cv[0][0] skinCluster179.w[9] HeadA_J 0.653093
...so that I can correctly collate the information.

I don't mind constructing such a listing mechanism myself, but I can't even get to first base finding a reliable way to match the values of .wl[] and w[] to actual joints and vertices/CVs, and it's necessary since I'm reassigning values as I subtract the weight values from say NeckB_J, NeckC_J and JawA_J and add them to HeadA_J and HeadB_J. I currently use skinPercent for this, but only once per vertex with all the joint/weight assignments in one command line. I also turn off undo while executing this (saves about 20 seconds out of 2 minutes 20 seconds for a whole low res character).

Thanks again for your help Rob, you really helped me out on my animation loader. I had no idea that the "print" command used up so much horsepower (now I throw the stuff I used to put in "print" into a textScrollList window when I'm debugging something smallish, a log file when it's larger, which still slows things down, but not as much). I gave you props on my blog that nobody reads (http://car2ns3d.blogspot.com/ and I don't blame anyone for not reading it since it's long and boring) ;)

Robert Bateman
05-19-2006, 11:12 AM
aha, you're in the land of evil nurbs! erm, the rules change here slightly (as in a lot!). I've got a few things i need to get done right now, but i'll get back to this later this afternoon. (and i need to hunt down some old code to answer this). You will find that periodic surfaces (sphere/torus), will have a lot of zero weights in - since hidden from you are some extra CV's (that maya locks to pretend that it is a single CV).

StephG
05-19-2006, 04:46 PM
Heh. Mixed NURBS and polys ;)

It occurred to me that I better make sure anything I come up with works on both. I'm glad I don't have to try and make it work with sub-Ds too. Thanks again for your help.

No super rush. I've got a working tool right now, even if it's a "smoke a cigarette tool". Wouldn't be so bad if I still smoked :D

kiaran
02-13-2007, 06:23 PM
Here's a proc to get the joint indice from a skincluster. Thought it might help you:

global proc int getJointIndex(string $jointName, string $skinCluster)
{
int $jointIndex;
int $found;
while (!$found)
{
string $connections[] = `listConnections -type "joint" ($skinCluster + ".matrix["+$jointIndex+"]")`;
if ($connections[0] == $jointName)
$found = 1;
else
$jointIndex++;
}
return $jointIndex;
}

StephG
02-13-2007, 09:09 PM
It's been awhile since I've thought about the problem. I'll have to investigate this when I get a break. Thanks for the suggestion.

hibigibees
02-17-2007, 03:44 PM
Hi,
If speed is the issue, there is one way of doing it faster than mel and slower than a plugin considering both are coded with a cool algo and a average programmer...

Say if u want to transfer weights/write the weights/read-load weights .. etc for a given geo(s)...

1. write a small script initially for writing the selection to a notepad file using cmdFileOutput cmd and let the last line of that script be
string $currentFile=(`file -q -sn`+"_copy");
now use file -rename cmd and file -save cmd to make a copy of the file in the same dir...
system("maya -prompt -file $currentFile -source \"c:/mySkinScript.mel\"");
2. Now in the mySkinScript.mel write the skin weights code however needed but please avoid all commands related to UI and commands like `file -q -sn` cause they might return a error in cmd prompt...
3. Now u can open the file _copy one to c the weights transfered /written to another notepad/read-load from notepad...

There are so many possibilities of doing the same but there are few things which we might need to figure out before attempting such stuff, like,

do we need such a procedure to speed up our process... is the process going to be so intense and time consuming if done from maya GUI... how frequent is this tool needed and so on...

its like all our mel scripts does in the Maya GUI is to write a text file which can be read by another mel script triggered by another maya in cmd prompt mode so that things are faster...

One last thing... if a 350 ma scene file has more than 3000 geometries and 80000 transforms and if we need to do some automation, this saves alot of time, but not for basic requirments... A plugin might be more faster for this case and we dont need to open a new maya in cmd prompt mode to do our transfer and other stuff...

StephG
02-17-2007, 07:39 PM
The I/O speed of reading and writing the file isn't really the issue. I've got some more recent code which reads the whole damn file for a character in a couple of seconds and can locate something I'm looking for in the weights, loaded into an array. That's for a 12 mb text file.

The scripts I used earlier were sped up a little by reading the contents of the file into an array, and doing the operations from the array.

The main problem is the skinPercent command. Lately, I've been using copySkinWeights which is a zillion times faster, for deskinning/reskinning operations. Since it's a command, I can't examine the entrails to see exactly how it's working, and if it's one of those things that can be done only through the API, I'd like to see exactly how such an API script is written.

Only problem with doing it that way, is that if something fails in the script, I'm left with a bunch of copied geometry in my scene I've got to get rid of, and it really loads up the undo buffer.

BoostAbuse
02-18-2007, 06:44 AM
The main problem is the skinPercent command. Lately, I've been using copySkinWeights which is a zillion times faster, for deskinning/reskinning operations. Since it's a command, I can't examine the entrails to see exactly how it's working, and if it's one of those things that can be done only through the API, I'd like to see exactly how such an API script is written.

Only problem with doing it that way, is that if something fails in the script, I'm left with a bunch of copied geometry in my scene I've got to get rid of, and it really loads up the undo buffer.

The CopySkinWeights command is infact an API implementation, there's very little documentation on it other than trying to hunt-down some of the code and find where it plugs itself into. The only link I've been able to track down is the `performCopySkinWeights` command which can be found in:

C:/Program Files/Alias/Maya8.0/scripts/others/performCopySkinWeights.mel

As for the geometry issue, if you find your undo queue becoming horribly unruly, you can flush the memory cache in Maya by executing `flushUndo`. I use a small script for copying weights from different resolutions that imports the mesh, copies the weights, deletes the imported mesh, flushes the undo cache and then exports the file to a new scene (helps cut down any extra junk that gets brought in). Be careful with flushUndo though as if you need the queue you won't be able to retrieve any of it after flushing.

-s

StephG
02-18-2007, 08:22 AM
Yeah. Actually, rather than flushUndo, if I find memory is a problem I just start the script with undoInfo -swf 0; and end it with undoInfo -swf 1;

Of course, I only do that after I know it works every time ;)

Anyway, that keeps the undo cache intact except for everything you just ran.

I'm using a similar method to yours for stripping skin off, zeroing transforms or resetting the skeleton and then putting it back on (temporary duplicate objects with the skin copied). I have to go the extra step of disconnecting all the connections to the joints, putting those connections in an array, and rehooking them up.

BoostAbuse
02-18-2007, 06:42 PM
Yeah. Actually, rather than flushUndo, if I find memory is a problem I just start the script with undoInfo -swf 0; and end it with undoInfo -swf 1;

Of course, I only do that after I know it works every time ;)

Anyway, that keeps the undo cache intact except for everything you just ran.

I'm using a similar method to yours for stripping skin off, zeroing transforms or resetting the skeleton and then putting it back on (temporary duplicate objects with the skin copied). I have to go the extra step of disconnecting all the connections to the joints, putting those connections in an array, and rehooking them up.

Just an after thought here (morning coffee does wonders for the brain). I've got a script that's been kicking about at work for some time now that I forgot about... It basically reads the weight values off by using skinPercent, dumps them out to a text based file in an easy to read format using either worldspace or object space to determine positioning and then calls back in the weight file and uses setAttr to re-assign the value to each.

The storing of connections to me sounds like it could get quite hairy given some very complex setups (there's a large number of connections coming off the joints on the rigs we have, everything from drive pose locators for corrective shapes, muscle interactions, twist, roll and other deformation pieces). I used to use a tool at a past studio that would export the skin weight data in a readable XML file, very light and very quick to read back in (meshes were about 20,000 poly's for game work), might be something worthwhile to check out and see if you want to go the route of writing out XML files to read back in the values.

-s

CGTalk Moderation
02-18-2007, 06:42 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.