/// <summary>
        /// Tries to get the local transform and blend weight of the specified bone.
        /// </summary>
        public bool TryGetBoneTransform(int bone, out Matrix transform, out float blendWeight)
        {
            blendWeight = 1;

            if (bone >= AnimationClip.Transforms.Length || AnimationClip.Transforms[bone] == null)
            {
                transform = Matrix.Identity;
                return(false);
            }

            if (InterpolationEnabled && shouldLerp)
            {
                transform = LerpHelper.Slerp(
                    AnimationClip.Transforms[bone][startFrame],
                    AnimationClip.Transforms[bone][endFrame], percentage);
            }
            else
            {
                transform = AnimationClip.Transforms[bone][startFrame];
            }

            return(true);
        }
Example #2
0
        /// <summary>
        /// Updates the bone transforms.
        /// </summary>
        private void UpdateBoneTransforms(float elapsedTime)
        {
            // Update default blend
            float blendLerp = 0;

            if (BlendEnabled)
            {
                blendTimer += elapsedTime;
                blendLerp   = (float)(blendTimer / BlendDuration.TotalSeconds);
            }

            // Update controller transforms
            Array.Clear(weightedBones, 0, weightedBones.Length);

            for (int controllerIndex = 0; controllerIndex < Controllers.Count; controllerIndex++)
            {
                for (int bone = 0; bone < Skeleton.BoneTransforms.Length; bone++)
                {
                    int index = controllerIndex * numBones + bone;
                    if (Controllers[controllerIndex].Controller.TryGetBoneTransform(
                            bone, out weightedBones[index].Transform,
                            out weightedBones[index].BlendWeight))
                    {
                        weightedBones[index].BlendWeight *= Controllers[controllerIndex].BlendWeight * (
                            Controllers[controllerIndex].BoneWeights[bone].Enabled ?
                            Controllers[controllerIndex].BoneWeights[bone].BlendWeight : 0);
                    }
                    else
                    {
                        weightedBones[index].BlendWeight = 0;
                    }
                }
            }

            // Normalize weights
            for (int bone = 0; bone < Skeleton.BoneTransforms.Length; bone++)
            {
                int   firstNonZeroChannel = -1;
                float totalWeight         = 0;

                for (int controllerIndex = 0; controllerIndex < Controllers.Count; controllerIndex++)
                {
                    int index = controllerIndex * numBones + bone;
                    if (firstNonZeroChannel < 0 && weightedBones[index].BlendWeight > 0)
                    {
                        firstNonZeroChannel = controllerIndex;
                    }

                    totalWeight += weightedBones[index].BlendWeight;
                }

                if (totalWeight <= 0)
                {
                    continue;
                }

                Matrix transform = weightedBones[firstNonZeroChannel * numBones + bone].Transform;

                for (int controllerIndex = firstNonZeroChannel + 1; controllerIndex < Controllers.Count; controllerIndex++)
                {
                    int index = controllerIndex * numBones + bone;
                    if (weightedBones[index].BlendWeight <= float.Epsilon)
                    {
                        continue;
                    }

                    // This is not mathmatically correct, but produces an acceptable result.
                    transform = LerpHelper.Slerp(transform,
                                                 weightedBones[index].Transform,
                                                 weightedBones[index].BlendWeight / totalWeight);
                }

                // Perform default blend
                if (BlendEnabled && blendTarget != null && blendLerp <= 1)
                {
                    transform = LerpHelper.Slerp(blendTarget[bone], transform, MathHelper.SmoothStep(0, 1, blendLerp));
                }

                Skeleton.BoneTransforms[bone] = transform;
            }
        }
        private BoneAnimationClip ConvertAnimationClip(AnimationClip animation)
        {
            BoneAnimationClip boneAnimation = new BoneAnimationClip();

            boneAnimation.FramesPerSecond = FramesPerSecond;
            boneAnimation.TotalFrames     = (int)Math.Round(animation.Duration.TotalSeconds * FramesPerSecond);


            int maxBones = 0;
            Dictionary <int, List <Keyframe> > keyframes = new Dictionary <int, List <Keyframe> >();

            foreach (Keyframe keyframe in animation.Keyframes)
            {
                if (keyframe.Bone > maxBones)
                {
                    maxBones = keyframe.Bone;
                }

                if (!keyframes.ContainsKey(keyframe.Bone))
                {
                    keyframes.Add(keyframe.Bone, new List <Keyframe>());
                }

                keyframes[keyframe.Bone].Add(keyframe);
            }


            boneAnimation.Transforms = new Matrix[maxBones + 1][];
            for (int i = 0; i <= maxBones; ++i)
            {
                if (keyframes.ContainsKey(i))
                {
                    boneAnimation.Transforms[i] = new Matrix[boneAnimation.TotalFrames];
                }
            }


            TimeSpan time = TimeSpan.Zero;
            TimeSpan step = TimeSpan.FromSeconds(1.0 / FramesPerSecond);

            for (int frame = 0; frame < boneAnimation.TotalFrames; frame++)
            {
                foreach (int bone in keyframes.Keys)
                {
                    List <Keyframe> channel   = keyframes[bone];
                    Matrix          transform = Matrix.Identity;

                    if (time <= channel[0].Time)
                    {
                        transform = channel[0].Transform;
                    }
                    else if (time >= channel[channel.Count - 1].Time)
                    {
                        transform = channel[channel.Count - 1].Transform;
                    }
                    else
                    {
                        int k = 0;
                        while (channel[k].Time < time)
                        {
                            k++;
                        }

                        double lerp = (channel[k].Time - time).TotalSeconds /
                                      (channel[k].Time - channel[k - 1].Time).TotalSeconds;

                        transform = LerpHelper.Slerp(
                            channel[k].Transform,
                            channel[k - 1].Transform, (float)lerp);
                    }

                    boneAnimation.Transforms[bone][frame] = transform;
                }

                time += step;
            }

            FigureOutPreferredEnding(boneAnimation);

            return(boneAnimation);
        }
