예제 #1
0
    public IEnumerator TwistChainConstraint_ApplyWeight()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        Transform[] chain = ConstraintsUtils.ExtractChain(constraint.data.root, constraint.data.tip);

        // Chain with no constraint.
        Vector3[] bindPoseChain = chain.Select(transform => transform.position).ToArray();

        var tipTarget  = constraint.data.tipTarget;
        var rootTarget = constraint.data.rootTarget;

        rootTarget.rotation = Quaternion.Euler(0, 0, 0);
        tipTarget.rotation  = Quaternion.Euler(0, 0, 50);

        yield return(null);

        // Chain with TwistChain constraint.
        Vector3[] weightedChain = chain.Select(transform => transform.position).ToArray();

        // In-between chains.
        var inBetweenChains = new List <Vector3[]>();

        for (int i = 0; i <= 5; ++i)
        {
            float w = i / 5.0f;

            data.constraint.weight = w;
            yield return(null);

            inBetweenChains.Add(chain.Select(transform => transform.position).ToArray());
        }

        var floatComparer = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        for (int i = 0; i <= 5; ++i)
        {
            Vector3[] prevChain    = (i > 0) ? inBetweenChains[i - 1] : bindPoseChain;
            Vector3[] currentChain = inBetweenChains[i];
            Vector3[] nextChain    = (i < 5) ? inBetweenChains[i + 1] : weightedChain;

            for (int j = 0; j < bindPoseChain.Length - 1; ++j)
            {
                Vector2 dir1 = prevChain[j + 1] - prevChain[j];
                Vector2 dir2 = currentChain[j + 1] - currentChain[j];
                Vector2 dir3 = nextChain[j + 1] - nextChain[j];

                float maxAngle = Vector2.Angle(dir1, dir3);
                float angle    = Vector2.Angle(dir1, dir2);

                Assert.That(angle, Is.GreaterThanOrEqualTo(0f).Using(floatComparer));
                Assert.That(angle, Is.LessThanOrEqualTo(maxAngle).Using(floatComparer));
            }
        }
    }
        public override IEnumerable <EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, TwistChainConstraint constraint)
        {
            var bindings = new List <EditorCurveBinding>();

            // Retrieve chain in-between root and tip transforms.
            Transform[] chain = ConstraintsUtils.ExtractChain(constraint.data.root, constraint.data.tip);

            for (int i = 0; i < chain.Length; ++i)
            {
                EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, chain[i], bindings);
            }

            return(bindings);
        }
예제 #3
0
    public void TwistChainConstraint_TransferMotionToConstraint()
    {
        var data       = TwistChainConstraintTests.SetupConstraintRig();
        var constraint = data.constraint;

        var rootGO     = data.rigData.rootGO;
        var rigBuilder = rootGO.GetComponent <RigBuilder>();

        var tip  = constraint.data.tip;
        var root = constraint.data.root;

        var clip = new AnimationClip();


        // Add keyframes for root and tips.
        Transform[] chain = ConstraintsUtils.ExtractChain(root, tip);

        var rootPath = AnimationUtility.CalculateTransformPath(root, rootGO.transform);

        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(rootPath, typeof(Transform), "localEulerAnglesRaw.x"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(rootPath, typeof(Transform), "localEulerAnglesRaw.y"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(rootPath, typeof(Transform), "localEulerAnglesRaw.z"), AnimationCurve.Linear(0f, 0f, 1f, -50f));

        var tipPath = AnimationUtility.CalculateTransformPath(tip, rootGO.transform);

        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(tipPath, typeof(Transform), "localEulerAnglesRaw.x"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(tipPath, typeof(Transform), "localEulerAnglesRaw.y"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(tipPath, typeof(Transform), "localEulerAnglesRaw.z"), AnimationCurve.Linear(0f, 0f, 1f, 50f));

        // Also keyframe inbetween keys
        for (int i = 1; i < chain.Length - 1; ++i)
        {
            var path = AnimationUtility.CalculateTransformPath(chain[i], rootGO.transform);
            AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(path, typeof(Transform), "localEulerAnglesRaw.x"), AnimationCurve.Constant(0f, 1f, 0f));
            AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(path, typeof(Transform), "localEulerAnglesRaw.y"), AnimationCurve.Constant(0f, 1f, 0f));
            AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(path, typeof(Transform), "localEulerAnglesRaw.z"), AnimationCurve.Constant(0f, 1f, 0f));
        }

        RuntimeRiggingEditorTestFixture.TestTransferMotionToConstraint(constraint, rigBuilder, clip, new Transform[] { root, tip }, CompareFlags.Rotation);
    }
예제 #4
0
    public void TwistChainConstraint_TransferMotionToSkeleton()
    {
        var data       = TwistChainConstraintTests.SetupConstraintRig();
        var constraint = data.constraint;

        var rootGO     = data.rigData.rootGO;
        var rigBuilder = rootGO.GetComponent <RigBuilder>();

        var tip  = constraint.data.tip;
        var root = constraint.data.root;

        var tipTarget  = constraint.data.tipTarget;
        var rootTarget = constraint.data.rootTarget;

        var clip = new AnimationClip();

        var tipTargetPath  = AnimationUtility.CalculateTransformPath(tipTarget, rootGO.transform);
        var rootTargetPath = AnimationUtility.CalculateTransformPath(rootTarget, rootGO.transform);

        // Add keyframes for twist chain constraint.
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(rootTargetPath, typeof(Transform), "localEulerAnglesRaw.x"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(rootTargetPath, typeof(Transform), "localEulerAnglesRaw.y"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(rootTargetPath, typeof(Transform), "localEulerAnglesRaw.z"), AnimationCurve.Linear(0f, 0f, 1f, -50f));

        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(tipTargetPath, typeof(Transform), "localEulerAnglesRaw.x"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(tipTargetPath, typeof(Transform), "localEulerAnglesRaw.y"), AnimationCurve.Constant(0f, 1f, 0f));
        AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(tipTargetPath, typeof(Transform), "localEulerAnglesRaw.z"), AnimationCurve.Linear(0f, 0f, 1f, 50f));

        RuntimeRiggingEditorTestFixture.TestTransferMotionToSkeleton(constraint, rigBuilder, clip, ConstraintsUtils.ExtractChain(root, tip), CompareFlags.TR);
    }