public void test_defer_stream()
    {
        var stream = new AnimationStream(AnimationStreamType.DEFER, 1);
        var curve = fixture_curve();
        Assert(stream.Add(curve.Item1));
        Assert(stream.Add(fixture()));

        /// Expire first item
        curve.Item2.Complete = true;
        stream.Update<Streams>(1.0f, null);

        this.TearDown();
    }
    public void test_reject_stream()
    {
        var stream = new AnimationStream(AnimationStreamType.REJECT, 1);
        var curve = fixture_curve();
        Assert(stream.Add(curve.Item1));

        // can't add while full
        Assert(!stream.Add(fixture()));

        // after complete, can add
        curve.Item2.Complete = true;
        stream.Update<Streams>(1.0f, null);
        Assert(stream.Add(fixture()));

        this.TearDown();
    }
        public void ProcessAnimation(AnimationStream stream)
        {
            float w = jobWeight.Get(stream);

            if (w > 0f)
            {
                AnimationStreamHandleUtility.ReadFloats(stream, sourceWeights, weightBuffer);

                float sumWeights = AnimationRuntimeUtils.Sum(weightBuffer);
                if (sumWeights < k_Epsilon)
                {
                    return;
                }

                float weightScale = sumWeights > 1f ? 1f / sumWeights : 1f;

                float accumWeights = 0f;
                var   accumTx      = new AffineTransform(Vector3.zero, QuaternionExt.zero);
                for (int i = 0; i < sourceTransforms.Length; ++i)
                {
                    ReadOnlyTransformHandle sourceTransform = sourceTransforms[i];
                    var normalizedWeight = weightBuffer[i] * weightScale;
                    if (normalizedWeight < k_Epsilon)
                    {
                        continue;
                    }

                    sourceTransform.GetGlobalTR(stream, out Vector3 srcWPos, out Quaternion srcWRot);
                    var sourceTx = new AffineTransform(srcWPos, srcWRot);
                    sourceTx *= sourceOffsets[i];

                    accumTx.translation += sourceTx.translation * normalizedWeight;
                    accumTx.rotation     = QuaternionExt.Add(accumTx.rotation, QuaternionExt.Scale(sourceTx.rotation, normalizedWeight));

                    // Required to update handles with binding info.
                    sourceTransforms[i] = sourceTransform;
                    accumWeights       += normalizedWeight;
                }

                accumTx.rotation = QuaternionExt.NormalizeSafe(accumTx.rotation);
                if (accumWeights < 1f)
                {
                    driven.GetGlobalTR(stream, out Vector3 currentWPos, out Quaternion currentWRot);
                    accumTx.translation += currentWPos * (1f - accumWeights);
                    accumTx.rotation     = Quaternion.Lerp(currentWRot, accumTx.rotation, accumWeights);
                }

                // Convert accumTx to local space
                if (drivenParent.IsValid(stream))
                {
                    drivenParent.GetGlobalTR(stream, out Vector3 parentWPos, out Quaternion parentWRot);
                    var parentTx = new AffineTransform(parentWPos, parentWRot);
                    accumTx = parentTx.InverseMul(accumTx);
                }

                driven.GetLocalTRS(stream, out Vector3 currentLPos, out Quaternion currentLRot, out Vector3 currentLScale);
                if (Vector3.Dot(positionAxesMask, positionAxesMask) < 3f)
                {
                    accumTx.translation = AnimationRuntimeUtils.Lerp(currentLPos, accumTx.translation, positionAxesMask);
                }
                if (Vector3.Dot(rotationAxesMask, rotationAxesMask) < 3f)
                {
                    accumTx.rotation = Quaternion.Euler(AnimationRuntimeUtils.Lerp(currentLRot.eulerAngles, accumTx.rotation.eulerAngles, rotationAxesMask));
                }

                driven.SetLocalTRS(
                    stream,
                    Vector3.Lerp(currentLPos, accumTx.translation, w),
                    Quaternion.Lerp(currentLRot, accumTx.rotation, w),
                    currentLScale
                    );
            }
            else
            {
                AnimationRuntimeUtils.PassThrough(stream, driven);
            }
        }
Example #4
0
 //Gets the offset from last position of the last bone to its current position.
 private float GetPositionOffset(AnimationStream s, Vector3 localDirection)
 {
     return(Vector3.SqrMagnitude(localDirection - lastLocalDirection));
 }
Example #5
0
 public float GetAngle(AnimationStream s, Vector3 axis, Vector3 IKPosition)
 {
     return(Vector3.Angle(_transform.GetRotation(s) * axis, IKPosition - _transform.GetPosition(s)));
 }
Example #6
0
        private void Update(AnimationStream s)
        {
            if (!_target.IsValid(s))
            {
                return;
            }
            if (!_poleTarget.IsValid(s))
            {
                return;
            }
            if (!_transform.IsValid(s))
            {
                return;
            }

            Vector3 axis     = new Vector3(_axisX.GetFloat(s), _axisY.GetFloat(s), _axisZ.GetFloat(s));
            Vector3 poleAxis = new Vector3(_poleAxisX.GetFloat(s), _poleAxisY.GetFloat(s), _poleAxisZ.GetFloat(s));

            float poleWeight = _poleWeight.GetFloat(s);

            poleWeight = Mathf.Clamp(poleWeight, 0f, 1f);

            if (axis == Vector3.zero)
            {
                return;
            }
            if (poleAxis == Vector3.zero && poleWeight > 0f)
            {
                return;
            }

            float IKPositionWeight = _IKPositionWeight.GetFloat(s);

            if (IKPositionWeight <= 0)
            {
                return;
            }
            IKPositionWeight = Mathf.Min(IKPositionWeight, 1f);

            bool  XY                = _XY.GetBool(s);
            float maxIterations     = _maxIterations.GetInt(s);
            float tolerance         = _tolerance.GetFloat(s);
            bool  useRotationLimits = _useRotationLimits.GetBool(s);

            Vector3 IKPosition = _target.GetPosition(s);

            if (XY)
            {
                IKPosition.z = bones[0].GetPosition(s).z;
            }

            Vector3 polePosition = _poleTarget.GetPosition(s);

            if (XY)
            {
                polePosition.z = IKPosition.z;
            }

            float clampWeight = _clampWeight.GetFloat(s);

            clampWeight = Mathf.Clamp(clampWeight, 0f, 1f);
            int clampSmoothing = _clampSmoothing.GetInt(s);

            clampSmoothing = Mathf.Clamp(clampSmoothing, 0, 2);

            Vector3    transformPosition = _transform.GetPosition(s);
            Quaternion transformRotation = _transform.GetRotation(s);
            Vector3    transformAxis     = transformRotation * axis;

            Vector3 clampedIKPosition = GetClampedIKPosition(s, clampWeight, clampSmoothing, IKPosition, transformPosition, transformAxis);

            Vector3 dir = clampedIKPosition - transformPosition;

            dir = Vector3.Slerp(transformAxis * dir.magnitude, dir, IKPositionWeight);
            clampedIKPosition = transformPosition + dir;

            // Iterating the solver
            for (int i = 0; i < maxIterations; i++)
            {
                // Optimizations
                if (i >= 0 && tolerance > 0 && GetAngle(s, axis, IKPosition) < tolerance)
                {
                    break;
                }
                lastLocalDirection = GetLocalDirection(s, _transform.GetRotation(s) * axis);

                for (int n = 0; n < bones.Length - 1; n++)
                {
                    RotateToTarget(s, clampedIKPosition, polePosition, n, step * (n + 1) * IKPositionWeight * boneWeights[n].GetFloat(s), poleWeight, XY, useRotationLimits, axis, poleAxis);
                }

                RotateToTarget(s, clampedIKPosition, polePosition, bones.Length - 1, IKPositionWeight * boneWeights[bones.Length - 1].GetFloat(s), poleWeight, XY, useRotationLimits, axis, poleAxis);
            }

            lastLocalDirection = GetLocalDirection(s, _transform.GetRotation(s) * axis);
        }
