Example #1
0
 public AwQuaternion(AwQuaternion q)
 {
     w = q.w;
     x = q.x;
     y = q.y;
     z = q.z;
 }
Example #2
0
 public AwQuaternion(AwQuaternion q)
 {
     w = q.w;
     x = q.x;
     y = q.y;
     z = q.z;
 }
Example #3
0
        public AwQuaternion mul(AwQuaternion rhs)
        {
            AwQuaternion result = new AwQuaternion();

            result.w = rhs.w * w - (rhs.x * x + rhs.y * y + rhs.z * z);
            result.x = rhs.w * x + rhs.x * w + rhs.y * z - rhs.z * y;
            result.y = rhs.w * y + rhs.y * w + rhs.z * x - rhs.x * z;
            result.z = rhs.w * z + rhs.z * w + rhs.x * y - rhs.y * x;
            return(result);
        }
Example #4
0
        public AwVector rotateBy(AwQuaternion q)
        {
            double   rw = -q.x * x - q.y * y - q.z * z;
            double   rx = q.w * x + q.y * z - q.z * y;
            double   ry = q.w * y + q.z * x - q.x * z;
            double   rz = q.w * z + q.x * y - q.y * x;
            AwVector v  = new AwVector(-rw * q.x + rx * q.w - ry * q.z + rz * q.y,
                                       -rw * q.y + ry * q.w - rz * q.x + rx * q.z,
                                       -rw * q.z + rz * q.w - rx * q.y + ry * q.x);

            return(v);
        }
Example #5
0
 public AwQuaternion mul(AwQuaternion rhs)
 {
     AwQuaternion result = new AwQuaternion();
     result.w = rhs.w * w - (rhs.x * x + rhs.y * y + rhs.z * z);
     result.x = rhs.w * x + rhs.x * w + rhs.y * z - rhs.z * y;
     result.y = rhs.w * y + rhs.y * w + rhs.z * x - rhs.x * z;
     result.z = rhs.w * z + rhs.z * w + rhs.x * y - rhs.y * x;
     return result;
 }
Example #6
0
        public override void doSolve()
        {
            MIkHandleGroup handle_group = handleGroup;

            if (handle_group == null)
            {
                throw new InvalidOperationException("Invalid handle group");
            }

            MObject     handle     = handle_group.handle(0);
            MDagPath    handlePath = MDagPath.getAPathTo(handle);
            MFnIkHandle handleFn   = new MFnIkHandle(handlePath);

            //Effector
            //
            MDagPath effectorPath = new MDagPath();

            handleFn.getEffector(effectorPath);
            MFnIkEffector effectorFn = new MFnIkEffector(effectorPath);

            effectorPath.pop();
            MFnIkJoint midJoinFn = new MFnIkJoint(effectorPath);

            // Start Joint
            //
            MDagPath startJointPath = new MDagPath();

            handleFn.getStartJoint(startJointPath);
            MFnIkJoint startJointFn = new MFnIkJoint(startJointPath);

            // Preferred angles
            //
            double [] startJointPrefAngle = new double[3];
            double[]  midJointPrefAngle   = new double[3];

            startJointFn.getPreferedAngle(startJointPrefAngle);
            midJoinFn.getPreferedAngle(midJointPrefAngle);

            // Set to preferred angles
            //
            startJointFn.setRotation(startJointPrefAngle, startJointFn.rotationOrder);

            midJoinFn.setRotation(midJointPrefAngle, midJoinFn.rotationOrder);

            MPoint  handlePos   = handleFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awHandlePos = new AwPoint(handlePos.x, handlePos.y, handlePos.z, handlePos.w);

            MPoint  effectorPos   = effectorFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awEffectorPos = new AwPoint(effectorPos.x, effectorPos.y, effectorPos.z, effectorPos.w);

            MPoint  midJoinPos   = midJoinFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awMidJoinPos = new AwPoint(midJoinPos.x, midJoinPos.y, midJoinPos.z, midJoinPos.w);

            MPoint  startJointPos   = startJointFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awStartJointPos = new AwPoint(startJointPos.x, startJointPos.y, startJointPos.z, startJointPos.w);

            AwVector poleVector = poleVectorFromHandle(handlePath);
            MMatrix  m          = handlePath.exclusiveMatrix;
            AwMatrix awM        = new AwMatrix();

            awM.setMatrix(m);
            poleVector = poleVector.mulMatrix(awM);
            double twistValue = twistFromHandle(handlePath);

            AwQuaternion qStart = new AwQuaternion();
            AwQuaternion qMid   = new AwQuaternion();

            solveIK(awStartJointPos, awMidJoinPos, awEffectorPos, awHandlePos,
                    poleVector, twistValue, qStart, qMid);

            MQuaternion mid   = new MQuaternion(qMid.x, qMid.y, qMid.z, qMid.w);
            MQuaternion start = new MQuaternion(qStart.x, qStart.y, qStart.z, qStart.w);

            midJoinFn.rotateBy(mid, MSpace.Space.kWorld);
            startJointFn.rotateBy(start, MSpace.Space.kWorld);

            return;
        }
