示例#1
0
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                data.ProfilerMarker.Begin();
                var output = ctx.Resolve(ref ports.Output);

                output.CopyFrom(ctx.Resolve(in ports.Input));

                var weightValue = ctx.Resolve(ports.Weight);

                if (weightValue > 0f)
                {
                    var stream = AnimationStreamProvider.Create(data.RigDefinition, output);
                    if (stream.IsNull)
                    {
                        data.ProfilerMarker.End();
                        return;
                    }

                    var pos = stream.GetLocalToRigTranslation(data.Data.BoneIndex);
                    pos += data.Data.offset * weightValue;
                    stream.SetLocalToRigTranslation(data.Data.BoneIndex, pos);
                }

                data.ProfilerMarker.End();
            }
示例#2
0
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                data.ProfilerMarker.Begin();
                CopyInputToOutputBuffer(ctx, ports.Input, ports.Output);

                var weightValue = ctx.Resolve(ports.Weight);

                if (weightValue > 0f)
                {
                    var ouptutArray   = ctx.Resolve(ref ports.Output);
                    var blendPosition = ctx.Resolve(ports.BlendPosition);
                    var blendRotation = ctx.Resolve(ports.BlendRotation);

                    var stream = AnimationStreamProvider.Create(data.RigDefinition, ouptutArray);
                    if (stream.IsNull || (blendPosition == 0 && blendRotation == 0))
                    {
                        data.ProfilerMarker.End();
                        return;
                    }

                    stream.GetLocalToRigTR(data.Data.Constrained, out float3 constrainedT, out quaternion constrainedR);

                    if (blendPosition == 1)
                    {
                        var positionWeight = ctx.Resolve(ports.PositionWeight);

                        float3 posBlend = math.lerp(
                            stream.GetLocalToRigTranslation(data.Data.SourceA) + data.Data.SourceAOffset.pos,
                            stream.GetLocalToRigTranslation(data.Data.SourceB) + data.Data.SourceBOffset.pos,
                            positionWeight
                            );

                        stream.SetLocalToRigTranslation(
                            data.Data.Constrained,
                            math.lerp(constrainedT, posBlend, weightValue)
                            );
                    }

                    if (blendRotation == 1)
                    {
                        var rotationWeight = ctx.Resolve(ports.RotationWeight);

                        quaternion rotBlend = math.nlerp(
                            math.mul(stream.GetLocalToRigRotation(data.Data.SourceA), data.Data.SourceAOffset.rot),
                            math.mul(stream.GetLocalToRigRotation(data.Data.SourceB), data.Data.SourceBOffset.rot),
                            rotationWeight
                            );

                        stream.SetLocalToRigRotation(
                            data.Data.Constrained,
                            math.nlerp(constrainedR, rotBlend, weightValue)
                            );
                    }
                }

                data.ProfilerMarker.End();
            }
示例#3
0
        public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
        {
            data.ProfileMarker.Begin();

            var output = context.Resolve(ref ports.Output);

            output.CopyFrom(context.Resolve(in ports.Input));

            var stream = AnimationStreamProvider.Create(data.RigDefinition, output);

            if (stream.IsNull)
            {
                data.ProfileMarker.End();
                return;
            }

            var driverIndex = data.Settings.boneReferences.DriverIndex;
            var twistIndexA = data.Settings.boneReferences.TwistJointA;
            var twistIndexB = data.Settings.boneReferences.TwistJointB;
            var twistIndexC = data.Settings.boneReferences.TwistJointC;

            if (driverIndex != -1)
            {
                var driverRot     = stream.GetLocalToParentRotation(driverIndex);
                var driverBindRot = data.RigDefinition.Value.DefaultValues.LocalRotations[driverIndex];

                var driverDelta = math.mul(math.inverse(driverBindRot), driverRot);
                var twist       = new quaternion(0.0f, driverDelta.value.y * data.Settings.twistMult, 0.0f, driverDelta.value.w);

                if (twistIndexA != -1)
                {
                    var twistRotation = mathex.lerp(quaternion.identity, twist, data.Settings.factors.FactorA);
                    stream.SetLocalToParentRotation(data.Settings.boneReferences.TwistJointA, twistRotation);
                }

                if (twistIndexB != -1)
                {
                    var twistRotation = mathex.lerp(quaternion.identity, twist, data.Settings.factors.FactorB);
                    stream.SetLocalToParentRotation(data.Settings.boneReferences.TwistJointB, twistRotation);
                }

                if (twistIndexC != -1)
                {
                    var twistRotation = mathex.lerp(quaternion.identity, twist, data.Settings.factors.FactorC);
                    stream.SetLocalToParentRotation(data.Settings.boneReferences.TwistJointC, twistRotation);
                }
            }

            data.ProfileMarker.End();
        }