Example #7
0
    private void SyncIKFromPose()
    {
        var selectedTransform = Selection.transforms;

        var stream = new AnimationStream();

        if (m_Animator.OpenAnimationStream(ref stream))
        {
            AnimationHumanStream humanStream = stream.AsHuman();

            // don't sync if transform is currently selected
            if (!Array.Exists(selectedTransform, tr => tr == m_LeftFootEffector.transform))
            {
                m_LeftFootEffector.transform.position = humanStream.GetGoalPositionFromPose(AvatarIKGoal.LeftFoot);
                m_LeftFootEffector.transform.rotation = humanStream.GetGoalRotationFromPose(AvatarIKGoal.LeftFoot);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_RightFootEffector.transform))
            {
                m_RightFootEffector.transform.position = humanStream.GetGoalPositionFromPose(AvatarIKGoal.RightFoot);
                m_RightFootEffector.transform.rotation = humanStream.GetGoalRotationFromPose(AvatarIKGoal.RightFoot);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_LeftHandEffector.transform))
            {
                m_LeftHandEffector.transform.position = humanStream.GetGoalPositionFromPose(AvatarIKGoal.LeftHand);
                m_LeftHandEffector.transform.rotation = humanStream.GetGoalRotationFromPose(AvatarIKGoal.LeftHand);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_RightHandEffector.transform))
            {
                m_RightHandEffector.transform.position = humanStream.GetGoalPositionFromPose(AvatarIKGoal.RightHand);
                m_RightHandEffector.transform.rotation = humanStream.GetGoalRotationFromPose(AvatarIKGoal.RightHand);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_LeftKneeHintEffector.transform))
            {
                m_LeftKneeHintEffector.transform.position = humanStream.GetHintPosition(AvatarIKHint.LeftKnee);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_RightKneeHintEffector.transform))
            {
                m_RightKneeHintEffector.transform.position = humanStream.GetHintPosition(AvatarIKHint.RightKnee);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_LeftElbowHintEffector.transform))
            {
                m_LeftElbowHintEffector.transform.position = humanStream.GetHintPosition(AvatarIKHint.LeftElbow);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_RightElbowHintEffector.transform))
            {
                m_RightElbowHintEffector.transform.position = humanStream.GetHintPosition(AvatarIKHint.RightElbow);
            }

            if (!Array.Exists(selectedTransform, tr => tr == m_BodyRotationEffector.transform))
            {
                m_BodyRotationEffector.transform.position = humanStream.bodyPosition;
                m_BodyRotationEffector.transform.rotation = humanStream.bodyRotation;
            }

            m_Animator.CloseAnimationStream(ref stream);
        }
    }
Example #8
0
        public void CanEvaluateCycleRootClipNode(float time)
        {
            var entity = m_Manager.CreateEntity();

            RigEntityBuilder.SetupRigEntity(entity, m_Manager, m_Rig);

            var clipNode = CreateNode <ConfigurableClipNode>();

            Set.SendMessage(clipNode, ConfigurableClipNode.SimulationPorts.Configuration, new ClipConfiguration {
                Mask = ClipConfigurationMask.CycleRootMotion, MotionID = new StringHash("Motion")
            });
            Set.SendMessage(clipNode, ConfigurableClipNode.SimulationPorts.Rig, m_Rig);
            Set.SendMessage(clipNode, ConfigurableClipNode.SimulationPorts.Clip, m_Clip);
            Set.SetData(clipNode, ConfigurableClipNode.KernelPorts.Time, time);

            var entityNode = CreateComponentNode(entity);

            Set.Connect(clipNode, ConfigurableClipNode.KernelPorts.Output, entityNode);

            m_Manager.AddComponent <PreAnimationGraphTag>(entity);

            m_AnimationGraphSystem.Update();

            var normalizedTime    = time;
            var normalizedTimeInt = (int)normalizedTime;
            var cycle             = math.select(normalizedTimeInt, normalizedTimeInt - 1, normalizedTime < 0);

            normalizedTime = math.select(normalizedTime - normalizedTimeInt, normalizedTime - normalizedTimeInt + 1, normalizedTime < 0);

            // start and stop root transform
            var startTProj = new float3(m_StartTranslation.x, 0, m_StartTranslation.z);
            var startRProj = math.normalize(new quaternion(0, m_StartRotation.value.y / m_StartRotation.value.w, 0, 1));

            var stopTProj = new float3(m_StopTranslation.x, 0, m_StopTranslation.z);
            var stopRProj = math.normalize(new quaternion(0, m_StopRotation.value.y / m_StopRotation.value.w, 0, 1));

            // current root transform
            var translation = m_StopTranslation * normalizedTime + m_StartTranslation * (1f - normalizedTime);
            var rotation    = math.normalize(new quaternion(math.normalize(m_StopRotation).value *normalizedTime + math.normalize(m_StartRotation).value *(1f - normalizedTime)));

            var tProj = new float3(translation.x, 0, translation.z);
            var rProj = math.normalize(new quaternion(0, rotation.value.y / rotation.value.w, 0, 1));

            // cycled root transform
            var startX = cycle >= 0 ? new RigidTransform(startRProj, startTProj) : new RigidTransform(stopRProj, stopTProj);
            var stopX  = cycle >= 0 ? new RigidTransform(stopRProj, stopTProj) : new RigidTransform(startRProj, startTProj);

            var            x      = new RigidTransform(rProj, tProj);
            RigidTransform cycleX = mathex.rigidPow(math.mul(stopX, math.inverse(startX)), math.asuint(math.abs(cycle)));

            x = math.mul(cycleX, x);


            var streamECS = AnimationStream.CreateReadOnly(
                m_Rig,
                m_Manager.GetBuffer <AnimatedData>(entity).AsNativeArray()
                );

            // validate
            var rootTranslation = streamECS.GetLocalToParentTranslation(0);

            Assert.That(rootTranslation, Is.EqualTo(x.pos));
            var rootRotation = streamECS.GetLocalToParentRotation(0);

            Assert.That(rootRotation, Is.EqualTo(x.rot).Using(RotationComparer));
        }
Example #9
0
    public void ProcessAnimation(AnimationStream stream)
    {
        if (!m_AimDirectionInitialized)
        {
            m_CurrentYaw              = animState.aimYaw;
            m_CurrentPitch            = animState.aimPitch;
            m_AimDirectionInitialized = true;
        }

        // TODO: (sunek) Get rid of stuttering
        var t = settings.stiffness * stream.deltaTime;

        m_CurrentYaw   = Mathf.LerpAngle(m_CurrentYaw, animState.aimYaw, t);
        m_CurrentPitch = Mathf.LerpAngle(m_CurrentPitch, animState.aimPitch, t);

        var deltaYaw      = Mathf.DeltaAngle(animState.aimYaw, m_CurrentYaw);
        var deltaPitch    = Mathf.DeltaAngle(animState.aimPitch, m_CurrentPitch);
        var deltaRotation = Quaternion.Euler(new Vector3(-deltaPitch, deltaYaw, 0));

        var angle = Quaternion.Angle(Quaternion.identity, deltaRotation);

        if (angle > settings.maxAngle)
        {
            t              = settings.maxAngle / angle;
            m_CurrentYaw   = Mathf.LerpAngle(animState.aimYaw, m_CurrentYaw, t);
            m_CurrentPitch = Mathf.LerpAngle(animState.aimPitch, m_CurrentPitch, t);

            deltaYaw      = Mathf.DeltaAngle(animState.aimYaw, m_CurrentYaw);
            deltaPitch    = Mathf.DeltaAngle(animState.aimPitch, m_CurrentPitch);
            deltaRotation = Quaternion.Euler(new Vector3(-deltaPitch, deltaYaw, 0));
        }

        if (m_DragHistory.Count <= settings.rollDelay)
        {
            m_DragHistory.Enqueue(deltaRotation);
        }

        var drag = Quaternion.SlerpUnclamped(Quaternion.identity, deltaRotation, settings.dragWeight);
        var roll = m_DragHistory.Count < settings.rollDelay + 1 ? m_DragHistory.Peek() : m_DragHistory.Dequeue();

        roll = Quaternion.SlerpUnclamped(Quaternion.identity, new Quaternion(0f, roll.y, 0f, roll.w), settings.rollWeight);

        var handPosition        = m_Effectorhandle.GetPosition(stream);
        var handRotation        = m_Effectorhandle.GetRotation(stream);
        var weaponPivotPosition = m_WeaponPivot.GetPosition(stream);
        var weaponPivotRotation = m_WeaponPivot.GetRotation(stream);

        var dragPivot = weaponPivotRotation * settings.dragPivot;
        var rollPivot = weaponPivotRotation * settings.rollPivot;

        var dragPivotDelta = handPosition - (weaponPivotPosition + dragPivot);
        var rollPivotDelta = handPosition - (weaponPivotPosition + rollPivot);

        var handOffset = drag * dragPivotDelta;

        handOffset = handOffset - dragPivotDelta;

        var rollOffset = roll * rollPivotDelta;

        rollOffset = rollOffset - rollPivotDelta;

        handPosition = handPosition + handOffset + rollOffset;
        handRotation = drag * handRotation * roll;

        m_WeaponHandResult.SetPosition(stream, handPosition);
        m_WeaponHandResult.SetRotation(stream, handRotation);
    }
