/// <summary>
        /// Defines what to do when processing the animation.
        /// </summary>
        /// <param name="stream">The animation stream to work on.</param>
        public void ProcessAnimation(AnimationStream stream)
        {
            jobWeight.Set(stream, 1f);

            var lRot   = driven.GetLocalRotation(stream);
            var offset = drivenOffset.Get(stream);

            if (Vector3.Dot(offset, offset) > 0f)
            {
                lRot *= Quaternion.Inverse(Quaternion.Euler(offset));
            }

            var wRot = lRot;

            if (drivenParent.IsValid(stream))
            {
                wRot = drivenParent.GetRotation(stream) * wRot;
            }

            for (int i = 0; i < sourceTransforms.Length; ++i)
            {
                sourceWeights[i].SetFloat(stream, 1f);

                ReadWriteTransformHandle sourceTransform = sourceTransforms[i];

                sourceTransform.SetRotation(stream, wRot * sourceOffsets[i]);

                // Required to update handles with binding info.
                sourceTransforms[i] = sourceTransform;
            }
        }
示例#2
0
    public void ProcessAnimation(AnimationStream stream)
    {
        float w = jobWeight.Get(stream);

        if (w > 0f)
        {
            var sliderPos = Slider.GetLocalPosition(stream);
            var t         = Mathf.Clamp01(sliderPos.y);
            Slider.SetLocalPosition(stream, new Vector3(0, t, 0));

            if (Rotation)
            {
                var rot = Quaternion.Lerp(
                    SourceA.GetRotation(stream),
                    SourceB.GetRotation(stream),
                    t
                    );

                var targetRot = Target.GetRotation(stream);
                Target.SetRotation(stream, Quaternion.Lerp(targetRot, rot, w));
            }

            if (Position)
            {
                var pos = Vector3.Lerp(
                    SourceA.GetPosition(stream),
                    SourceB.GetPosition(stream),
                    t
                    );

                var targetPos = Target.GetPosition(stream);
                Target.SetPosition(stream, Vector3.Lerp(targetPos, pos, w));
            }
        }
    }
        public void ProcessAnimation(AnimationStream stream)
        {
            jobWeight.Set(stream, 1f);

            var lRot   = driven.GetLocalRotation(stream);
            var offset = drivenOffset.Get(stream);

            if (Vector3.Dot(offset, offset) > 0f)
            {
                lRot *= Quaternion.Inverse(Quaternion.Euler(offset));
            }

            var localToWorld = Quaternion.identity;
            var wPos         = driven.GetPosition(stream);

            if (drivenParent.IsValid(stream))
            {
                localToWorld = drivenParent.GetRotation(stream);
            }

            for (int i = 0; i < sourceTransforms.Length; ++i)
            {
                sourceWeights[i].SetFloat(stream, 1f);

                var sourceTransform = sourceTransforms[i];

                sourceTransform.SetPosition(stream, wPos + localToWorld * sourceOffsets[i] * lRot * aimAxis);

                // Required to update handles with binding info.
                sourceTransforms[i] = sourceTransform;
            }
        }
        public void ProcessAnimation(AnimationStream stream)
        {
            jobWeight.Set(stream, 1f);

            rootTarget.SetPosition(stream, root.GetPosition(stream));
            rootTarget.SetRotation(stream, root.GetRotation(stream));

            tipTarget.SetPosition(stream, tip.GetPosition(stream));
            tipTarget.SetRotation(stream, tip.GetRotation(stream));
        }
        /// <summary>
        /// Defines what to do when processing the animation.
        /// </summary>
        /// <param name="stream">The animation stream to work on.</param>
        public void ProcessAnimation(AnimationStream stream)
        {
            float w = jobWeight.Get(stream);

            if (w > 0f)
            {
                if (blendPosition.Get(stream))
                {
                    Vector3 posBlend = Vector3.Lerp(
                        sourceA.GetPosition(stream) + sourceAOffset.translation,
                        sourceB.GetPosition(stream) + sourceBOffset.translation,
                        positionWeight.Get(stream)
                        );
                    driven.SetPosition(stream, Vector3.Lerp(driven.GetPosition(stream), posBlend, w));
                }
                else
                {
                    driven.SetLocalPosition(stream, driven.GetLocalPosition(stream));
                }

                if (blendRotation.Get(stream))
                {
                    Quaternion rotBlend = Quaternion.Lerp(
                        sourceA.GetRotation(stream) * sourceAOffset.rotation,
                        sourceB.GetRotation(stream) * sourceBOffset.rotation,
                        rotationWeight.Get(stream)
                        );
                    driven.SetRotation(stream, Quaternion.Lerp(driven.GetRotation(stream), rotBlend, w));
                }
                else
                {
                    driven.SetLocalRotation(stream, driven.GetLocalRotation(stream));
                }
            }
            else
            {
                AnimationRuntimeUtils.PassThrough(stream, driven);
            }
        }
    public void ProcessAnimation(AnimationStream stream)
    {
        float w = jobWeight.Get(stream);

        var sliderPos = Slider.GetLocalPosition(stream);
        var t         = Mathf.Clamp01(sliderPos.y);

        Slider.SetLocalPosition(stream, new Vector3(0, t, 0));

        if (w > 0f)
        {
            var rootRot = Root.GetRotation(stream);
            var midRot  = Mid.GetRotation(stream);
            var tipRot  = Tip.GetRotation(stream);

            var rootRotFK = Quaternion.Lerp(rootRot, FK_Root.GetRotation(stream), w);
            var midRotFK  = Quaternion.Lerp(midRot, FK_Mid.GetRotation(stream), w);
            var tipRotFK  = tipRot;

            AnimationRuntimeUtils.SolveTwoBoneIK(
                stream, Root, Mid, Tip, IK_Target, IK_Hint,
                posWeight: 1f * w,
                rotWeight: 0 * w,
                hintWeight: 1f * w,
                limbLengths: LinkLengths,
                targetOffset: AffineTransform.identity
                );
            var rootRotIK = Root.GetRotation(stream);
            var midRotIK  = Mid.GetRotation(stream);
            var tipRotIK  = Tip.GetRotation(stream);

            Root.SetRotation(stream, Quaternion.Lerp(rootRotFK, rootRotIK, t));
            Mid.SetRotation(stream, Quaternion.Lerp(midRotFK, midRotIK, t));
            Tip.SetRotation(stream, Quaternion.Lerp(tipRotFK, tipRotIK, t));
        }
    }