示例#4
0
        public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
        {
            data.ProfileMarker.Begin();

            var output = context.Resolve(ref ports.Output);

            output.CopyFrom(context.Resolve(in ports.Input));

            var bankAmount = context.Resolve(ports.BankAmount);

            if (math.abs(bankAmount) < 0.001f)
            {
                data.ProfileMarker.End();
                return;
            }

            var stream = AnimationStreamProvider.Create(data.RigDefinition, output);

            if (stream.IsNull)
            {
                data.ProfileMarker.End();
                return;
            }

            var bankPosition         = data.BankingData.Position * bankAmount * 0.01f;
            var weightedBankRotation = quaternion.Euler(math.radians(data.BankingData.EulerRotation * bankAmount * (1 - data.BankingData.SpineMultiplier)));
            var bankRotation         = quaternion.Euler(math.radians(data.BankingData.EulerRotation * bankAmount));
            var footPosition         = data.BankingData.Position * bankAmount * 0.01f * data.BankingData.FootMultiplier;

            //TODO: A multiplier here??
            // Rig axis are reverted for left and right feet.
            var leftFootRotation  = quaternion.Euler(math.radians(-1.0f * data.BankingData.EulerRotation * bankAmount * data.BankingData.FootMultiplier));
            var rightFootRotation = quaternion.Euler(math.radians(data.BankingData.EulerRotation * bankAmount * data.BankingData.FootMultiplier));

            // No centre of mass so for now we use the hips
            var hipPos = stream.GetLocalToRigTranslation(data.BankingData.boneReferences.HipsIndex);
            var hipRot = stream.GetLocalToRigRotation(data.BankingData.boneReferences.HipsIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.HipsIndex, math.mul(weightedBankRotation, hipRot));
            stream.SetLocalToRigTranslation(data.BankingData.boneReferences.HipsIndex, math.mul(bankRotation, hipPos) + bankPosition);

            // Head banking
            var multiplier = bankAmount * 0.075f * data.BankingData.HeadMultiplier / k_numHeadHandles;

            // Head and neck have the same range of movement [-40, 40] degrees.
            var axis        = quaternion.AxisAngle(new float3(0f, -1f, -1f), math.radians(40f));
            var weightedRot = mathex.quatWeight(axis, multiplier);
            var neck        = stream.GetLocalToRigRotation(data.BankingData.boneReferences.NeckLeftRightIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.NeckLeftRightIndex, math.mul(weightedRot, neck));
            var head = stream.GetLocalToRigRotation(data.BankingData.boneReferences.HeadLeftRightIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.HeadLeftRightIndex, math.mul(weightedRot, head));

            // Spine banking
            multiplier = bankAmount * 0.075f * data.BankingData.SpineMultiplier / k_numSpineHandles;

            // Spine and chest have the same range of movement [-40, 40] degrees.
            axis        = quaternion.AxisAngle(new float3(0f, 0f, -1f), math.radians(40f));
            weightedRot = mathex.quatWeight(axis, multiplier);
            var spine = stream.GetLocalToRigRotation(data.BankingData.boneReferences.SpineLeftRightIndex);
            var chest = stream.GetLocalToRigRotation(data.BankingData.boneReferences.ChestLeftRightIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.SpineLeftRightIndex, math.mul(weightedRot, spine));
            stream.SetLocalToRigRotation(data.BankingData.boneReferences.ChestLeftRightIndex, math.mul(weightedRot, chest));
            // Upper chest has a range of movement of [-20, 20] degrees.
            axis        = quaternion.AxisAngle(new float3(0f, 0f, -1f), math.radians(20f));
            weightedRot = mathex.quatWeight(axis, multiplier);
            var upperChest = stream.GetLocalToRigRotation(data.BankingData.boneReferences.UpperChestLeftRightIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.UpperChestLeftRightIndex, math.mul(weightedRot, upperChest));

            // Feet IK
            var leftFootPos = stream.GetLocalToRigTranslation(data.BankingData.boneReferences.LeftFootIKIndex);

            stream.SetLocalToRigTranslation(data.BankingData.boneReferences.LeftFootIKIndex, leftFootPos + footPosition);
            var leftFootRot = stream.GetLocalToRigRotation(data.BankingData.boneReferences.LeftFootIKIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.LeftFootIKIndex, math.mul(leftFootRot, leftFootRotation));

            var rightFootPos = stream.GetLocalToRigTranslation(data.BankingData.boneReferences.RightFootIKIndex);

            stream.SetLocalToRigTranslation(data.BankingData.boneReferences.RightFootIKIndex, rightFootPos + footPosition);
            var rightFootRot = stream.GetLocalToRigRotation(data.BankingData.boneReferences.RightFootIKIndex);

            stream.SetLocalToRigRotation(data.BankingData.boneReferences.RightFootIKIndex, math.mul(rightFootRot, rightFootRotation));

            data.ProfileMarker.End();
        }