Example #7
0
        void solveIK(AwPoint startJointPos,
                     AwPoint midJointPos,
                     AwPoint effectorPos,
                     AwPoint handlePos,
                     AwVector poleVector,
                     double twistValue,
                     AwQuaternion qStart,
                     AwQuaternion qMid)
        // This is method that actually computes the IK solution.
        //
        {
            // vector from startJoint to midJoint
            AwVector vector1 = midJointPos.sub(startJointPos);
            // vector from midJoint to effector
            AwVector vector2 = effectorPos.sub(midJointPos);
            // vector from startJoint to handle
            AwVector vectorH = handlePos.sub(startJointPos);
            // vector from startJoint to effector
            AwVector vectorE = effectorPos.sub(startJointPos);

            // lengths of those vectors
            double length1 = vector1.length();
            double length2 = vector2.length();
            double lengthH = vectorH.length();

            double   d       = vector1.mul(vectorE) / vectorE.mul(vectorE);
            AwVector vectorO = vector1.sub(vectorE.mul(d));

            //////////////////////////////////////////////////////////////////
            // calculate q12 which solves for the midJoint rotation
            //////////////////////////////////////////////////////////////////
            // angle between vector1 and vector2
            double vectorAngle12 = vector1.angle(vector2);

            // vector orthogonal to vector1 and 2
            AwVector vectorCross12  = vector1.crossProduct(vector2);
            double   lengthHsquared = lengthH * lengthH;

            // angle for arm extension
            double cos_theta =
                (lengthHsquared - length1 * length1 - length2 * length2)
                / (2 * length1 * length2);

            if (cos_theta > 1)
            {
                cos_theta = 1;
            }
            else if (cos_theta < -1)
            {
                cos_theta = -1;
            }

            double theta = Math.Acos(cos_theta);

            AwQuaternion q12 = new AwQuaternion(theta - vectorAngle12, vectorCross12);

            //////////////////////////////////////////////////////////////////
            // calculate qEH which solves for effector rotating onto the handle
            //////////////////////////////////////////////////////////////////
            // vector2 with quaternion q12 applied
            vector2 = vector2.rotateBy(q12);
            // vectorE with quaternion q12 applied
            vectorE = vector1.add(vector2);
            // quaternion for rotating the effector onto the handle
            AwQuaternion qEH = new AwQuaternion(vectorE, vectorH);

            // calculate qNP which solves for the rotate plane
            //////////////////////////////////////////////////////////////////
            // vector1 with quaternion qEH applied
            vector1 = vector1.rotateBy(qEH);
            if (vector1.isParallel(vectorH, AwMath.kDoubleEpsilon))
            {
                // singular case, use orthogonal component instead
                vector1 = vectorO.rotateBy(qEH);
            }

            AwQuaternion qNP = new AwQuaternion();

            if (!poleVector.isParallel(vectorH, AwMath.kDoubleEpsilon) && (lengthHsquared != 0))
            {
                double   temp    = poleVector.mul(vectorH) / lengthHsquared;
                AwVector vectorN = vector1.sub(vectorH.mul(temp));

                AwVector vectorP = poleVector.sub(vectorH.mul(vector1.mul(vectorH) / lengthHsquared));

                double dotNP = (vectorN.mul(vectorP)) / (vectorN.length() * vectorP.length());

                if (Math.Abs(dotNP + 1.0) < kEpsilon)
                {
                    // singular case, rotate halfway around vectorH
                    AwQuaternion qNP1 = new AwQuaternion(AwMath.kPi, vectorH);
                    qNP = qNP1;
                }
                else
                {
                    AwQuaternion qNP2 = new AwQuaternion(vectorN, vectorP);
                    qNP = qNP2;
                }
            }

            //////////////////////////////////////////////////////////////////
            // calculate qTwist which adds the twist
            //////////////////////////////////////////////////////////////////
            AwQuaternion qTwist = new AwQuaternion(twistValue, vectorH);

            // quaternion for the mid joint
            qMid = q12;
            // concatenate the quaternions for the start joint
            AwQuaternion qTemp = qEH.mul(qNP);

            qStart = qTemp.mul(qTwist);
        }
