public override OverrideTransformJob Create(Animator animator, ref T data, Component component) { var job = new OverrideTransformJob(); var cacheBuilder = new AnimationJobCacheBuilder(); job.driven = ReadWriteTransformHandle.Bind(animator, data.constrainedObject); if (data.sourceObject != null) { // Cache source to possible space rotation offsets (world, local and pivot) // at bind time so we can switch dynamically between them at runtime. job.source = ReadOnlyTransformHandle.Bind(animator, data.sourceObject); var sourceLocalTx = new AffineTransform(data.sourceObject.localPosition, data.sourceObject.localRotation); job.sourceInvLocalBindTx = sourceLocalTx.Inverse(); var sourceWorldTx = new AffineTransform(data.sourceObject.position, data.sourceObject.rotation); var drivenWorldTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); job.sourceToWorldRot = sourceWorldTx.Inverse().rotation; job.sourceToPivotRot = sourceWorldTx.InverseMul(drivenWorldTx).rotation; var drivenParent = data.constrainedObject.parent; if (drivenParent != null) { var drivenParentWorldTx = new AffineTransform(drivenParent.position, drivenParent.rotation); job.sourceToLocalRot = sourceWorldTx.InverseMul(drivenParentWorldTx).rotation; } else { job.sourceToLocalRot = job.sourceToPivotRot; } } job.spaceIdx = cacheBuilder.Add(data.space); if (data.space == (int)OverrideTransformJob.Space.Pivot) { job.sourceToCurrSpaceRotIdx = cacheBuilder.Add(job.sourceToPivotRot); } else if (data.space == (int)OverrideTransformJob.Space.Local) { job.sourceToCurrSpaceRotIdx = cacheBuilder.Add(job.sourceToLocalRot); } else { job.sourceToCurrSpaceRotIdx = cacheBuilder.Add(job.sourceToWorldRot); } job.position = Vector3Property.Bind(animator, component, data.positionVector3Property); job.rotation = Vector3Property.Bind(animator, component, data.rotationVector3Property); job.positionWeight = FloatProperty.Bind(animator, component, data.positionWeightFloatProperty); job.rotationWeight = FloatProperty.Bind(animator, component, data.rotationWeightFloatProperty); job.cache = cacheBuilder.Build(); return(job); }
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); }
public override DampedTransformJob Create(Animator animator, ref T data) { var job = new DampedTransformJob(); var cacheBuilder = new AnimationJobCacheBuilder(); job.driven = TransformHandle.Bind(animator, data.constrainedObject); job.source = TransformHandle.Bind(animator, data.source); var drivenTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); var sourceTx = new AffineTransform(data.source.position, data.source.rotation); job.localBindTx = sourceTx.InverseMul(drivenTx); job.prevDrivenTx = drivenTx; job.dampPositionIdx = cacheBuilder.Add(data.dampPosition); job.dampRotationIdx = cacheBuilder.Add(data.dampRotation); if (data.maintainAim && AnimationRuntimeUtils.SqrDistance(data.constrainedObject.position, data.source.position) > 0f) { job.aimBindAxis = Quaternion.Inverse(data.constrainedObject.rotation) * (sourceTx.translation - drivenTx.translation).normalized; } else { job.aimBindAxis = Vector3.zero; } job.cache = cacheBuilder.Build(); return(job); }
public void ProcessAnimation(AnimationStream stream) { float jobWeight = stream.GetInputWeight(0); if (jobWeight > 0f) { float sumWeights = AnimationRuntimeUtils.Sum(cache, sourceWeightStartIdx, sources.Length); if (sumWeights < k_Epsilon) { return; } float weightScale = sumWeights > 1f ? 1f / sumWeights : 1f; Vector3 currentWPos = driven.GetPosition(stream); Quaternion currentWRot = driven.GetRotation(stream); var accumTx = new AffineTransform(currentWPos, currentWRot); for (int i = 0; i < sources.Length; ++i) { var normalizedWeight = cache.GetRaw(sourceWeightStartIdx, i) * weightScale; if (normalizedWeight < k_Epsilon) { continue; } var sourceTx = new AffineTransform(sources[i].GetPosition(stream), sources[i].GetRotation(stream)); sourceTx *= sourceOffsets[i]; accumTx.rotation = Quaternion.Lerp(accumTx.rotation, sourceTx.rotation, normalizedWeight); accumTx.translation += (sourceTx.translation - currentWPos) * normalizedWeight; } // Convert accumTx to local space if (drivenParent.IsValid(stream)) { var parentTx = new AffineTransform(drivenParent.GetPosition(stream), drivenParent.GetRotation(stream)); accumTx = parentTx.InverseMul(accumTx); } Vector3 currentLPos = driven.GetLocalPosition(stream); Quaternion currentLRot = driven.GetLocalRotation(stream); 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.SetLocalPosition(stream, Vector3.Lerp(currentLPos, accumTx.translation, jobWeight)); driven.SetLocalRotation(stream, Quaternion.Lerp(currentLRot, accumTx.rotation, jobWeight)); } else { AnimationRuntimeUtils.PassThrough(stream, driven); } }
public override MultiParentConstraintJob Create(Animator animator, ref T data) { var job = new MultiParentConstraintJob(); var cacheBuilder = new AnimationJobCacheBuilder(); job.driven = TransformHandle.Bind(animator, data.constrainedObject); job.drivenParent = TransformHandle.Bind(animator, data.constrainedObject.parent); var src = data.sourceObjects; var srcWeights = data.sourceWeights; job.sources = new NativeArray <TransformHandle>(src.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); job.sourceOffsets = new NativeArray <AffineTransform>(src.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); job.sourceWeightStartIdx = cacheBuilder.AllocateChunk(srcWeights.Length); var drivenTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); for (int i = 0; i < src.Length; ++i) { job.sources[i] = TransformHandle.Bind(animator, src[i]); cacheBuilder.SetValue(job.sourceWeightStartIdx, i, srcWeights[i]); var srcTx = new AffineTransform(src[i].position, src[i].rotation); var srcOffset = AffineTransform.identity; var tmp = srcTx.InverseMul(drivenTx); if (data.maintainPositionOffset) { srcOffset.translation = tmp.translation; } if (data.maintainRotationOffset) { srcOffset.rotation = tmp.rotation; } job.sourceOffsets[i] = srcOffset; } job.positionAxesMask = new Vector3( System.Convert.ToSingle(data.constrainedPositionXAxis), System.Convert.ToSingle(data.constrainedPositionYAxis), System.Convert.ToSingle(data.constrainedPositionZAxis) ); job.rotationAxesMask = new Vector3( System.Convert.ToSingle(data.constrainedRotationXAxis), System.Convert.ToSingle(data.constrainedRotationYAxis), System.Convert.ToSingle(data.constrainedRotationZAxis) ); job.cache = cacheBuilder.Build(); return(job); }
public override MultiParentConstraintJob Create(Animator animator, ref T data, Component component) { var job = new MultiParentConstraintJob(); job.driven = ReadWriteTransformHandle.Bind(animator, data.constrainedObject); job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent); WeightedTransformArray sourceObjects = data.sourceObjects; WeightedTransformArrayBinder.BindReadOnlyTransforms(animator, component, sourceObjects, out job.sourceTransforms); WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights); job.sourceOffsets = new NativeArray <AffineTransform>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); job.weightBuffer = new NativeArray <float>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); var drivenTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); for (int i = 0; i < sourceObjects.Count; ++i) { var sourceTransform = sourceObjects[i].transform; var srcTx = new AffineTransform(sourceTransform.position, sourceTransform.rotation); var srcOffset = AffineTransform.identity; var tmp = srcTx.InverseMul(drivenTx); if (data.maintainPositionOffset) { srcOffset.translation = tmp.translation; } if (data.maintainRotationOffset) { srcOffset.rotation = tmp.rotation; } job.sourceOffsets[i] = srcOffset; } job.positionAxesMask = new Vector3( System.Convert.ToSingle(data.constrainedPositionXAxis), System.Convert.ToSingle(data.constrainedPositionYAxis), System.Convert.ToSingle(data.constrainedPositionZAxis) ); job.rotationAxesMask = new Vector3( System.Convert.ToSingle(data.constrainedRotationXAxis), System.Convert.ToSingle(data.constrainedRotationYAxis), System.Convert.ToSingle(data.constrainedRotationZAxis) ); return(job); }
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); } }