JME GUI ModelImporter

Updated for v1.5

The new release of the jMonkey Model Importer! Screenshots below:

And of the new render window (implemented with a canvas):

It should be relatively easy to understand, you designate a repository where your models are, you specify the format, then a list is generated where you can choose all or one to convert. By default, when you designate a repository for models, your texture path will automatically be set to it - if your textures are in a different folder, change the path after you designate the model path. This was for convenience, as a lot of us just dump all the files in one folder ;).

Also note that the scale is: large numbers = scales down, small numbers ( 0 < x < 1) scale up.

File Formats: dxs, 3ds, obj, ms3d, md2,md3,x3d, ase

After the conversion, your models will be displayed for viewing. One model will show at a time, but you can cycle forward/backwards through all the models you converted. All the controls are listed in the render window, you can also zoom out/in with the mouse wheel. You can fine tune for some of the parameters (the camera’s location and max zoom are adjusted based on the model’s world bound, so the camera’s pretty general, but for very large or very small models, you may want to increase/decrease how fast you can scroll/etc), if need be in the third tab.

There are two ways of getting this, I’ve got a webstart version:

…and a stand-alone version:

I can’t test on anything other than windows at the moment, but it should have the look and feel, and run on mac/linux. Please let me know if you find any bugs or anything that fails! I’ve tested this a lot with just about all of the file formats (dxs, ms3d, 3ds most extensively).

The next bit on the to-do list for features is support for collada/md5/ogre.xml. Probably won’t be a big deal…but I’ll have to play around with those loaders a bit.


Cool! Great job and thanks for sharing it.

Which 3d modellers save as dxs? Delgine?

I also forgot to mention - this is JME2.0, from my understanding you CANNOT use .jme files between versions, so be aware of that.

The .dxs format is the format of DeleD3D (so yes, from

Updated to V1.0, so it's basically complete now.

-Added much needed robustness, fixed some errors on the UI

-Refactored and cleaned up much of the code

-Added graphical feedback showing when conversion is taking place/done

-All formats should be able to be used (all can be scaled, 3ds automatically corrects for the z-up axis), save for collada/md5

-Reads/writes an ini file, so the directories you were working in will be saved after you're done with your current conversion session :wink:

I don't really have any test cases for milkshape,x3d,md2,md3 so they were bit of a shot in the dark. Not all the format converters specify if you have to set a texture directory, so textures not being applied may be still be iffy. But I'll deal with that when the need arrives.

I also wanted to try out a distribution method, using Launch4j, somewhat haphazardly however.

Please try and break it and report bugs as you see 'em.

Great Work!

Seems great, I'll check if it works on Mac :slight_smile:

keeskist said:

Seems great, I'll check if it works on Mac :)

The native libraries aren't included in the above zip for mac, although I was trying out launch4j for a win32 .exe, you can launch it via the modelImporter.jar in the root directory and I'm sure if you add the lwjgl native (.os?) files to the root directory, it should work.

Within the actual tool, I made an attempt to be as machine-independent as possible, but I dont have a mac or a linux machine to easily make sure everything's working.

Working on the next release:

I’ve brought the main application out of JME and into its own swing app, but have embedded a jme canvas into one of the tabs. At the moment its not suitable for a release as I need to add some appropriate measures to handle models of all size, and perhaps add some controls to cycle through models, turn off rotation, etc.

I’ll also be releasing this with other native files other than win32, and hopefully find some folks to test that release to make sure everything’s working too.

Nice job… I could test some Linux/Mac versions on my own. Looking forward to see where this goes.  XD

Ok! This was in stasis while I worked on some other projects, and in general life! However, I'm pleased to announce I finished the next version, and this time I'm trying out webstart distribution ;). I've included the libraries for linux/mac, and there should be graphical support for those platforms – please test to verify!

The original post has been updated with the pertinent information.

