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
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