예제 #1
0
        /// <summary>
        /// Filters the animation to the specified sub-trees given by <see cref="roots"/>.
        /// </summary>
        /// <param name="nodes">The node hierarchy.</param>
        /// <param name="roots">The node roots of sub-trees that should be active (others will be filtered out).</param>
        public void FilterNodes(ModelNodeDefinition[] nodes, params string[] roots)
        {
            // Initialize list of factors (matching nodes list)
            var nodeFactors = new float[nodes.Length];

            for (int index = 0; index < nodes.Length; index++)
            {
                var node = nodes[index];
                if (roots.Contains(node.Name) ||
                    (node.ParentIndex != -1 && nodeFactors[node.ParentIndex] == 1.0f))
                {
                    nodeFactors[index] = 1.0f;
                }
            }

            //Make sure Evaluator is populated
            //TODO this is not optimal, but since evaluators are being pooled there is no other safe way
            if (Evaluator == null)
            {
                Evaluator = AnimationComponent.Blender.CreateEvaluator(Clip);
            }

            // Update animation channel factors
            var blenderChannels = Evaluator.BlenderChannels;
            var channels        = Evaluator.Channels.Items;

            for (int index = 0; index < blenderChannels.Count; index++)
            {
                var blenderChannel = blenderChannels[index];

                // Find node index
                var nodeName  = MeshAnimationUpdater.GetNodeName(blenderChannel.PropertyName);
                var nodeIndex = nodes.IndexOf(x => x.Name == nodeName);

                if (nodeIndex != -1)
                {
                    // Update factor
                    channels[index].Factor *= nodeFactors[nodeIndex];
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Creates a new animation pop operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <param name="time">The time.</param>
 /// <returns></returns>
 public static AnimationOperation NewPop(AnimationClipEvaluator evaluator, TimeSpan time)
 {
     return new AnimationOperation { Type = AnimationOperationType.Pop, Evaluator = evaluator, Time = time };
 }
예제 #3
0
 /// <summary>
 /// Creates a new animation push operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <returns></returns>
 public static AnimationOperation NewPush(AnimationClipEvaluator evaluator)
 {
     return new AnimationOperation { Type = AnimationOperationType.Push, Evaluator = evaluator, Time = TimeSpan.Zero };
 }
예제 #4
0
        public AnimationClipEvaluator CreateEvaluator(AnimationClip clip)
        {
            // Check if this clip has already been used
            if (clips.Add(clip))
            {
                // If new clip, let's scan its channel to add new ones.
                foreach (var curve in clip.Channels)
                {
                    Channel channel;
                    if (channelsByName.TryGetValue(curve.Key, out channel))
                    {
                        // TODO: Check if channel matches
                    }
                    else
                    {
                        // New channel, add it to every evaluator

                        // Find blend type
                        var blendType   = BlendType.None;
                        var elementType = curve.Value.ElementType;

                        if (elementType == typeof(Quaternion))
                        {
                            blendType = BlendType.Quaternion;
                        }
                        else if (elementType == typeof(float))
                        {
                            blendType = BlendType.Float1;
                        }
                        else if (elementType == typeof(Vector2))
                        {
                            blendType = BlendType.Float2;
                        }
                        else if (elementType == typeof(Vector3))
                        {
                            blendType = BlendType.Float3;
                        }
                        else if (elementType == typeof(Vector4))
                        {
                            blendType = BlendType.Float4;
                        }

                        // Create channel structure
                        channel.BlendType    = blendType;
                        channel.Offset       = structureSize;
                        channel.PropertyName = curve.Key;

                        // TODO: Remove this totally hardcoded property name parsing!
                        channel.NodeName = curve.Value.NodeName;
                        channel.Type     = curve.Value.Type;

                        channel.Size = curve.Value.ElementSize;

                        // Add channel
                        channelsByName.Add(channel.PropertyName, channel);
                        channels.Add(channel);

                        // Update new structure size
                        // We also reserve space for a float that will specify channel existence and factor in case of subtree blending
                        structureSize += sizeof(float) + channel.Size;

                        // Add new channel update info to every evaluator
                        // TODO: Maybe it's better lazily done? (avoid need to store list of all evaluators)
                        foreach (var currentEvaluator in evaluators)
                        {
                            currentEvaluator.AddChannel(ref channel);
                        }
                    }
                }
            }

            // Update results to fit the new data size
            lock (availableResultsPool)
            {
                foreach (var result in availableResultsPool)
                {
                    if (result.DataSize < structureSize)
                    {
                        result.DataSize = structureSize;
                        result.Data     = new byte[structureSize];
                    }
                }
            }

            // Create evaluator and store it in list of instantiated evaluators
            AnimationClipEvaluator evaluator;

            lock (evaluatorPool)
            {
                if (evaluatorPool.Count > 0)
                {
                    evaluator = evaluatorPool.Pop();
                }
                else
                {
                    evaluator = new AnimationClipEvaluator();
                }
            }

            evaluator.Initialize(clip, channels);
            evaluators.Add(evaluator);

            return(evaluator);
        }
예제 #5
0
        /// <summary>
        /// Filters the animation to the specified sub-trees given by <see cref="roots"/>.
        /// </summary>
        /// <param name="nodes">The node hierarchy.</param>
        /// <param name="roots">The node roots of sub-trees that should be active (others will be filtered out).</param>
        public void FilterNodes(ModelNodeDefinition[] nodes, params string[] roots)
        {
            // Initialize list of factors (matching nodes list)
            var nodeFactors = new float[nodes.Length];
            for (int index = 0; index < nodes.Length; index++)
            {
                var node = nodes[index];
                if (roots.Contains(node.Name)
                    || (node.ParentIndex != -1 && nodeFactors[node.ParentIndex] == 1.0f))
                {
                    nodeFactors[index] = 1.0f;
                }
            }

            //Make sure Evaluator is populated
            //TODO this is not optimal, but since evaluators are being pooled there is no other safe way
            if (Evaluator == null)
            {
                Evaluator = AnimationComponent.Blender.CreateEvaluator(Clip);
            }

            // Update animation channel factors
            var blenderChannels = Evaluator.BlenderChannels;
            var channels = Evaluator.Channels.Items;
            for (int index = 0; index < blenderChannels.Count; index++)
            {
                var blenderChannel = blenderChannels[index];

                // Find node index
                var nodeName = MeshAnimationUpdater.GetNodeName(blenderChannel.PropertyName);
                var nodeIndex = nodes.IndexOf(x => x.Name == nodeName);

                if (nodeIndex != -1)
                {
                    // Update factor
                    channels[index].Factor *= nodeFactors[nodeIndex];
                }
            }
        }
예제 #6
0
        public AnimationClipEvaluator CreateEvaluator(AnimationClip clip)
        {
            // Check if this clip has already been used
            if (clips.Add(clip))
            {
                // If new clip, let's scan its channel to add new ones.
                foreach (var curve in clip.Channels)
                {
                    Channel channel;
                    if (channelsByName.TryGetValue(curve.Key, out channel))
                    {
                        // TODO: Check if channel matches
                    }
                    else
                    {
                        // New channel, add it to every evaluator

                        // Find blend type
                        var blendType = BlendType.None;
                        var elementType = curve.Value.ElementType;

                        if (elementType == typeof(Quaternion))
                        {
                            blendType = BlendType.Quaternion;
                        }
                        else if (elementType == typeof(float))
                        {
                            blendType = BlendType.Float1;
                        }
                        else if (elementType == typeof(Vector2))
                        {
                            blendType = BlendType.Float2;
                        }
                        else if (elementType == typeof(Vector3))
                        {
                            blendType = BlendType.Float3;
                        }
                        else if (elementType == typeof(Vector4))
                        {
                            blendType = BlendType.Float4;
                        }

                        // Create channel structure
                        channel.BlendType = blendType;
                        channel.Offset = structureSize;
                        channel.PropertyName = curve.Key;

                        // TODO: Remove this totally hardcoded property name parsing!
                        channel.NodeName = curve.Value.NodeName;
                        channel.Type = curve.Value.Type;

                        channel.Size = curve.Value.ElementSize;

                        // Add channel
                        channelsByName.Add(channel.PropertyName, channel);
                        channels.Add(channel);

                        // Update new structure size
                        // We also reserve space for a float that will specify channel existence and factor in case of subtree blending
                        structureSize += sizeof(float) + channel.Size;

                        // Add new channel update info to every evaluator
                        // TODO: Maybe it's better lazily done? (avoid need to store list of all evaluators)
                        foreach (var currentEvaluator in evaluators)
                        {
                            currentEvaluator.AddChannel(ref channel);
                        }
                    }
                }
            }

            // Update results to fit the new data size
            lock (availableResultsPool)
            {
                foreach (var result in availableResultsPool)
                {
                    if (result.DataSize < structureSize)
                    {
                        result.DataSize = structureSize;
                        result.Data = new byte[structureSize];
                    }
                }
            }

            // Create evaluator and store it in list of instantiated evaluators
            AnimationClipEvaluator evaluator;
            lock (evaluatorPool)
            {
                if (evaluatorPool.Count > 0)
                {
                    evaluator = evaluatorPool.Pop();
                }
                else
                {
                    evaluator = new AnimationClipEvaluator();
                }
            }
            
            evaluator.Initialize(clip, channels);
            evaluators.Add(evaluator);

            return evaluator;
        }
예제 #7
0
 public void ReleaseEvaluator(AnimationClipEvaluator evaluator)
 {
     lock (evaluatorPool)
     {
         evaluators.Remove(evaluator);
         evaluator.Cleanup();
         evaluatorPool.Push(evaluator);
     }
 }
예제 #8
0
 /// <summary>
 /// Creates a new animation pop operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <param name="time">The time.</param>
 /// <returns></returns>
 public static AnimationOperation NewPop(AnimationClipEvaluator evaluator, TimeSpan time)
 {
     return(new AnimationOperation {
         Type = AnimationOperationType.Pop, Evaluator = evaluator, Time = time
     });
 }
예제 #9
0
 /// <summary>
 /// Creates a new animation push operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <returns></returns>
 public static AnimationOperation NewPush(AnimationClipEvaluator evaluator)
 {
     return(new AnimationOperation {
         Type = AnimationOperationType.Push, Evaluator = evaluator, Time = TimeSpan.Zero
     });
 }