j3o models not loading consistently

Hello,



I am trying to load two .j3o models. One is a terrain made with the terrain editor, and it works fine. The other is a model I imported (the Ninja), and the same code that loads the terrain j3o does not work for the Ninja model. According to the tutorials, I am using the right commands, though I do find it confusing that some objects don’t seem to be added to the root node or any other node as far as I can tell. Also, I can’t find an explanation for the following code in the tutorial:



player_model = (Node) assetManager.loadModel(“Models/Ninja/Ninja.j3o”);



why is (Node) in there? Why not just:



player_model = assetManager.loadModel(“Models/Ninja/Ninja.j3o”);



In any event, the model refuses to load either way, even though it seems to have been imported properly ( I could see it in the import preview window). Can anyone help me understand this? Here is my code:



[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Spatial;

import com.jme3.math.ColorRGBA;

import com.jme3.input.ChaseCamera;

import com.jme3.scene.Node;





/**

  • test
  • @author normenhansen

    */

    public class Main extends SimpleApplication {



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    private Spatial scene_model;

    private Spatial player_model;



    @Override

    public void simpleInitApp() {

    init_cameras();

    init_models();

    }



    private void init_models() {

    player_model = (Node) assetManager.loadModel("Models/Ninja/Ninja.j3o");

    player_model.setLocalScale(10f);

    player_model.setLocalTranslation(0, 0, 0);

    rootNode.attachChild(player_model);



    scene_model = assetManager.loadModel("Scenes/TerrainTest.j3o");

    scene_model.setLocalTranslation(0, -100, 0);

    scene_model.setLocalScale(10f, 0.5f, 10f);

    rootNode.attachChild(scene_model);

    }



    private void init_cameras() {

    viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1));

    flyCam.setMoveSpeed(50);

    }



    @Override

    public void simpleUpdate(float tpf) {

    //TODO: add update code

    }



    @Override

    public void simpleRender(RenderManager rm) {

    //TODO: add render code

    }

    }

    [/java]



    Thanks in advance!

    Matt

I guess you miss a light. You can attach the ninja to the terrain if you added a light to it since its a Node (hence the cast to Node). https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:scenegraph_for_dummies

Thanks! I am confused though, does the model have to be cast as a Node to appear? I only did that because the tutorial did, but in the explanatory text it wasn’t there.



Thanks again,

Matt

No. The assetManager.loadModel() loads a Spatial…so this spatial can be instanced by its subclasses that can be a geometry, a node, etc. But in this case it’s instanced by a node object. So both lines below works:

[java]

Node player_model = (Node) assetManager.loadModel(“Models/Ninja/Ninja.j3o”);

[/java]

or

[java]

Spatial player_model = assetManager.loadModel(“Models/Ninja/Ninja.j3o”);

[/java]



It’s not a jme question, it’s a java question. You must learning more about “POLYMORPHISM”.

1 Like

I think that if a model contains more than 1 mesh it will return a Node, else a Geometry, but the end result is casted to a Spatial.

wezrule said:
I think that if a model contains more than 1 mesh it will return a Node, else a Geometry, but the end result is casted to a Spatial.


A model doens't contains meshes, it might to contains geometries ;P, and each geometry contains a mesh. And it isn't casted to a spatial, it's polymorphism ;P :
[java]
Monkey monkey = new Monkey();
Babbon babbon = new Babbon();
monkey = babbon;
[/java]
;)
1 Like
glaucomardano said:
A model doens't contains meshes, it might to contains geometries ;P, and each geometry contains a mesh. And it isn't casted to a spatial, it's polymorphism ;P :
[java]
Monkey monkey = new Monkey();
Babbon babbon = new Babbon();
monkey = babbon;
[/java]
;)

it is still casted to a spatial, look at the source code
wezrule said:
it is still casted to a spatial, look at the source code

[java]
public <T> T loadAsset(AssetKey<T> key){
if (eventListener != null)
eventListener.assetRequested(key);

AssetKey smartKey = null;
Object o = null;
if (key.shouldCache()){
if (key.useSmartCache()){
SmartAssetInfo smartInfo = cache.getFromSmartCache(key);
if (smartInfo != null){
smartKey = smartInfo.smartKey.get();
if (smartKey != null){
o = smartInfo.asset;
}
}
}else{
o = cache.getFromCache(key);
}
}
if (o == null){
AssetLoader loader = handler.aquireLoader(key);
if (loader == null){
throw new IllegalStateException("No loader registered for type "" +
key.getExtension() + """);
}

if (handler.getLocatorCount() == 0){
throw new IllegalStateException("There are no locators currently"+
" registered. Use AssetManager."+
"registerLocator() to register a"+
" locator.");
}

AssetInfo info = handler.tryLocate(key);
if (info == null){
throw new AssetNotFoundException(key.toString());
}

try {
o = loader.load(info);
} catch (IOException ex) {
throw new AssetLoadException("An exception has occured while loading asset: " + key, ex);
}
if (o == null){
throw new AssetLoadException("Error occured while loading asset "" + key + "" using" + loader.getClass().getSimpleName());
}else{
if (logger.isLoggable(Level.FINER)){
logger.log(Level.FINER, "Loaded {0} with {1}",
new Object[]{key, loader.getClass().getSimpleName()});
}

// do processing on asset before caching
o = key.postProcess(o);

if (key.shouldCache())
cache.addToCache(key, o);

if (eventListener != null)
eventListener.assetLoaded(key);
}
}

// object o is the asset
// create an instance for user
T clone = (T) key.createClonedInstance(o);

if (key.useSmartCache()){
if (smartKey != null){
// smart asset was already cached, use original key
((Asset)clone).setKey(smartKey);
}else{
// smart asset was cached on this call, use our key
((Asset)clone).setKey(key);
}
}

return clone;
}

public Spatial loadModel(ModelKey key){
return (Spatial) loadAsset(key);
}
[/java]

Yeah, of course the loadModel method casts it to Spatial because the ModelKey might be any kinda Spatial ;P.

yes :P, i was just contradicting this point you made - “And it isn’t casted to a spatial” :slight_smile:

Yep! Sorry! But that cast doesn’t make any difference, it’s just to return a spatial :), because the ModelKey was instanced by a kinda Spatial.