예제 #1
0
        private void InterpolateKeys(double animationTime, AnimationLayer layer, ref Quaternion rotation, ref Vector3 translation, ref Vector3 scale, PRSKey prsKey, PRSKey nextPrsKey)
        {
            var nextTime = (nextPrsKey.Time < prsKey.Time
                ? (nextPrsKey.Time + Animation.Duration)
                : nextPrsKey.Time);

            var blend = ( float )(animationTime / nextTime);

            if (prsKey.HasRotation)
            {
                rotation = Quaternion.Slerp(prsKey.Rotation, nextPrsKey.Rotation, blend);
            }

            if (prsKey.HasPosition)
            {
                translation = Vector3.Lerp(prsKey.Position * layer.PositionScale,
                                           nextPrsKey.Position * layer.PositionScale,
                                           blend);
            }

            if (prsKey.HasScale)
            {
                scale = Vector3.Lerp(prsKey.Scale * layer.ScaleScale,
                                     nextPrsKey.Scale * layer.ScaleScale,
                                     blend);
            }
        }
예제 #2
0
        public static Animation ConvertFromAssimpScene(Ai.Scene aiScene, Ai.Animation aiAnimation, AnimationConverterOptions options)
        {
            var animation = new Animation(options.Version);

            animation.Duration = ConvertTime(aiAnimation.DurationInTicks, aiAnimation.TicksPerSecond);

            foreach (var aiChannel in aiAnimation.NodeAnimationChannels)
            {
                if (AssimpConverterCommon.MeshAttachmentNameRegex.IsMatch(aiChannel.NodeName))
                {
                    continue;
                }

                var nodeName = AssimpConverterCommon.UnescapeName(aiChannel.NodeName);

                Ai.Node node = aiScene.RootNode.FindNode(nodeName);
                if (node == null)
                {
                    continue;
                }

                var controller = new AnimationController(options.Version)
                {
                    TargetKind = TargetKind.Node,
                    TargetName = nodeName,
                    TargetId   = GetTargetIdForNode(aiScene.RootNode, nodeName)
                };

                var layer = new AnimationLayer(options.Version);

                // NodePRS only for now
                layer.KeyType = KeyType.NodePRS;

                // Fetch the unique key frame timings from all position, rotation and scale keys.
                var aiKeyTimings = aiChannel.PositionKeys
                                   .Select(x => x.Time)
                                   .Concat(aiChannel.RotationKeys.Select(x => x.Time))
                                   .Concat(aiChannel.ScalingKeys.Select(x => x.Time))
                                   .Distinct()
                                   .OrderBy(x => x)
                                   .ToList();

                // Decompose the local transform of the affected node so we can use them as the base values for our keyframes

                node.Transform.Decompose(out var nodeBaseScale, out var nodeBaseRotation, out var nodeBaseTranslation);

                // Keep track of the last position, rotation and scale used to ensure that interpolation works properly
                var lastPosition = nodeBaseTranslation;
                var lastRotation = nodeBaseRotation;
                var lastScale    = nodeBaseScale;

                for (var i = 0; i < aiKeyTimings.Count; i++)
                {
                    var aiTime = aiKeyTimings[i];

                    // Start building the keyframe
                    var key = new PRSKey(layer.KeyType)
                    {
                        Position = new Vector3(lastPosition.X, lastPosition.Y, lastPosition.Z),
                        Rotation = new Quaternion(lastRotation.X, lastRotation.Y, lastRotation.Z, lastRotation.W),
                        Scale    = new Vector3(lastScale.X, lastScale.Y, lastScale.Z)
                    };

                    // Fetch the Assimp keys for this time
                    var aiPositionKey = aiChannel.PositionKeys.SingleOrDefault(x => x.Time == aiTime);
                    var aiRotationKey = aiChannel.RotationKeys.SingleOrDefault(x => x.Time == aiTime);
                    var aiScaleKey    = aiChannel.ScalingKeys.SingleOrDefault(x => x.Time == aiTime);

                    if (aiPositionKey != default)
                    {
                        key.Position = new Vector3(aiPositionKey.Value.X, aiPositionKey.Value.Y, aiPositionKey.Value.Z);
                        lastPosition = aiPositionKey.Value;
                    }

                    if (aiRotationKey != default)
                    {
                        key.Rotation = new Quaternion(aiRotationKey.Value.X, aiRotationKey.Value.Y, aiRotationKey.Value.Z,
                                                      aiRotationKey.Value.W);
                        lastRotation = aiRotationKey.Value;
                    }

                    if (aiScaleKey != default)
                    {
                        key.Scale = new Vector3(aiScaleKey.Value.X, aiScaleKey.Value.Y, aiScaleKey.Value.Z);
                        lastScale = aiScaleKey.Value;
                    }

                    key.Time = ConvertTime(aiTime, aiAnimation.TicksPerSecond);
                    layer.Keys.Add(key);
                }

                controller.Layers.Add(layer);
                animation.Controllers.Add(controller);
            }

            return(animation);
        }