/// <summary>
    /// Transfer half the rotation from a parent transform to a roll joint.
    /// The rotation is transferred only along the rotation axis of the roll joint
    /// </summary>
    /// <param name="rollJointWrapper">Roll joint information</param>
    private void rollRotation(RollJointWrapper rollJointWrapper)
    {
        Transform parent = rollJointWrapper.m_transform.parent;
        // get the current twist direction
        Vector3 twistDir = (Quaternion.Inverse(parent.localRotation) * rollJointWrapper.m_inverseOriginalParentRotation) * rollJointWrapper.m_localTwistDir;
        // get the swing direction
        Quaternion dirRotation = Quaternion.FromToRotation(twistDir, rollJointWrapper.m_localTwistDir);
        // the twist rotation is the full rotation minus the swing rotation
        Quaternion twistQuat = rollJointWrapper.m_originalParentRotation * parent.localRotation * Quaternion.Inverse(dirRotation);

        // get the twist angle
        float   angle;
        Vector3 rotation_axis;

        twistQuat.ToAngleAxis(out angle, out rotation_axis);

        if (!Mathf.Approximately(angle, 0) && !Mathf.Approximately(angle, 360))
        {
            // apply half the angle to the parent and half to the roll joint
            float halfAngle = 0;
            if (angle > 180)
            {
                halfAngle = (angle + 360) / 2;
            }
            else
            {
                halfAngle = angle / 2;
            }
            twistQuat            = Quaternion.AngleAxis(halfAngle, rotation_axis);
            parent.localRotation = Quaternion.Slerp(parent.localRotation, parent.localRotation * Quaternion.Inverse(twistQuat), m_weight);
            rollJointWrapper.m_transform.localRotation = Quaternion.Slerp(rollJointWrapper.m_transform.localRotation, twistQuat * rollJointWrapper.m_originalRotation, m_weight);
        }
    }
    // initialize a roll joint data for the given joint as parent
    private void JoinRollJoint(string rollJointName, Omek.JointID parentJointID)
    {
        TransformWrapper tw  = m_hierarchyList.Find((a) => { return(a.m_jointID == parentJointID); });
        RollJointWrapper rjw = m_rollJointsList.Find((a) => { return(a.m_name == rollJointName); });

        tw.m_rollJoint      = rjw;
        rjw.m_parentWrapper = tw;
        if (tw.m_transform != null)
        {
            rjw.m_originalParentRotation        = tw.m_transform.localRotation;
            rjw.m_inverseOriginalParentRotation = Quaternion.Inverse(rjw.m_originalParentRotation);
        }
    }
    private void SetJointActiveForChildren(Transform trans, bool isActive)
    {
        TransformWrapper tw = m_hierarchyList.Find((a) => { return(a.m_transform == trans); });

        if (tw != null)
        {
            tw.m_active = isActive;
        }
        RollJointWrapper rjw = m_rollJointsList.Find((a) => { return(a.m_transform == trans); });

        if (rjw != null)
        {
            rjw.m_active = isActive;
        }
        foreach (Transform child in trans)
        {
            SetJointActiveForChildren(child, isActive);
        }
    }