Пример #1
0
        public static void SaveToCollada(RwAnimationNode animation, RwFrameListNode frameList, string path)
        {
            var aiScene = ToAssimpScene(animation, frameList);

            using (var aiContext = new Assimp.AssimpContext())
            {
                if (!aiContext.ExportFile(aiScene, path, "collada"))
                {
                    throw new Exception("Failed to export");
                }
            }
        }
Пример #2
0
        public static RwAnimationNode FromAssimpScene(RwNode parent, RwFrameListNode frameList, string path)
        {
            var             aiContext   = new Assimp.AssimpContext();
            var             aiScene     = aiContext.ImportFile(path);
            var             aiAnimation = aiScene.Animations.FirstOrDefault();
            RwAnimationNode animationNode;

            if (aiAnimation != null)
            {
                animationNode = new RwAnimationNode(parent, RwKeyFrameType.Uncompressed, ( float )(aiAnimation.DurationInTicks / aiAnimation.TicksPerSecond));
                var nodeNameToHAnimId = aiAnimation.NodeAnimationChannels.ToDictionary(x => x.NodeName, x => frameList.GetNameIdByName(x.NodeName));
                var nodeKeyframeTimes = aiAnimation.NodeAnimationChannels.SelectMany(x => x.PositionKeys)
                                        .Select(x => x.Time)
                                        .Concat(aiAnimation.NodeAnimationChannels.SelectMany(x => x.RotationKeys.Select(y => y.Time)))
                                        .Distinct()
                                        .OrderBy(x => x)
                                        .ToList();

                var previousKeyFrames = new Dictionary <int, RwKeyFrame>();
                var nodeKeyFrames     = new Dictionary <int, List <RwKeyFrame> >();

                // Add initial pose
                foreach (var hierarchyNode in frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes)
                {
                    var frame            = frameList[frameList.GetFrameIndexByNameId(hierarchyNode.NodeId)];
                    var firstRotation    = Quaternion.CreateFromRotationMatrix(frame.Transform);
                    var firstTranslation = frame.Transform.Translation;

                    var channel = aiAnimation.NodeAnimationChannels.FirstOrDefault(x => nodeNameToHAnimId[x.NodeName] == hierarchyNode.NodeId);
                    if (channel != null)
                    {
                        if (channel.HasRotationKeys)
                        {
                            firstRotation = ToQuaternion(channel.RotationKeys.First().Value);
                        }

                        if (channel.HasPositionKeys)
                        {
                            firstTranslation = ToVector3(channel.PositionKeys.First().Value);
                        }
                    }

                    var keyFrame = new RwKeyFrame(0, firstRotation, firstTranslation, null);
                    animationNode.KeyFrames.Add(keyFrame);

                    previousKeyFrames[hierarchyNode.NodeId] = keyFrame;
                    nodeKeyFrames[hierarchyNode.NodeId]     = new List <RwKeyFrame>();
                }

                foreach (var keyFrameTime in nodeKeyframeTimes)
                {
                    if (keyFrameTime == 0.0f)
                    {
                        continue;
                    }

                    foreach (var channel in aiAnimation.NodeAnimationChannels)
                    {
                        if (!channel.HasPositionKeys && !channel.HasRotationKeys)
                        {
                            continue;
                        }

                        if (!channel.RotationKeys.Any(x => x.Time == keyFrameTime) || !channel.PositionKeys.Any(x => x.Time == keyFrameTime))
                        {
                            continue;
                        }

                        var hierarchAnimNodeId = nodeNameToHAnimId[channel.NodeName];
                        var previousKeyFrame   = previousKeyFrames[hierarchAnimNodeId];
                        var rotation           = previousKeyFrame.Rotation;
                        var translation        = previousKeyFrame.Translation;

                        var rotationKeys = channel.RotationKeys.Where(x => x.Time == keyFrameTime);
                        if (rotationKeys.Any())
                        {
                            var aiRotation = rotationKeys.First().Value;
                            rotation = new Quaternion(aiRotation.X, aiRotation.Y, aiRotation.Z, aiRotation.W);
                        }

                        var translationKeys = channel.PositionKeys.Where(x => x.Time == keyFrameTime);
                        if (translationKeys.Any())
                        {
                            var aiTranslation = translationKeys.First().Value;
                            translation = new Vector3(aiTranslation.X, aiTranslation.Y, aiTranslation.Z);
                        }

                        var keyFrame = new RwKeyFrame(( float )(keyFrameTime / aiAnimation.TicksPerSecond), rotation, translation, previousKeyFrame);
                        nodeKeyFrames[hierarchAnimNodeId].Add(keyFrame);
                        previousKeyFrames[hierarchAnimNodeId] = keyFrame;
                    }
                }

                while (!nodeKeyFrames.All(x => x.Value.Count == 0))
                {
                    foreach (var kvp in nodeKeyFrames)
                    {
                        if (animationNode.KeyFrames.Count == 0)
                        {
                            continue;
                        }

                        var keyFrame = kvp.Value.First();
                        animationNode.KeyFrames.Add(keyFrame);
                        kvp.Value.Remove(keyFrame);

                        if (animationNode.KeyFrames.Count == 0)
                        {
                            var previousKeyFrame = previousKeyFrames[kvp.Key];
                            if (previousKeyFrame.Time != animationNode.Duration)
                            {
                                var lastRotation    = previousKeyFrame.Rotation;
                                var lastTranslation = previousKeyFrame.Translation;
                                var channel         = aiAnimation.NodeAnimationChannels.SingleOrDefault(x => nodeNameToHAnimId[x.NodeName] == kvp.Key);
                                if (channel != null)
                                {
                                    if (channel.HasRotationKeys)
                                    {
                                        lastRotation = ToQuaternion(channel.RotationKeys.Last().Value);
                                    }

                                    if (channel.HasPositionKeys)
                                    {
                                        lastTranslation = ToVector3(channel.PositionKeys.Last().Value);
                                    }
                                }

                                animationNode.KeyFrames.Add(new RwKeyFrame(animationNode.Duration, lastRotation, lastTranslation, previousKeyFrame));
                            }
                        }
                    }
                }
            }
            else
            {
                animationNode = new RwAnimationNode(null, RwKeyFrameType.Uncompressed, 0f);
            }

            return(animationNode);
        }