Example #10
0
    public void ProcessAnimation(AnimationStream stream)
    {
        if (math.abs(bankAmount) < 0.001f)
        {
            return;
        }

        var bankPosition = new Vector3(
            settings.position.x * bankAmount * 0.01f,
            settings.position.y * bankAmount * 0.01f,
            settings.position.z * bankAmount * 0.01f);

        var weightedBankRotation = Quaternion.Euler(new Vector3(
                                                        settings.rotation.x * bankAmount * (1 - settings.spineMultiplier),
                                                        settings.rotation.y * bankAmount * (1 - settings.spineMultiplier),
                                                        settings.rotation.z * bankAmount) * (1 - settings.spineMultiplier));

        var bankRotation = Quaternion.Euler(new Vector3(
                                                settings.rotation.x * bankAmount,
                                                settings.rotation.y * bankAmount,
                                                settings.rotation.z * bankAmount));

        var footPosition = new Vector3(
            settings.position.x * bankAmount * 0.01f * settings.footMultiplier,
            settings.position.y * bankAmount * 0.01f * settings.footMultiplier,
            settings.position.z * bankAmount * 0.01f * settings.footMultiplier);

        //TODO: A multiplier here??
        var footRotation = Quaternion.Euler(new Vector3(
                                                settings.rotation.x * bankAmount * settings.footMultiplier,
                                                settings.rotation.y * bankAmount * settings.footMultiplier,
                                                settings.rotation.z * bankAmount * settings.footMultiplier));

        // Humanoid
        if (stream.isHumanStream)
        {
            var humanStream = stream.AsHuman();

            var position = humanStream.bodyLocalPosition;
            humanStream.bodyLocalRotation = weightedBankRotation * humanStream.bodyLocalRotation;
            humanStream.bodyLocalPosition = bankRotation * position + bankPosition;

            var numHandles = m_HeadLeftRightMuscles.Length;
            var multiplier = bankAmount * 0.075f * settings.headMultiplier / numHandles;
            for (var i = 0; i < numHandles; i++)
            {
                var headLeftRight = humanStream.GetMuscle(m_HeadLeftRightMuscles[i]);
                humanStream.SetMuscle(m_HeadLeftRightMuscles[i], headLeftRight + multiplier);
            }

            numHandles = m_SpineLeftRightMuscles.Length;
            multiplier = bankAmount * 0.075f * settings.spineMultiplier / numHandles;
            for (var i = 0; i < numHandles; i++)
            {
                var spineLeftRight = humanStream.GetMuscle(m_SpineLeftRightMuscles[i]);
                humanStream.SetMuscle(m_SpineLeftRightMuscles[i], spineLeftRight + multiplier);
            }

            humanStream.SetGoalLocalPosition(AvatarIKGoal.LeftFoot, humanStream.GetGoalLocalPosition(AvatarIKGoal.LeftFoot) + footPosition);
            humanStream.SetGoalRotation(AvatarIKGoal.LeftFoot, humanStream.GetGoalRotation(AvatarIKGoal.LeftFoot) * footRotation);
            humanStream.SetGoalLocalPosition(AvatarIKGoal.RightFoot, humanStream.GetGoalLocalPosition(AvatarIKGoal.RightFoot) + footPosition);
            humanStream.SetGoalRotation(AvatarIKGoal.RightFoot, humanStream.GetGoalRotation(AvatarIKGoal.RightFoot) * footRotation);
        }

        // Generic
        else         // TODO: Flesh this path out or consider loosing it
        {
            m_SkeletonHandle.SetLocalPosition(stream, m_SkeletonHandle.GetLocalPosition(stream) + bankPosition);
            m_SkeletonHandle.SetLocalRotation(stream, m_SkeletonHandle.GetLocalRotation(stream) * bankRotation);
        }
    }
    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));
        }
    }
Example #12
0
 public static void PassThrough(AnimationStream stream, TransformHandle handle)
 {
     handle.SetLocalPosition(stream, handle.GetLocalPosition(stream));
     handle.SetLocalRotation(stream, handle.GetLocalRotation(stream));
     handle.SetLocalScale(stream, handle.GetLocalScale(stream));
 }
Example #13
0
 public void ProcessAnimation(AnimationStream stream)
 {
     Solve(stream, joint, target, axis, minAngle, maxAngle);
 }
        public void AimConstraintFollowsSources()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var aimConstraintData = Core.AimConstraintData.Default();

            aimConstraintData.Index           = 1;
            aimConstraintData.LocalAimAxis    = new float3(1f, 0f, 0f);
            aimConstraintData.SourcePositions = new NativeArray <float3>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            aimConstraintData.SourceOffsets   = new NativeArray <quaternion>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            aimConstraintData.SourceWeights   = new NativeArray <float>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);

            RigidTransform defaultTx;

            stream.GetLocalToRootTR(aimConstraintData.Index, out defaultTx.pos, out defaultTx.rot);

            aimConstraintData.SourcePositions[0] = defaultTx.pos + new float3(1f, 3f, 0f);
            aimConstraintData.SourcePositions[1] = defaultTx.pos + new float3(1f, -3f, 0f);
            aimConstraintData.SourceOffsets[0]   = quaternion.identity;
            aimConstraintData.SourceOffsets[1]   = quaternion.identity;

            // w0 = 0, w1 = 0
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(aimConstraintData.Index), Is.EqualTo(defaultTx.pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(aimConstraintData.Index), Is.EqualTo(defaultTx.rot).Using(RotationComparer));

            // w0 = 1, w1 = 0
            aimConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);

            RigidTransform constrainedTx;

            stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
            float3 currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
            float3 src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);
            float3 src1Dir = math.normalize(aimConstraintData.SourcePositions[1] - constrainedTx.pos);

            Assert.AreEqual(0f, mathex.angle(currAim, src0Dir), k_Epsilon);
            Assert.AreNotEqual(0f, mathex.angle(currAim, src1Dir));

            // w0 = 0, w1 = 1
            aimConstraintData.SourceWeights[0] = 0f;
            aimConstraintData.SourceWeights[1] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);

            stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
            currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
            src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);
            src1Dir = math.normalize(aimConstraintData.SourcePositions[1] - constrainedTx.pos);
            Assert.AreNotEqual(0f, mathex.angle(currAim, src0Dir));
            Assert.AreEqual(0f, mathex.angle(currAim, src1Dir), k_Epsilon);

            // w0 = 1, w1 = 1
            // Since both sources are opposite, they should cancel each other out
            aimConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);

            stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
            currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
            src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);
            src1Dir = math.normalize(aimConstraintData.SourcePositions[1] - constrainedTx.pos);
            Assert.AreNotEqual(0f, mathex.angle(currAim, src0Dir));
            Assert.AreNotEqual(0f, mathex.angle(currAim, src1Dir));
            Assert.AreEqual(0f, mathex.angle(currAim, math.mul(defaultTx.rot, aimConstraintData.LocalAimAxis)), k_Epsilon);

            buffer.Dispose();
            aimConstraintData.SourcePositions.Dispose();
            aimConstraintData.SourceOffsets.Dispose();
            aimConstraintData.SourceWeights.Dispose();
        }
        public void ParentConstraintFollowsSources()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var parentConstraintData = Core.ParentConstraintData.Default();

            parentConstraintData.Index         = 1;
            parentConstraintData.SourceTx      = new NativeArray <RigidTransform>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            parentConstraintData.SourceOffsets = new NativeArray <RigidTransform>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            parentConstraintData.SourceWeights = new NativeArray <float>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);

            for (int i = 0; i < 2; ++i)
            {
                parentConstraintData.SourceTx[i]      = RigidTransform.identity;
                parentConstraintData.SourceOffsets[i] = RigidTransform.identity;
            }

            RigidTransform defaultTx;

            stream.GetLocalToRootTR(parentConstraintData.Index, out defaultTx.pos, out defaultTx.rot);

            // w0 = 0, w1 = 0
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(defaultTx.pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(defaultTx.rot).Using(RotationComparer));

            // Displace sources
            parentConstraintData.SourceTx[0] = new RigidTransform(mathex.mul(defaultTx.rot, quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(-90))), defaultTx.pos + new float3(0f, 1f, 0f));
            parentConstraintData.SourceTx[1] = new RigidTransform(mathex.mul(defaultTx.rot, quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(60))), defaultTx.pos + new float3(0f, 0f, 1f));

            // w0 = 1, w1 = 0
            parentConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[0].pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[0].rot).Using(RotationComparer));

            // w0 = 0, w1 = 1
            parentConstraintData.SourceWeights[0] = 0f;
            parentConstraintData.SourceWeights[1] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[1].pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[1].rot).Using(RotationComparer));

            // w0 = 1, w1 = 1
            parentConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);

            var posRes = (parentConstraintData.SourceTx[0].pos + parentConstraintData.SourceTx[1].pos) * 0.5f;
            var rotRes = math.normalizesafe(mathex.add(parentConstraintData.SourceTx[0].rot.value * 0.5f, parentConstraintData.SourceTx[1].rot.value * 0.5f));

            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(posRes).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(rotRes).Using(RotationComparer));

            buffer.Dispose();
            parentConstraintData.SourceTx.Dispose();
            parentConstraintData.SourceOffsets.Dispose();
            parentConstraintData.SourceWeights.Dispose();
        }
