Program hang when loading models

I am loading .3ds or .obj models using the method ModelLoader.loadModel(File file); the program simply hang at this method, i'm just doing the simplest thing possible in the simpleInitGame() -> load the model as a node, then attach it to the rootNode. The following dump msg was from the log and it is stuck and no longer continuing:



Mar 17, 2007 1:19:29 PM com.jme.app.BaseGame start

INFO: Application started.

Mar 17, 2007 1:19:30 PM com.jme.system.PropertiesIO <init>

INFO: PropertiesIO created

Mar 17, 2007 1:19:30 PM com.jme.system.PropertiesIO load

INFO: Read properties

Mar 17, 2007 1:19:32 PM com.jme.input.joystick.DummyJoystickInput <init>

INFO: Joystick support is disabled

Mar 17, 2007 1:19:32 PM com.jme.system.lwjgl.LWJGLDisplaySystem <init>

INFO: LWJGL Display System created.

Mar 17, 2007 1:19:32 PM com.jme.system.lwjgl.LWJGLDisplaySystem getValidDisplayMode

INFO: Selected DisplayMode: 640 x 480 x 16 @60Hz

Mar 17, 2007 1:19:32 PM com.jme.system.PropertiesIO save

INFO: Saved properties

Mar 17, 2007 1:19:32 PM com.jme.app.BaseSimpleGame initSystem

INFO: jME version 0.11 beta

Mar 17, 2007 1:19:33 PM com.jme.renderer.lwjgl.LWJGLRenderer <init>

INFO: LWJGLRenderer created. W:

Alright now i can load models with texture using methods other than ModelLoader. Just one thing curious, what is the use of ModelLoader.loadModel(File file)? is it a new feature in the nightly build? How and when to use it?

i have the same problem :frowning:

Can you post the code that works so I can contrast it with what is in ModelLoader to help diagnose the problem?

the collada importer seems to work. just not modelloader

ModelLoader is a user created tool iirc, not an official part of jme

Actually, it is an official part of jmex that I wrote.  However, there are quite a few additions that have been posted by users.

The following code snipped was what i did, it was truly simple



protected void simpleInitGame() {

And sorry there is another question. I tried to load the same model exported as .DAE and the model loads correctly. Unfortunately i couldn't see the texture. In the latest version of JME, if a texture is missing, a warning message is logged and the texture will be replaced by a warning texture. Is that right? Well in my loading of .DAE model, I don't even see that kind of logging message. Does it mean that jme didn't even load these textures? Would anyone who have experience in loading collada files shed some lights and thanks in advance.



FYI:



collada version: 1.4.1 (dunno whether this one is causing the prob, but i manually change to 1.4.0 to no avail)

model tool: 3ds MAX 7.0

return future.get();



i dug deeper and this is the line it freezes on

If it hangs in this last line:



    public static Node loadModel( final File file ) throws Exception {
       // Add to resource locator
       SimpleResourceLocator locator = new SimpleResourceLocator(file.getParentFile().toURI());
        ResourceLocatorTool.addResourceLocator(ResourceLocatorTool.TYPE_TEXTURE, locator);
       
        String extension = extensionOf( file );

        ModelLoaderCallable callable = loaders.get( extension );
        if ( callable == null ) {
            throw new UnsupportedOperationException( "Unknown file type: " + file.getName() );
        }
        callable.setFile( file );
        Future<Node> future = GameTaskQueueManager.getManager().update( callable );
        return future.get();
    }



then it is a threading problem. This is saying that the GL thread should execute whatever the callable in loaders.get( extension )... it is either hanging there inside, or in the queue.

Maybe the ModelLoader only works in conjunction with StandardGame?

As in SimpleGame there is no separate OpenGl thread and stuff

ModelLoader should work on anything.

I have experienced this same problem, and the way to fix it is very interesting…



Since ModelLoader uses the GameTaskQueue, you need to call

GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE ).execute();



in your simpleUpdate method. However, this on its own does not solve the problem because whenever you try to call ModelLoader.loadModel from your main thread (say in simpleInit or simpleUpdate) it will not call the execute that is required for the future call to succeed.

Instead you should do something like this... first, make your Node volatile (private volatile Node model = null;) then in simpleInit:

         new Thread() {
             public void run() {
                try {
                   model  = ModelLoader.loadModel( new File( "model.3ds" ) );
                } catch( Exception e ) { e.printStackTrace(); }
             }
          }.start();



Finally in your simpleUpdate do:

       GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE ).execute();
       if( model != null && ! rootNode.hasChild( model ) )
          rootNode.attachChild( model );



Hope it helps

Multi threading is  :evil:



Similar issue with JMEDeskttopState



So, GameTaskQueue fixes things when using multi threading, but breaks things when using a single thread.


Hi,



can someone explaing why the ModelLoader uses the GameTaskQueueManager? When I replace it's method



   public static Node loadModel(final String file) throws Exception {

      String extension = extensionOf(file);

      ModelLoaderCallable callable = loaders.get(extension);
      if (callable == null) {
         throw new UnsupportedOperationException("Unknown file type: "
               + file);
      }
      callable.setFile(file);
      Future<Node> future = GameTaskQueueManager.getManager().update(
      callable );
      return future.get();
   }



by an equivalent method that does not use the GameTaskQueueManager


   public static Node loadModel(final String file) throws Exception {

      String extension = extensionOf(file);

      ModelLoaderCallable callable = loaders.get(extension);
      if (callable == null) {
         throw new UnsupportedOperationException("Unknown file type: "
               + file);
      }
      callable.setFile(file);
      return callable.call();
   }



then my program does not hang (as the original poster described).

I guess there is a reason for the usage of the GameTaskQueueManager?

Thanks in advance.
Artjom

No reason, it should not be in there. The user of the ModelLoader is responsible for calling this method in the GameTaskQueueManager if its not in the Open GL thread …



I will create a patch and report back.



EDIT: here we go: http://www.jmonkeyengine.com/forum/index.php?topic=13884

The program hangs because when you execute the loadModel() method inside your OpenGL thread and call future.get() the calling thread waits for the GameTaskQueue to return the result. The GameTaskQueue is processed by the OpenGL thread though, so the OGL thread waits for itself -> deadlock