Пример #3
0
        public static Assimp.Scene ToAssimpScene(RwAnimationNode animation, RwFrameListNode frameList)
        {
            var aiScene = new Assimp.Scene();

            // RootNode
            var rootFrame  = frameList[0];
            var aiRootNode = new Assimp.Node("RootNode", null);

            aiRootNode.Transform = new Assimp.Matrix4x4(rootFrame.Transform.M11, rootFrame.Transform.M21, rootFrame.Transform.M31, rootFrame.Transform.M41,
                                                        rootFrame.Transform.M12, rootFrame.Transform.M22, rootFrame.Transform.M32, rootFrame.Transform.M42,
                                                        rootFrame.Transform.M13, rootFrame.Transform.M23, rootFrame.Transform.M33, rootFrame.Transform.M43,
                                                        rootFrame.Transform.M14, rootFrame.Transform.M24, rootFrame.Transform.M34, rootFrame.Transform.M44);

            aiScene.RootNode = aiRootNode;

            for (int i = 1; i < frameList.Count; i++)
            {
                var frame     = frameList[i];
                var frameName = "_" + frame.HAnimFrameExtensionNode.NameId;

                Assimp.Node aiParentNode = null;
                if (frame.Parent != null)
                {
                    string parentName = "RootNode";
                    if (frame.Parent.HasHAnimExtension)
                    {
                        parentName = "_" + frame.Parent.HAnimFrameExtensionNode.NameId;
                    }

                    aiParentNode = aiRootNode.FindNode(parentName);
                }

                var aiNode = new Assimp.Node(frameName, aiParentNode);
                aiNode.Transform = new Assimp.Matrix4x4(frame.Transform.M11, frame.Transform.M21, frame.Transform.M31, frame.Transform.M41,
                                                        frame.Transform.M12, frame.Transform.M22, frame.Transform.M32, frame.Transform.M42,
                                                        frame.Transform.M13, frame.Transform.M23, frame.Transform.M33, frame.Transform.M43,
                                                        frame.Transform.M14, frame.Transform.M24, frame.Transform.M34, frame.Transform.M44);
                aiParentNode.Children.Add(aiNode);
            }

            var aiAnimation = new Assimp.Animation();

            aiAnimation.TicksPerSecond  = FPS;
            aiAnimation.DurationInTicks = animation.Duration * FPS;
            aiAnimation.Name            = "Take 01";
            aiScene.Animations.Add(aiAnimation);

            var keyFrameToNodeAnimationChannel = new Dictionary <RwKeyFrame, Assimp.NodeAnimationChannel>();

            for (var i = 0; i < frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes.Count; i++)
            {
                var hierarchyNode = frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes[i];
                var keyFrame      = animation.KeyFrames[i];

                // Create channel
                var aiNodeAnimationChannel = new Assimp.NodeAnimationChannel();
                aiNodeAnimationChannel.NodeName  = "_" + hierarchyNode.NodeId;
                aiNodeAnimationChannel.PostState = Assimp.AnimationBehaviour.Default;
                aiNodeAnimationChannel.PreState  = Assimp.AnimationBehaviour.Default;
                aiNodeAnimationChannel.PositionKeys.Add(new Assimp.VectorKey(0, new Assimp.Vector3D(keyFrame.Translation.X, keyFrame.Translation.Y, keyFrame.Translation.Z)));
                aiNodeAnimationChannel.RotationKeys.Add(new Assimp.QuaternionKey(0, new Assimp.Quaternion(keyFrame.Rotation.X, keyFrame.Rotation.Y, keyFrame.Rotation.Z, keyFrame.Rotation.W)));
                aiNodeAnimationChannel.ScalingKeys.Add(new Assimp.VectorKey(0, new Assimp.Vector3D(1, 1, 1)));
                aiNodeAnimationChannel.ScalingKeys.Add(new Assimp.VectorKey(Math.Round(animation.Duration * FPS), new Assimp.Vector3D(1, 1, 1)));

                keyFrameToNodeAnimationChannel[keyFrame] = aiNodeAnimationChannel;
                aiAnimation.NodeAnimationChannels.Add(aiNodeAnimationChannel);
            }

            for (int i = frameList.AnimationRootNode.HAnimFrameExtensionNode.Hierarchy.Nodes.Count; i < animation.KeyFrames.Count; i++)
            {
                var keyFrame = animation.KeyFrames[i];

                // Add keys
                var aiNodeAnimationChannel = keyFrameToNodeAnimationChannel[keyFrame.Previous];
                aiNodeAnimationChannel.PositionKeys.Add(new Assimp.VectorKey(keyFrame.Time * FPS, new Assimp.Vector3D(keyFrame.Translation.X, keyFrame.Translation.Y, keyFrame.Translation.Z)));
                aiNodeAnimationChannel.RotationKeys.Add(new Assimp.QuaternionKey(keyFrame.Time * FPS, new Assimp.Quaternion(keyFrame.Rotation.X, keyFrame.Rotation.Y, keyFrame.Rotation.Z, keyFrame.Rotation.W)));

                keyFrameToNodeAnimationChannel[keyFrame] = aiNodeAnimationChannel;
            }

            return(aiScene);
        }