Example #16
0
 public void Set(AnimationStream stream, float v) => value.SetFloat(stream, v);
        public void ProcessAnimation(AnimationStream stream)
        {
            float w = jobWeight.Get(stream);

            if (w > 0f)
            {
                AnimationStreamHandleUtility.ReadFloats(stream, sourceWeights, weightBuffer);

                float sumWeights = AnimationRuntimeUtils.Sum(weightBuffer);
                if (sumWeights < k_Epsilon)
                {
                    AnimationRuntimeUtils.PassThrough(stream, driven);
                    return;
                }

                float weightScale = sumWeights > 1f ? 1f / sumWeights : 1f;

                Vector2 minMaxAngles = new Vector2(minLimit.Get(stream), maxLimit.Get(stream));

                var        drivenWPos         = driven.GetPosition(stream);
                var        drivenLRot         = driven.GetLocalRotation(stream);
                var        drivenParentInvRot = Quaternion.Inverse(drivenParent.GetRotation(stream));
                Quaternion accumDeltaRot      = QuaternionExt.zero;
                var        fromDir            = drivenLRot * aimAxis;
                float      accumWeights       = 0f;
                for (int i = 0; i < sourceTransforms.Length; ++i)
                {
                    var normalizedWeight = weightBuffer[i] * weightScale;
                    if (normalizedWeight < k_Epsilon)
                    {
                        continue;
                    }

                    ReadOnlyTransformHandle sourceTransform = sourceTransforms[i];

                    var toDir = drivenParentInvRot * (sourceTransform.GetPosition(stream) - drivenWPos);
                    if (toDir.sqrMagnitude < k_Epsilon)
                    {
                        continue;
                    }

                    var crossDir = Vector3.Cross(fromDir, toDir).normalized;
                    if (Vector3.Dot(axesMask, axesMask) < 3f)
                    {
                        crossDir = AnimationRuntimeUtils.Select(Vector3.zero, crossDir, axesMask).normalized;
                        if (Vector3.Dot(crossDir, crossDir) > k_Epsilon)
                        {
                            fromDir = AnimationRuntimeUtils.ProjectOnPlane(fromDir, crossDir);
                            toDir   = AnimationRuntimeUtils.ProjectOnPlane(toDir, crossDir);
                        }
                        else
                        {
                            toDir = fromDir;
                        }
                    }

                    var rotToSource = Quaternion.AngleAxis(
                        Mathf.Clamp(Vector3.Angle(fromDir, toDir), minMaxAngles.x, minMaxAngles.y),
                        crossDir
                        );

                    accumDeltaRot = QuaternionExt.Add(
                        accumDeltaRot,
                        QuaternionExt.Scale(sourceOffsets[i] * rotToSource, normalizedWeight)
                        );

                    // Required to update handles with binding info.
                    sourceTransforms[i] = sourceTransform;
                    accumWeights       += normalizedWeight;
                }

                accumDeltaRot = QuaternionExt.NormalizeSafe(accumDeltaRot);
                if (accumWeights < 1f)
                {
                    accumDeltaRot = Quaternion.Lerp(Quaternion.identity, accumDeltaRot, accumWeights);
                }

                Quaternion newRot = accumDeltaRot * drivenLRot;
                if (Vector3.Dot(axesMask, axesMask) < 3f)
                {
                    newRot = Quaternion.Euler(AnimationRuntimeUtils.Select(drivenLRot.eulerAngles, newRot.eulerAngles, axesMask));
                }

                var offset = drivenOffset.Get(stream);
                if (Vector3.Dot(offset, offset) > 0f)
                {
                    newRot *= Quaternion.Euler(offset);
                }

                driven.SetLocalRotation(stream, Quaternion.Lerp(drivenLRot, newRot, w));
            }
            else
            {
                AnimationRuntimeUtils.PassThrough(stream, driven);
            }
        }
        /// <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)
            {
                AnimationStreamHandleUtility.ReadFloats(stream, sourceWeights, weightBuffer);

                float sumWeights = AnimationRuntimeUtils.Sum(weightBuffer);
                if (sumWeights < k_Epsilon)
                {
                    AnimationRuntimeUtils.PassThrough(stream, driven);
                    return;
                }

                float weightScale = sumWeights > 1f ? 1f / sumWeights : 1f;

                float      accumWeights = 0f;
                Quaternion accumRot     = QuaternionExt.zero;
                for (int i = 0; i < sourceTransforms.Length; ++i)
                {
                    var normalizedWeight = weightBuffer[i] * weightScale;
                    if (normalizedWeight < k_Epsilon)
                    {
                        continue;
                    }

                    ReadOnlyTransformHandle sourceTransform = sourceTransforms[i];
                    accumRot = QuaternionExt.Add(accumRot, QuaternionExt.Scale(sourceTransform.GetRotation(stream) * sourceOffsets[i], normalizedWeight));

                    // Required to update handles with binding info.
                    sourceTransforms[i] = sourceTransform;
                    accumWeights       += normalizedWeight;
                }

                accumRot = QuaternionExt.NormalizeSafe(accumRot);
                if (accumWeights < 1f)
                {
                    accumRot = Quaternion.Lerp(driven.GetRotation(stream), accumRot, accumWeights);
                }

                // Convert accumRot to local space
                if (drivenParent.IsValid(stream))
                {
                    accumRot = Quaternion.Inverse(drivenParent.GetRotation(stream)) * accumRot;
                }

                Quaternion currentLRot = driven.GetLocalRotation(stream);
                if (Vector3.Dot(axesMask, axesMask) < 3f)
                {
                    accumRot = Quaternion.Euler(AnimationRuntimeUtils.Lerp(currentLRot.eulerAngles, accumRot.eulerAngles, axesMask));
                }

                var offset = drivenOffset.Get(stream);
                if (Vector3.Dot(offset, offset) > 0f)
                {
                    accumRot *= Quaternion.Euler(offset);
                }

                driven.SetLocalRotation(stream, Quaternion.Lerp(currentLRot, accumRot, w));
            }
            else
            {
                AnimationRuntimeUtils.PassThrough(stream, driven);
            }
        }
        public void ProcessAnimation(AnimationStream stream)
        {
            float w = jobWeight.Get(stream);

            if (w > 0f)
            {
                AffineTransform overrideTx;
                if (source.IsValid(stream))
                {
                    source.GetLocalTRS(stream, out Vector3 srcLPos, out Quaternion srcLRot, out _);
                    var sourceLocalTx    = new AffineTransform(srcLPos, srcLRot);
                    var sourceToSpaceRot = cache.Get <Quaternion>(sourceToCurrSpaceRotIdx);
                    overrideTx = Quaternion.Inverse(sourceToSpaceRot) * (sourceInvLocalBindTx * sourceLocalTx) * sourceToSpaceRot;
                }
                else
                {
                    overrideTx = new AffineTransform(position.Get(stream), Quaternion.Euler(rotation.Get(stream)));
                }

                Space overrideSpace = (Space)cache.GetRaw(spaceIdx);
                var   posW          = positionWeight.Get(stream) * w;
                var   rotW          = rotationWeight.Get(stream) * w;
                switch (overrideSpace)
                {
                case Space.World:
                {
                    driven.GetGlobalTR(stream, out Vector3 drivenWPos, out Quaternion drivenWRot);
                    driven.SetGlobalTR(
                        stream,
                        Vector3.Lerp(drivenWPos, overrideTx.translation, posW),
                        Quaternion.Lerp(drivenWRot, overrideTx.rotation, rotW)
                        );
                }
                break;

                case Space.Local:
                {
                    driven.GetLocalTRS(stream, out Vector3 drivenLPos, out Quaternion drivenLRot, out Vector3 drivenLScale);
                    driven.SetLocalTRS(
                        stream,
                        Vector3.Lerp(drivenLPos, overrideTx.translation, posW),
                        Quaternion.Lerp(drivenLRot, overrideTx.rotation, rotW),
                        drivenLScale
                        );
                }
                break;

                case Space.Pivot:
                {
                    driven.GetLocalTRS(stream, out Vector3 drivenLPos, out Quaternion drivenLRot, out Vector3 drivenLScale);
                    var drivenLocalTx = new AffineTransform(drivenLPos, drivenLRot);
                    overrideTx = drivenLocalTx * overrideTx;

                    driven.SetLocalTRS(
                        stream,
                        Vector3.Lerp(drivenLocalTx.translation, overrideTx.translation, posW),
                        Quaternion.Lerp(drivenLocalTx.rotation, overrideTx.rotation, rotW),
                        drivenLScale
                        );
                }
                break;

                default:
                    break;
                }
            }
            else
            {
                AnimationRuntimeUtils.PassThrough(stream, driven);
            }
        }