Ever since I added the renderer window in, I've been thinking of making it eventually a full blown model viewer (where you can see animations, see all the meshes and their hierarchy, hide/display meshes, see all the debug stuff, see bones, etc). And incorporate a save function, ie lets say you made an avatar model with multiple armour meshes all in one file, you can turn off what you dont want, and save it to a new file…or lets say you have an old model, but you have a new texture, you load up the .jme file, swap in the new texture, and save. The whole point is to have a convenience tool  that non-programmers can use thats easy, fast, and gives instant feedback.

I'm thinking this might be "too large" in the model importer, as that rendering window was intended for a quick feedback to the user, that his model converted like it should have. A stand alone app for it may be better.

What do you guys think? And what do you think of a model viewer? Has anyone done this yet? A while back ago, I found someone also did a model importer gui, but it was for JME1.0, and didn't seem maintained/nor have the features I included with this one. I don't want to re-invent the wheel…

But I also made this, for myself and for my own needs, the model viewer idea would follow the same purpose, but I am willing to share the tools as I see they can benefit the community.

Hi, I'm new to jMe, and I've been trying to find a way to embed a jMe canvas into a Swing application.

At the moment I'm working on a Mac, so I haven't been able to run your exporter on my work machine, but I will be trying it on my Windows laptop.

I would like to find out how you went about putting the jMe canvas in your application.

Thanks for trying it on a mac! What sort of error messages did you get, if any when you attempted to run it?

As for the canvas implementation, refer to Renanse's RenParticleEditor (in the jmetest.effects package) and RenControlEditor (in the jmetest.input package), both of those are excellent usages of the putting a canvas into a swing panel. More or less, those two apps are where I referenced the canvas implementation. I can post some skeleton code if you need it, as those two apps are rather large! It took some trial and error myself in getting it working.

Ok, here's a stripped down implementation of a canvas in a Swing App. It's just a JFrame with a JPanel holding the canvas. It's mostly cut and paste, but it should demonstrate how to setup something similar up. Nearly all of the code is from Renanse's editors.

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.util.concurrent.Callable;
import jmetest.input.ControlImplementor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import com.jme.input.InputSystem;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.system.DisplaySystem;
import com.jme.system.canvas.JMECanvas;
import com.jme.system.lwjgl.LWJGLSystemProvider;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jmex.awt.input.AWTKeyInput;
import com.jmex.awt.input.AWTMouseInput;
import com.jmex.awt.lwjgl.LWJGLAWTCanvasConstructor;

