/// <inheritdoc /> public override DampedTransformJob Create(Animator animator, ref T data, Component component) { var job = new DampedTransformJob(); job.driven = ReadWriteTransformHandle.Bind(animator, data.constrainedObject); job.source = ReadOnlyTransformHandle.Bind(animator, data.sourceObject); var drivenTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); var sourceTx = new AffineTransform(data.sourceObject.position, data.sourceObject.rotation); job.localBindTx = sourceTx.InverseMul(drivenTx); job.prevDrivenTx = drivenTx; job.dampPosition = FloatProperty.Bind(animator, component, data.dampPositionFloatProperty); job.dampRotation = FloatProperty.Bind(animator, component, data.dampRotationFloatProperty); if (data.maintainAim && AnimationRuntimeUtils.SqrDistance(data.constrainedObject.position, data.sourceObject.position) > 0f) { job.aimBindAxis = Quaternion.Inverse(data.constrainedObject.rotation) * (sourceTx.translation - drivenTx.translation).normalized; } else { job.aimBindAxis = Vector3.zero; } return(job); }
/// <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); float streamDt = Mathf.Abs(stream.deltaTime); driven.GetGlobalTR(stream, out Vector3 drivenPos, out Quaternion drivenRot); if (w > 0f && streamDt > 0f) { source.GetGlobalTR(stream, out Vector3 sourcePos, out Quaternion sourceRot); var sourceTx = new AffineTransform(sourcePos, sourceRot); var targetTx = sourceTx * localBindTx; targetTx.translation = Vector3.Lerp(drivenPos, targetTx.translation, w); targetTx.rotation = Quaternion.Lerp(drivenRot, targetTx.rotation, w); var dampPosW = AnimationRuntimeUtils.Square(1f - dampPosition.Get(stream)); var dampRotW = AnimationRuntimeUtils.Square(1f - dampRotation.Get(stream)); bool doAimAjustements = Vector3.Dot(aimBindAxis, aimBindAxis) > 0f; while (streamDt > 0f) { float factoredDt = k_DampFactor * Mathf.Min(k_FixedDt, streamDt); prevDrivenTx.translation += (targetTx.translation - prevDrivenTx.translation) * dampPosW * factoredDt; prevDrivenTx.rotation *= Quaternion.Lerp( Quaternion.identity, Quaternion.Inverse(prevDrivenTx.rotation) * targetTx.rotation, dampRotW * factoredDt ); if (doAimAjustements) { var fromDir = prevDrivenTx.rotation * aimBindAxis; var toDir = sourceTx.translation - prevDrivenTx.translation; prevDrivenTx.rotation = Quaternion.AngleAxis(Vector3.Angle(fromDir, toDir), Vector3.Cross(fromDir, toDir).normalized) * prevDrivenTx.rotation; } streamDt -= k_FixedDt; } driven.SetGlobalTR(stream, prevDrivenTx.translation, prevDrivenTx.rotation); } else { prevDrivenTx.Set(drivenPos, drivenRot); AnimationRuntimeUtils.PassThrough(stream, driven); } }
public void MultiPositionConstraint_TransferMotionToConstraint( [Values(false, true)] bool applySourceOffsets, [Values(false, true)] bool applyDrivenOffset, [Values(AxesMask.X, AxesMask.XY, AxesMask.XYZ)] AxesMask axesMask) { var data = MultiPositionConstraintTests.SetupConstraintRig(); var constraint = data.constraint; var rootGO = data.rigData.rootGO; var rigBuilder = rootGO.GetComponent <RigBuilder>(); var constrainedObject = constraint.data.constrainedObject; var sources = constraint.data.sourceObjects; var vectorMask = new Vector3( System.Convert.ToSingle(RuntimeRiggingEditorTestFixture.TestXAxis(axesMask)), System.Convert.ToSingle(RuntimeRiggingEditorTestFixture.TestYAxis(axesMask)), System.Convert.ToSingle(RuntimeRiggingEditorTestFixture.TestZAxis(axesMask)) ); constraint.data.maintainOffset = applySourceOffsets; constraint.data.offset = applyDrivenOffset ? AnimationRuntimeUtils.Select(Vector3.zero, new Vector3(1f, 2f, 3f), vectorMask) : Vector3.zero; constraint.data.constrainedXAxis = RuntimeRiggingEditorTestFixture.TestXAxis(axesMask); constraint.data.constrainedYAxis = RuntimeRiggingEditorTestFixture.TestYAxis(axesMask); constraint.data.constrainedZAxis = RuntimeRiggingEditorTestFixture.TestZAxis(axesMask); var src0 = sources[0].transform; var src1 = sources[1].transform; src0.transform.position += Vector3.right; src1.transform.position += Vector3.up; var clip = new AnimationClip(); var constraintPath = AnimationUtility.CalculateTransformPath(constraint.transform, rootGO.transform); var constrainedObjectPath = AnimationUtility.CalculateTransformPath(constraint.data.constrainedObject, rootGO.transform); var weight0Attribute = ((IMultiPositionConstraintData)constraint.data).sourceObjectsProperty + ".m_Item0.weight"; var weight1Attribute = ((IMultiPositionConstraintData)constraint.data).sourceObjectsProperty + ".m_Item1.weight"; AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(constraintPath, typeof(MultiPositionConstraint), weight0Attribute), AnimationCurve.Constant(0f, 1f, 0.5f)); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(constraintPath, typeof(MultiPositionConstraint), weight1Attribute), AnimationCurve.Constant(0f, 1f, 0.5f)); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(constrainedObjectPath, typeof(Transform), "m_LocalPosition.x"), AnimationCurve.Linear(0f, -0.5f, 1f, 0.5f)); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(constrainedObjectPath, typeof(Transform), "m_LocalPosition.y"), AnimationCurve.Linear(0f, -1.5f, 1f, 1.5f)); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(constrainedObjectPath, typeof(Transform), "m_LocalPosition.z"), AnimationCurve.Linear(0f, -2.5f, 1f, 2.5f)); RuntimeRiggingEditorTestFixture.TestTransferMotionToConstraint(constraint, rigBuilder, clip, new Transform[] { constrainedObject }, CompareFlags.TR); }
public void ProcessAnimation(AnimationStream stream) { float w = jobWeight.Get(stream); if (w > 0f) { AnimationRuntimeUtils.SolveTwoBoneIK( stream, root, mid, tip, target, hint, targetPositionWeight.Get(stream) * w, targetRotationWeight.Get(stream) * w, hintWeight.Get(stream) * w, targetOffset ); } else { AnimationRuntimeUtils.PassThrough(stream, root); AnimationRuntimeUtils.PassThrough(stream, mid); AnimationRuntimeUtils.PassThrough(stream, tip); } }
/// <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) { if (blendPosition.Get(stream)) { Vector3 posBlend = Vector3.Lerp( sourceA.GetPosition(stream) + sourceAOffset.translation, sourceB.GetPosition(stream) + sourceBOffset.translation, positionWeight.Get(stream) ); driven.SetPosition(stream, Vector3.Lerp(driven.GetPosition(stream), posBlend, w)); } else { driven.SetLocalPosition(stream, driven.GetLocalPosition(stream)); } if (blendRotation.Get(stream)) { Quaternion rotBlend = Quaternion.Lerp( sourceA.GetRotation(stream) * sourceAOffset.rotation, sourceB.GetRotation(stream) * sourceBOffset.rotation, rotationWeight.Get(stream) ); driven.SetRotation(stream, Quaternion.Lerp(driven.GetRotation(stream), rotBlend, w)); } else { driven.SetLocalRotation(stream, driven.GetLocalRotation(stream)); } } else { AnimationRuntimeUtils.PassThrough(stream, driven); } }
public void ProcessAnimation(AnimationStream stream) { float w = jobWeight.Get(stream); var sliderPos = Slider.GetLocalPosition(stream); var t = Mathf.Clamp01(sliderPos.y); Slider.SetLocalPosition(stream, new Vector3(0, t, 0)); if (w > 0f) { var rootRot = Root.GetRotation(stream); var midRot = Mid.GetRotation(stream); var tipRot = Tip.GetRotation(stream); var rootRotFK = Quaternion.Lerp(rootRot, FK_Root.GetRotation(stream), w); var midRotFK = Quaternion.Lerp(midRot, FK_Mid.GetRotation(stream), w); var tipRotFK = tipRot; AnimationRuntimeUtils.SolveTwoBoneIK( stream, Root, Mid, Tip, IK_Target, IK_Hint, posWeight: 1f * w, rotWeight: 0 * w, hintWeight: 1f * w, limbLengths: LinkLengths, targetOffset: AffineTransform.identity ); var rootRotIK = Root.GetRotation(stream); var midRotIK = Mid.GetRotation(stream); var tipRotIK = Tip.GetRotation(stream); Root.SetRotation(stream, Quaternion.Lerp(rootRotFK, rootRotIK, t)); Mid.SetRotation(stream, Quaternion.Lerp(midRotFK, midRotIK, t)); Tip.SetRotation(stream, Quaternion.Lerp(tipRotFK, tipRotIK, t)); } }
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); } }