Example #20
0
    public void ProcessAnimation(AnimationStream stream)
    {
        var invDeltaTime = 1.0f / stream.deltaTime;

        // Store from pose
        if (doTransition)
        {
            var row             = 0;
            var prevIndexOffset = (m_CurrentBufferIndex + 1) % k_OutputBufferCount;
            for (var i = 0; i < m_Bones.Length; i++)
            {
                var lastOutputBufferIndex = row + m_CurrentBufferIndex;
                var prevOutputBufferIndex = row + prevIndexOffset;

                // Position
                {
                    var currentPos = (float3)m_Bones[i].GetLocalPosition(stream);
                    var vLast      = m_OutputPositions[lastOutputBufferIndex];
                    var vPrev      = m_OutputPositions[prevOutputBufferIndex];

                    var vDelta = vLast - currentPos;
                    var delta  = math.length(vDelta);
                    var dir    = math.normalize(vDelta);

                    var vDeltaPrev = vPrev - currentPos;
                    var deltaPrev  = math.dot(vDeltaPrev, dir);

                    var vel = (delta - deltaPrev) * invDeltaTime;

//                    if(i == k_debugBone)
//                        Debug.Log("start delta:" + delta + " vel:" + vel);


                    // If delta is negative we invert properties to keep delta positive
                    if (delta < 0)
                    {
                        delta = -delta;
                        vel   = -vel;
                        dir   = -dir;
//
//                        if(i == k_debugBone)
//                            Debug.Log("   ... negated to delta:" + delta + " vel:" + vel);
                    }

//                    if(i == k_debugBone && vel > 0)
//                        Debug.Log("   ... vel positive so its clamped to 0");

                    vel = vel < 0 ? vel : 0;



                    m_PosDirArray[i]      = dir;
                    m_PosDeltaArray[i]    = delta;
                    m_PosDeltaVelArray[i] = vel;
                }

                // Rotation
                {
                    var currentRot = m_Bones[i].GetLocalRotation(stream);
                    var qLast      = m_OutputRotations[lastOutputBufferIndex];
                    var qPrev      = m_OutputRotations[prevOutputBufferIndex];

                    var qInvCurrentRot = math.inverse(currentRot);
                    var qDeltaRot      = math.mul(qLast, qInvCurrentRot);
                    var qDeltaPrevRot  = math.mul(qPrev, qInvCurrentRot);

                    float3 rotAxis;
                    float  delta;
                    GetAxisAngle(qDeltaRot, out rotAxis, out delta);

                    // TODO (mogensh) use this !!
                    var prevRot = TwistAroundAxis(qDeltaPrevRot, rotAxis);

                    float3 rotAxis2;
                    float  rot2;
                    GetAxisAngle(qDeltaPrevRot, out rotAxis2, out rot2);

                    var vel = (delta - rot2) * invDeltaTime;

                    m_RotAxisArray[i]     = rotAxis;
                    m_RotDeltaArray[i]    = delta;
                    m_RotDeltaVelArray[i] = vel;
                }

                // Scale
                m_StarteScaleArray[i] = m_OutputScales[lastOutputBufferIndex];

                row += k_OutputBufferCount;
            }

            for (var i = 0; i < k_NumIkHandles; i++)
            {
                var index = i * k_OutputBufferCount + m_CurrentBufferIndex;
                m_FromIkPositions[i] = m_OutputIkPositions[index];
                m_FromIkRotations[i] = m_OutputIkRotations[index];
            }

            doTransition = false;
        }

        // Decrement delta
        transitionTimeRemaining -= stream.deltaTime; // TODO: Find meaningful way of decrementing this
        if (transitionTimeRemaining <= 0f)
        {
            inTransition = false;
        }

        if (inTransition)
        {
            var transitionTime = transitionDuration - transitionTimeRemaining;

            var factor = transitionTimeRemaining / transitionDuration;
            for (var i = 0; i < m_Bones.Length; i++)
            {
                // Position
                {
                    var startDelta = m_PosDeltaArray[i];
                    var deltaVel   = m_PosDeltaVelArray[i];

//                    var delta = startDelta + deltaVel * transitionTime;

                    var delta = Approach(startDelta, deltaVel, transitionDuration, transitionTime);

//                    if(i == k_debugBone)
//                        Debug.Log("startDelta:" + startDelta + " deltaVel:" + deltaVel + " time:" + transitionTime + " delta:" + delta);

                    var dir       = m_PosDirArray[i];
                    var vDelta    = delta * dir;
                    var streamPos = (float3)m_Bones[i].GetLocalPosition(stream);

                    var pos = streamPos + vDelta;
                    m_Bones[i].SetLocalPosition(stream, pos);
                }

                // Rotation
                {
                    var startDelta = m_RotDeltaArray[i];
                    var deltaVel   = m_RotDeltaVelArray[i];
                    // var delta = startDelta + deltaVel * transitionTime;
                    var delta = Approach(startDelta, deltaVel, transitionDuration, transitionTime);

                    var rotAxis    = m_RotAxisArray[i];
                    var qDeltaRot  = quaternion.AxisAngle(rotAxis, delta);
                    var qStreamRot = m_Bones[i].GetLocalRotation(stream);

                    var qRot = qDeltaRot * qStreamRot;


                    m_Bones[i].SetLocalRotation(stream, qStreamRot);
                }


                // Scale
                m_Bones[i].SetLocalScale(stream, m_Bones[i].GetLocalScale(stream));
            }


            if (stream.isHumanStream)
            {
                var humanStream = stream.AsHuman();
                for (var i = 0; i < k_NumIkHandles; i++)
                {
                    var position = math.lerp(humanStream.GetGoalLocalPosition((AvatarIKGoal)i), m_FromIkPositions[i], factor);
                    humanStream.SetGoalLocalPosition((AvatarIKGoal)i, position);
                    var rotation = math.slerp(humanStream.GetGoalLocalRotation((AvatarIKGoal)i), m_FromIkRotations[i], factor);
                    humanStream.SetGoalLocalRotation((AvatarIKGoal)i, rotation);
                }
            }
        }

        // Store output values
        StoreOutput(stream);
    }
Example #21
0
 public void ProcessAnimation(AnimationStream stream)
 {
     Update(stream);
 }
