Accessing IK Chain Data [MEL]



The above view of the hypergraph shows a simple 3 bone IK chain. The dashed red line on the left hand side indicates the bones that form the chain itself.

When you create an IK chain in Maya, you will also create two additional nodes, an IkHandle and an IkEffector. The effector is basically a transform that determines the end position of the IkChain. The IkHandle represents the start of the Ik chain and is also the parent transform of the Effector.

One common additional element you may expect to find is a pole vector constraint. When an animator sets up an Ik Chain in maya, it often has a tendancy to bend the wrong way. To fix this, a locator node is usually used as a guide to determine which direction the elbow should bend in.

note, a locator node is not the only object that may be used. Often simple mesh shapes are preferred by animators since different shaped controls can give a visual aid as to what part of the model they control. It should not really be of any concern since it is actually the transform that is important for the Pole vector constraint. If however you find a shape used as the contraining object, you should easily be able to prevent the shape from being exported.

If your intention is to re-create the animation using an Ik Rig and animation curve data, then be very aware of the way in which your art team are rigging their models. Often Ik chains are used along-side multiple point, orientation, scale, parent and/or aim contraints. You should really handle these contraints types if you want your Ik chains to animate exactly as the animator intended.





Finding all the Ik Handles
in a Scene

















































// create an iterator to go through all curves
MItDag it(MFn::kIkHandle);


// attach the function set to the object

// get the start joint and the effector
MDagPath start,eff;

MFnDagNode fnEffector(eff);
MFnDagNode fnStart(start);

MFnIkSolver fnSolver(fn.solver());

cout<<"IK " << << endl;
cout<<"\tmaxIterations "<< fnSolver.maxIterations();
cout<<"\n\ttolerance " << fnSolver.tolerance();
cout<<"\n\tpriority " << fnSolver.priority();
cout<<"\n\tweight " << fn.weight();
cout<<"\n\tpoWeight " << fn.poWeight();
cout<<"\n\tstickiness " << fn.stickiness();
cout<<"\n\tstart " <<;
cout<<"\n\teffector " <<;

// now lets hunt for a pole vector constraint
MPlug pvx = fn.findPlug("poleVectorX");
MPlug pvy = fn.findPlug("poleVectorY");
MPlug pvz = fn.findPlug("poleVectorZ");

// get the pole vector values
float px,py,pz;

// get any plugs connected to the pole vector

bool found=false;

cout << "\tpoleVector ";

for(unsigned int i=0;i<plugs.length();++i)


MObject obj = plugs[i].node();

// if we have found a pole vector constraint
// attached to the IK handle

if (obj.hasFn(MFn::kPoleVectorConstraint))


// attach a dependency node function
// set to the pole vector constraint

MFnDependencyNode fnPole(plugs[i].node());

// now hunt for the actual transform that
// is driving the pole vector. This will be
// connected to

MPlug targetplug = fnPole.findPlug("target");
MPlug target0;

// get target[0]
target0= targetplug.elementByPhysicalIndex(0);

// get target[0].targetTranslate

MPlug conn = target0.child(0);

// get connections to that plug

MPlugArray aplugs;

// if there are any
(aplugs.length()>0) {


// attach a dependency node to the xform
MFnDependencyNode fnX(aplugs[0].node());

// output its name
cout << << endl;

// flag the fact we found it





if(!found) cout << px << " " << py << " " << pz << endl;

// get next curve;




What Next?

Transformation Data

Blend Shape Deformers

Lattice Deformers


Rob Bateman [2004]