public IEnumerator OverrideTransform_ApplyWeight() { var data = SetupConstraintRig(); var constraint = data.constraint; var constrainedTransform = constraint.data.constrainedObject; var sourceTransform = constraint.data.sourceObject; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); Vector3 constrainedPos1 = constrainedTransform.position; constraint.data.space = OverrideTransformData.Space.World; yield return(null); sourceTransform.position = new Vector3(0f, 0.5f, 0f); yield return(null); Vector3 constrainedPos2 = constrainedTransform.position; for (int i = 0; i <= 5; ++i) { float w = i / 5.0f; data.constraint.weight = w; yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Vector3 weightedConstrainedPos = Vector3.Lerp(constrainedPos1, constrainedPos2, w); Vector3 constrainedPos = constrainedTransform.position; Assert.That(weightedConstrainedPos, Is.EqualTo(constrainedPos).Using(positionComparer), String.Format("Expected constrainedPos.x to be {0} for a weight of {1}, but was {2}", weightedConstrainedPos, w, constrainedPos)); } }
public IEnumerator MultiPositionConstraint_ApplyWeight() { var data = SetupConstraintRig(); var constraint = data.constraint; var constrainedObject = constraint.data.constrainedObject; var sources = constraint.data.sourceObjects; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); sources[0].transform.position += Vector3.forward; sources.SetWeight(0, 1f); constraint.data.sourceObjects = sources; for (int i = 0; i <= 5; ++i) { float w = i / 5.0f; data.constraint.weight = w; yield return(null); Vector3 weightedPos = Vector3.Lerp(data.constrainedObjectRestPosition, sources[0].transform.position, w); Assert.That( constrainedObject.position, Is.EqualTo(weightedPos).Using(positionComparer), String.Format("Expected constrainedObject to be at {0} for a weight of {1}, but was {2}", weightedPos, w, constrainedObject.position) ); } }
public IEnumerator OverrideTransform_FollowsSource_PivotSpace() { var data = SetupConstraintRig(); var constraint = data.constraint; var constrainedTransform = constraint.data.constrainedObject; var sourceTransform = constraint.data.sourceObject; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); Vector3 originalPosition = constrainedTransform.position; constraint.data.space = OverrideTransformData.Space.Pivot; yield return(null); for (int i = 0; i < 5; ++i) { sourceTransform.position += new Vector3(0f, 0.1f, 0.0f); yield return(null); Vector3 sourcePosition = sourceTransform.position; Vector3 constrainedPosition = constrainedTransform.position; Vector3 expectedPosition = sourcePosition + originalPosition; Assert.That(expectedPosition, Is.EqualTo(constrainedPosition).Using(positionComparer), String.Format("Expected constrainedPosition.x to be {0}, but was {1}", expectedPosition, constrainedPosition)); } }
public IEnumerator BlendConstraint_ApplyWeight() { var data = SetupConstraintRig(); var constraint = data.constraint; var srcObjB = constraint.data.sourceObjectB; var constrainedObj = constraint.data.constrainedObject; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); var rotationComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon); // SourceB has full influence constraint.data.positionWeight = 1f; constraint.data.rotationWeight = 1f; srcObjB.rotation *= Quaternion.AngleAxis(90, Vector3.right); yield return(null); for (int i = 0; i <= 5; ++i) { float w = i / 5.0f; data.constraint.weight = w; yield return(null); var weightedPos = Vector3.Lerp(data.restPose.translation, srcObjB.position, w); var weightedRot = Quaternion.Lerp(data.restPose.rotation, srcObjB.rotation, w); Assert.That(constrainedObj.position, Is.EqualTo(weightedPos).Using(positionComparer)); Assert.That(constrainedObj.rotation, Is.EqualTo(weightedRot).Using(rotationComparer)); } }
public IEnumerator TwoBoneIKConstraint_ApplyWeight() { var data = SetupConstraintRig(); var constraint = data.constraint; var tip = constraint.data.tip; var target = constraint.data.target; Vector3 tipPos1 = tip.position; target.position += new Vector3(0f, 0.5f, 0f); yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Vector3 tipPos2 = tip.position; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); for (int i = 0; i <= 5; ++i) { float w = i / 5.0f; constraint.weight = w; yield return(null); Vector3 weightedTipPos = Vector3.Lerp(tipPos1, tipPos2, w); Vector3 tipPos = tip.position; Assert.That(tipPos, Is.EqualTo(weightedTipPos).Using(positionComparer), String.Format("Expected tip to be {0} for a weight of {1}, but was {2}", weightedTipPos, w, tipPos)); } }
public IEnumerator MultiReferentialConstraint_ApplyWeight() { var data = SetupConstraintRig(); var constraint = data.constraint; var sources = constraint.data.sourceObjects; constraint.data.driver = 1; constraint.weight = 0f; yield return(null); sources[1].position += Vector3.right; sources[1].rotation *= Quaternion.AngleAxis(-90, Vector3.up); var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); var rotationComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon); for (int i = 0; i <= 5; ++i) { float w = i / 5.0f; constraint.weight = w; yield return(null); var weightedPos = Vector3.Lerp(data.restPose.translation, sources[1].position, w); Assert.That( sources[0].position, Is.EqualTo(weightedPos).Using(positionComparer), String.Format("Expected Source0 to be at {0} for a weight of {1}, but was {2}", weightedPos, w, sources[0].position) ); Assert.That( sources[2].position, Is.EqualTo(weightedPos).Using(positionComparer), String.Format("Expected Source2 to be at {0} for a weight of {1}, but was {2}", weightedPos, w, sources[2].position) ); var weightedRot = Quaternion.Lerp(data.restPose.rotation, sources[1].rotation, w); Assert.That( sources[0].rotation, Is.EqualTo(weightedRot).Using(rotationComparer), String.Format("Expected rotations to be equal for a weight of {0}", w) ); Assert.That( sources[2].rotation, Is.EqualTo(weightedRot).Using(rotationComparer), String.Format("Expected rotations to be equal for a weight of {0}", w) ); // Since we have no animation in the stream the new rest pose // should be the last evaluated one. data.restPose.translation = sources[0].position; data.restPose.rotation = sources[0].rotation; } }
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)); }
public IEnumerator DampedTransform_ApplyWeight() { var data = SetupConstraintRig(); var constraint = data.constraint; var rigBuilder = data.rigData.rootGO.GetComponent <RigBuilder>(); var playableGraph = rigBuilder.graph; playableGraph.Stop(); // no position damping, full rotation damp constraint.data.dampPosition = 0f; constraint.data.dampRotation = 1f; data.constraint.weight = 0f; yield return(null); 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; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); for (int i = 0; i <= 5; ++i) { float w = i / 5.0f; data.constraint.weight = w; // DampedTransform has a damp factor of 40. This means it'll take 1/40 second for source to reach its target. // Evaluate with a large enough deltaTime to make sure source reaches its target. playableGraph.Evaluate(1f); yield return(null); Vector3 weightedConstrainedPos = Vector3.Lerp(constrainedPos1, constrainedPos2, w); Vector3 constrainedPos = constrainedTransform.position; Assert.That(weightedConstrainedPos, Is.EqualTo(constrainedPos).Using(positionComparer), String.Format("Expected constrainedPos to be {0} for a weight of {1}, but was {2}", weightedConstrainedPos, w, constrainedPos)); } }
public IEnumerator MultiPositionConstraint_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); // 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.constrainedObjectRestPosition).Using(positionComparer)); // Add displacement to source objects sources[0].transform.position += Vector3.right; sources[1].transform.position += Vector3.left; // src0.w = 1, src1.w = 0 sources.SetWeight(0, 1f); constraint.data.sourceObjects = sources; yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(constrainedObject.position, Is.EqualTo(sources[0].transform.position).Using(positionComparer)); // src0.w = 0, src1.w = 1 sources.SetWeight(0, 0f); sources.SetWeight(1, 1f); constraint.data.sourceObjects = sources; yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(constrainedObject.position, Is.EqualTo(sources[1].transform.position).Using(positionComparer)); // src0.w = 1, src1.w = 1 // since source object positions are mirrored, we should simply evaluate to the original rest pos. sources.SetWeight(0, 1f); constraint.data.sourceObjects = sources; yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(constrainedObject.position, Is.EqualTo(data.constrainedObjectRestPosition).Using(positionComparer)); }
public IEnumerator MultiReferentialConstraint_FollowSourceObjects() { var data = SetupConstraintRig(); var constraint = data.constraint; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); var rotationComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon); var sources = constraint.data.sourceObjects; constraint.data.driver = 0; var driver = sources[0]; driver.position += Vector3.forward; driver.rotation *= Quaternion.AngleAxis(90, Vector3.up); yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(driver.position, Is.EqualTo(sources[1].position).Using(positionComparer)); Assert.That(driver.rotation, Is.EqualTo(sources[1].rotation).Using(rotationComparer)); Assert.That(driver.position, Is.EqualTo(sources[2].position).Using(positionComparer)); Assert.That(driver.rotation, Is.EqualTo(sources[2].rotation).Using(rotationComparer)); constraint.data.driver = 1; driver = sources[1]; driver.position += Vector3.back; driver.rotation *= Quaternion.AngleAxis(-90, Vector3.up); yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(driver.position, Is.EqualTo(sources[0].position).Using(positionComparer)); Assert.That(driver.rotation, Is.EqualTo(sources[0].rotation).Using(rotationComparer)); Assert.That(driver.position, Is.EqualTo(sources[2].position).Using(positionComparer)); Assert.That(driver.rotation, Is.EqualTo(sources[2].rotation).Using(rotationComparer)); constraint.data.driver = 2; driver = sources[2]; driver.position += Vector3.up; driver.rotation *= Quaternion.AngleAxis(90, Vector3.left); yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(driver.position, Is.EqualTo(sources[0].position).Using(positionComparer)); Assert.That(driver.rotation, Is.EqualTo(sources[0].rotation).Using(rotationComparer)); Assert.That(driver.position, Is.EqualTo(sources[1].position).Using(positionComparer)); Assert.That(driver.rotation, Is.EqualTo(sources[1].rotation).Using(rotationComparer)); }
public IEnumerator MultiParentConstraint_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 rotationComprarer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon); // 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(rotationComprarer)); // Add displacement to source objects sources[0].transform.position += Vector3.right; sources[0].transform.rotation *= Quaternion.AngleAxis(-90, Vector3.up); sources[1].transform.position += Vector3.left; sources[1].transform.rotation *= Quaternion.AngleAxis(90, Vector3.up); // src0.w = 1, src1.w = 0 sources.SetWeight(0, 1f); constraint.data.sourceObjects = sources; yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(constrainedObject.position, Is.EqualTo(sources[0].transform.position).Using(positionComparer)); Assert.That(constrainedObject.rotation, Is.EqualTo(sources[0].transform.rotation).Using(rotationComprarer)); // src0.w = 0, src1.w = 1 sources.SetWeight(0, 0f); sources.SetWeight(1, 1f); constraint.data.sourceObjects = sources; yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Assert.That(constrainedObject.position, Is.EqualTo(sources[1].transform.position).Using(positionComparer)); Assert.That(constrainedObject.rotation, Is.EqualTo(sources[1].transform.rotation).Using(rotationComprarer)); }
public IEnumerator BlendConstraint_FollowsSourceObjects() { var data = SetupConstraintRig(); var constraint = data.constraint; var srcObjA = constraint.data.sourceObjectA; var srcObjB = constraint.data.sourceObjectB; var constrainedObj = constraint.data.constrainedObject; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); var rotationComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_Epsilon); // Apply rotation on sourceB srcObjB.rotation *= Quaternion.AngleAxis(90, Vector3.right); yield return(null); // SourceA has full influence constraint.data.positionWeight = 0f; constraint.data.rotationWeight = 0f; yield return(null); Assert.That(constrainedObj.position, Is.EqualTo(srcObjA.position).Using(positionComparer)); Assert.That(constrainedObj.rotation, Is.EqualTo(srcObjA.rotation).Using(rotationComparer)); // SourceB has full influence constraint.data.positionWeight = 1f; constraint.data.rotationWeight = 1f; yield return(null); Assert.That(constrainedObj.position, Is.EqualTo(srcObjB.position).Using(positionComparer)); Assert.That(constrainedObj.rotation, Is.EqualTo(srcObjB.rotation).Using(rotationComparer)); // Translation/Rotation blending between sources is disabled constraint.data.blendPosition = false; constraint.data.blendRotation = false; yield return(null); Assert.That(constrainedObj.position, Is.EqualTo(data.restPose.translation).Using(positionComparer)); Assert.That(constrainedObj.rotation, Is.EqualTo(data.restPose.rotation).Using(rotationComparer)); }
public IEnumerator ChainIKConstraint_FollowsTarget() { var data = SetupConstraintRig(); var constraint = data.constraint; var target = constraint.data.target; var tip = constraint.data.tip; var root = constraint.data.root; var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); for (int i = 0; i < 5; ++i) { target.position += new Vector3(0f, 0.1f, 0f); yield return(RuntimeRiggingTestFixture.YieldTwoFrames()); Vector3 rootToTip = (tip.position - root.position).normalized; Vector3 rootToTarget = (target.position - root.position).normalized; Assert.That(rootToTarget, Is.EqualTo(rootToTip).Using(positionComparer), String.Format("Expected rootToTip to be {0}, but was {1}", rootToTip, rootToTarget)); } }
public static void TestTransferMotionToConstraint <T>(T constraint, RigBuilder rigBuilder, AnimationClip clip, IList <Transform> targetTransforms, CompareFlags flags) where T : MonoBehaviour, IRigConstraint { Animator animator = rigBuilder.GetComponent <Animator>(); int numberOfFrames = 60; float dt = 1f / numberOfFrames; var defaultPoseClip = CreateDefaultPose(rigBuilder.gameObject); #if DEBUG_BAKE_TO_CONSTRAINT AssetDatabase.CreateAsset(clip, "Assets/bakeToConstraintBefore.anim"); clip = UnityEngine.Object.Instantiate(clip) as AnimationClip; #endif // Evaluate clip without constraint and take snapshots. var translationsBeforeBaking = new Vector3[targetTransforms.Count, numberOfFrames + 1]; var rotationsBeforeBaking = new Quaternion[targetTransforms.Count, numberOfFrames + 1]; using (var graph = new EvaluationGraph(rigBuilder.GetComponent <Animator>(), clip)) { graph.Evaluate(0f); for (int transformIndex = 0; transformIndex < targetTransforms.Count; ++transformIndex) { translationsBeforeBaking[transformIndex, 0] = targetTransforms[transformIndex].position; rotationsBeforeBaking[transformIndex, 0] = targetTransforms[transformIndex].rotation; } for (int frame = 1; frame <= numberOfFrames; ++frame) { graph.Evaluate(dt); for (int transformIndex = 0; transformIndex < targetTransforms.Count; ++transformIndex) { translationsBeforeBaking[transformIndex, frame] = targetTransforms[transformIndex].position; rotationsBeforeBaking[transformIndex, frame] = targetTransforms[transformIndex].rotation; } } } RestoreDefaultPose(animator, defaultPoseClip); // Bake and inverse solve to constraint. var bakeParameters = BakeUtils.FindBakeParameters(constraint); Assert.That(bakeParameters, Is.Not.Null); var bindings = bakeParameters.GetSourceCurveBindings(rigBuilder, constraint); AnimationMode.StartAnimationMode(); BakeUtils.BakeToConstraint(constraint, clip, defaultPoseClip, bindings, k_DefaultCurveFilterOptions); AnimationMode.StopAnimationMode(); #if DEBUG_BAKE_TO_CONSTRAINT AssetDatabase.CreateAsset(clip, "Assets/bakeToConstraintAfter.anim"); #endif RestoreDefaultPose(animator, defaultPoseClip); // Evaluate again with constraint active and take snapshots. var translationsAfterBaking = new Vector3[targetTransforms.Count, numberOfFrames + 1]; var rotationsAfterBaking = new Quaternion[targetTransforms.Count, numberOfFrames + 1]; using (var graph = new EvaluationGraph(rigBuilder, clip)) { graph.Evaluate(0f); for (int transformIndex = 0; transformIndex < targetTransforms.Count; ++transformIndex) { translationsAfterBaking[transformIndex, 0] = targetTransforms[transformIndex].position; rotationsAfterBaking[transformIndex, 0] = targetTransforms[transformIndex].rotation; } for (int frame = 1; frame <= numberOfFrames; ++frame) { graph.Evaluate(dt); for (int transformIndex = 0; transformIndex < targetTransforms.Count; ++transformIndex) { translationsAfterBaking[transformIndex, frame] = targetTransforms[transformIndex].position; rotationsAfterBaking[transformIndex, frame] = targetTransforms[transformIndex].rotation; } } } RestoreDefaultPose(animator, defaultPoseClip); if ((flags & CompareFlags.Rotation) != 0) { // Compare rotations var quaternionComparer = new RuntimeRiggingTestFixture.QuaternionEqualityComparer(k_RotationEpsilon); for (int transformIndex = 0; transformIndex < targetTransforms.Count; ++transformIndex) { for (int frame = 0; frame <= numberOfFrames; ++frame) { Assert.That(rotationsAfterBaking[transformIndex, frame], Is.EqualTo(rotationsBeforeBaking[transformIndex, frame]).Using(quaternionComparer), String.Format("Transform '{0}' rotation is set to {1} at frame {2}, but was expected to be {3}", targetTransforms[transformIndex].name, rotationsAfterBaking[transformIndex, frame].eulerAngles, frame, rotationsBeforeBaking[transformIndex, frame].eulerAngles)); } } } if ((flags & CompareFlags.Translation) != 0) { // Compare translations var positionComparer = new RuntimeRiggingTestFixture.Vector3EqualityComparer(k_Epsilon); for (int transformIndex = 0; transformIndex < targetTransforms.Count; ++transformIndex) { for (int frame = 0; frame <= numberOfFrames; ++frame) { Assert.That(translationsAfterBaking[transformIndex, frame], Is.EqualTo(translationsBeforeBaking[transformIndex, frame]).Using(positionComparer), String.Format("Transform '{0}' position is set to {1} at frame {2}, but was expected to be {3}", targetTransforms[transformIndex].name, translationsAfterBaking[transformIndex, frame], frame, translationsBeforeBaking[transformIndex, frame])); } } } }