Example #22
0
        public void CanRemapRigRotationOffset()
        {
            var sourceChannels = new IAnimationChannel[]
            {
                new LocalRotationChannel {
                    Id = "Root", DefaultValue = m_ExpectedSourceRotation
                },
                new LocalRotationChannel {
                    Id = "Child", DefaultValue = m_ExpectedSourceRotation
                },
            };

            var sourceRig = new Rig {
                Value = RigBuilder.CreateRigDefinition(sourceChannels)
            };

            var destinationChannels = new IAnimationChannel[]
            {
                new LocalRotationChannel {
                    Id = "AnotherRoot", DefaultValue = quaternion.identity
                },
                new LocalRotationChannel {
                    Id = "AnotherChild", DefaultValue = quaternion.identity
                },
            };

            var destinationRig = new Rig {
                Value = RigBuilder.CreateRigDefinition(destinationChannels)
            };
            var rigEntity = m_Manager.CreateEntity();

            RigEntityBuilder.SetupRigEntity(rigEntity, m_Manager, destinationRig);

            var rigRemapQuery = new RigRemapQuery
            {
                RotationChannels = new []
                {
                    new ChannelMap {
                        SourceId = "Root", DestinationId = "AnotherRoot"
                    },
                    new ChannelMap {
                        SourceId = "Child", DestinationId = "AnotherChild", OffsetIndex = 1
                    }
                },

                RotationOffsets = new []
                {
                    new RigRotationOffset(),
                    new RigRotationOffset {
                        PreRotation = math.normalize(math.quaternion(1, 2, 3, 4)), PostRotation = math.normalize(math.quaternion(5, 6, 7, 8))
                    }
                }
            };

            var remapTable = rigRemapQuery.ToRigRemapTable(sourceRig, destinationRig);

            // Here I'm using a layerMixer with no inputs connected
            // the expected result is to inject the default pose into Graph samples buffer
            var layerMixer = CreateNode <LayerMixerNode>();

            Set.SendMessage(layerMixer, LayerMixerNode.SimulationPorts.Rig, sourceRig);

            var rigRemapper = CreateNode <RigRemapperNode>();

            Set.Connect(layerMixer, LayerMixerNode.KernelPorts.Output, rigRemapper, RigRemapperNode.KernelPorts.Input);

            Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.SourceRig, sourceRig);
            Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.DestinationRig, destinationRig);
            Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.RemapTable, remapTable);

            var entityNode = CreateComponentNode(rigEntity);

            Set.Connect(rigRemapper, RigRemapperNode.KernelPorts.Output, entityNode);

            m_Manager.AddComponent <PreAnimationGraphTag>(rigEntity);

            m_AnimationGraphSystem.Update();

            var streamECS = AnimationStream.CreateReadOnly(
                destinationRig,
                m_Manager.GetBuffer <AnimatedData>(rigEntity).AsNativeArray()
                );

            Assert.That(streamECS.GetLocalToParentRotation(1), Is.EqualTo(math.mul(rigRemapQuery.RotationOffsets[1].PreRotation, math.mul(m_ExpectedSourceRotation, rigRemapQuery.RotationOffsets[1].PostRotation))).Using(RotationComparer), "Channel localRotation doesn't match destination rig default value with rig rotation offset");
        }
Example #23
0
        // Rotating bone to get transform aim closer to target
        private void RotateToTarget(AnimationStream s, Vector3 targetPosition, Vector3 polePosition, int i, float weight, float poleWeight, bool XY, bool useRotationLimits, Vector3 axis, Vector3 poleAxis)
        {
            // Swing
            if (XY)
            {
                if (weight >= 0f)
                {
                    Vector3 dir       = _transform.GetRotation(s) * axis;
                    Vector3 targetDir = targetPosition - _transform.GetPosition(s);

                    float angleDir    = Mathf.Atan2(dir.x, dir.y) * Mathf.Rad2Deg;
                    float angleTarget = Mathf.Atan2(targetDir.x, targetDir.y) * Mathf.Rad2Deg;

                    bones[i].SetRotation(s, Quaternion.AngleAxis(Mathf.DeltaAngle(angleDir, angleTarget), Vector3.back) * bones[i].GetRotation(s));
                }
            }
            else
            {
                if (weight >= 0f)
                {
                    Quaternion rotationOffset = Quaternion.FromToRotation(_transform.GetRotation(s) * axis, targetPosition - _transform.GetPosition(s));

                    if (weight >= 1f)
                    {
                        bones[i].SetRotation(s, rotationOffset * bones[i].GetRotation(s));
                    }
                    else
                    {
                        bones[i].SetRotation(s, Quaternion.Lerp(Quaternion.identity, rotationOffset, weight) * bones[i].GetRotation(s));
                    }
                }

                // Pole
                if (poleWeight > 0f)
                {
                    Vector3 poleDirection = polePosition - _transform.GetPosition(s);

                    // Ortho-normalize to transform axis to make this a twisting only operation
                    Vector3 poleDirOrtho = poleDirection;
                    Vector3 normal       = _transform.GetRotation(s) * axis;
                    Vector3.OrthoNormalize(ref normal, ref poleDirOrtho);

                    Quaternion toPole = Quaternion.FromToRotation(_transform.GetRotation(s) * poleAxis, poleDirOrtho);
                    bones[i].SetRotation(s, Quaternion.Lerp(Quaternion.identity, toPole, weight * poleWeight) * bones[i].GetRotation(s));
                }
            }

            // Rotation Constraints
            if (useRotationLimits)
            {
                if (hingeFlags[i] == 1)
                {
                    Quaternion localRotation = Quaternion.Inverse(limitDefaultLocalRotationArray[i]) * bones[i].GetLocalRotation(s);
                    Quaternion lastRotation  = hingeLastRotations[i];
                    float      lastAngle     = hingeLastAngles[i];
                    Quaternion r             = RotationLimitUtilities.LimitHinge(localRotation, hingeMinArray[i].GetFloat(s), hingeMaxArray[i].GetFloat(s), hingeUseLimitsArray[i].GetBool(s), limitAxisArray[i], ref lastRotation, ref lastAngle);
                    hingeLastRotations[i] = lastRotation;
                    hingeLastAngles[i]    = lastAngle;
                    bones[i].SetLocalRotation(s, limitDefaultLocalRotationArray[i] * r);
                }
                else if (angleFlags[i] == 1)
                {
                    Quaternion localRotation = Quaternion.Inverse(limitDefaultLocalRotationArray[i]) * bones[i].GetLocalRotation(s);
                    Quaternion r             = RotationLimitUtilities.LimitAngle(localRotation, limitAxisArray[i], angleSecondaryAxisArray[i], angleLimitArray[i].GetFloat(s), angleTwistLimitArray[i].GetFloat(s));
                    bones[i].SetLocalRotation(s, limitDefaultLocalRotationArray[i] * r);
                }
            }
        }
