예제 #1
0
        /// <summary>
        /// This method can be called when the flex move didn't reach the target yet, to continue to converge
        /// <returns>true if the flex move still need to be updated</returns>
        /// </summary>
        public bool update()
        {
            if (mCurrentUpdateStatus == IKSolver.CCDResult.Processing)
            {
                // a threshold tuning variable for reaching target
                const double REACH_TARGET_PRECISION_IN_STUD = 0.1;
                int          lastBone = mBoneList.Count;

                if (mUseTwoTargets)
                {
                    // if we use two targets, do the first pass on the second target
                    // reverse the Y because BlueBrick use an indirect coord sys, and the IKSolver a direct one
                    IKSolver.CalcIK_2D_CCD(ref mBoneList, mSecondaryTarget.X, -mSecondaryTarget.Y,
                                           REACH_TARGET_PRECISION_IN_STUD, lastBone - 1);
                    computeBrickPositionAndOrientation();
                }

                // do the normal pass on the final target
                // reverse the Y because BlueBrick use an indirect coord sys, and the IKSolver a direct one
                mCurrentUpdateStatus = IKSolver.CalcIK_2D_CCD(ref mBoneList, mPrimaryTarget.X, -mPrimaryTarget.Y,
                                                              REACH_TARGET_PRECISION_IN_STUD, lastBone);
                computeBrickPositionAndOrientation();
            }

            // return true if we still need to update
            return(mCurrentUpdateStatus == IKSolver.CCDResult.Processing);
        }
예제 #2
0
        /// <summary>
        /// Try to reach the specify target position with this chain
        /// </summary>
        /// <param name="targetInWorldStudCoord">the target position in world stud coord</param>
        /// <param name="targetConnection">If the end of the flex chain need to be connected to a connection, this parameter indicates which one, otherwise it is null</param>
        public void reachTarget(PointF targetInWorldStudCoord, LayerBrick.Brick.ConnectionPoint targetConnection)
        {
            // save the primary target
            mPrimaryTarget = targetInWorldStudCoord;

            // check if we need to compute a second target position
            mUseTwoTargets = (targetConnection != null);
            if (mUseTwoTargets)
            {
                // rotate the second target vector according to the orientation of the snapped connection
                PointF[] translation = { mLastBoneVector };
                Matrix   rotation    = new Matrix();
                rotation.Rotate(targetConnection.mMyBrick.Orientation + targetConnection.Angle + 180);
                rotation.TransformVectors(translation);

                // translate the target with the rotated vector for the second target
                mSecondaryTarget.X = targetInWorldStudCoord.X + translation[0].X;
                mSecondaryTarget.Y = targetInWorldStudCoord.Y + translation[0].Y;
            }

            // reset the status flag
            mCurrentUpdateStatus = IKSolver.CCDResult.Processing;

            // and call the update method
            update();
        }
