Esempio n. 1
0
        public unsafe void Compute(CompressedTimeSpan newTime, AnimationClipResult result)
        {
            fixed(byte *structures = result.Data)
            {
                // Update factors
                for (int index = 0; index < Channels.Count; index++)
                {
                    // For now, objects are not supported, so treat everything as a blittable struct.
                    var channel = Channels.Items[index];

                    var structureStart = (float *)(structures + channel.Offset);

                    // Write a float specifying channel factor (1 if exists, 0 if doesn't exist)
                    *structureStart = channel.Factor;
                }

                if (curveEvaluatorOptimizedVector3 != null)
                {
                    curveEvaluatorOptimizedVector3.Evaluate(newTime, (IntPtr)structures);
                }

                if (curveEvaluatorOptimizedQuaternion != null)
                {
                    curveEvaluatorOptimizedQuaternion.Evaluate(newTime, (IntPtr)structures);
                }

                // Write interpolated data
                curveEvaluatorFloat.Evaluate(newTime, (IntPtr)structures);
                curveEvaluatorVector3.Evaluate(newTime, (IntPtr)structures);
                curveEvaluatorQuaternion.Evaluate(newTime, (IntPtr)structures);
            }
        }
Esempio n. 2
0
 internal void FreeIntermediateResult(AnimationClipResult result)
 {
     // Returns it to pool of available intermediate results
     lock (availableResultsPool)
     {
         result.Channels = null;
         availableResultsPool.Push(result);
     }
 }
