Exemple #1
0
        public override MultiRotationConstraintJob Create(Animator animator, ref T data)
        {
            var job          = new MultiRotationConstraintJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.driven          = TransformHandle.Bind(animator, data.constrainedObject);
            job.drivenParent    = TransformHandle.Bind(animator, data.constrainedObject.parent);
            job.drivenOffsetIdx = cacheBuilder.Add(data.offset);

            var src        = data.sourceObjects;
            var srcWeights = data.sourceWeights;

            job.sources              = new NativeArray <TransformHandle>(src.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.sourceOffsets        = new NativeArray <Quaternion>(src.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.sourceWeightStartIdx = cacheBuilder.AllocateChunk(srcWeights.Length);

            Quaternion drivenRot = 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]);
                job.sourceOffsets[i] = data.maintainOffset ?
                                       (Quaternion.Inverse(src[i].rotation) * drivenRot) : Quaternion.identity;
            }

            job.axesMask = new Vector3(
                System.Convert.ToSingle(data.constrainedXAxis),
                System.Convert.ToSingle(data.constrainedYAxis),
                System.Convert.ToSingle(data.constrainedZAxis)
                );
            job.cache = cacheBuilder.Build();

            return(job);
        }
Exemple #2
0
        public override TwoBoneIKConstraintJob Create(Animator animator, ref T data)
        {
            var job          = new TwoBoneIKConstraintJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.root   = TransformHandle.Bind(animator, data.root);
            job.mid    = TransformHandle.Bind(animator, data.mid);
            job.tip    = TransformHandle.Bind(animator, data.tip);
            job.target = TransformHandle.Bind(animator, data.target);

            if (data.hint != null)
            {
                job.hint = TransformHandle.Bind(animator, data.hint);
            }

            job.targetOffset = AffineTransform.identity;
            if (data.maintainTargetPositionOffset)
            {
                job.targetOffset.translation = data.tip.position - data.target.position;
            }
            if (data.maintainTargetRotationOffset)
            {
                job.targetOffset.rotation = Quaternion.Inverse(data.target.rotation) * data.tip.rotation;
            }

            job.linkLengths[0] = Vector3.Distance(data.root.position, data.mid.position);
            job.linkLengths[1] = Vector3.Distance(data.mid.position, data.tip.position);

            job.targetPositionWeightIdx = cacheBuilder.Add(data.targetPositionWeight);
            job.targetRotationWeightIdx = cacheBuilder.Add(data.targetRotationWeight);
            job.hintWeightIdx           = cacheBuilder.Add(data.hintWeight);
            job.cache = cacheBuilder.Build();

            return(job);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        public override BlendConstraintJob Create(Animator animator, ref T data)
        {
            var job          = new BlendConstraintJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.driven     = TransformHandle.Bind(animator, data.constrainedObject);
            job.sourceA    = TransformHandle.Bind(animator, data.sourceA);
            job.sourceB    = TransformHandle.Bind(animator, data.sourceB);
            job.optionsIdx = cacheBuilder.Add(BlendConstraintJob.PackFlags(data.blendPosition, data.blendRotation));

            job.sourceAOffset = job.sourceBOffset = AffineTransform.identity;
            if (data.maintainPositionOffsets)
            {
                var drivenPos = data.constrainedObject.position;
                job.sourceAOffset.translation = drivenPos - data.sourceA.position;
                job.sourceBOffset.translation = drivenPos - data.sourceB.position;
            }

            if (data.maintainRotationOffsets)
            {
                var drivenRot = data.constrainedObject.rotation;
                job.sourceAOffset.rotation = Quaternion.Inverse(data.sourceA.rotation) * drivenRot;
                job.sourceBOffset.rotation = Quaternion.Inverse(data.sourceB.rotation) * drivenRot;
            }

            job.positionWeightIdx = cacheBuilder.Add(data.positionWeight);
            job.rotationWeightIdx = cacheBuilder.Add(data.rotationWeight);
            job.cache             = cacheBuilder.Build();

            return(job);
        }
        public override OverrideTransformJob Create(Animator animator, ref T data)
        {
            var job          = new OverrideTransformJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.driven = TransformHandle.Bind(animator, data.constrainedObject);

            if (data.source != 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 = TransformHandle.Bind(animator, data.source);
                var sourceLocalTx = new AffineTransform(data.source.localPosition, data.source.localRotation);
                job.sourceInvLocalBindTx = sourceLocalTx.Inverse();

                var sourceWorldTx = new AffineTransform(data.source.position, data.source.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.positionIdx       = cacheBuilder.Add(data.position);
            job.rotationIdx       = cacheBuilder.Add(data.rotation);
            job.positionWeightIdx = cacheBuilder.Add(data.positionWeight);
            job.rotationWeightIdx = cacheBuilder.Add(data.rotationWeight);
            job.cache             = cacheBuilder.Build();

            return(job);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        public override ChainIKConstraintJob Create(Animator animator, ref T data)
        {
            List <Transform> chain = new List <Transform>();
            Transform        tmp   = data.tip;

            while (tmp != data.root)
            {
                chain.Add(tmp);
                tmp = tmp.parent;
            }
            chain.Add(data.root);
            chain.Reverse();

            var job = new ChainIKConstraintJob();

            job.chain         = new NativeArray <TransformHandle>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.linkLengths   = new NativeArray <float>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.linkPositions = new NativeArray <Vector3>(chain.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.maxReach      = 0f;

            int tipIndex = chain.Count - 1;

            for (int i = 0; i < chain.Count; ++i)
            {
                job.chain[i]       = TransformHandle.Bind(animator, chain[i]);
                job.linkLengths[i] = (i != tipIndex) ? Vector3.Distance(chain[i].position, chain[i + 1].position) : 0f;
                job.maxReach      += job.linkLengths[i];
            }

            job.target       = TransformHandle.Bind(animator, data.target);
            job.targetOffset = AffineTransform.identity;
            if (data.maintainTargetPositionOffset)
            {
                job.targetOffset.translation = data.tip.position - data.target.position;
            }
            if (data.maintainTargetRotationOffset)
            {
                job.targetOffset.rotation = Quaternion.Inverse(data.target.rotation) * data.tip.rotation;
            }

            var cacheBuilder = new AnimationJobCacheBuilder();

            job.chainRotationWeightIdx = cacheBuilder.Add(data.chainRotationWeight);
            job.tipRotationWeightIdx   = cacheBuilder.Add(data.tipRotationWeight);
            job.maxIterationsIdx       = cacheBuilder.Add(data.maxIterations);
            job.toleranceIdx           = cacheBuilder.Add(data.tolerance);
            job.cache = cacheBuilder.Build();

            return(job);
        }
Exemple #8
0
        public static TransformHandle Bind(Animator animator, Transform transform)
        {
            TransformHandle handle = new TransformHandle();

            if (transform == null)
            {
                return(handle);
            }

            handle.m_InStream = (byte)(transform.IsChildOf(animator.transform) ? 1 : 0);
            if (handle.m_InStream == 1)
            {
                handle.m_StreamHandle = animator.BindStreamTransform(transform);
            }
            else
            {
                handle.m_SceneHandle = animator.BindSceneTransform(transform);
            }

            return(handle);
        }
        public override MultiReferentialConstraintJob Create(Animator animator, ref T data)
        {
            var job          = new MultiReferentialConstraintJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.driverIdx = cacheBuilder.Add(data.driver);

            var sources = data.sourceObjects;

            job.sources      = new NativeArray <TransformHandle>(sources.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.sourceBindTx = new NativeArray <AffineTransform>(sources.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.offsetTx     = new NativeArray <AffineTransform>(sources.Length - 1, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

            for (int i = 0; i < sources.Length; ++i)
            {
                job.sources[i]      = TransformHandle.Bind(animator, sources[i].transform);
                job.sourceBindTx[i] = new AffineTransform(sources[i].position, sources[i].rotation);
            }
            job.cache = cacheBuilder.Build();
            job.UpdateOffsets();

            return(job);
        }
Exemple #10
0
        public override TwistCorrectionJob Create(Animator animator, ref T data)
        {
            var job          = new TwistCorrectionJob();
            var cacheBuilder = new AnimationJobCacheBuilder();

            job.source = TransformHandle.Bind(animator, data.source);
            job.sourceInverseBindRotation = Quaternion.Inverse(data.source.localRotation);
            job.axisMask = data.twistAxis;

            var twistNodes       = data.twistNodes;
            var twistNodeWeights = data.twistNodeWeights;

            job.twistNodes          = new NativeArray <TransformHandle>(twistNodes.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            job.twistWeightStartIdx = cacheBuilder.AllocateChunk(twistNodes.Length);

            for (int i = 0; i < twistNodes.Length; ++i)
            {
                job.twistNodes[i] = TransformHandle.Bind(animator, twistNodes[i]);
                cacheBuilder.SetValue(job.twistWeightStartIdx, i, twistNodeWeights[i]);
            }
            job.cache = cacheBuilder.Build();

            return(job);
        }
 public static void PassThrough(AnimationStream stream, TransformHandle handle)
 {
     handle.SetLocalPosition(stream, handle.GetLocalPosition(stream));
     handle.SetLocalRotation(stream, handle.GetLocalRotation(stream));
     handle.SetLocalScale(stream, handle.GetLocalScale(stream));
 }
        public static void SolveTwoBoneIK(
            AnimationStream stream,
            TransformHandle root,
            TransformHandle mid,
            TransformHandle tip,
            TransformHandle target,
            TransformHandle hint,
            float posWeight,
            float rotWeight,
            float hintWeight,
            Vector2 limbLengths,
            AffineTransform targetOffset
            )
        {
            Vector3    aPosition = root.GetPosition(stream);
            Vector3    bPosition = mid.GetPosition(stream);
            Vector3    cPosition = tip.GetPosition(stream);
            Vector3    tPosition = Vector3.Lerp(cPosition, target.GetPosition(stream) + targetOffset.translation, posWeight);
            Quaternion tRotation = Quaternion.Lerp(tip.GetRotation(stream), target.GetRotation(stream) * targetOffset.rotation, rotWeight);
            bool       hasHint   = hint.IsValid(stream) && hintWeight > 0f;

            Vector3 ab = bPosition - aPosition;
            Vector3 bc = cPosition - bPosition;
            Vector3 ac = cPosition - aPosition;
            Vector3 at = tPosition - aPosition;

            float oldAbcAngle = TriangleAngle(ac.magnitude, limbLengths[0], limbLengths[1]);
            float newAbcAngle = TriangleAngle(at.magnitude, limbLengths[0], limbLengths[1]);

            // Bend normal strategy is to take whatever has been provided in the animation
            // stream to minimize configuration changes, however if this is collinear
            // try computing a bend normal given the desired target position.
            // If this also fails, try resolving axis using hint if provided.
            Vector3 axis = Vector3.Cross(ab, bc);

            if (axis.sqrMagnitude < k_SqrEpsilon)
            {
                axis = Vector3.Cross(at, bc);
                if (axis.sqrMagnitude < k_SqrEpsilon)
                {
                    axis = hasHint ? Vector3.Cross(hint.GetPosition(stream) - aPosition, bc) : Vector3.up;
                }
            }
            axis = Vector3.Normalize(axis);

            float      a      = 0.5f * (oldAbcAngle - newAbcAngle);
            float      sin    = Mathf.Sin(a);
            float      cos    = Mathf.Cos(a);
            Quaternion deltaR = new Quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos);

            mid.SetRotation(stream, deltaR * mid.GetRotation(stream));

            cPosition = tip.GetPosition(stream);
            ac        = cPosition - aPosition;
            root.SetRotation(stream, QuaternionExt.FromToRotation(ac, at) * root.GetRotation(stream));

            if (hasHint)
            {
                float acSqrMag = ac.sqrMagnitude;
                if (acSqrMag > 0f)
                {
                    bPosition = mid.GetPosition(stream);
                    cPosition = tip.GetPosition(stream);
                    ab        = bPosition - aPosition;
                    ac        = cPosition - aPosition;

                    Vector3 acNorm = ac / Mathf.Sqrt(acSqrMag);
                    Vector3 ah     = hint.GetPosition(stream) - aPosition;
                    Vector3 abProj = ab - acNorm * Vector3.Dot(ab, acNorm);
                    Vector3 ahProj = ah - acNorm * Vector3.Dot(ah, acNorm);

                    float maxReach = limbLengths[0] + limbLengths[1];
                    if (abProj.sqrMagnitude > (maxReach * maxReach * 0.001f) && ahProj.sqrMagnitude > 0f)
                    {
                        Quaternion hintR = QuaternionExt.FromToRotation(abProj, ahProj);
                        hintR.x *= hintWeight;
                        hintR.y *= hintWeight;
                        hintR.z *= hintWeight;
                        root.SetRotation(stream, hintR * root.GetRotation(stream));
                    }
                }
            }

            tip.SetRotation(stream, tRotation);
        }