/// <inheritdoc/>
 public void SetIdentity(ref AvatarExpression identity)
 {
     identity.LeftEye      = AvatarEye.Neutral;
     identity.LeftEyebrow  = AvatarEyebrow.Neutral;
     identity.Mouth        = AvatarMouth.Neutral;
     identity.RightEye     = AvatarEye.Neutral;
     identity.RightEyebrow = AvatarEyebrow.Neutral;
 }
Exemple #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AvatarPose"/> class for the given skeleton.
        /// </summary>
        /// <param name="skeleton">The skeleton.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="skeleton"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="skeleton"/> is not a valid Xbox LIVE Avatar skeleton.
        /// </exception>
        public AvatarPose(Skeleton skeleton)
        {
            if (skeleton.NumberOfBones != AvatarRenderer.BoneCount)
            {
                throw new ArgumentException("The specified skeleton is not a valid Avatar skeleton.", "skeleton");
            }

            _expressionWrapper = new DelegateAnimatableProperty <AvatarExpression>(
                () => _expression,     // Getter
                e => _expression = e); // Setter

            _skeletonPose = SkeletonPose.Create(skeleton);
        }
Exemple #3
0
        /// <summary>
        /// Updates the expression with the correct keyframes based on the current time.
        /// </summary>
        /// <param name="playingForward">
        /// If true, the animation is playing forward; otherwise, it is playing backwards
        /// </param>
        private void UpdateAvatarExpression(bool playingForward)
        {
            // Check to see if we have an expression animation
            if (ExpressionKeyframes == null || ExpressionKeyframes.Count == 0)
            {
                return;
            }

            if (playingForward)
            {
                while (currentExpressionKeyframe < ExpressionKeyframes.Count)
                {
                    // Get the current keyframe
                    AvatarExpressionKeyFrame keyframe = ExpressionKeyframes[currentExpressionKeyframe];

                    // Stop when we've read up to the current time.
                    if (keyframe.Time >= currentPosition)
                    {
                        break;
                    }

                    // Set the current expression
                    avatarExpression = keyframe.Expression;

                    // Move the current keyframe forward.
                    currentExpressionKeyframe++;
                }
            }
            else
            {
                while (currentExpressionKeyframe >= 0)
                {
                    // Get the current keyframe
                    AvatarExpressionKeyFrame keyframe = ExpressionKeyframes[currentExpressionKeyframe];

                    // Stop when we've read back to the current time.
                    if (keyframe.Time <= currentPosition)
                    {
                        break;
                    }

                    // Set the current expression
                    avatarExpression = keyframe.Expression;

                    // Move the current keyframe backwards.
                    currentExpressionKeyframe--;
                }
            }
        }
        /// <summary>
        /// Converts the input expression animation file into expression animation keyframes
        /// </summary>
        private List <AvatarExpressionKeyFrame> ProcessExpressionAnimation()
        {
            List <AvatarExpressionKeyFrame> expressionAnimationKeyFrames = new List <AvatarExpressionKeyFrame>();

            FileStream   fs = File.OpenRead(ExpressionFile);
            StreamReader sr = new StreamReader(fs);

            while (!sr.EndOfStream)
            {
                string currentLine = sr.ReadLine();

                // Skip comment lines
                if (currentLine.StartsWith("#"))
                {
                    continue;
                }

                string[] Components = currentLine.Split(',');

                // Check for the correct number of components
                if (Components.Length != 6)
                {
                    throw new InvalidContentException("Error processing facial expression file");
                }

                try
                {
                    TimeSpan         time             = TimeSpan.FromMilliseconds(Convert.ToDouble(Components[0]));
                    AvatarExpression avatarExpression = new AvatarExpression();
                    avatarExpression.LeftEye      = (AvatarEye)Convert.ToInt32(Components[1]);
                    avatarExpression.LeftEyebrow  = (AvatarEyebrow)Convert.ToInt32(Components[2]);
                    avatarExpression.Mouth        = (AvatarMouth)Convert.ToInt32(Components[3]);
                    avatarExpression.RightEye     = (AvatarEye)Convert.ToInt32(Components[4]);
                    avatarExpression.RightEyebrow = (AvatarEyebrow)Convert.ToInt32(Components[5]);

                    AvatarExpressionKeyFrame expressionKeyframe = new AvatarExpressionKeyFrame(time, avatarExpression);
                    expressionAnimationKeyFrames.Add(expressionKeyframe);
                }
                catch (Exception)
                {
                    throw new InvalidContentException("Error processing facial expression file");
                }
            }

            // Sort the animation frames
            expressionAnimationKeyFrames.Sort((frame1, frame2) => frame1.Time.CompareTo(frame2.Time));

            return(expressionAnimationKeyFrames);
        }
 /// <inheritdoc/>
 public void Interpolate(ref AvatarExpression source, ref AvatarExpression target, float parameter, ref AvatarExpression result)
 {
     result = source;
 }
 /// <inheritdoc/>
 /// <exception cref="NotSupportedException"><see cref="AvatarExpression"/>s cannot be multiplied.</exception>
 public void Multiply(ref AvatarExpression value, int factor, ref AvatarExpression result)
 {
     throw new NotSupportedException("AvatarExpressions cannot be multiplied.");
 }
 /// <inheritdoc/>
 /// <exception cref="NotSupportedException"><see cref="AvatarExpression"/>s cannot be added.</exception>
 public void Add(ref AvatarExpression value0, ref AvatarExpression value1, ref AvatarExpression result)
 {
     throw new NotSupportedException("AvatarExpressions cannot be added.");
 }
 /// <inheritdoc/>
 /// <exception cref="NotSupportedException">
 /// <see cref="AvatarExpression"/> does not have an inverse.
 /// </exception>
 public void Invert(ref AvatarExpression value, ref AvatarExpression inverse)
 {
     throw new NotSupportedException("AvatarExpression animations cannot be looped using the loop behaviors CycleOffset. Use Cycle instead.");
 }
 /// <inheritdoc/>
 public void Set(ref AvatarExpression value, IAnimatableProperty <AvatarExpression> property)
 {
     property.AnimationValue = value;
 }
 /// <summary>
 /// Constructs a new AvatarExpressionKeyFrame object.
 /// </summary>
 public AvatarExpressionKeyFrame(TimeSpan time, AvatarExpression expression)
 {
     Time       = time;
     Expression = expression;
 }
 /// <inheritdoc/>
 public void Recycle(ref AvatarExpression value)
 {
 }
 /// <inheritdoc/>
 public void Create(ref AvatarExpression reference, out AvatarExpression value)
 {
     value = new AvatarExpression();
 }
 /// <inheritdoc/>
 public void EndBlend(ref AvatarExpression value)
 {
 }
