Beispiel #1
0
    public IEnumerator TwistCorrection_ApplyWeight()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        var sourceObject = constraint.data.sourceObject;
        var twistNodes   = constraint.data.twistNodes;

        var floatComparer = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        // Apply rotation to source object
        sourceObject.localRotation = sourceObject.localRotation * Quaternion.AngleAxis(90, Vector3.left);
        twistNodes.SetWeight(0, 1f);
        constraint.data.twistNodes = twistNodes;

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

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

            var weightedRot = Quaternion.Lerp(data.restLocalRotation, sourceObject.localRotation, w);
            Assert.That(twistNodes[0].transform.localRotation.x, Is.EqualTo(weightedRot.x).Using(floatComparer));
            Assert.That(twistNodes[0].transform.localRotation.w, Is.EqualTo(weightedRot.w).Using(floatComparer));
        }
    }
Beispiel #2
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));
            }
        }
    }
Beispiel #3
0
    public IEnumerator TwistCorrection_FollowsSourceObject()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        var sourceObject = constraint.data.sourceObject;
        var twistNodes   = constraint.data.twistNodes;

        var rotationComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon);
        var floatComparer    = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        // Apply rotation to source object
        sourceObject.localRotation = sourceObject.localRotation * Quaternion.AngleAxis(90, Vector3.left);

        // twistNode0.w = 0.0f, twistNode1.w = 0.0f [does not influence twist nodes]
        Assert.AreEqual(twistNodes[0].weight, 0.0f);
        Assert.AreEqual(twistNodes[1].weight, 0.0f);
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        Assert.That(sourceObject.localRotation, Is.Not.EqualTo(data.restLocalRotation).Using(rotationComparer));
        Assert.That(twistNodes[0].transform.localRotation, Is.EqualTo(Quaternion.identity).Using(rotationComparer));
        Assert.That(twistNodes[1].transform.localRotation, Is.EqualTo(Quaternion.identity).Using(rotationComparer));

        // twistNode0.w = 1f, twistNode1.w = 1f [twist nodes should be equal to source]
        twistNodes.SetWeight(0, 1f);
        twistNodes.SetWeight(1, 1f);
        constraint.data.twistNodes = twistNodes;
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        // Verify twist on X axis
        Assert.That(twistNodes[0].transform.localRotation.x, Is.EqualTo(sourceObject.localRotation.x).Using(floatComparer));
        Assert.That(twistNodes[0].transform.localRotation.w, Is.EqualTo(sourceObject.localRotation.w).Using(floatComparer));
        Assert.That(twistNodes[1].transform.localRotation.x, Is.EqualTo(sourceObject.localRotation.x).Using(floatComparer));
        Assert.That(twistNodes[1].transform.localRotation.w, Is.EqualTo(sourceObject.localRotation.w).Using(floatComparer));

        // twistNode0.w = -1f, twistNode1.w = -1f [twist nodes should be inverse to source]
        twistNodes.SetWeight(0, -1f);
        twistNodes.SetWeight(1, -1f);
        constraint.data.twistNodes = twistNodes;
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        var invTwist = Quaternion.Inverse(sourceObject.localRotation);

        // Verify twist on X axis
        Assert.That(twistNodes[0].transform.localRotation.x, Is.EqualTo(invTwist.x).Using(floatComparer));
        Assert.That(twistNodes[0].transform.localRotation.w, Is.EqualTo(invTwist.w).Using(floatComparer));
        Assert.That(twistNodes[1].transform.localRotation.x, Is.EqualTo(invTwist.x).Using(floatComparer));
        Assert.That(twistNodes[1].transform.localRotation.w, Is.EqualTo(invTwist.w).Using(floatComparer));
    }
Beispiel #4
0
    public IEnumerator MultiAimConstraint_FollowSourceObjects()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        var constrainedObject = constraint.data.constrainedObject;
        var sources           = constraint.data.sourceObjects;

        var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon);
        var rotationComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon);
        var floatComparer    = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        // Add displacement to source objects
        sources[0].transform.position += Vector3.left;
        sources[1].transform.position += Vector3.right;

        // src0.w = 0, src1.w = 0
        Assert.Zero(sources[0].weight);
        Assert.Zero(sources[1].weight);
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        Assert.That(constrainedObject.position, Is.EqualTo(data.constrainedObjectRestTx.translation).Using(positionComparer));
        Assert.That(constrainedObject.rotation, Is.EqualTo(data.constrainedObjectRestTx.rotation).Using(rotationComparer));

        // src0.w = 1, src1.w = 0
        sources.SetWeight(0, 1f);
        constraint.data.sourceObjects = sources;
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        Vector3 currAim = constrainedObject.rotation * Vector3.forward;
        Vector3 src0Dir = (sources[0].transform.position - constrainedObject.position).normalized;
        Vector3 src1Dir = (sources[1].transform.position - constrainedObject.position).normalized;

        Assert.That(Vector3.Angle(currAim, src0Dir), Is.EqualTo(0f).Using(floatComparer));
        Assert.That(Vector3.Angle(currAim, src1Dir), Is.Not.EqualTo(0f).Using(floatComparer));

        // src0.w = 0, src1.w = 1
        sources.SetWeight(0, 0f);
        sources.SetWeight(1, 1f);
        constraint.data.sourceObjects = sources;
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        currAim = constrainedObject.rotation * Vector3.forward;
        src0Dir = (sources[0].transform.position - constrainedObject.position).normalized;
        src1Dir = (sources[1].transform.position - constrainedObject.position).normalized;
        Assert.That(Vector3.Angle(currAim, src0Dir), Is.Not.EqualTo(0f).Using(floatComparer));
        Assert.That(Vector3.Angle(currAim, src1Dir), Is.EqualTo(0f).Using(floatComparer));
    }