Example #24
0
        public void CanRemapAllIntChannel()
        {
            var sourceChannels = new IAnimationChannel[]
            {
                new IntChannel {
                    Id = "Root", DefaultValue = m_ExpectedSourceInt
                },
                new IntChannel {
                    Id = "Child1", DefaultValue = m_ExpectedSourceInt
                },
                new IntChannel {
                    Id = "Child2", DefaultValue = m_ExpectedSourceInt
                },
            };

            var sourceRig = new Rig {
                Value = RigBuilder.CreateRigDefinition(sourceChannels)
            };

            var destinationChannels = new IAnimationChannel[]
            {
                new IntChannel {
                    Id = "AnotherRoot", DefaultValue = 0
                },
                new IntChannel {
                    Id = "AnotherChild1", DefaultValue = 0
                },
                new IntChannel {
                    Id = "AnotherChild2", DefaultValue = 0
                },
            };
            var destinationRig = new Rig {
                Value = RigBuilder.CreateRigDefinition(destinationChannels)
            };
            var rigEntity = m_Manager.CreateEntity();

            RigEntityBuilder.SetupRigEntity(rigEntity, m_Manager, destinationRig);

            var rigRemapQuery = new RigRemapQuery
            {
                AllChannels = new [] {
                    new ChannelMap {
                        SourceId = "Root", DestinationId = "AnotherRoot"
                    },
                    new ChannelMap {
                        SourceId = "Child1", DestinationId = "AnotherChild1"
                    },
                    new ChannelMap {
                        SourceId = "Child2", DestinationId = "AnotherChild2"
                    }
                }
            };
            var remapTable = rigRemapQuery.ToRigRemapTable(sourceRig, destinationRig);

            // Here I'm using a layerMixer with no inputs connected
            // the expected result is to inject the default pose into Graph samples buffer
            var layerMixer = CreateNode <LayerMixerNode>();

            Set.SendMessage(layerMixer, LayerMixerNode.SimulationPorts.Rig, sourceRig);

            var rigRemapper = CreateNode <RigRemapperNode>();

            Set.Connect(layerMixer, LayerMixerNode.KernelPorts.Output, rigRemapper, RigRemapperNode.KernelPorts.Input);

            Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.SourceRig, sourceRig);
            Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.DestinationRig, destinationRig);
            Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.RemapTable, remapTable);

            var entityNode = CreateComponentNode(rigEntity);

            Set.Connect(rigRemapper, RigRemapperNode.KernelPorts.Output, entityNode);

            m_Manager.AddComponent <PreAnimationGraphTag>(rigEntity);

            m_AnimationGraphSystem.Update();

            var streamECS = AnimationStream.CreateReadOnly(
                destinationRig,
                m_Manager.GetBuffer <AnimatedData>(rigEntity).AsNativeArray()
                );

            Assert.That(streamECS.GetInt(0), Is.EqualTo(m_ExpectedSourceInt), "Channel int 0 doesn't match source rig default value");
            Assert.That(streamECS.GetInt(1), Is.EqualTo(m_ExpectedSourceInt), "Channel int 1 doesn't match source rig default value");
            Assert.That(streamECS.GetInt(2), Is.EqualTo(m_ExpectedSourceInt), "Channel int 2 doesn't match source rig default value");
        }
Example #25
0
 //Gets the direction from last bone to first bone in first bone's local space.
 private Vector3 GetLocalDirection(AnimationStream s, Vector3 transformAxis)
 {
     return(Quaternion.Inverse(bones[0].GetRotation(s)) * transformAxis);
 }
Example #26
0
        public void ProcessAnimation(AnimationStream stream)
        {
            // Debug.Log($"Process animation {stream.isValid}");
            if (stream.inputStreamCount == 0)
            {
                return;
            }

            var streamA    = stream.GetInputStream(0);
            var streamB    = stream.GetInputStream(1);
            var numHandles = handles.Length;

            if (useBonesLastAsFirst &&
                streamA.isValid)
            {
                if (!isTransitioning)
                {
                    isTransitioning = true;
                    bonesLastFrame.CopyTo(bonesLastState);
                    // Debug.LogError("Start new mixer transition");
                }

                for (var i = 0; i < numHandles; ++i)
                {
                    var handle = handles[i];

                    var posA = bonesLastState[i].position;
                    var posB = handle.GetLocalPosition(streamA);
                    var pos  = Vector3Blend[blendMode](posA, posB, weight *boneWeights[i]);
                    handle.SetLocalPosition(stream, pos);

                    var rotA = bonesLastState[i].rotation;
                    var rotB = handle.GetLocalRotation(streamA);
                    var rot  = QuaternionBlend[blendMode](rotA, rotB, weight *boneWeights[i]);
                    handle.SetLocalRotation(stream, rot);

                    bonesLastFrame[i] = new BoneLocation(pos, rot);
                }

                return;
            }

            if (!streamA.isValid && !streamB.isValid)
            {
                return;
            }

            if (stream.inputStreamCount < 2 || !streamB.isValid)
            {
                for (var i = 0; i < numHandles; ++i)
                {
                    var handle = handles[i];

                    var posA = handle.GetLocalPosition(streamA);
                    handle.SetLocalPosition(stream, posA);

                    var rotA = handle.GetLocalRotation(streamA);
                    handle.SetLocalRotation(stream, rotA);

                    bonesLastFrame[i] = new BoneLocation(posA, rotA);
                }

                return;
            }

            for (var i = 0; i < numHandles; ++i)
            {
                var handle = handles[i];

                var posA = handle.GetLocalPosition(streamB);
                var posB = handle.GetLocalPosition(streamA);
                var pos  = Vector3Blend[blendMode](posA, posB, weight *boneWeights[i]);
                handle.SetLocalPosition(stream, pos);

                var rotA = handle.GetLocalRotation(streamB);
                var rotB = handle.GetLocalRotation(streamA);
                var rot  = QuaternionBlend[blendMode](rotA, rotB, weight *boneWeights[i]);
                handle.SetLocalRotation(stream, rot);

                bonesLastFrame[i] = new BoneLocation(pos, rot);
            }
        }
