Пример #1
0
        public void InterpolateTest()
        {
            SrtTransform a = new SrtTransform(new Vector3F(1, 2, 3), new QuaternionF(1, 2, 3, 4).Normalized, new Vector3F(4, 5, 6));
            SrtTransform b = a;

            var c = SrtTransform.Interpolate(a, b, 0.5f);

            Assert.AreEqual(a, c);

            b = new SrtTransform(new Vector3F(7, 9, 8), new QuaternionF(6, 6, 4, 2).Normalized, new Vector3F(-2, 4, -9));
            c = SrtTransform.Interpolate(a, b, 0);
            Assert.AreEqual(a, c);

            c = SrtTransform.Interpolate(a, b, 1);
            Assert.AreEqual(b, c);

            c = SrtTransform.Interpolate(a, b, 0.3f);
            Assert.AreEqual(a.Translation * 0.7f + b.Translation * 0.3f, c.Translation);
            Assert.AreEqual(a.Scale * 0.7f + b.Scale * 0.3f, c.Scale);
            Assert.IsTrue(QuaternionF.AreNumericallyEqual(
                              new QuaternionF(
                                  a.Rotation.W * 0.7f + b.Rotation.W * 0.3f,
                                  a.Rotation.V * 0.7f + b.Rotation.V * 0.3f).Normalized,
                              c.Rotation));
        }
Пример #2
0
        /// <inheritdoc/>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="source"/>, <paramref name="target"/> or <paramref name="result"/> is
        /// <see langword="null"/>.
        /// </exception>
        public void Interpolate(ref SkeletonPose source, ref SkeletonPose target, float parameter, ref SkeletonPose result)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            var sourceTransforms = source.BoneTransforms;
            var targetTransforms = target.BoneTransforms;
            var resultTransforms = result.BoneTransforms;

            for (int i = 0; i < resultTransforms.Length; i++)
            {
                SrtTransform.Interpolate(ref sourceTransforms[i], ref targetTransforms[i], parameter, ref resultTransforms[i]);
            }

            result.Invalidate();
        }
Пример #3
0
        /// <summary>
        /// Gets the bone transform for a certain time considering key frame interpolation.
        /// </summary>
        /// <param name="channelIndex">The index in <see cref="_channels"/>.</param>
        /// <param name="timeIndex">The index in <see cref="_times"/>.</param>
        /// <param name="time">The animation time.</param>
        /// <returns>The animation value.</returns>
        private SrtTransform GetBoneTransform(int channelIndex, int timeIndex, TimeSpan time)
        {
            // Get index in the key frames list using the _indices lookup table.
            int keyFrameIndex = _indices[timeIndex * _channels.Length + channelIndex];

            if (EnableInterpolation && keyFrameIndex + 1 < ((Array)_keyFrames[channelIndex]).Length)
            {
                // ----- Key frame interpolation.
                // Get the key frame before and after the specified time.
                TimeSpan     previousTime, nextTime;
                SrtTransform previousTransform, nextTransform;
                GetBoneKeyFrames(channelIndex, keyFrameIndex, out previousTime, out previousTransform, out nextTime, out nextTransform);

                float parameter = (float)(time.Ticks - previousTime.Ticks) / (nextTime - previousTime).Ticks;
                SrtTransform.Interpolate(ref previousTransform, ref nextTransform, parameter, ref previousTransform);
                return(previousTransform);
            }

            // ----- No key frame interpolation.
            //TimeSpan time;
            SrtTransform transform;

            GetBoneKeyFrame(channelIndex, keyFrameIndex, out time, out transform);
            return(transform);
        }
        public void InterpolationTest()
        {
            var traits = SrtTransformTraits.Instance;
            var value0 = NextRandomValue();
            var value1 = NextRandomValue();

            Assert.IsTrue(SrtTransform.AreNumericallyEqual(value0, traits.Interpolate(value0, value1, 0.0f)));
            Assert.IsTrue(SrtTransform.AreNumericallyEqual(value1, traits.Interpolate(value0, value1, 1.0f)) ||
                          SrtTransform.AreNumericallyEqual(new SrtTransform(value1.Scale, -value1.Rotation, value1.Translation), traits.Interpolate(value0, value1, 1.0f)));
            Assert.IsTrue(SrtTransform.AreNumericallyEqual(SrtTransform.Interpolate(value0, value1, 0.75f), traits.Interpolate(value0, value1, 0.75f)));
        }
Пример #5
0
 /// <inheritdoc/>
 public void Interpolate(ref SrtTransform source, ref SrtTransform target, float parameter, ref SrtTransform result)
 {
     SrtTransform.Interpolate(ref source, ref target, parameter, ref result);
 }