Beispiel #5
0
    public IEnumerator TwoBoneIKConstraint_UsesHint()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        var target = constraint.data.target;
        var hint   = constraint.data.hint;
        var mid    = constraint.data.mid;

        var floatComparer = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        Vector3 midPos1 = mid.position;

        // Make left arm flex.
        target.position += new Vector3(0.2f, 0.0f, 0f);

        hint.position = mid.position + new Vector3(0f, 1f, 0f);
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        Vector3 midPos2 = mid.position;

        Assert.That(midPos2.y, Is.GreaterThan(midPos1.y).Using(floatComparer), String.Format("Expected mid2.y to be greater than mid1.y"));
        Assert.That(midPos1.z, Is.EqualTo(midPos2.z).Using(floatComparer), String.Format("Expected mid2.z to be {0}, but was {1}", midPos1.z, midPos2.z));

        hint.position = mid.position + new Vector3(0f, -1f, 0f);
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        midPos2 = mid.position;
        Assert.That(midPos2.y, Is.LessThan(midPos1.y).Using(floatComparer), String.Format("Expected mid2.y to be lower than mid1.y"));
        Assert.That(midPos1.z, Is.EqualTo(midPos2.z).Using(floatComparer), String.Format("Expected mid2.z to be {0}, but was {1}", midPos1.z, midPos2.z));

        hint.position = mid.position + new Vector3(0f, 0f, 1f);
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        midPos2 = mid.position;
        Assert.That(midPos1.y, Is.EqualTo(midPos2.y).Using(floatComparer), String.Format("Expected mid2.y to be {0}, but was {1}", midPos1.y, midPos2.y));
        Assert.That(midPos2.z, Is.GreaterThan(midPos1.z).Using(floatComparer), String.Format("Expected mid2.y to be greater than mid1.y"));

        hint.position = mid.position + new Vector3(0f, 0f, -1f);
        yield return(RuntimeRiggingTestFixture.YieldTwoFrames());

        midPos2 = mid.position;
        Assert.That(midPos1.y, Is.EqualTo(midPos2.y).Using(floatComparer), String.Format("Expected mid2.y to be {0}, but was {1}", midPos1.y, midPos2.y));
        Assert.That(midPos2.z, Is.LessThan(midPos1.z).Using(floatComparer), String.Format("Expected mid2.y to be greater than mid1.y"));
    }
Beispiel #6
0
    public IEnumerator DampedTransform_FollowsSource()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        var constrainedTransform = constraint.data.constrainedObject;
        var sourceTransform      = constraint.data.sourceObject;

        Vector3 constrainedPos1 = constrainedTransform.position;

        Vector3 offset = new Vector3(0f, 0.5f, 0f);

        sourceTransform.localPosition += offset;

        Vector3 constrainedPos2 = constrainedPos1 + offset;

        const int kMaxIter = 15;

        List <Vector3> positions = new List <Vector3>(kMaxIter);

        for (int i = 0; i < kMaxIter; ++i)
        {
            yield return(null);

            positions.Add(constrainedTransform.position);
        }

        float[] distances = positions.Select((pos) => (pos - constrainedPos1).magnitude).ToArray();

        var floatComparer = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        for (int i = 0; i < kMaxIter - 1; ++i)
        {
            Vector3 dir = positions[i + 1] - positions[i];

            Assert.That(Vector3.Angle(dir, offset), Is.EqualTo(0f).Using(floatComparer), String.Format("Offset direction mismatch at index {0}", i));
            Assert.That(distances[i + 1], Is.GreaterThanOrEqualTo(distances[i]).Using(floatComparer));
            Assert.That(distances[i], Is.LessThanOrEqualTo(0.5f).Using(floatComparer));
        }
    }
Beispiel #7
0
    public IEnumerator MultiAimConstraint_ApplyWeight()
    {
        var data       = SetupConstraintRig();
        var constraint = data.constraint;

        var constrainedObject = constraint.data.constrainedObject;
        var sources           = constraint.data.sourceObjects;

        var floatComparer = new RuntimeRiggingTestFixture.FloatEqualityComparer(k_Epsilon);

        Assert.Zero(sources[0].weight);
        Assert.Zero(sources[1].weight);

        sources[0].transform.position += Vector3.left;
        sources.SetWeight(0, 1f);
        constraint.data.sourceObjects = sources;

        var src0Pos = sources[0].transform.position;

        var angle = 180f;

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

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

            var currAim   = constrainedObject.rotation * Vector3.forward;
            var src0Dir   = (src0Pos - constrainedObject.position).normalized;
            var angleTest = Vector3.Angle(currAim, src0Dir);

            Assert.That(angleTest, Is.LessThan(angle).Using(floatComparer), "Angle between currAim and src0Dir should be smaller than last frame since constraint weight is greater.");
            angle = angleTest;
        }
    }