示例#5
0
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                data.ProfilerMarker.Begin();
                var output = ctx.Resolve(ref ports.Output);

                output.CopyFrom(ctx.Resolve(in ports.Input));

                var weightValue = ctx.Resolve(ports.Weight);

                if (weightValue > 0f)
                {
                    var stream = AnimationStreamProvider.Create(data.RigDefinition, output);
                    if (stream.IsNull)
                    {
                        data.ProfilerMarker.End();
                        return;
                    }

                    // TODO: (sunek) Get a real number! Requires replicating and incrementing the IK weight in update
                    // ikWeight = Mathf.Clamp01(ikWeight + (1 - settings.enterStateEaseIn));

                    var ikWeight = data.Data.Weight;
                    var settings = data.Data.Settings;

                    var leftToePos  = stream.GetLocalToRigTranslation(data.Data.LeftToeIdx);
                    var rightToePos = stream.GetLocalToRigTranslation(data.Data.RightToeIdx);

                    var leftIkOffset  = data.Data.ikOffset.x * ikWeight;
                    var rightIkOffset = data.Data.ikOffset.y * ikWeight;

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

                    var leftAnklePos  = stream.GetLocalToRigTranslation(data.Data.LeftFootIkIdx);
                    var rightAnklePos = stream.GetLocalToRigTranslation(data.Data.RightFootIkIdx);
                    var leftAnkleRot  = stream.GetLocalToRigRotation(data.Data.LeftFootIkIdx);
                    var rightAnkleRot = stream.GetLocalToRigRotation(data.Data.RightFootIkIdx);

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

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

                    // TODO: (sunek) Rework weight shift to move towards actual lower foot?
                    hipHeightOffset += Mathf.Abs(leftIkOffset - rightIkOffset) * settings.weightShiftVertical;
                    var standAngle = math.mul(quaternion.AxisAngle(Vector3.up, math.radians(settings.weightShiftAngle)), data.VectorForward);

                    var hipsPosition = stream.GetLocalToRigTranslation(data.Data.HipsIdx);
                    hipsPosition += new float3(standAngle.x * forwardBackBias, hipHeightOffset, standAngle.z * forwardBackBias);
                    stream.SetLocalToRigTranslation(data.Data.HipsIdx, hipsPosition);

                    // Figure out the normal rotation
                    var leftNormalRot  = quaternion.identity;
                    var rightNormalRot = quaternion.identity;

                    if (!data.Data.normalLeftFoot.Equals(float3.zero))
                    {
                        leftNormalRot  = quaternion.LookRotationSafe(data.Data.normalLeftFoot, data.VectorForward);
                        rightNormalRot = quaternion.LookRotationSafe(data.Data.normalRightFoot, data.VectorForward);
                        leftNormalRot  = math.mul(leftNormalRot, data.OffsetRotation);
                        rightNormalRot = math.mul(rightNormalRot, data.OffsetRotation);
                    }

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

                    if (leftAngle > settings.maxFootRotationOffset && settings.maxFootRotationOffset > 0f)
                    {
                        var fraction = settings.maxFootRotationOffset / leftAngle;
                        leftNormalRot = math.nlerp(Quaternion.identity, leftNormalRot, fraction);
                    }

                    if (rightAngle > settings.maxFootRotationOffset && settings.maxFootRotationOffset > 0f)
                    {
                        var fraction = settings.maxFootRotationOffset / rightAngle;
                        rightNormalRot = math.nlerp(Quaternion.identity, rightNormalRot, fraction);
                    }

                    // Apply rotation to ankle
                    var leftToesMatrix  = Matrix4x4.TRS(leftToePos, quaternion.identity, data.VectorOne);
                    var rightToesMatrix = Matrix4x4.TRS(rightToePos, quaternion.identity, data.VectorOne);

                    leftNormalRot  = math.normalize(leftNormalRot);
                    rightNormalRot = math.normalize(rightNormalRot);

                    leftAnkleRot  = math.normalize(leftAnkleRot);
                    rightAnkleRot = math.normalize(rightAnkleRot);

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

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

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

                    // Todo:Find a better way to do this?
                    var leftColumn = leftAnkleMatrix.GetColumn(3);
                    leftAnkleIkPos = new float3(leftColumn[0], leftColumn[1], leftColumn[2]); // TODO: (sunek) Is there a slicing syntax instead?
                    var rightColumn = rightAnkleMatrix.GetColumn(3);
                    rightAnkleIkPos = new float3(rightColumn[0], rightColumn[1], rightColumn[2]);

                    leftAnkleRot  = math.nlerp(leftAnkleRot, leftAnkleMatrix.rotation, ikWeight);
                    rightAnkleRot = math.nlerp(rightAnkleRot, rightAnkleMatrix.rotation, ikWeight);

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

                    stream.SetLocalToRigTranslation(data.Data.LeftFootIkIdx, leftPosition);
                    stream.SetLocalToRigTranslation(data.Data.RightFootIkIdx, rightPosition);

                    stream.SetLocalToRigRotation(data.Data.LeftFootIkIdx, leftAnkleRot);
                    stream.SetLocalToRigRotation(data.Data.RightFootIkIdx, rightAnkleRot);
                }

                data.ProfilerMarker.End();
            }
