Split FBX animations?

Jul 2, 2012 at 11:19 PM

Hi, I'm in the process of integrating Xen into my current project, and man thats quite a lot of work. I read that it's not recommended, and I definitely understand why, but I'm impressed by Xen and would really benefit from it. Great work on it, too bad you cannot work on it any longer, I'd love to have seen that deferred renderer you were making.

 

Previously I used a framework which supported animations to be split into several fbx files, this is really ideal since animations and model assets can be updated seperately without lots of extra work.

I can't find this functionality in the content processor settings, is there any way to add support for this in the xen model importer? The SkinnedModelSample has support for it.

Jul 2, 2012 at 11:54 PM

I've found a solution to this, add this line in the beginning of Process method of Xen.Ex.ModelImporter,

AnimationMerger.Merge(MergeAnimations, input.Animations, input.Identity, context);

 

and these methods:

                public static void Merge(string animationFiles, AnimationContentDictionary animationDictionary,

                                 ContentIdentity contentIdentity, ContentProcessorContext context)
        {
            if (string.IsNullOrEmpty(animationFiles))
                return;

            string sourcePath = Path.GetDirectoryName(contentIdentity.SourceFilename);

            var files = animationFiles.Split(';')
                                      .Select(s => s.Trim())
                                      .Where(s => !string.IsNullOrEmpty(s));
            foreach (string file in files)
            {
                string filePath = Path.GetFullPath(Path.Combine(sourcePath, file));
                MergeAnimation(filePath, animationDictionary, contentIdentity, context);
            }
        }


        private static void MergeAnimation(string animationFilePath, AnimationContentDictionary animationDictionary,
                                           ContentIdentity contentIdentity, ContentProcessorContext context)
        {
            NodeContent mergeModel = context.BuildAndLoadAsset<NodeContent, NodeContent>(new ExternalReference<NodeContent>(animationFilePath), null);

            BoneContent mergeRoot = MeshHelper.FindSkeleton(mergeModel);
            if (mergeRoot == null)
            {
                context.Logger.LogWarning(null, contentIdentity, "Animation model file '{0}' has no root bone. Cannot merge animations.", animationFilePath);
                return;
            }

            foreach (string animationName in mergeRoot.Animations.Keys)
            {
                if (animationDictionary.ContainsKey(animationName))
                {
                    context.Logger.LogWarning(null, contentIdentity,
                        "Replacing animation '{0}' from '{1}' with merged animation.",
                        animationName, animationFilePath);

                    animationDictionary[animationName] = mergeRoot.Animations[animationName];
                }
                else
                {
                    context.Logger.LogImportantMessage("Merging animation '{0}' from '{1}'.", animationName, animationFilePath);

                    animationDictionary.Add(animationName, mergeRoot.Animations[animationName]);
                }
            }
        }

Developer
Jul 3, 2012 at 1:34 AM

I meant to look into this sometime as well, but we finally stopped using hand authored animations all together, so never really got around to it. This is really good info.

Thanks for sharing it.

Cheers