Example #8
0
        // This is method that actually computes the IK solution.
        //
        void solveIK( AwPoint startJointPos,
            AwPoint midJointPos,
            AwPoint effectorPos,
            AwPoint handlePos,
            AwVector poleVector,
            double twistValue,
            AwQuaternion qStart,
            AwQuaternion qMid)
        {
            // vector from startJoint to midJoint
            AwVector vector1 = midJointPos.sub(startJointPos);
            // vector from midJoint to effector
            AwVector vector2 = effectorPos.sub(midJointPos);
            // vector from startJoint to handle
            AwVector vectorH = handlePos.sub(startJointPos);
            // vector from startJoint to effector
            AwVector vectorE = effectorPos.sub(startJointPos);

            // lengths of those vectors
            double length1 = vector1.length();
            double length2 = vector2.length();
            double lengthH = vectorH.length();

            double d = vector1.mul(vectorE) / vectorE.mul(vectorE);
            AwVector vectorO = vector1.sub(vectorE.mul(d));

            //////////////////////////////////////////////////////////////////
            // calculate q12 which solves for the midJoint rotation
            //////////////////////////////////////////////////////////////////
            // angle between vector1 and vector2
            double vectorAngle12 = vector1.angle(vector2);

            // vector orthogonal to vector1 and 2
            AwVector vectorCross12 = vector1.crossProduct(vector2);
            double lengthHsquared = lengthH * lengthH;

            // angle for arm extension
            double cos_theta =
                (lengthHsquared - length1*length1 - length2*length2)
                /(2*length1*length2);

            if (cos_theta > 1)
                cos_theta = 1;
            else if (cos_theta < -1)
                cos_theta = -1;

            double theta = Math.Acos(cos_theta);

            AwQuaternion q12 = new AwQuaternion(theta - vectorAngle12, vectorCross12);

            //////////////////////////////////////////////////////////////////
            // calculate qEH which solves for effector rotating onto the handle
            //////////////////////////////////////////////////////////////////
            // vector2 with quaternion q12 applied
            vector2 = vector2.rotateBy(q12);
            // vectorE with quaternion q12 applied
            vectorE = vector1.add(vector2);
            // quaternion for rotating the effector onto the handle
            AwQuaternion qEH = new AwQuaternion(vectorE, vectorH);

            // calculate qNP which solves for the rotate plane
            //////////////////////////////////////////////////////////////////
            // vector1 with quaternion qEH applied
            vector1 = vector1.rotateBy(qEH);
            if (vector1.isParallel(vectorH,AwMath.kDoubleEpsilon))
                // singular case, use orthogonal component instead
                vector1 = vectorO.rotateBy(qEH);

            AwQuaternion qNP = new AwQuaternion();
            if (!poleVector.isParallel(vectorH, AwMath.kDoubleEpsilon) && (lengthHsquared != 0))
            {
                double temp = poleVector.mul(vectorH) / lengthHsquared;
                AwVector vectorN = vector1.sub(vectorH.mul(temp));

                AwVector vectorP = poleVector.sub(vectorH.mul(vector1.mul(vectorH) / lengthHsquared));

                double dotNP = (vectorN.mul(vectorP)) / (vectorN.length() * vectorP.length());

                if (Math.Abs(dotNP + 1.0) < kEpsilon)
                {
                    // singular case, rotate halfway around vectorH
                    AwQuaternion qNP1 = new AwQuaternion(AwMath.kPi, vectorH);
                    qNP = qNP1;
                }
                else
                {
                    AwQuaternion qNP2 = new AwQuaternion(vectorN, vectorP);
                    qNP = qNP2;
                }
            }

            //////////////////////////////////////////////////////////////////
            // calculate qTwist which adds the twist
            //////////////////////////////////////////////////////////////////
            AwQuaternion qTwist = new AwQuaternion(twistValue, vectorH);

            // quaternion for the mid joint
            qMid = q12;
            // concatenate the quaternions for the start joint
            AwQuaternion qTemp = qEH.mul(qNP);
            qStart = qTemp.mul(qTwist);
        }
