예제 #1
0
        public override void Update(byte dirt)
        {
            ActorBone      bone            = m_Parent as ActorBone;
            ActorBone      parentBone      = bone.Parent as ActorBone;
            JellyComponent parentBoneJelly = parentBone == null ? null : parentBone.m_Jelly;

            Mat2D inverseWorld = new Mat2D();

            if (!Mat2D.Invert(inverseWorld, bone.WorldTransform))
            {
                return;
            }

            if (m_InTarget != null)
            {
                Vec2D translation = m_InTarget.GetWorldTranslation(new Vec2D());
                Vec2D.TransformMat2D(m_InPoint, translation, inverseWorld);
                Vec2D.Normalize(m_InDirection, m_InPoint);
            }
            else if (parentBone != null)
            {
                if (parentBone.FirstBone == bone && parentBoneJelly != null && parentBoneJelly.m_OutTarget != null)
                {
                    Vec2D translation    = parentBoneJelly.m_OutTarget.GetWorldTranslation(new Vec2D());
                    Vec2D localParentOut = Vec2D.TransformMat2D(new Vec2D(), translation, inverseWorld);
                    Vec2D.Normalize(localParentOut, localParentOut);
                    Vec2D.Negate(m_InDirection, localParentOut);
                }
                else
                {
                    Vec2D d1 = new Vec2D(1.0f, 0.0f);
                    Vec2D d2 = new Vec2D(1.0f, 0.0f);

                    Vec2D.TransformMat2(d1, d1, parentBone.WorldTransform);
                    Vec2D.TransformMat2(d2, d2, bone.WorldTransform);

                    Vec2D sum = Vec2D.Add(new Vec2D(), d1, d2);
                    Vec2D.TransformMat2(m_InDirection, sum, inverseWorld);
                    Vec2D.Normalize(m_InDirection, m_InDirection);
                }
                m_InPoint[0] = m_InDirection[0] * m_EaseIn * bone.Length * CurveConstant;
                m_InPoint[1] = m_InDirection[1] * m_EaseIn * bone.Length * CurveConstant;
            }
            else
            {
                m_InDirection[0] = 1.0f;
                m_InDirection[1] = 0.0f;
                m_InPoint[0]     = m_InDirection[0] * m_EaseIn * bone.Length * CurveConstant;
            }

            if (m_OutTarget != null)
            {
                Vec2D translation = m_OutTarget.GetWorldTranslation(new Vec2D());
                Vec2D.TransformMat2D(m_OutPoint, translation, inverseWorld);
                Vec2D tip = new Vec2D(bone.Length, 0.0f);
                Vec2D.Subtract(m_OutDirection, m_OutPoint, tip);
                Vec2D.Normalize(m_OutDirection, m_OutDirection);
            }
            else if (bone.FirstBone != null)
            {
                ActorBone      firstBone      = bone.FirstBone;
                JellyComponent firstBoneJelly = firstBone.m_Jelly;
                if (firstBoneJelly != null && firstBoneJelly.m_InTarget != null)
                {
                    Vec2D translation     = firstBoneJelly.m_InTarget.GetWorldTranslation(new Vec2D());
                    Vec2D worldChildInDir = Vec2D.Subtract(new Vec2D(), firstBone.GetWorldTranslation(new Vec2D()), translation);
                    Vec2D.TransformMat2(m_OutDirection, worldChildInDir, inverseWorld);
                }
                else
                {
                    Vec2D d1 = new Vec2D(1.0f, 0.0f);
                    Vec2D d2 = new Vec2D(1.0f, 0.0f);

                    Vec2D.TransformMat2(d1, d1, firstBone.WorldTransform);
                    Vec2D.TransformMat2(d2, d2, bone.WorldTransform);

                    Vec2D sum = Vec2D.Add(new Vec2D(), d1, d2);
                    Vec2D.Negate(sum, sum);
                    Vec2D.TransformMat2(m_OutDirection, sum, inverseWorld);
                    Vec2D.Normalize(m_OutDirection, m_OutDirection);
                }
                Vec2D.Normalize(m_OutDirection, m_OutDirection);
                Vec2D scaledOut = Vec2D.Scale(new Vec2D(), m_OutDirection, m_EaseOut * bone.Length * CurveConstant);
                m_OutPoint[0] = bone.Length;
                m_OutPoint[1] = 0.0f;
                Vec2D.Add(m_OutPoint, m_OutPoint, scaledOut);
            }
            else
            {
                m_OutDirection[0] = -1.0f;
                m_OutDirection[1] = 0.0f;

                Vec2D scaledOut = Vec2D.Scale(new Vec2D(), m_OutDirection, m_EaseOut * bone.Length * CurveConstant);
                m_OutPoint[0] = bone.Length;
                m_OutPoint[1] = 0.0f;
                Vec2D.Add(m_OutPoint, m_OutPoint, scaledOut);
            }

            UpdateJellies();
        }
