View Full Version : orient joints

12 December 2003, 12:46 AM
I've been working on some scripts to automate a lot of my rigging work... so far so good. Right now I'm trying to figure out how to orient joints and have an up vector... like Jason's joint orient script. I want figure out more about mel so I can rely on my own scripts. I tried digging through his code but I couldn't quite figure out what I wanted to know. If some one could post a little snippet of code or give me an idea as to how I can do this. Just a simple example would suffice, I think I should be able to alter it to my needs.

12 December 2003, 07:14 AM
i'm not quite sure what you're after, but here is a proc i use to find the up vector of an object. its a bit hacky, but hey... thats what happens when you don't know 3d maths. :)

//this function will return a string indicating the axis of an object, closest in orientation to a compare vector.
global proc string getUpVector ( string $obj, float $compareVector[] ) {
string $return = "none";
string $locator[] = `spaceLocator -p 0 0 0`;
float $initialPosFloats[] = `xform -q -ws -rp $obj`;
float $Xfloats[];
float $Yfloats[];
float $Zfloats[];
vector $initalVector = <<$initialPosFloats[0],$initialPosFloats[1],$initialPosFloats[2]>>;
vector $upVector = <<$compareVector[0], $compareVector[1], $compareVector[2]>>;
vector $Xvector;
vector $Yvector;
vector $Zvector;

parent -r $locator[0] $obj;
xform -r -os -t 1 0 0 $locator[0];
$Xfloats = `xform -q -ws -t $locator[0]`;
xform -r -os -t -1 0 0 $locator[0];
xform -r -os -t 0 1 0 $locator[0];
$Yfloats = `xform -q -ws -t $locator[0]`;
xform -r -os -t 0 -1 0 $locator[0];
xform -r -os -t 0 0 1 $locator[0];
$Zfloats = `xform -q -ws -t $locator[0]`;
delete $locator[0];

$Xvector = <<$Xfloats[0], $Xfloats[1], $Xfloats[2]>> - $initalVector;
$Yvector = <<$Yfloats[0], $Yfloats[1], $Yfloats[2]>> - $initalVector;
$Zvector = <<$Zfloats[0], $Zfloats[1], $Zfloats[2]>> - $initalVector;

float $dotList[] = {abs( $Xvector*$upVector ), abs( $Yvector*$upVector ), abs( $Zvector*$upVector )};
float $sorted[] = `sort $dotList`; //sort them into a lowest to highest array

if ( $sorted[2] == -1*( $Xvector*$upVector )) $return = "-1 0 0";
if ( $sorted[2] == -1*( $Yvector*$upVector )) $return = "0 -1 0";
if ( $sorted[2] == -1*( $Zvector*$upVector )) $return = "0 0 -1";

if ( $sorted[2] == ( $Xvector*$upVector )) $return = "1 0 0";
if ( $sorted[2] == ( $Yvector*$upVector )) $return = "0 1 0";
if ( $sorted[2] == ( $Zvector*$upVector )) $return = "0 0 1";
return $return;

this is great for automating feet and hand setups, because it can help you figure out which direction the hands are facing, and whats the best axis to use as an up vector.

so just say you've got an ankle joint, and a toe joint. you can take away the translation of the ankle from the joint , to give you a direction vector for your foot bone. then just use that as the $compareVector.

float $ankle[] = `xform -q -ws -rp ankleJoint`;
float $toe[] = `xform -q -ws -rp toeJoint`;
float $compareVector[];

$compareVector[0] = $toe[0]-$ankle[0];
$compareVector[1] = $toe[1]-$ankle[1];
$compareVector[2] = $toe[2]-$ankle[2];

getUpVector "ankle" $compareVector;

this will tell you which axis points towards the toe on the ankle. you can also use:
getUpVector ankle {0,1,0}

to get the axis that points up.

12 December 2003, 03:48 PM

I wrote a script that does exactly this, in the "Tools" section of my dwRiggingTools scripts. Itīs based on jsOrientJoint, but allows you to orient any number of joints at once, and allows you to orient joints along any axis (jsOrientJoint, last I saw, only oriented with the Y pointing down the joint).

The script basically creates an aimConstraint on the current joint, and aims it to the jointīs first child joint. The up vector is given by the aimConstraintīs -upVector flag, which in my script is given by placing a locator either in the +Z or -Z.

Hope this helps. You can get the script on my website if youīre interested.


12 December 2003, 04:13 PM
yeah thanks dwalden74, I dug through Jason's script again and kinda figured out what he was doing to create the orient. I found the lines in it that use the aim constraint with the vector. Thanks I'll definately check out your tools, I've been meaning to, I just keep forgetting. :shrug:

12 December 2003, 01:22 AM
I'm gonna bring this thread back for another question. I'm trying to write my own version of a orient script. Cause I'm trying to learn as much about scripting as I can. Right now this is what I have, its real simple. I am just using the x axis for aim right now and y axis for up vector. It simply pickwalks up and down from the joint you want to orient to get the parent and child. The script works as long as the joint in question has a parent, but if it doesn't have a parent it doesn't work. My question is how can I script it so if the joint doesn't have a parent it will skip it, and operate correctly. In other words how can I improve what I've done so far. I'm sure this is not the best way to do it, but hey, I'm learning here. Also how can I script it so that I can orient several joints at once instead of one.


I'm interested in your example that you posted, could you go through and comment the parts clearly or explain a little more about whats goin on.


// aim x axis down arm with y as up vector

global proc orientArmJoint (string $joint)

// get and store joint names
string $child[] = `listRelatives -c $joint`;
string $parent[] = `listRelatives -p $joint`;

// unparent joints

if (size ($child) > 0)
select $child;
parent -w;
}else {

if (size ($parent) > 0)
select $joint;
parent -w;

if (size ($child) > 0)
// select joints and create aim constraint
select $child $joint;

$const = `aimConstraint -offset 0 0 0 -weight 1
-aimVector 1 0 0 -upVector 0 1 0
-worldUpType "vector" -worldUpVector 0 1 0`;

delete $const;

// set joint orient to rotations and zero out
$r = `getAttr ($joint + ".r")`;
setAttr ($joint + ".jo") $r[0] $r[1] $r[2];
setAttr ($joint + ".r") 0 0 0;

select -d;

// reparent joints

if (size ($child) > 0)
select $child $joint;
select -d;

if (size ($parent) > 0)
select $joint $parent;
select -d;


12 December 2003, 06:05 AM
You could try the "listRelatives" command. I believe that it should tell you if the joint you are working on has a parent or not.

12 December 2003, 02:29 AM
Yeah thanks ajk48n the listRelatives command worked great. I've changed my code in the previous post to reflect the changes I made. My question now is how would alter what I've got to work on more than one joint at a time. For instance how could I alter so that I could select multiple joints and script would orient all of them at once. Thanks for your help guys I'm learning a ton !!! :thumbsup: :bounce:

CGTalk Moderation
01 January 2006, 11:00 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.