Esempio n. 3
0
        public unsafe void AddCurveValues(CompressedTimeSpan newTime, AnimationClipResult result)
        {
            fixed(byte *structures = result.Data)
            {
                for (int index = 0; index < Channels.Count; index++)
                {
                    var channel = Channels.Items[index];

                    // For now, objects are not supported, so treat everything as a blittable struct.
                    channel.Curve.AddValue(newTime, (IntPtr)(structures + channel.Offset));
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Computes the specified animation operations.
        /// </summary>
        /// <param name="animationOperations">The animation operations to perform.</param>
        /// <param name="result">The optional result (if not null, it expects the final stack to end up with this element).</param>
        public void Compute(FastList <AnimationOperation> animationOperations, ref AnimationClipResult result)
        {
            // Clear animation stack
            animationStack.Clear();

            // Apply first operation (should be a push), directly into result (considered first item in the stack)
            var animationOperation0 = animationOperations.Items[0];

            if (animationOperation0.Type != AnimationOperationType.Push)
            {
                throw new InvalidOperationException("First operation should be a push");
            }

            // TODO: Either result is null (should have a Pop operation) or result is non null (stack end up being size 1)
            var hasResult = result != null;

            if (hasResult)
            {
                // Ensure there is enough size
                // TODO: Force result allocation to happen on user side?
                if (result.DataSize < structureSize)
                {
                    result.DataSize = structureSize;
                    result.Data     = new byte[structureSize];
                }

                result.Channels = channels;
            }
            else
            {
                result = AllocateIntermediateResult();
            }

            animationOperation0.Evaluator.Compute((CompressedTimeSpan)animationOperation0.Time, result);

            animationStack.Push(result);

            for (int index = 1; index < animationOperations.Count; index++)
            {
                var animationOperation = animationOperations.Items[index];

                ApplyAnimationOperation(ref animationOperation);
            }

            if (hasResult && (animationStack.Count != 1 || animationStack.Pop() != result))
            {
                throw new InvalidOperationException("Stack should end up with result.");
            }
        }
Esempio n. 5
0
        public static unsafe void Blend(AnimationBlendOperation blendOperation, float blendFactor, AnimationClipResult sourceLeft, AnimationClipResult sourceRight, AnimationClipResult result)
        {
            fixed(byte *sourceLeftDataStart = sourceLeft.Data)
            fixed(byte *sourceRightDataStart = sourceRight.Data)
            fixed(byte *resultDataStart      = result.Data)
            {
                foreach (var channel in sourceLeft.Channels)
                {
                    int offset          = channel.Offset;
                    var sourceLeftData  = (float *)(sourceLeftDataStart + offset);
                    var sourceRightData = (float *)(sourceRightDataStart + offset);
                    var resultData      = (float *)(resultDataStart + offset);

                    float factorLeft  = *sourceLeftData++;
                    float factorRight = *sourceRightData++;

                    // Ignore this channel
                    if (factorLeft == 0.0f && factorRight == 0.0f)
                    {
                        *resultData++ = 0.0f;
                        continue;
                    }

                    // Use left value
                    if (factorLeft > 0.0f && factorRight == 0.0f)
                    {
                        *resultData++ = 1.0f;
                        Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
                        continue;
                    }

                    // Use right value
                    if (factorRight > 0.0f && factorLeft == 0.0f)
                    {
                        *resultData++ = 1.0f;
                        Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceRightData, channel.Size);
                        continue;
                    }

                    // Blending
                    *resultData++ = 1.0f;

                    switch (blendOperation)
                    {
                    case AnimationBlendOperation.LinearBlend:
                        // Perform linear blending
                        // It will blend between left (0.0) and right (1.0)
                        switch (channel.BlendType)
                        {
                        case BlendType.None:
                            Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
                            break;

                        case BlendType.Float2:
                            Vector2.Lerp(ref *(Vector2 *)sourceLeftData, ref *(Vector2 *)sourceRightData, blendFactor, out *(Vector2 *)resultData);
                            break;

                        case BlendType.Float3:
                            Vector3.Lerp(ref *(Vector3 *)sourceLeftData, ref *(Vector3 *)sourceRightData, blendFactor, out *(Vector3 *)resultData);
                            break;

                        case BlendType.Quaternion:
                            Quaternion.Slerp(ref *(Quaternion *)sourceLeftData, ref *(Quaternion *)sourceRightData, blendFactor, out *(Quaternion *)resultData);
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                        break;

                    case AnimationBlendOperation.Add:
                        // Perform additive blending
                        // It will blend between left (0.0) and left + right (1.0).
                        switch (channel.BlendType)
                        {
                        case BlendType.None:
                            Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
                            break;

                        case BlendType.Float2:
                            Vector2 rightValue2;
                            Vector2.Add(ref *(Vector2 *)sourceLeftData, ref *(Vector2 *)sourceRightData, out rightValue2);
                            Vector2.Lerp(ref *(Vector2 *)sourceLeftData, ref rightValue2, blendFactor, out *(Vector2 *)resultData);
                            break;

                        case BlendType.Float3:
                            Vector3 rightValue3;
                            Vector3.Add(ref *(Vector3 *)sourceLeftData, ref *(Vector3 *)sourceRightData, out rightValue3);
                            Vector3.Lerp(ref *(Vector3 *)sourceLeftData, ref rightValue3, blendFactor, out *(Vector3 *)resultData);
                            break;

                        case BlendType.Quaternion:
                            Quaternion rightValueQ;
                            Quaternion.Multiply(ref *(Quaternion *)sourceLeftData, ref *(Quaternion *)sourceRightData, out rightValueQ);
                            Quaternion.Normalize(ref rightValueQ, out rightValueQ);
                            Quaternion.Slerp(ref *(Quaternion *)sourceLeftData, ref rightValueQ, blendFactor, out *(Quaternion *)resultData);
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                        break;

                    case AnimationBlendOperation.Subtract:
                        // Perform subtractive blending
                        // It will blend between left (0.0) and left - right (1.0).
                        switch (channel.BlendType)
                        {
                        case BlendType.None:
                            Utilities.CopyMemory((IntPtr)resultData, (IntPtr)sourceLeftData, channel.Size);
                            break;

                        case BlendType.Float2:
                            Vector2 rightValue2;
                            Vector2.Subtract(ref *(Vector2 *)sourceLeftData, ref *(Vector2 *)sourceRightData, out rightValue2);
                            Vector2.Lerp(ref *(Vector2 *)sourceLeftData, ref rightValue2, blendFactor, out *(Vector2 *)resultData);
                            break;

                        case BlendType.Float3:
                            Vector3 rightValue3;
                            Vector3.Subtract(ref *(Vector3 *)sourceLeftData, ref *(Vector3 *)sourceRightData, out rightValue3);
                            Vector3.Lerp(ref *(Vector3 *)sourceLeftData, ref rightValue3, blendFactor, out *(Vector3 *)resultData);
                            break;

                        case BlendType.Quaternion:
                            Quaternion rightValueQ;
                            // blend between left (0.0) and left * conjugate(right) (1.0)
                            Quaternion.Invert(ref *(Quaternion *)sourceRightData, out rightValueQ);
                            Quaternion.Multiply(ref rightValueQ, ref *(Quaternion *)sourceLeftData, out rightValueQ);
                            Quaternion.Normalize(ref rightValueQ, out rightValueQ);
                            //throw new NotImplementedException();
                            Quaternion.Slerp(ref *(Quaternion *)sourceLeftData, ref rightValueQ, blendFactor, out *(Quaternion *)resultData);
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("blendOperation");
                    }
                }
            }
        }