Example #9
0
        public override void doSolve()
        {
            MIkHandleGroup handle_group = handleGroup;
            if (handle_group == null)
                throw new InvalidOperationException("Invalid handle group");

            MObject handle = handle_group.handle(0);
            MDagPath handlePath = MDagPath.getAPathTo(handle);
            MFnIkHandle handleFn = new MFnIkHandle(handlePath);

            //Effector
            //
            MDagPath effectorPath = new MDagPath();
            handleFn.getEffector(effectorPath);
            MFnIkEffector effectorFn = new MFnIkEffector(effectorPath);

            effectorPath.pop();
            MFnIkJoint midJoinFn = new MFnIkJoint(effectorPath);

            // Start Joint
            //
            MDagPath startJointPath = new MDagPath();
            handleFn.getStartJoint(startJointPath);
            MFnIkJoint startJointFn = new MFnIkJoint(startJointPath);

            // Preferred angles
            //
            double [] startJointPrefAngle = new double[3];
            double[]  midJointPrefAngle = new double[3];

            startJointFn.getPreferedAngle(startJointPrefAngle);
            midJoinFn.getPreferedAngle(midJointPrefAngle);

            // Set to preferred angles
            //
            startJointFn.setRotation(startJointPrefAngle, startJointFn.rotationOrder);

            midJoinFn.setRotation(midJointPrefAngle, midJoinFn.rotationOrder);

            MPoint handlePos = handleFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awHandlePos = new AwPoint(handlePos.x, handlePos.y, handlePos.z, handlePos.w);

            MPoint effectorPos = effectorFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awEffectorPos = new AwPoint(effectorPos.x, effectorPos.y, effectorPos.z, effectorPos.w);

            MPoint midJoinPos = midJoinFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awMidJoinPos = new AwPoint(midJoinPos.x, midJoinPos.y, midJoinPos.z, midJoinPos.w);

            MPoint startJointPos = startJointFn.rotatePivot(MSpace.Space.kWorld);
            AwPoint awStartJointPos = new AwPoint(startJointPos.x, startJointPos.y, startJointPos.z, startJointPos.w);

            AwVector poleVector = poleVectorFromHandle(handlePath);
            MMatrix m = handlePath.exclusiveMatrix;
            AwMatrix awM = new AwMatrix();
            awM.setMatrix(m);
            poleVector = poleVector.mulMatrix(awM);
            double twistValue = twistFromHandle(handlePath);

            AwQuaternion qStart = new AwQuaternion();
            AwQuaternion qMid = new AwQuaternion();

            solveIK(awStartJointPos, awMidJoinPos, awEffectorPos, awHandlePos,
                poleVector, twistValue, qStart, qMid);

            MQuaternion mid = new MQuaternion(qMid.x, qMid.y, qMid.z, qMid.w);
            MQuaternion start = new MQuaternion(qStart.x, qStart.y, qStart.z, qStart.w);

            midJoinFn.rotateBy(mid, MSpace.Space.kWorld);
            startJointFn.rotateBy(start, MSpace.Space.kWorld);

            return;
        }
Example #10
0
 public AwVector rotateBy( AwQuaternion q)
 {
     double rw = -q.x * x - q.y * y - q.z * z;
     double rx = q.w * x + q.y * z - q.z * y;
     double ry = q.w * y + q.z * x - q.x * z;
     double rz = q.w * z + q.x * y - q.y * x;
     AwVector v = new AwVector(-rw * q.x + rx * q.w - ry * q.z + rz * q.y,
                     -rw * q.y + ry * q.w - rz * q.x + rx * q.z,
                     -rw * q.z + rz * q.w - rx * q.y + ry * q.x);
     return v;
 }