Example #27
0
    public void ProcessAnimation(AnimationStream stream)
    {
        var w = jobWeight.Get(stream);

        float thumbT  = 1 - thumbAmount.Get(stream);
        float indexT  = 1 - indexAmount.Get(stream);
        float middleT = 1 - middleAmount.Get(stream);
        float ringT   = 1 - ringAmount.Get(stream);
        float littleT = 1 - littleAmount.Get(stream);
        float allT    = 1 - allAmount.Get(stream);
        float spreadT = 1 - spreadAmount.Get(stream);

        if (w > 0)
        {
            // Thumb
            var proximalThumbHandleRot = Quaternion.Euler(
                math.lerp(ProximalThumbXRotationRange.y, ProximalThumbXRotationRange.x, thumbT * allT),
                0,
                math.lerp(ProximalThumbZRotationRange.y, ProximalThumbZRotationRange.x, spreadT)
                );
            var proximalThumbRot = ProximalThumb.GetLocalRotation(stream);
            ProximalThumb.SetLocalRotation(stream, Quaternion.Lerp(
                                               proximalThumbRot,
                                               proximalThumbHandleRot,
                                               w
                                               ));

            var intermediateThumbHandleRot = Quaternion.Euler(
                math.lerp(IntermediateThumbXRotationRange.y, IntermediateThumbXRotationRange.x, thumbT * allT),
                0,
                0
                );
            var intermediateThumbRot = IntermediateThumb.GetLocalRotation(stream);
            IntermediateThumb.SetLocalRotation(stream, Quaternion.Lerp(
                                                   intermediateThumbRot,
                                                   intermediateThumbHandleRot,
                                                   w
                                                   ));

            var distalThumbHandleRot = Quaternion.Euler(
                math.lerp(DistalThumbXRotationRange.y, DistalThumbXRotationRange.x, thumbT * allT),
                0,
                0
                );
            var distalThumbRot = DistalThumb.GetLocalRotation(stream);
            DistalThumb.SetLocalRotation(stream, Quaternion.Lerp(
                                             distalThumbRot,
                                             distalThumbHandleRot,
                                             w
                                             ));

            // Index
            var proximalIndexHandleRot = Quaternion.Euler(
                0,
                math.lerp(ProximalIndexYRotationRange.y, ProximalIndexYRotationRange.x, spreadT),
                math.lerp(ProximalIndexZRotationRange.y, ProximalIndexZRotationRange.x, indexT * allT)
                );
            var proximalIndexRot = ProximalIndex.GetLocalRotation(stream);
            ProximalIndex.SetLocalRotation(stream, Quaternion.Lerp(
                                               proximalIndexRot,
                                               proximalIndexHandleRot,
                                               w
                                               ));

            var intermediateIndexHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(IntermediateIndexZRotationRange.y, IntermediateIndexZRotationRange.x, indexT * allT)
                );
            var intermediateIndexRot = IntermediateIndex.GetLocalRotation(stream);
            IntermediateIndex.SetLocalRotation(stream, Quaternion.Lerp(
                                                   intermediateIndexRot,
                                                   intermediateIndexHandleRot,
                                                   w
                                                   ));

            var distalIndexHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(DistalIndexZRotationRange.y, DistalIndexZRotationRange.x, indexT * allT)
                );
            var distalIndexRot = DistalIndex.GetLocalRotation(stream);
            DistalIndex.SetLocalRotation(stream, Quaternion.Lerp(
                                             distalIndexRot,
                                             distalIndexHandleRot,
                                             w
                                             ));

            // Middle
            var proximalMiddleHandleRot = Quaternion.Euler(
                0,
                math.lerp(ProximalMiddleYRotationRange.y, ProximalMiddleYRotationRange.x, spreadT),
                math.lerp(ProximalMiddleZRotationRange.y, ProximalMiddleZRotationRange.x, middleT * allT)
                );
            var proximalMiddleRot = ProximalMiddle.GetLocalRotation(stream);
            ProximalMiddle.SetLocalRotation(stream, Quaternion.Lerp(
                                                proximalMiddleRot,
                                                proximalMiddleHandleRot,
                                                w
                                                ));

            var intermediateMiddleHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(IntermediateMiddleZRotationRange.y, IntermediateMiddleZRotationRange.x, middleT * allT)
                );
            var intermediateMiddleRot = IntermediateMiddle.GetLocalRotation(stream);
            IntermediateMiddle.SetLocalRotation(stream, Quaternion.Lerp(
                                                    intermediateMiddleRot,
                                                    intermediateMiddleHandleRot,
                                                    w
                                                    ));

            var distalMiddleHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(DistalMiddleZRotationRange.y, DistalMiddleZRotationRange.x, middleT * allT)
                );
            var distalMiddleRot = DistalMiddle.GetLocalRotation(stream);
            DistalMiddle.SetLocalRotation(stream, Quaternion.Lerp(
                                              distalMiddleRot,
                                              distalMiddleHandleRot,
                                              w
                                              ));

            // Ring
            var proximalRingHandleRot = Quaternion.Euler(
                0,
                math.lerp(ProximalRingYRotationRange.y, ProximalRingYRotationRange.x, spreadT),
                math.lerp(ProximalRingZRotationRange.y, ProximalRingZRotationRange.x, ringT * allT)
                );
            var proximalRingRot = ProximalRing.GetLocalRotation(stream);
            ProximalRing.SetLocalRotation(stream, Quaternion.Lerp(
                                              proximalRingRot,
                                              proximalRingHandleRot,
                                              w
                                              ));

            var intermediateRingHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(IntermediateRingZRotationRange.y, IntermediateRingZRotationRange.x, ringT * allT)
                );
            var intermediateRingRot = IntermediateRing.GetLocalRotation(stream);
            IntermediateRing.SetLocalRotation(stream, Quaternion.Lerp(
                                                  intermediateRingRot,
                                                  intermediateRingHandleRot,
                                                  w
                                                  ));

            var distalRingHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(DistalRingZRotationRange.y, DistalRingZRotationRange.x, ringT * allT)
                );
            var distalRingRot = DistalRing.GetLocalRotation(stream);
            DistalRing.SetLocalRotation(stream, Quaternion.Lerp(
                                            distalRingRot,
                                            distalRingHandleRot,
                                            w
                                            ));

            // Little
            var proximalLittleHandleRot = Quaternion.Euler(
                0,
                math.lerp(ProximalLittleYRotationRange.y, ProximalLittleYRotationRange.x, spreadT),
                math.lerp(ProximalLittleZRotationRange.y, ProximalLittleZRotationRange.x, littleT * allT)
                );
            var proximalLittleRot = ProximalLittle.GetLocalRotation(stream);
            ProximalLittle.SetLocalRotation(stream, Quaternion.Lerp(
                                                proximalLittleRot,
                                                proximalLittleHandleRot,
                                                w
                                                ));

            var intermediateLittleHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(IntermediateLittleZRotationRange.y, IntermediateLittleZRotationRange.x, littleT * allT)
                );
            var intermediateLittleRot = IntermediateLittle.GetLocalRotation(stream);
            IntermediateLittle.SetLocalRotation(stream, Quaternion.Lerp(
                                                    intermediateLittleRot,
                                                    intermediateLittleHandleRot,
                                                    w
                                                    ));

            var distalLittleHandleRot = Quaternion.Euler(
                0,
                0,
                math.lerp(DistalLittleZRotationRange.y, DistalLittleZRotationRange.x, littleT * allT)
                );
            var distalLittleRot = DistalLittle.GetLocalRotation(stream);
            DistalLittle.SetLocalRotation(stream, Quaternion.Lerp(
                                              distalLittleRot,
                                              distalLittleHandleRot,
                                              w
                                              ));
        }
    }
Example #28
0
 public void ProcessAnimation(AnimationStream stream)
 {
 }
Example #29
0
 public void ProcessRootMotion(AnimationStream stream)
 {
 }
        public static void SolveTwoBoneIK(
            AnimationStream stream,
            ReadWriteTransformHandle root,
            ReadWriteTransformHandle mid,
            ReadWriteTransformHandle tip,
            ReadOnlyTransformHandle target,
            ReadOnlyTransformHandle hint,
            float posWeight,
            float rotWeight,
            float hintWeight,
            Vector2 limbLengths,
            AffineTransform targetOffset
            )
        {
            Vector3 aPosition = root.GetPosition(stream);
            Vector3 bPosition = mid.GetPosition(stream);
            Vector3 cPosition = tip.GetPosition(stream);

            target.GetGlobalTR(stream, out Vector3 targetPos, out Quaternion targetRot);
            Vector3    tPosition = Vector3.Lerp(cPosition, targetPos + targetOffset.translation, posWeight);
            Quaternion tRotation = Quaternion.Lerp(tip.GetRotation(stream), targetRot * targetOffset.rotation, rotWeight);
            bool       hasHint   = hint.IsValid(stream) && hintWeight > 0f;

            Vector3 ab = bPosition - aPosition;
            Vector3 bc = cPosition - bPosition;
            Vector3 ac = cPosition - aPosition;
            Vector3 at = tPosition - aPosition;

            float oldAbcAngle = TriangleAngle(ac.magnitude, limbLengths[0], limbLengths[1]);
            float newAbcAngle = TriangleAngle(at.magnitude, limbLengths[0], limbLengths[1]);

            // 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.
            Vector3 axis = Vector3.Cross(ab, bc);

            if (axis.sqrMagnitude < k_SqrEpsilon)
            {
                axis = hasHint ? Vector3.Cross(hint.GetPosition(stream) - aPosition, bc) : Vector3.zero;

                if (axis.sqrMagnitude < k_SqrEpsilon)
                {
                    axis = Vector3.Cross(at, bc);
                }

                if (axis.sqrMagnitude < k_SqrEpsilon)
                {
                    axis = Vector3.up;
                }
            }
            axis = Vector3.Normalize(axis);

            float      a      = 0.5f * (oldAbcAngle - newAbcAngle);
            float      sin    = Mathf.Sin(a);
            float      cos    = Mathf.Cos(a);
            Quaternion deltaR = new Quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos);

            mid.SetRotation(stream, deltaR * mid.GetRotation(stream));

            cPosition = tip.GetPosition(stream);
            ac        = cPosition - aPosition;
            root.SetRotation(stream, QuaternionExt.FromToRotation(ac, at) * root.GetRotation(stream));

            if (hasHint)
            {
                float acSqrMag = ac.sqrMagnitude;
                if (acSqrMag > 0f)
                {
                    bPosition = mid.GetPosition(stream);
                    cPosition = tip.GetPosition(stream);
                    ab        = bPosition - aPosition;
                    ac        = cPosition - aPosition;

                    Vector3 acNorm = ac / Mathf.Sqrt(acSqrMag);
                    Vector3 ah     = hint.GetPosition(stream) - aPosition;
                    Vector3 abProj = ab - acNorm * Vector3.Dot(ab, acNorm);
                    Vector3 ahProj = ah - acNorm * Vector3.Dot(ah, acNorm);

                    float maxReach = limbLengths[0] + limbLengths[1];
                    if (abProj.sqrMagnitude > (maxReach * maxReach * 0.001f) && ahProj.sqrMagnitude > 0f)
                    {
                        Quaternion hintR = QuaternionExt.FromToRotation(abProj, ahProj);
                        hintR.x *= hintWeight;
                        hintR.y *= hintWeight;
                        hintR.z *= hintWeight;
                        root.SetRotation(stream, hintR * root.GetRotation(stream));
                    }
                }
            }

            tip.SetRotation(stream, tRotation);
        }
 public static void PassThrough(AnimationStream stream, ReadWriteTransformHandle handle)
 {
     handle.GetLocalTRS(stream, out Vector3 position, out Quaternion rotation, out Vector3 scale);
     handle.SetLocalTRS(stream, position, rotation, scale);
 }
Example #32
0
 public float Get(AnimationStream stream) => value.GetFloat(stream);