3dsmax animation in JME - SOLVED + TUTORIAL

Hi there, is there any tutorial that describes the whole process from creating a model in 3dsmax, adding animations, exporting to OgreXML, importing to JME and using the animation? I don’t get it.
What I used to do to animate a model in 3dsmax:
-Create model
-Create bones
-Apply Skin modifier on the model and add the bones
-Animate the bones

So I tried the same for a game model to export it to OgreXML. In the object settings of OgreMax I created a mesh animation track and exported the scene. I got a scene file, a mesh.xml file and even a skeleton.xml file containing the nodes. There is also a AnimControl on the mesh, but without any animation track. The scene file also does not contain an animation.

What am I missing?

Not for max directly but you can translate whats written for blender here to max, the general circumstances are the same:
https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:external:blender

1 Like

I’ve already noticed that tutorial, but that doesn’t help me through the max export. OgreMax provides so many loosely documented settings and I don’t know how to configure it right. :frowning:

Well go along the terms, look them up in the max documentation, see how you can achieve the same thing. Then ideally write it all down and make some screens for the wiki :wink:

1 Like

Yes, you’re right. Here is my short tutorial. Feel free to use, edit and add it to the tutorials section as desired.

3ds Max Bone Animation to JME3 using OgreMax plugin

For this tutorial I used 3D Studio Max 2012 and OgreMax 2.4.3 free edition

==Create Model and Bones==

-Create a new file

-Select the “Create” tab > “Geometry” > “Cylinder”

-Draw a cylinder, lets say with 8 height segments (must be enough for a smooth deformation)

-Also check “Generate Mapping Coords.”

-Click “Create” tab > “Systems” > “Bones”

-Add some bones in the center of the cylinder

-Select the cylinder, right click it and click “Convert To:” > “Convert to Editable Mesh” to prevent issues with OgreMax

-Click the “Modify” tab > “Modifier List” and add the “Skin” modifier

-Beneath “Bones:” click “Add” and select all of your bones

-You may also edit the envelopes, but for a small test the default settings are ok

==Create the animation==

-Select the cylinder, and click “Display” tab > “Freeze Selected” so it is easier to select the bones during animation

-Select the two top bones and enable the “Auto Key” mode

-The first key frame will be created automatically. Move the animation track slider to frame 5

-Move the selected bones a bit. The cylinder mesh will be deformed. Because you are in the "Auto

Key" mode, a key frame will be created

-Create some additional key frames. You may also select more bones and move or rotate them

I’ve created 25 frames and the last key frame equals the first, so the animation is loopable

-After creating the animation, disable the “Auto Key” mode

==OgreMax settings==

-Open the “OgreMax Scene Settings” dialogue from the menu

-In the “Meshes” tab, enable “Export XML Files” and disable “Export Binary Files” as well as

“Export Vertex Colors”

-Click the “Environment” tab and uncheck “Export Environment Settings”. Otherwise the JME importer will throw a NullPointerException

-If you have textured your model, you may also check “Copy Bitmaps to Export Directory” in the

“Bitmaps” tab

-Unfreeze the cylinder by clicking “Display” tab > “Unfreeze All” and select it

-While having the cylinder selected, open the “OgreMax Object Settings” dialogue from the menu

-Open the “Mesh Animations” tab and select type “Skeleton”, “Export Skeleton” : “Yes”

-Below “Mesh Animations” hit the “Add…” button

-Assign a name to the track, maybe “wobble”. The track type must be "Skin. Set the right "Start/End

Frames" for your animation

-Hit ok and you will see the animation in the table. You may add additional animations by selecting other frame ranges, if desired

==Export and Import==

-When all animations are in the list, select “OgreMax” > “Export” > “Export Scene” and name the file “worm.scene”

-Create a JME test class that imports the file, get the animation controller and start the “wobble” animation

[java]
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.Skeleton;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.light.AmbientLight;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.debug.SkeletonDebugger;

/**

  • This is a test class for loading a Ogre XML scene exported by OgreMax.
  • @author Stephan Dreyer

*/
public class TestOgreMaxImport extends SimpleApplication {

@Override
public void simpleInitApp() {
	// register the asset path where your model is
	assetManager.registerLocator("Assets/model/ogre/test/", FileLocator.class);

	// create the geometry and attach it
	final Node model = (Node) assetManager.loadModel("worm.scene");
	// resize it, because of the large 3dsmax scales
	model.setLocalScale(.008f);

	// attach to root node
	rootNode.attachChild(model);

	final AnimControl ac = findAnimControl(model);

	// add a skeleton debugger to make bones visible
	final Skeleton skel = ac.getSkeleton();
	final SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton",
			skel);
	final Material mat = new Material(assetManager,
			"Common/MatDefs/Misc/Unshaded.j3md");
	mat.setColor("Color", ColorRGBA.Green);
	mat.getAdditionalRenderState().setDepthTest(false);
	skeletonDebug.setMaterial(mat);
	model.attachChild(skeletonDebug);