示例#7
0
    public void ProcessAnimation(AnimationStream stream)
    {
        var w = jobWeight.Get(stream);

        if (w == 0f)
        {
            return;
        }

        var offset = ikOffset.Get(stream);

        var leftToePos  = leftToe.GetPosition(stream);
        var rightToePos = rightToe.GetPosition(stream);

        var leftIkOffset  = offset.x * w;
        var rightIkOffset = offset.y * w;

        leftToePos  += new Vector3(0f, leftIkOffset, 0f);
        rightToePos += new Vector3(0f, rightIkOffset, 0f);


        var leftAnklePos  = leftAnkle.GetPosition(stream);
        var rightAnklePos = rightAnkle.GetPosition(stream);
        var leftAnkleRot  = leftAnkle.GetRotation(stream);
        var rightAnkleRot = rightAnkle.GetRotation(stream);

        var leftAnkleIkPos  = new Vector3(leftAnklePos.x, leftAnklePos.y + leftIkOffset, leftAnklePos.z);
        var rightAnkleIkPos = new Vector3(rightAnklePos.x, rightAnklePos.y + rightIkOffset, rightAnklePos.z);

        var hipHeightOffset = (leftIkOffset + rightIkOffset) * 0.5f;
        var forwardBackBias = (leftIkOffset - rightIkOffset) * weightShiftHorizontal.Get(stream);

        float maxRotationOffset = maxFootRotationOffset.Get(stream);

        // TODO: (sunek) Rework weight shift to move towards actual lower foot?
        hipHeightOffset += Mathf.Abs(leftIkOffset - rightIkOffset) * weightShiftVertical.Get(stream);
        var standAngle = Quaternion.AngleAxis(weightShiftAngle.Get(stream), Vector3.up) * Vector3.forward;

        hips.SetPosition(stream, hips.GetPosition(stream) + new Vector3(standAngle.x * forwardBackBias, hipHeightOffset, standAngle.z * forwardBackBias));

        // Figure out the normal rotation
        var leftNormalRot  = Quaternion.LookRotation(Vector3.forward, normalLeftFoot.Get(stream));
        var rightNormalRot = Quaternion.LookRotation(Vector3.forward, normalRightFoot.Get(stream));

        // Clamp normal rotation
        var leftAngle  = Quaternion.Angle(Quaternion.identity, leftNormalRot);
        var rightAngle = Quaternion.Angle(Quaternion.identity, rightNormalRot);

        if (leftAngle > maxRotationOffset && maxRotationOffset > 0f)
        {
            var fraction = maxRotationOffset / leftAngle;
            leftNormalRot = Quaternion.Lerp(Quaternion.identity, leftNormalRot, fraction);
        }

        if (rightAngle > maxRotationOffset && maxRotationOffset > 0f)
        {
            var fraction = maxRotationOffset / rightAngle;
            rightNormalRot = Quaternion.Lerp(Quaternion.identity, rightNormalRot, fraction);
        }

        // Apply rotation to ankle
        var leftToesMatrix  = Matrix4x4.TRS(leftToePos, Quaternion.identity, Vector3.one);
        var rightToesMatrix = Matrix4x4.TRS(rightToePos, Quaternion.identity, Vector3.one);

        var leftToesNormalDeltaMatrix  = Matrix4x4.TRS(leftToePos, leftNormalRot, Vector3.one) * leftToesMatrix.inverse;
        var rightToesNormalDeltaMatrix = Matrix4x4.TRS(rightToePos, rightNormalRot, Vector3.one) * rightToesMatrix.inverse;

        var leftAnkleMatrix  = Matrix4x4.TRS(leftAnkleIkPos, leftAnkleRot, Vector3.one) * leftToesMatrix.inverse;
        var rightAnkleMatrix = Matrix4x4.TRS(rightAnkleIkPos, rightAnkleRot, Vector3.one) * rightToesMatrix.inverse;

        leftAnkleMatrix  = leftToesNormalDeltaMatrix * leftAnkleMatrix * leftToesMatrix;
        rightAnkleMatrix = rightToesNormalDeltaMatrix * rightAnkleMatrix * rightToesMatrix;

        leftAnkleIkPos  = leftAnkleMatrix.GetColumn(3);
        rightAnkleIkPos = rightAnkleMatrix.GetColumn(3);

        leftAnkleRot  = Quaternion.Lerp(leftAnkleRot, leftAnkleMatrix.rotation, w);
        rightAnkleRot = Quaternion.Lerp(rightAnkleRot, rightAnkleMatrix.rotation, w);

        // Update ik position
        // TODO: (sunek) Consider combating leg overstretch
        var leftPosition  = Vector3.Lerp(leftAnklePos, leftAnkleIkPos, w);
        var rightPosition = Vector3.Lerp(rightAnklePos, rightAnkleIkPos, w);

        leftEffector.SetPosition(stream, leftPosition);
        rightEffector.SetPosition(stream, rightPosition);
        leftEffector.SetRotation(stream, leftAnkleRot);
        rightEffector.SetRotation(stream, rightAnkleRot);
    }
        public void ProcessAnimation(AnimationStream stream)
        {
            var jointCount  = boneChain.Length;
            var boneCount   = jointCount - 1;
            var tipPosition = tipTarget.GetPosition(stream);
            var weight      = jobWeight.Get(stream);
            var positions   = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var tangents    = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var normals     = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var v0          = boneChain[0].GetRotation(stream) * Vector3.up;

            // fill the local buffer of positions
            for (var i = 0; i < jointCount; i++)
            {
                positions[i] = boneChain[i].GetPosition(stream);
            }

            // perform solver iterations
            for (var i = 0; i < iterationCount; i++)
            {
                // force final position to the tip target... unsure if this is the best...
                positions[positions.Length - 1] = tipPosition;

                // project distance constraints
                for (var j = 0; j < boneCount; j++)
                {
                    var invMass0 = j == 0 ? 0f : 1f;
                    var invMass1 = j == boneCount - 1 ? 0 : 1f;
                    var p0       = positions[j + 0];
                    var p1       = positions[j + 1];
                    var d        = restLengths[j];
                    var C        = distance(p0, p1) - d;

                    if (C < float.Epsilon && C > -float.Epsilon)
                    {
                        continue;
                    }

                    var direction = normalize(p0 - p1);
                    var lambda    = C * direction;

                    positions[j + 0] -= invMass0 / (invMass0 + invMass1) * lambda;
                    positions[j + 1] += invMass1 / (invMass0 + invMass1) * lambda;
                }

                // project collisions
                for (var j = 0; j < jointCount; j++)
                {
                    var p = positions[j];

                    p.y          = max(p.y, minimumHeight);
                    positions[j] = p;
                }
            }

            // Set the new bone rotations
            for (var i = 0; i < boneCount; i++)
            {
                var prevDir            = boneChain[i + 1].GetPosition(stream) - boneChain[i + 0].GetPosition(stream);
                var newDir             = positions[i + 1] - positions[i];
                var currentRotation    = boneChain[i].GetRotation(stream);
                var additionalRotation = QuaternionExt.FromToRotation(prevDir, newDir);

                boneChain[i].SetRotation(stream, Quaternion.Lerp(currentRotation, additionalRotation * currentRotation, weight));
            }

            boneChain[jointCount - 1].SetRotation(stream, tipTarget.GetRotation(stream));

            positions.Dispose();
            tangents.Dispose();
            normals.Dispose();
        }
    public void ProcessAnimation(AnimationStream stream)
    {
        float w = jobWeight.Get(stream);

        if (w > 0f)
        {
            var cursorPos = FootRollCursor.GetLocalPosition(stream);
            FootRollCursor.SetLocalPosition(stream, new Vector3(cursorPos.x, cursorPos.y, 0));

            var pos = FootControllerBase.GetPosition(stream);
            var rot = FootControllerBase.GetRotation(stream);

            if (cursorPos.x < 0f)
            {
                var footRightSidePos = FootRightSide.GetPosition(stream);
                var axisZ            = rot * Vector3.forward;
                var rotZ             = Quaternion.AngleAxis(180 * cursorPos.x, axisZ);
                pos = footRightSidePos + rotZ * (pos - footRightSidePos);
                rot = rotZ * rot;

                if (cursorPos.y >= 0f)
                {
                    var toePos = footRightSidePos + rotZ * (ToeEnd.GetPosition(stream) - footRightSidePos);
                    var axisX  = rot * Vector3.right;
                    var rotX   = Quaternion.AngleAxis(180 * cursorPos.y, axisX);
                    pos = toePos + rotX * (pos - toePos);
                    rot = rotX * rot;
                }
                else
                {
                    var heelPos = footRightSidePos + rotZ * (FootHeel.GetPosition(stream) - footRightSidePos);
                    var axisX   = rot * Vector3.right;
                    var rotX    = Quaternion.AngleAxis(180 * cursorPos.y, axisX);
                    pos = heelPos + rotX * (pos - heelPos);
                    rot = rotX * rot;
                }
            }
            else
            {
                var footLeftSidePos = FootLeftSide.GetPosition(stream);
                var axisZ           = rot * Vector3.forward;
                var rotZ            = Quaternion.AngleAxis(180 * cursorPos.x, axisZ);
                pos = footLeftSidePos + rotZ * (pos - footLeftSidePos);
                rot = rotZ * rot;

                if (cursorPos.y >= 0f)
                {
                    var toePos = footLeftSidePos + rotZ * (ToeEnd.GetPosition(stream) - footLeftSidePos);
                    var axisX  = rot * Vector3.right;
                    var rotX   = Quaternion.AngleAxis(180 * cursorPos.y, axisX);
                    pos = toePos + rotX * (pos - toePos);
                    rot = rotX * rot;
                }
                else
                {
                    var heelPos = footLeftSidePos + rotZ * (FootHeel.GetPosition(stream) - footLeftSidePos);
                    var axisX   = rot * Vector3.right;
                    var rotX    = Quaternion.AngleAxis(180 * cursorPos.y, axisX);
                    pos = heelPos + rotX * (pos - heelPos);
                    rot = rotX * rot;
                }
            }

            var footIKTargetPos = FootIKTarget.GetPosition(stream);
            var footIKTargetRot = FootIKTarget.GetRotation(stream);
            FootIKTarget.SetPosition(stream, Vector3.Lerp(footIKTargetPos, pos, w));
            FootIKTarget.SetRotation(stream, Quaternion.Lerp(footIKTargetRot, rot, w));
        }
    }