Updating the source skeleton

A custom function can be defined to retrieve the data from the solver and to write it to source skeleton.

Example code: (source skeleton is SkeletonInstance here):

static void updateSkeleton() {
const FIK::Real* quat;
Bone* bone;
for(int i=0;igetNumBones();i++)
    bone->setOrientation(quat[3], quat[0], quat[1], quat[2]);

This function should be called each time after calling


The bones / degrees of freedom that are inactive or frozen can be skipped. There is no need to update bone positions as parent space offsets will not have changed, except for the root bone when solving for root translation. If the client application wishes to use the resulting global positions, it can traverse segments and call

 const Real* IKSegment::getGlobalPos() 

To get the accumulated global bone orientations in skeleton space, call

 const Real* IKSegment::getGlobalQ()

Before retrieving the global transforms, it might be necessary to call


first as global transforms will otherwise not include the last incremental angle update from the solution. This needs to be done if solving for root translation as the last update can still be significant in that case.

The main class is IKSolver. This has a vector of IKSegment objects to represent the imported skeleton. The segments are hierarchically linked in terms of parent/child/sibling relationships and are a virtual copy of the source figure skeleton. They are primarily used for forward kinematics, i.e. to update global bone orientations based on increments produced by the solver each iteration.

Segment objects are also used to store animation targets, joint limits information, weights and activity flags per degree of freedom of each imported bone.

All segments are spherical segments (3 degrees of freedom) by default.


removes/enables solving for a particular bone. This can also be done on a degree-of-freedom basis by calling

 void setActiveDofs(bool x, bool y, bool z, bool rotation=true);

In this way, custom hinge, swing, twist and elbow joints can be created. The segment degrees of freedom can also be differently weighted with

 IKSegment::setWeight(int dof_id, Real weight)

The weight represents the mobility of the bone (which is 1 - stiffness) and can be greater than 1.

The third class is IKTask, with subclasses IKPositionTask, IKOrientationTask and IKBalanceTask. The tasks hold the position/orientation targets set by the user and pass these demands to the solver.

IKSolver allocates tasks and solves for all the active tasks each time


is called. Each task is associated with a particular bone (all bones for the balance task).

The targets set previously remain in force until they are changed or the task is removed with

 IKSolver::removeTask(IKTask* task) 

or set inactive with


The first option is for permanent removal (memory will be deallocated), the second for disabling/enabling input from a task very frequently.

The task can also be partially or fully disabled/enabled by calling

 IKTask::setDofs(bool x, bool y, bool z). 

This is useful, for example, for position tasks with don't care conditions, such as placing a foot on a plane, where only one degree of freedom (the skeleton height dimension) is important. This is quite efficient and can also be used for disabling/enabling tasks long-term, hence this should be the preferred option.

Tasks can be added and removed any time, also at runtime. Activity flags on tasks and segments can also be set at any time. All the relevant bones should be imported at the setup stage by using a vector of ImportBone structures, passed to

 IKSolver::importBones(ImportBone* first_bone, unsigned int count).

In addition to tasks, targets for desired local orientation can be passed to each segment by calling

 IKSegment::setTargetOrientation(Real x, Real y, Real z, Real w)

These will typically be the local space orientations from the animation/motion capture that are underlying the current motion. The solver will find a local orientation for each bone that satisfies the task targets and at the same time the desired orientation. The desired orientation targets remain in force until changed or


is called.

The function


defines a target local orientation in the solver and this is different from


which defines directly the local orientation outside the solver.