public class ModelViewer extends JFrame {
   private static final long serialVersionUID = 1L;;
   private DisplaySystem display;
   private JPanel canvasPanel;
   private Canvas glCanvas;
   private int cwidth,cheight;
   private ControlImplementor impl;
   public static void main(String[] args) {
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
           public void run() {
              new ModelViewer();
   public ModelViewer(){
      //Create the JPanel that will hold our canvas
      canvasPanel = new JPanel();
      canvasPanel.setLayout(new BorderLayout());
      canvasPanel.setMinimumSize(new Dimension(150,150));
      //Set initial dimensions
      //Add canvas to the canvasPanel
      //Frame stuff
      this.setDefaultCloseOperation(EXIT_ON_CLOSE );
      this.setTitle("Canvas Example");
      this.setMaximumSize(new Dimension(640,480));
     * Create the rendering window to be embedded in the jPanel
     * From Renanse's RenParticleEditor.
     * @return glCanvas
   protected Canvas getGLCanvas(){
      if(glCanvas == null){


         // make the canvas:
           display = DisplaySystem.getDisplaySystem(LWJGLSystemProvider.LWJGL_SYSTEM_IDENTIFIER);
           display.registerCanvasConstructor("AWT", LWJGLAWTCanvasConstructor.class);
            glCanvas = (Canvas)display.createCanvas(cwidth, cheight);
            glCanvas.setMinimumSize(new Dimension(100, 100));

         // add a listener... if window is resized, we can do something about
         // it.
            glCanvas.addComponentListener(new ComponentAdapter() {
                public void componentResized(ComponentEvent ce) {
            //Add in a focus listener so the canvas can respond to mouse
            //and key inputs
         glCanvas.addFocusListener(new FocusListener() {

            public void focusGained(FocusEvent arg0) {
               ((AWTKeyInput) KeyInput.get()).setEnabled(true);
               ((AWTMouseInput) MouseInput.get()).setEnabled(true);

            public void focusLost(FocusEvent arg0) {
               ((AWTKeyInput) KeyInput.get()).setEnabled(false);
               ((AWTMouseInput) MouseInput.get()).setEnabled(false);

         KeyInput.setProvider( InputSystem.INPUT_SYSTEM_AWT );
         ((AWTKeyInput) KeyInput.get()).setEnabled(false);
         KeyListener kl = (KeyListener) KeyInput.get();
         AWTMouseInput.setup(glCanvas, true );

         // Important!  Here is where we add the guts to the canvas:
         //Normally we'd implement our own class that subclasses
         //SimpleCanvasImpl, which would handle our scene like
         //a regular JME App would do. For ease, I'm using
         //the ControlImplementor from Renanse's RenControlEditor.
         //impl = new MyImplementor(cwidth, cheight);
         impl = new ControlImplementor(cwidth,cheight);
         ((JMECanvas) glCanvas).setImplementor(impl);

            Callable<Void> exe = new Callable<Void>() {
                public Void call() {
                    ((JMECanvas) glCanvas).setTargetRate(60);
                    return null;
      return glCanvas;
    * Resizes the canvas when we resize the window.
    *  From Renanse's RenParticleEditor.
      protected void doResize() {
           if (impl != null) {
               impl.resizeCanvas(glCanvas.getWidth(), glCanvas.getHeight());
               if (impl.getCamera() != null) {
                   Callable<Void> exe = new Callable<Void>() {
                       public Void call() {
                                   (float) glCanvas.getWidth()
                                           / (float) glCanvas.getHeight(), 1,
                           return null;
    *  From Renanse's RenParticleEditor.
    public void forceUpdateToSize() {
        // force a resize to ensure proper canvas size.
        glCanvas.setSize(glCanvas.getWidth(), glCanvas.getHeight() + 1);
        glCanvas.setSize(glCanvas.getWidth(), glCanvas.getHeight() - 1);

Sweet, thanks. This is just what I need for my artists to do the converting, and send the .jme files to level designers who will use MW3D.

I suggest you check out PreviewTool:

PreviewTool was made be a model viewer application for viewing mesh.xml and md5 animated models, and as such you can choose the animation to play and speed in the viewer. You can change the view mode from wireframe, solid, textured and material.

In addition, it can import Ogre3D dotScene files, MD5 files (with Md5Importer library), and all other supported jME formats.

There's also a capability to export an entire scene to OBJ, JME, and JME-XML format.


There are a number of things I like about your tool, including the z axis fix for 3ds models.  I do have one problem though and I've had it with my own command line tools too, so this is probably a limitation of jme.  That is this:

When importing a model the reference to the texture files is stored as local to the machine on which you are running the import/export.  When the file is written out it writes this local reference.  If that resource is then deployed as an applet, the resource cannot be found. 

WARNING: Unable to locate: /C:/some_path/some_texture.jpg

Where some_path is the Texture Output Folder specified in the tool.  I assume you'd get the same results with a web start.

Anyway, have you had any experience with this?  Have you seen this working after deployment?

I've seen that error come up before in the logger, yet textures would still be found. Recently, though, I've been having missing textures whenever importing dxs files, but everything else works (e.g. 3ds). I've recently went from XP to Vista, and this only began after using Vista. Not to sure if there's any cause associated with that.

I'll definitely look into it*, but I have very little free time on my hands (burdened with college work, including a checkers client I've been writing for an engineering course, in which I ran into the mentioned error :wink: ). There are a number of fixes that I need to get in, as well as adding in texture copying/dae,md5,ogre3d importing.

And I still need to check out that model viewer momoko posted about too!

*Just tried webstart with some of my test models, they worked, but again the checker stuff I mentioned did not. Odd.