Example #4
0
        private void UpdateBoneTransforms(GameClock gameclock)
        {
            // update controller transforms
            Array.Clear(_weightedBones, 0, _weightedBones.Length);

            int numBones = _skeleton.BoneTransforms.Length;

            for (int i = 0; i < _controllers.Count; i++)
            {
                for (int b = 0; b < numBones; b++)
                {
                    int index = i * numBones + b;
                    if (_controllers[i].Controller.TryGetGoneTransforms(b, out _weightedBones[index].Transform, out _weightedBones[index].BlendWeight))
                    {
                        _weightedBones[index].BlendWeight *= _controllers[i].BlendWeight * (_controllers[i].BoneWeights[b].Enabled ? _controllers[i].BoneWeights[b].BlendWeight : 0);
                    }
                    else
                    {
                        _weightedBones[index].BlendWeight = 0;
                    }
                }
            }

            // Normalize weights
            for (int bone = 0; bone < numBones; bone++)
            {
                int   firstNonZeroChannel = -1;
                float totalWeight         = 0;

                for (int i = 0; i < _controllers.Count; i++)
                {
                    int index = i * numBones + bone;
                    if (firstNonZeroChannel < 0 && _weightedBones[index].BlendWeight > 0)
                    {
                        firstNonZeroChannel = i;
                    }

                    totalWeight += _weightedBones[i].BlendWeight;
                }

                if (totalWeight <= 0)
                {
                    continue;
                }

                // ToDo: Modify to use seperate translation, rotation and scale.
                Matrix4 transform = _weightedBones[firstNonZeroChannel * numBones + bone].Transform;

                for (int i = 0; i < _controllers.Count; i++)
                {
                    int index = i * numBones + bone;
                    if (_weightedBones[index].BlendWeight <= float.Epsilon)
                    {
                        continue;
                    }

                    // this is not matmatically correct, but produces an acceptable result.
                    transform = LerpHelper.Slerp(transform, _weightedBones[index].Transform,
                                                 _weightedBones[index].BlendWeight / totalWeight);
                }

                _skeleton.BoneTransforms[bone] = transform;
            }
        }