	// create a channel and start the wobble animation
	final AnimChannel channel = ac.createChannel();
	channel.setAnim("wobble");

	// add some lights
	rootNode.addLight(new AmbientLight());
	rootNode.addLight(new PointLight());
}

/**
 * Method to find the animation control, because it is not on the models root
 * node.
 * 
 * @param parent
 *          The spatial to search.
 * @return The {@link AnimControl} or <code>null</code> if it does not exist.
 */
public AnimControl findAnimControl(final Spatial parent) {
	final AnimControl animControl = parent.getControl(AnimControl.class);
	if (animControl != null) {
		return animControl;
	}

	if (parent instanceof Node) {
		for (final Spatial s : ((Node) parent).getChildren()) {
			final AnimControl animControl2 = findAnimControl(s);
			if (animControl2 != null) {
				return animControl2;
			}
		}
	}

	return null;
}

public static void main(final String[] args) {
	new TestOgreMaxImport().start();
}

}
[/java]

You will see your worms strange movements. Have fun!

6 Likes

Wow, nice one :slight_smile:

I guess someone needs to create a new wiki page for them to go on and link it in somewhere appropriate?

Thats awesome, thanks :slight_smile: I’ll add it to the wiki at some point if nobody else is faster :wink: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:external:ogremax

I added it already :wink: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:external:3dsmax

1 Like

Very nice, but the source code looks a little bit screwed up. :stuck_out_tongue_winking_eye: Fixed it.
I’m just glad it finally worked, bone animation in JME is really impressive.

Sadly the importer can not handle the ambient setting of OgreMax. I took a look into the scene file.

The importer does not expect the ambient and clipping tags at this location. Does it support Ogre 1.8?

Edit: I can not add the damn xml file, not with java or code tag.

Use xml tags for xml. Can you show the exact error and upload an example file for the import problem? Maybe @Momoko_Fan can do something about that.

No, that doesn’t work. I can not add xml.

[xml]
Moep
[/xml]

[xml] tag works fine for me - Otherwise, you could just post the error log at http://pastebin.com/ and share the url here. :slight_smile:

It does not work with the xml tag, sorry.

With this scene file the exporter runs into a NPE:

http://pastebin.com/4KsC2fzS

The SceneLoader expects the root node to be not null, but it is. I guess the environment tag is at another location than it is in the blender exported Ogre scene.
Maybe @Momoko_Fan can take a look into that.

I updated the tutorial on https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:external:3dsmax and added biped animation.

It’s really awesome how nice this is working once I found all the right settings!

2 Likes
@3H said: I updated the tutorial on https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:external:3dsmax and added biped animation.

It’s really awesome how nice this is working once I found all the right settings!


Awesome. Yeah, theres always 100 ways to do it wrong an 1 to do it right…

Hello @3H and @normen, I have follow the 3ds Max bone Animation tutorial, and I design and animate a manikin (model), then I exported to jme3 with the ogremax. The problem is when I implement the TestOgreMaxImport class of the tutorial, where it use the skeleton debugger. My model and there skeleton appears separately each other, and really don’t know why, although, the animation is executed by the model and the skeleton correctly.
Anyone know what could be happening?

1 Like

Hi @cboyain, its nice to hear that the animation is played correctly. :slight_smile:

I have the same issue with the SkeletonDebugger, seems like the bones location/rotation is not translated correctly to world coordinates. I just ignored that because the optical result was good.

Edit: I fixed it for my case, please try it yourself:

[java] final SceneGraphVisitorAdapter visitor = new SceneGraphVisitorAdapter() {

    @Override
    public void visit(final Node geom) {
      if (geom.getControl(AnimControl.class) != null) {
        // add the skeleton debugger to the node with the anim control

        // you can do this in the anim control retrieval step

        final SkeletonDebugger skeletonDebug = new SkeletonDebugger(
            "skeleton", skel);
        final Material mat = new Material(assetManager,
            "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Green);
        mat.getAdditionalRenderState().setDepthTest(false);
        skeletonDebug.setMaterial(mat);
        geom.attachChild(skeletonDebug);
      }
    }
  };

  model1.depthFirstTraversal(visitor);[/java] 

The solution was to add the SkeletonDebugger to the node with the AnimControl instead of the model root.

I also updated the tutorial, thanks for the hint. :wink:

Hi @3H, thanks for your replay, you were right, the problem is attach the SkeletonDebugger to the node with the AnimControl, now all looks good.

I just have another question; do you think that this issue could give problems if i use collision detection?

No, I don’t think so. Do you actually have problems with collision detection?

No, but I’m planning to used with collision detection. Whatever happens i will post it, and thanks again.