예제 #3
0
        /// <summary>
        /// Perform an iteration of IK
        /// </summary>
        private void UpdateIK()
        {
            int numBones = Bones.Count;

            if (numBones == 0)
            {
                return;
            }

            // calculate the bone angles
            List <IKSolver.Bone_2D_CCD> ccdBones = new List <IKSolver.Bone_2D_CCD>();

            for (int boneIdx = 0; boneIdx <= numBones; ++boneIdx)
            {
                IKSolver.Bone_2D_CCD newCcdBone = new IKSolver.Bone_2D_CCD();
                newCcdBone.angle      = (boneIdx < numBones) ? Bones[boneIdx].Radians : 0;
                newCcdBone.x          = (boneIdx > 0) ? Bones[boneIdx - 1].Length : 0;
                newCcdBone.y          = 0;
                newCcdBone.minlimiter = (boneIdx < numBones) ? Bones[boneIdx].MinLimiter : 0;
                newCcdBone.maxlimiter = (boneIdx < numBones) ? Bones[boneIdx].MaxLimiter : 0;
                ccdBones.Add(newCcdBone);
            }

            // iterate CCD until limit is reached or we find a valid solution
            for (int itrCount = 0; itrCount < IterationsPerUpdate; ++itrCount)
            {
                IKSolver.CCDResult result = IKSolver.CalcIK_2D_CCD(ref ccdBones, TargetPosX, TargetPosY, ArrivalDist);
                if (result == IKSolver.CCDResult.Processing)
                {
                    CCDResult = "Обработка";
                }
                else if (result == IKSolver.CCDResult.Success)
                {
                    CCDResult = "Выполнено";
                    break;
                }
                else if (result == IKSolver.CCDResult.Failure)
                {
                    CCDResult = "Неудача";
                    break;
                }
                else
                {
                    Debug.Assert(false);
                    CCDResult = "[UNKNOWN]";
                    break;
                }
            }

            // extract the new bone data from the results
            for (int boneIdx = 0; boneIdx < numBones; ++boneIdx)
            {
                Bones[boneIdx].Radians = ccdBones[boneIdx].angle;
            }
        }
예제 #4
0
        /// <summary>
        /// This method can be called when the flex move didn't reach the target yet, to continue to converge
        /// <returns>true if the flex move still need to be updated</returns>
        /// </summary>
        public bool update()
        {
            if (mCurrentUpdateStatus == IKSolver.CCDResult.Processing)
            {
                // a threshold tuning variable for reaching target
                const double REACH_TARGET_PRECISION_IN_STUD = 0.1;
                int lastBone = mBoneList.Count;

                if (mUseTwoTargets)
                {
                    // if we use two targets, do the first pass on the second target
                    // reverse the Y because BlueBrick use an indirect coord sys, and the IKSolver a direct one
                    IKSolver.CalcIK_2D_CCD(ref mBoneList, mSecondaryTarget.X, -mSecondaryTarget.Y,
                                            REACH_TARGET_PRECISION_IN_STUD, lastBone - 1);
                    computeBrickPositionAndOrientation();
                }

                // do the normal pass on the final target
                // reverse the Y because BlueBrick use an indirect coord sys, and the IKSolver a direct one
                mCurrentUpdateStatus = IKSolver.CalcIK_2D_CCD(ref mBoneList, mPrimaryTarget.X, -mPrimaryTarget.Y,
                                                                    REACH_TARGET_PRECISION_IN_STUD, lastBone);
                computeBrickPositionAndOrientation();
            }

            // return true if we still need to update
            return (mCurrentUpdateStatus == IKSolver.CCDResult.Processing);
        }
예제 #5
0
        /// <summary>
        /// Try to reach the specify target position with this chain
        /// </summary>
        /// <param name="targetInWorldStudCoord">the target position in world stud coord</param>
        /// <param name="targetConnection">If the end of the flex chain need to be connected to a connection, this parameter indicates which one, otherwise it is null</param>
        public void reachTarget(PointF targetInWorldStudCoord, LayerBrick.Brick.ConnectionPoint targetConnection)
        {
            // save the primary target
            mPrimaryTarget = targetInWorldStudCoord;

            // check if we need to compute a second target position
            mUseTwoTargets = (targetConnection != null);
            if (mUseTwoTargets)
            {
                // rotate the second target vector according to the orientation of the snapped connection
                PointF[] translation = { mLastBoneVector };
                Matrix rotation = new Matrix();
                rotation.Rotate(targetConnection.mMyBrick.Orientation + targetConnection.Angle + 180);
                rotation.TransformVectors(translation);

                // translate the target with the rotated vector for the second target
                mSecondaryTarget.X = targetInWorldStudCoord.X + translation[0].X;
                mSecondaryTarget.Y = targetInWorldStudCoord.Y + translation[0].Y;
            }

            // reset the status flag
            mCurrentUpdateStatus = IKSolver.CCDResult.Processing;

            // and call the update method
            update();
        }