Пример #6
0
        /// <exception cref="AnimationException">
        /// This animation is not frozen. <see cref="Freeze"/> must be called before the animation can
        /// be used.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="defaultSource"/>, <paramref name="defaultTarget"/> or
        /// <paramref name="result"/> is <see langword="null"/>.
        /// </exception>
        /// <inheritdoc/>
        public void GetValue(TimeSpan time, ref SkeletonPose defaultSource, ref SkeletonPose defaultTarget, ref SkeletonPose result)
        {
            if (!IsFrozen)
            {
                throw new AnimationException("This animation is not frozen. Freeze() must be called before the animation can be used.");
            }
            if (defaultSource == null)
            {
                throw new ArgumentNullException("defaultSource");
            }
            if (defaultTarget == null)
            {
                throw new ArgumentNullException("defaultTarget");
            }
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            TimeSpan?animationTime = GetAnimationTime(time);

            if (animationTime == null)
            {
                // Animation is inactive and does not produce any output.
                if (defaultSource == result)
                {
                    return;
                }

                // Copy bone transforms of defaultSource to result for the animated channels.
                for (int i = 0; i < _channels.Length; i++)
                {
                    int boneIndex = _channels[i];
                    if (boneIndex >= result.BoneTransforms.Length)
                    {
                        break;
                    }

                    result.BoneTransforms[boneIndex] = defaultSource.BoneTransforms[boneIndex];
                }

                return;
            }

            time = animationTime.Value;

            // Clamp time to allowed range.
            var startTime = _times[0];
            var endTime   = _totalDuration;

            if (time < startTime)
            {
                time = startTime;
            }
            if (time > endTime)
            {
                time = endTime;
            }

            int timeIndex = GetTimeIndex(time);

            if (!IsAdditive)
            {
                // Evaluate animation.
                for (int channelIndex = 0; channelIndex < _channels.Length; channelIndex++)
                {
                    int boneIndex = _channels[channelIndex];
                    if (boneIndex >= result.BoneTransforms.Length)
                    {
                        break;
                    }

                    Debug.Assert(((Array)_keyFrames[channelIndex]).Length > 0, "Each channel must have at least 1 key frame.");

                    float weight = _weights[channelIndex];
                    if (weight == 0 && defaultSource != result)
                    {
                        // This channel is inactive.
                        result.BoneTransforms[boneIndex] = defaultSource.BoneTransforms[boneIndex];
                    }
                    else if (weight == 1)
                    {
                        // Channel is fully active.
                        result.BoneTransforms[boneIndex] = GetBoneTransform(channelIndex, timeIndex, time);
                    }
                    else
                    {
                        // Mix channel with source.
                        SrtTransform boneTransform = GetBoneTransform(channelIndex, timeIndex, time);
                        SrtTransform.Interpolate(ref defaultSource.BoneTransforms[boneIndex], ref boneTransform, weight, ref boneTransform);
                        result.BoneTransforms[boneIndex] = boneTransform;
                    }
                }
            }
            else
            {
                // Additive animation.
                for (int channelIndex = 0; channelIndex < _channels.Length; channelIndex++)
                {
                    int boneIndex = _channels[channelIndex];
                    if (boneIndex >= result.BoneTransforms.Length)
                    {
                        break;
                    }

                    Debug.Assert(((Array)_keyFrames[channelIndex]).Length > 0, "Each channel must have at least 1 key frame.");

                    float weight = _weights[channelIndex];
                    if (weight == 0 && defaultSource != result)
                    {
                        // Channel is inactive.
                        result.BoneTransforms[boneIndex] = defaultSource.BoneTransforms[boneIndex];
                    }
                    else if (weight == 1)
                    {
                        // Channel is fully active.
                        result.BoneTransforms[boneIndex] = defaultSource.BoneTransforms[boneIndex] * GetBoneTransform(channelIndex, timeIndex, time);
                    }
                    else
                    {
                        // Add only a part of this animation value.
                        SrtTransform boneTransform = GetBoneTransform(channelIndex, timeIndex, time);
                        SrtTransform identity      = SrtTransform.Identity;
                        SrtTransform.Interpolate(ref identity, ref boneTransform, weight, ref boneTransform);
                        result.BoneTransforms[boneIndex] = defaultSource.BoneTransforms[boneIndex] * boneTransform;
                    }
                }
            }
        }
Пример #7
0
 /// <summary>
 /// Applies the weight to a given bone by blending the bone transforms.
 /// </summary>
 /// <param name="originalTransform">
 /// In: The original bone transform.
 /// </param>
 /// <param name="targetTransform">
 /// In: The target bone transform.<br/>
 /// Out: The blended bone transform.
 /// </param>
 internal void BlendBoneTransform(ref SrtTransform originalTransform, ref SrtTransform targetTransform)
 {
     targetTransform = SrtTransform.Interpolate(originalTransform, targetTransform, Weight);
 }