예제 #2
0
        void Solve2(BoneChain fk1, BoneChain fk2, Vec2D worldTargetTranslation)
        {
            ActorBone b1         = fk1.m_Bone;
            ActorBone b2         = fk2.m_Bone;
            BoneChain firstChild = m_FKChain[fk1.m_Index + 1];

            Mat2D iworld = fk1.m_ParentWorldInverse;

            Vec2D pA  = b1.GetWorldTranslation(new Vec2D());
            Vec2D pC  = firstChild.m_Bone.GetWorldTranslation(new Vec2D());
            Vec2D pB  = b2.GetTipWorldTranslation(new Vec2D());;
            Vec2D pBT = new Vec2D(worldTargetTranslation);

            pA  = Vec2D.TransformMat2D(pA, pA, iworld);
            pC  = Vec2D.TransformMat2D(pC, pC, iworld);
            pB  = Vec2D.TransformMat2D(pB, pB, iworld);
            pBT = Vec2D.TransformMat2D(pBT, pBT, iworld);

            // http://mathworld.wolfram.com/LawofCosines.html
            Vec2D av = Vec2D.Subtract(new Vec2D(), pB, pC);
            float a  = Vec2D.Length(av);

            Vec2D bv = Vec2D.Subtract(new Vec2D(), pC, pA);
            float b  = Vec2D.Length(bv);

            Vec2D cv = Vec2D.Subtract(new Vec2D(), pBT, pA);
            float c  = Vec2D.Length(cv);

            float A = (float)Math.Acos(Math.Max(-1, Math.Min(1, (-a * a + b * b + c * c) / (2 * b * c))));
            float C = (float)Math.Acos(Math.Max(-1, Math.Min(1, (a * a + b * b - c * c) / (2 * a * b))));

            float r1, r2;

            if (b2.Parent != b1)
            {
                BoneChain secondChild = m_FKChain[fk1.m_Index + 2];

                Mat2D secondChildWorldInverse = secondChild.m_ParentWorldInverse;

                pC = firstChild.m_Bone.GetWorldTranslation(new Vec2D());
                pB = b2.GetTipWorldTranslation(new Vec2D());

                Vec2D avec            = Vec2D.Subtract(new Vec2D(), pB, pC);
                Vec2D avLocal         = Vec2D.TransformMat2(new Vec2D(), avec, secondChildWorldInverse);
                float angleCorrection = (float)-Math.Atan2(avLocal[1], avLocal[0]);

                if (m_InvertDirection)
                {
                    r1 = (float)Math.Atan2(cv[1], cv[0]) - A;
                    r2 = -C + PI + angleCorrection;
                }
                else
                {
                    r1 = A + (float)Math.Atan2(cv[1], cv[0]);
                    r2 = C - PI + angleCorrection;
                }
            }
            else if (m_InvertDirection)
            {
                r1 = (float)Math.Atan2(cv[1], cv[0]) - A;
                r2 = -C + PI;
            }
            else
            {
                r1 = A + (float)Math.Atan2(cv[1], cv[0]);
                r2 = C - PI;
            }

            ConstrainRotation(fk1, r1);
            ConstrainRotation(firstChild, r2);
            if (firstChild != fk2)
            {
                ActorBone bone = fk2.m_Bone;
                Mat2D.Multiply(bone.WorldTransform, bone.Parent.WorldTransform, bone.Transform);
            }

            // Simple storage, need this for interpolation.
            fk1.m_Angle        = r1;
            firstChild.m_Angle = r2;
        }