Exemple #14
0
        //--------------------------------------------------------------
        #region Avatar Expression Animation
        //--------------------------------------------------------------

        /// <summary>
        /// Converts the input expression animation file into expression animation keyframes.
        /// </summary>
        private AvatarExpressionKeyFrameAnimation ProcessExpressionAnimation(NodeContent input, ContentProcessorContext context)
        {
            if (string.IsNullOrEmpty(ExpressionFile))
            {
                return(null);
            }

            // Create a AvatarExpression key frame animation that will animate the Expression
            // property of an AvatarPose.
            var animation = new AvatarExpressionKeyFrameAnimation
            {
                TargetProperty = "Expression",
            };

            // Let the content pipeline know that we depend on this file and we need to rebuild the
            // content if the file is modified.
            string sourcePath = Path.GetDirectoryName(input.Identity.SourceFilename);
            string filePath   = Path.GetFullPath(Path.Combine(sourcePath, ExpressionFile));

            context.AddDependency(filePath);

            FileStream   fs = File.OpenRead(filePath);
            StreamReader sr = new StreamReader(fs);

            while (!sr.EndOfStream)
            {
                string currentLine = sr.ReadLine();

                // Skip comment lines
                if (currentLine.StartsWith("#"))
                {
                    continue;
                }

                string[] Components = currentLine.Split(',');

                // Check for the correct number of components
                if (Components.Length != 6)
                {
                    throw new InvalidContentException("Error processing facial expression file", input.Identity);
                }

                try
                {
                    TimeSpan         time             = TimeSpan.FromMilliseconds(Convert.ToDouble(Components[0]));
                    AvatarExpression avatarExpression = new AvatarExpression();
                    avatarExpression.LeftEye      = (AvatarEye)Convert.ToInt32(Components[1]);
                    avatarExpression.LeftEyebrow  = (AvatarEyebrow)Convert.ToInt32(Components[2]);
                    avatarExpression.Mouth        = (AvatarMouth)Convert.ToInt32(Components[3]);
                    avatarExpression.RightEye     = (AvatarEye)Convert.ToInt32(Components[4]);
                    avatarExpression.RightEyebrow = (AvatarEyebrow)Convert.ToInt32(Components[5]);

                    // Add key frame.
                    var keyFrame = new KeyFrame <AvatarExpression>(time, avatarExpression);
                    animation.KeyFrames.Add(keyFrame);
                }
                catch (Exception)
                {
                    throw new InvalidContentException("Error processing facial expression file", input.Identity);
                }
            }

            if (animation.KeyFrames.Count == 0)
            {
                return(null);
            }

            // Sort the animation frames
            animation.KeyFrames.Sort();

            return(animation);
        }
        private ITimeline BakeAnimation(AvatarAnimation avatarAnimation)
        {
            // Create an AvatarExpression key frame animation that will be applied to the Expression
            // property of an AvatarPose.
            AvatarExpressionKeyFrameAnimation expressionAnimation = new AvatarExpressionKeyFrameAnimation
            {
                TargetProperty = "Expression"
            };

            // Create a SkeletonPose key frame animation that will be applied to the SkeletonPose
            // property of an AvatarPose.
            SkeletonKeyFrameAnimation skeletonKeyFrameAnimation = new SkeletonKeyFrameAnimation
            {
                TargetProperty = "SkeletonPose"
            };

            // In the next loop, we sample the original animation with 30 Hz and store the key frames.
            int numberOfKeyFrames = 0;
            AvatarExpression previousExpression = new AvatarExpression();
            TimeSpan         time   = TimeSpan.Zero;
            TimeSpan         length = avatarAnimation.Length;
            TimeSpan         step   = new TimeSpan(333333); //  1/30 seconds;

            while (true)
            {
                // Advance time in AvatarAnimation.
                avatarAnimation.CurrentPosition = time;

                // Add expression key frame if this is the first key frame or if the key frame is
                // different from the last key frame.
                AvatarExpression expression = avatarAnimation.Expression;
                if (time == TimeSpan.Zero || !expression.Equals(previousExpression))
                {
                    expressionAnimation.KeyFrames.Add(new KeyFrame <AvatarExpression>(time, expression));
                }

                previousExpression = expression;

                // Convert bone transforms to SrtTransforms and add key frames to the SkeletonPose
                // animation.
                for (int i = 0; i < avatarAnimation.BoneTransforms.Count; i++)
                {
                    SrtTransform boneTransform = SrtTransform.FromMatrix(avatarAnimation.BoneTransforms[i]);
                    skeletonKeyFrameAnimation.AddKeyFrame(i, time, boneTransform);
                    numberOfKeyFrames++;
                }

                // Abort if we have arrived at the end time.
                if (time == length)
                {
                    break;
                }

                // Increase time. We check that we do not step over the end time.
                if (time + step > length)
                {
                    time = length;
                }
                else
                {
                    time += step;
                }
            }

            // Compress animation to save memory.
            float numberOfRemovedKeyFrames = skeletonKeyFrameAnimation.Compress(0.1f, 0.1f, 0.001f);

            Debug.WriteLine("Compression removed " + numberOfRemovedKeyFrames * 100 + "% of the key frames.");

            // Finalize the skeleton key frame animation. This optimizes the internal data structures.
            skeletonKeyFrameAnimation.Freeze();

            return(new TimelineGroup
            {
                expressionAnimation,
                skeletonKeyFrameAnimation,
            });
        }
 /// <inheritdoc/>
 /// <exception cref="NotSupportedException"><see cref="AvatarExpression"/>s cannot be blended.</exception>
 public void BeginBlend(ref AvatarExpression value)
 {
     throw new NotSupportedException("AvatarExpressions cannot be blended.");
 }
 /// <inheritdoc/>
 /// <exception cref="NotSupportedException"><see cref="AvatarExpression"/>s cannot be blended.</exception>
 public void BlendNext(ref AvatarExpression value, ref AvatarExpression nextValue, float normalizedWeight)
 {
     throw new NotSupportedException("AvatarExpressions cannot be blended.");
 }
 /// <inheritdoc/>
 public void Copy(ref AvatarExpression source, ref AvatarExpression target)
 {
     target = source;
 }