29 April, 2009

BlendShapes 1

If somehow (or by doing something stupid like I did) if you have blendshapes created which don't have the same vertex order as your base geometry or if geometry changes in the base model, don't panic! You can use already created blendshapes to make new ones. Use a wrap deformer to do this as explained below.

-> Take all old blendshape geometry and add them to old base geometry using "Blend Shape" deformer.
-> Align new geometry poition to match with the old base geometry (which has blendshapes).
-> Apply a wrap deformer so the old base geometry drives the new base geometry.
-> Now dial in each blendshape individually (you just need to do it for one side, left or right). This will deform the new geometry as the old base geometry deforms.
-> Duplicate your new deformed geometry. You have got a blendshape for new geometry!

You can adjust the options in wrap deformer to get the best results. And when you dial blendshapes make sure you don't get any undesired deformations. You can actually paint blendshape weight to remvoe it later if you have any extra vertices being affected.

20 April, 2009

Direction connection for rotation

From my experience so far, connecting rotation values directly is not a good practice. There are some pre-conditions that have to match in order for this to work. So you end up loosing quite a bit of flexibility and you have to make 110% sure that those conditions would not change after you make connections. Here are some main conditions that I learned.

1. Rotation orders have to be the exact same.

2. If local rotation axis between parent and child (relationship considering how connections are made) do not align all the time this will not work properly. So rotating parent will rotate child differently.

So if you still need to use the connections and solve at least the 2nd problem, then you need to create a node network that will find the offset between local rotation axis of both objects and then assign rotation value to the child object accordingly.

19 April, 2009

FK controllers - not as simple as I had thought

FK controllers are trickier than they seem to be. They are not simple! Here are some questions and thoughts I encountered while doing an arm setup.

1. How to bind controllers to the joints: Parent shapes? Constraint? Connections? Or combination of all these?
2. Constraint works, but you cannot take advantage of joint's inveseScale attribute directly. Connections have more issues, and it starts getting complicated when you parent stuff. Because the values don't update in channel if you have connected transform values directly using translate and rotate. More complicated connections can be established using worldMatrix and parentInverseMatrix to get proper world space transform value, but it just ends up being more complicated than it has to be. Unless I have a simple node that does this, which is what parentConstraint is.
3. Now this leaves us to parent shape method. It seems that this technique works the best amongst other techniques. The main advantage is that when scaling all child controllers follow with their respective joints. Here are the problems with parent shape method.
  • You cannot use translation values because joints will have some values already in there.
  • If you change rotation order of the controller you are changing the rotation order of the joint itself. This can cause the problem if you are blending between joint chains and you have not used constraints.
  • The main problem is that by parenting a shape you are directly manipulating the joint, which I think is not a good idea.
  • Scaling joints will also scale shapes (This could be good or bad).
So my conclusion is that the best way to make FK controls work with blending and scaling is to use parent constraints, parenting of controls and connections for scaling. I will post this in more detail later.

18 April, 2009

True on the fly Rotation Order Change

True on the fly rotation order change means that the object should not jump from its current pose. I started looking into matrix to achieve this. Basically, I thought if I can formulate the equation that involves rotation values and rotation order I can solve that equation to get the rotation values that will keep the object in the same pose. I found that I could actually have separate matrices for each axis, RX, RY and RZ and then multiply them one by one based on rotation order to get this rotation value. However, in trying to find if I can set matrix value of an object using MEL I ended up finding a solution of my actual problem. It can't get simpler than this.

xform -preserve true -rotateOrder yxz; 

Select your object, rotate in any position and then change rotation order using this command. Object will stay in the same pose! Thanks to "-preserve" flag.

17 April, 2009

"Easy Select" or "Proxy Select"

In the latest rigging project I have been working on this idea to make selection of controllers quick and easy. Generally the problem with curve controllers is that you cannot select them quickly because you have to be accurate in clicking the thin curves (unless you are an avid shooting game player and you have very high accuracy). In my experience sometimes it becomes a little annoying when it takes 3 clicks to select a controller.

So in this idea of "Easy Select" or "Proxy Select", I have hidden geometry that defines the selection area around a curve. Each controller has its own selection area defined this way. So instead of pin pointing on the curve you can click anywhere in this 3D area to select the curve controller. And a controller can have more than one objects defining its area, clicking on either of them will transfer selection to that controller.

I created a script to do this, so I click selection area geometry first and then select the target controller and click shelf button and I have "Easy Select" working for that controller. I also have an attribute on target controller so that I can turn this on and off. The big problem with this technique was that undo was creating this cycle where if I undo it goes back selecting proxy geometry and my scrip transfers that selection back to the control. And if I do undo again the same thing repeats. Hence I can't do any undo before "Easy Select" event. For the solution, I had to disable undo before I execute the function and turn it on at the end.

Different geo. that defines selection area for controllers.

I am still working on this script to make UI to list all "Easy Select" objects and their selection area objects. Also, I need to add a function to delete the nodes & attributes that I am creating so if you want to delete this feature from the scene you don't have to do it manually.

Connecting Geo Display Type

Generally you can link geometry display type by adding them to a layer and switch between "template", "reference" or "normal". Alternatively you can change its display override type to reference directly in the attribute editor. In later case it become difficult to debug, if you have to go back and find that geometry and change display type to "normal".

I find it more organized if I have an attribute in the main controller (hidden from animators) that I can use to change the display type of all geometry. This way I can go back and select geometry easily by dialing the number for respective display type. Also if we expose less non-animation related things to animators its safer for the rig and cleaner for animators.

09 April, 2009

Default Joint Connections

I have been using Hypergraph a lot lately. Today I found out that when you create a skeleton hierarchy, joints have scale->inverseScale connection by default. So when you scale the joints the children joints do not scale, they just move. But if you delete the scale connection joints follow the normal parent scale transform. Here are the screenshots. Simple, but useful.

Edit: I forgot to mention, "inverseScale" attribute is available only with joint transform.

putenv command on Vista

I am not sure if its vista (you bug me a lot sometimes) or Maya but when I use putenv command to create a custom environment variale it does not save the value. After I set the environment variable and then use "getenv" to read the value it works. But when I restart maya the variable is gone! It's set back to null. This is really annoying.

It looks like windows does not remember the environment variable itself. So if I use SET command to create a new environment variable then restart command prompt the variable is gone. Does this mean it's limited only for current tsession in vista? I believe when I used this script on XP it did not give me this problem.
I am going to try using Maya.env now.

06 April, 2009

A trick to increment a string in Maya

I was developing a script to increment version & save the current file where the script checks for version tag (*_v1.ma) and then increments it. I took a long path first where I extract the version tag then extract the number and increment it. And ofcourse Maya will give you a warning when it converts string to integer. So to solve that working I was wondering what to do and it clicked to me that maya can increment it for me. And it's simple!

You need to have the sub string where the numerical part is at the end
e.g. modlObj_artist_v1

Here is the sctipt.

string $curName = "modlObj_artist_v1";
// we will create nodes under this node so that we know they are unique
string $parent = `createNode transform`;
createNode -name $curName -parent $parent transform;
// create it again so maya renames it with incremental suffix
$newName = `createNode -name $curName -parent $parent transform`;
// delete
delete $parent;
print $newName;

Though in my case I still need to extract version tag in order to check if its present.