示例#6
0
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                data.ProfilerMarker.Begin();
                var output = ctx.Resolve(ref ports.Output);

                output.CopyFrom(ctx.Resolve(in ports.Input));

                var weightValue = ctx.Resolve(ports.Weight);

                if (weightValue > 0f)
                {
                    var stream = AnimationStreamProvider.Create(data.RigDefinition, output);
                    if (stream.IsNull)
                    {
                        data.ProfilerMarker.End();
                        return;
                    }

                    // Use the curve value if defined
                    if (data.IKData.WeightChannelIdx != -1)
                    {
                        weightValue *= stream.GetFloat(data.IKData.WeightChannelIdx);
                    }

                    weightValue = math.clamp(weightValue, 0f, 1f);

                    var targetPositionWeightValue = ctx.Resolve(ports.TargetPositionWeight);
                    var targetRotationWeightValue = ctx.Resolve(ports.TargetRotationWeight);
                    var hintWeightValue           = ctx.Resolve(ports.HintWeight);

                    float3 aPos = stream.GetLocalToRigTranslation(data.IKData.Root);
                    float3 bPos = stream.GetLocalToRigTranslation(data.IKData.Mid);
                    float3 cPos = stream.GetLocalToRigTranslation(data.IKData.Tip);

                    stream.GetLocalToRigTR(data.IKData.Target, out float3 targetPos, out quaternion targetRot);
                    float3     tPos       = math.lerp(cPos, targetPos + data.IKData.TargetOffset.pos, targetPositionWeightValue * weightValue);
                    quaternion tRot       = math.nlerp(stream.GetLocalToRigRotation(data.IKData.Tip), math.mul(targetRot, data.IKData.TargetOffset.rot), targetRotationWeightValue * weightValue);
                    float      hintWeight = hintWeightValue * weightValue;
                    bool       hasHint    = data.IKData.Hint > -1 && hintWeight > 0f;

                    float3 ab = bPos - aPos;
                    float3 bc = cPos - bPos;
                    float3 ac = cPos - aPos;
                    float3 at = tPos - aPos;

                    float oldAbcAngle = TriangleAngle(math.length(ac), data.IKData.LimbLengths);
                    float newAbcAngle = TriangleAngle(math.length(at), data.IKData.LimbLengths);

                    // Bend normal strategy is to take whatever has been provided in the animation
                    // stream to minimize configuration changes, however if this is collinear
                    // try computing a bend normal given the desired target position.
                    // If this also fails, try resolving axis using hint if provided.
                    float3 axis = math.cross(ab, bc);
                    if (math.lengthsq(axis) < k_SqEpsilon)
                    {
                        axis = math.cross(at, bc);
                        if (math.lengthsq(axis) < k_SqEpsilon)
                        {
                            axis = hasHint ? math.cross(stream.GetLocalToRigTranslation(data.IKData.Hint) - aPos, bc) : math.up();
                        }
                    }
                    axis = math.normalize(axis);

                    float      a        = 0.5f * (oldAbcAngle - newAbcAngle);
                    float      sin      = math.sin(a);
                    float      cos      = math.cos(a);
                    quaternion deltaRot = new quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos);
                    stream.SetLocalToRigRotation(data.IKData.Mid, math.mul(deltaRot, stream.GetLocalToRigRotation(data.IKData.Mid)));

                    cPos = stream.GetLocalToRigTranslation(data.IKData.Tip);
                    ac   = cPos - aPos;
                    stream.SetLocalToRigRotation(data.IKData.Root, math.mul(mathex.fromTo(ac, at), stream.GetLocalToRigRotation(data.IKData.Root)));

                    if (hasHint)
                    {
                        float acLengthSq = math.lengthsq(ac);
                        if (acLengthSq > 0f)
                        {
                            bPos = stream.GetLocalToRigTranslation(data.IKData.Mid);
                            cPos = stream.GetLocalToRigTranslation(data.IKData.Tip);
                            ab   = bPos - aPos;
                            ac   = cPos - aPos;

                            float3 acNorm = ac / math.sqrt(acLengthSq);
                            float3 ah     = stream.GetLocalToRigTranslation(data.IKData.Hint) - aPos;
                            float3 abProj = ab - acNorm * math.dot(ab, acNorm);
                            float3 ahProj = ah - acNorm * math.dot(ah, acNorm);

                            float maxReach = data.IKData.LimbLengths.x + data.IKData.LimbLengths.y;
                            if (math.lengthsq(abProj) > (maxReach * maxReach * 0.001f) && math.lengthsq(ahProj) > 0f)
                            {
                                quaternion hintRot = mathex.fromTo(abProj, ahProj);
                                hintRot.value.xyz *= hintWeight;
                                stream.SetLocalToRigRotation(data.IKData.Root, math.mul(hintRot, stream.GetLocalToRigRotation(data.IKData.Root)));
                            }
                        }
                    }

                    stream.SetLocalToRigRotation(data.IKData.Tip, tRot);
                }

                data.ProfilerMarker.End();
            }