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 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); } }
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); } }
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; Vector2 minMaxAngles = new Vector2(minLimit.Get(stream), maxLimit.Get(stream)); driven.GetGlobalTR(stream, out Vector3 currentWPos, out Quaternion currentWRot); Vector3 currentDir = currentWRot * aimAxis; Quaternion accumDeltaRot = QuaternionExt.zero; 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 = sourceTransform.GetPosition(stream) - currentWPos; if (toDir.sqrMagnitude < k_Epsilon) { continue; } var rotToSource = Quaternion.AngleAxis( Mathf.Clamp(Vector3.Angle(currentDir, toDir), minMaxAngles.x, minMaxAngles.y), Vector3.Cross(currentDir, toDir).normalized ); 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 * currentWRot; // Convert newRot to local space if (drivenParent.IsValid(stream)) { newRot = Quaternion.Inverse(drivenParent.GetRotation(stream)) * newRot; } Quaternion currentLRot = driven.GetLocalRotation(stream); if (Vector3.Dot(axesMask, axesMask) < 3f) { newRot = Quaternion.Euler(AnimationRuntimeUtils.Lerp(currentLRot.eulerAngles, newRot.eulerAngles, axesMask)); } var offset = drivenOffset.Get(stream); if (Vector3.Dot(offset, offset) > 0f) { newRot *= Quaternion.Euler(offset); } driven.SetLocalRotation(stream, Quaternion.Lerp(currentLRot, newRot, w)); } else { AnimationRuntimeUtils.PassThrough(stream, driven); } }