Importing Model and Animations from Unreal

It seems that I was not very clear about what I want to do so I am making a new question. I have a lot of assets I have received, either free or purchased at the Epic Games Store. The models and animations are stored as separate files and there is no way to export them as one file containing everything.


I right click on the skeletal mesh to export the model as either FBX or GLTF/B. I prefer GLTF because its text based and not binary as binary files are more difficult to manage with git.

So when I export from Unreal I have a GLTF file containing the model with all the bones, etc and separate GTLF files for each animation. Unreal does not offer a way to export this to a single file. Since JMonkey requires all the animations to be in the same file, is there a way I can accomplish this in Jmonkey?

I am on 3.7.0-stable using the engine is there a way to do this in the SDK then export it to my project using IntelliJ? I did find this which indicates that I might be able to accomplish it using the engine then just export it to my project. I would prefer to not have to do it in Blender as I have 0 Blender skills so it would take time so I prefer to avoid using blender unless I absolutely need to.

1 Like

If it just cant be done with GLTF, would it work with a different file type?

Perhaps you could import each gltf/fbx generated by unreal into blender, then export again as the single-file gltf format for jme? Idk, I’ve never worked with unreal assets before.

Oh, sorry, I missed that you want to avoid blender if possible. In that case, this might work:

Spatial model = assetManager.loadModel("myModel.gltf");
Spatial modelAnim1 = assetManager.loadModel("myModelAnim1.gltf");

AnimComposer anim = model.getControl(AnimComposer.class);
Action action1 = modelAnim1.getControl(AnimComposer.class).removeAction("myAction1");
anim.addAction("myAction1", action1);

BinaryExporter.getInstance().save(model, new File("myModel.j3o"));

I think it will be much easier in the long run to go ahead and learn blender, though. :wink:

1 Like

Yes probably. Thanks I will play around with this. I did find addAnimClip(clip) in AnimComposer but couldnt figure out how to convert the animation loaded to an AnimClip

AnimComposer does have a method for getting an AnimClip by name:

AnimClip clip = anim.getAnimClip("myAction");
2 Likes

I have a GLTF file containing the model with all the bones, etc and separate GTLF files for each animation. Unreal does not offer a way to export this to a single file. Since JMonkey requires all the animations to be in the same file, is there a way I can accomplish this in Jmonkey

If can you load the character and animation files into a JME application, you can combine them all into a single model by using the Wes library.

Start by finding the character’s Armature and AnimComposer:

        List<Armature> armatures
                = MySkeleton.listArmatures(characterRoot, null);
        assert armatures.size() == 1;
        Armature characterArmature = armatures.get(0);

        List<AnimComposer> composers = MySpatial.listControls(
                characterRoot, AnimComposer.class, null);
        assert composers.size() == 1;
        AnimComposer characterComposer = composers.get(0);

Then add each animation clip to the AnimComposer like so:

        // Retarget the clip to the character's armature:
        SkeletonMapping map = new SkeletonMapping(clipArmature);
        AnimClip retargeted = AnimationEdit.retargetAnimation(
                sourceClip, clipArmature, characterArmature, map, clipName);
        characterComposer.addAnimClip(retargeted);
2 Likes

I could check if the SDK could be made to assist in these types of tasks, ie merging animations into the base model.
I have, as well, used blender for this in the past.

4 Likes

Or if I just switch to using Ogre XML instead of GLTF this should all just work as long as the model and animation files are all in the same resource directory correct? Haven’t used it before so I’ll have to read up on it some.

I would avoid using ogre xml at all costs. It has not actively been supported by jme in years. Definitely go with gltf if possible.

3 Likes

Yes I just was looking around and found its old and soon to be depreciated. With GLTF I can get one animation working but still having issues with the animations coming from a different file. I get an exception saying it cant find the clip.
animComposer.addAction("name", animComposer.makeAction("name"))

I can get around it adding a call to addAnimClip but then it crashes saying AnimClip.tracks is null. How can I set the AnimTrack array?

animComposer.addAnimClip(AnimClip("name"))
val action1: Action = animComposer.makeAction("name")
animComposer.addAction("name", action1)

I think you’re going in the wrong direction here. Have you tried using Wes yet to retarget the animations as sgold suggested?

2 Likes

Yes I was focused and lost focus for a moment. I will retarget as @sgold suggested.

2 Likes

I just keep running into problems. I do know Blender basics so I know how to edit and make things so I can get some dev assets going if I need to. I think like its already been said, JMonkey will be happier if everything is in the same file. I have done some investigating and it seems like it shouldnt be very difficult to import separate animation files into an existing model so I should be able to accomplish it without too much difficulty.

I already suggested using a SkeletonMapping to re-target animation clips to a character’s AnimController.

Here’s another way (also using the Wes library) which might be even better:

    /**
     * Retarget an AnimClip to the specified Armature without using SkeletonMap.
     * This technique preserves any translation and/or scaling in the joint
     * tracks.
     *
     * @param clip the clip to retarget (not null)
     * @param armature the desired armature (not null, unaffected)
     * @param clipName desired name for the new clip
     * @return a new clip containing pre-existing tracks
     */
    private static AnimClip retargetClip(
            AnimClip clip, Armature armature, String clipName) {
        AnimTrack[] animTracks = clip.getTracks(); // alias
        AnimClip result = new AnimClip(clipName);
        for (AnimTrack animTrack : animTracks) {
            if (MyAnimation.isJointTrack(animTrack)) {
                TransformTrack transformTrack = (TransformTrack) animTrack;
                HasLocalTransform animTarget = transformTrack.getTarget();
                Joint animJoint = (Joint) animTarget;
                String jointName = animJoint.getName();
                Joint charaJoint = armature.getJoint(jointName);
                if (charaJoint != null) {
                    transformTrack.setTarget(charaJoint);
                    AnimationEdit.addTrack(result, transformTrack);
                }
            }
        }

        return result;
    }
1 Like

Yes I ran into a lot of issues trying to retarget the animation. The suggestion that I should fix the issue in Blender so all the animations are in one file with the model is probably a good idea. I should stop being so afraid of it. JMonkey wants everything in one file so I will make that happen in Blender then export it as one file and see if I still run into issues. If so I can make a new thread to discuss.

I’ve added this use case to the SDK: Merge animations actions by neph1 · Pull Request #626 · jMonkeyEngine/sdk · GitHub using the method (and library) suggested by @sgold

3 Likes