Getting Geometry from Spatial

I wanna use LoD for that model of House2. I understand that first I must get geometry from it’s spatial.
Here’s my tree:

I’m trying to use:
[java]Geometry submesh = (Geometry) rootNode.getChild(“House2”).getUserData(“geo”); [/java]

but the submesh is still null

“geo” is not user data. It’s a child of House2. Try:

Geometry geo = (Geometry) rootNode.getChild(“House2″).getChild(“geo”);

Note that Geometry is a subclass of Spatial.


[java] Node house = (Node) rootNode.getChild(“House2”);
Geometry geo = (Geometry) house.getChild(“geo”); [/java]

now work

But any way dunno why LoD doesn’t work:

[java] Node house = (Node) rootNode.getChild(“Blacksmith”);
Geometry geo = (Geometry) house.getChild(“geo”);
LodGenerator lodGenerator = new LodGenerator(geo);
lodGenerator.bakeLods(LodGenerator.TriangleReductionMethod.PROPORTIONAL, 0.10f);

Tried for 2 models. Do i have to set smth in Scene Composer? And what exactly is .setLodLevel() because sometimes i get : out of range. Where I can find correct?

According to the Javadoc:

Level 0 indicates that the default index buffer should be used, levels [1, LodLevels + 1] represent the levels set on the mesh with Mesh.setLodLevels(com.jme3.scene.VertexBuffer[]).

OK. Sorry again for bumping… (I bumped something else last week). I guess I came late to JMonkey but the title is exactly what I entered for my search and I found a better solution.
Here is a better way to get your geometry from your loaded model. It does it in the constructor (or anywhere) but you don’t have to attach the model to the root node first so you don’t interrupt the flow of your code.
And, you know…, tabs are more efficient than using 4 spaces…

    //in constructor or where ever
    //Material antMaterial
    Spatial tempSpatial = app.getAssetManager().loadModel("Models/Ant/AntSphere2.j3o");
    antMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
    antMaterial.setBoolean("UseMaterialColors", true);
    ColorRGBA tempColor = new ColorRGBA(ColorRGBA.randomColor());
    antMaterial.setColor("Diffuse", tempColor);
    antMaterial.setColor("Ambient", tempColor);
    antMaterial.setColor("Specular", sunColor);//1.0f, 1.0f, 1.0f, 1f
    antMaterial.setFloat("Shininess", 128f);
    Geometry myGeo = getMyGeometry(tempSpatial);//so easy
    //System.out.println("myGeo=" + myGeo);
    myGeo.setQueueBucket(Bucket.Transparent);//makes this simple

	//this only finds and returns one geometry but
	//if you have more, you can change it to return
	//the list
	public Geometry getMyGeometry(Spatial spatial){
		Node node = (Node)spatial;
		Geometry g = null;
		final List<Spatial> ants = new LinkedList<Spatial>();
		//node.breadthFirstTraversal(new SceneGraphVisitor() {
		node.depthFirstTraversal(new SceneGraphVisitor() {
			public void visit(Spatial spatial) {
				//System.out.println("visit class is " + spatial.getClass().getName());
				//System.out.println("visit spatial is " + spatial);
				if (spatial.getClass().getName().equals("com.jme3.scene.Geometry")) {
		if (!ants.isEmpty()) {
			//redundant - borrowed from Quixote TerrainTrackControl
			for (int i = 0;i < ants.size();i++){
				if (ants.get(i).getClass().getName().equals("com.jme3.scene.Geometry")){
					g = (Geometry)ants.get(i);
					//System.out.println("g (" + i + "/" + (ants.size() - 1) + ")=" + g);
			System.out.println("getMyGeometry()-Geometry not found");

Only if you program in edlin. Every modern IDE (and by modern I mean since 1989 or so) can auto indent with the tab key.

But spaces look right everywhere and tabs are only guaranteed to look right where you enter them. (Which is why you have huge indents in the code above.)

The tyranny of tabs almost died with emacs (8 column tab stops plus spaces to fill in the gaps) but then Eclipse defaulted to real tabs and then somehow made it (seemingly) tough to toggle tabs to spaces and the world is back to 40 years ago. 1970s called and they want their mainframe 100 baud teletype optimization back.

Anyway… you go through a lot of trouble to get child geometry.

Working from the bottom up:
if (spatial.getClass().getName().equals(“com.jme3.scene.Geometry”))
…is the fragile poor man’s way of:
if (spatial instanceof Geometry)

Using a loop just to get the first element of a list that you only filled with geometry in the first place is also a bit strange.

Also, if you use SceneGraphVisitorAdapter instead of raw SceneGraphVisitor then you can avoid the check.

public Geometry getFirstGeometry(Spatial spatial) {
    if( spatial instanceof Geometry ) {
        return (Geometry)spatial;
    } else if( !(spatial instanceof Node) ) {
        return null;
    Geometry result = null;
    Node node = (Node)spatial;
    node.depthFirstTraversal(new SceneGraphVisitorAdapter(){
            public void visit( Geometry geom ) {
                if( result != null ) {
                    result = geom;
    return result;

In the end, that may not be the geometry you want as it will be the first geometry found in a depth first search. It’s always always always better to know the structure of your scene and simply ask for the child you want by name. Then the above code reduces to:

Geometry geom = ((Node)spatial).getChild(“nameOfChildIWant”);


Got it! But, I had to change it to

    Geometry myGeo = (Geometry)((Node)tempSpatial).getChild("Sphere1");
    //nice inner casting - you don't need to create a temporary variable just 
    //to cast tempSpatial and recast the result to Geometry.  

And…, I forgot, before, to quote the guy in one post that said that there is a big jump in the book/tutorial when they change from making cubes to loading models. They need a half chapter updating all the things that are different. For example, they START with the geometry and have it for transparency but, they don’t tell how to GET YOUR GEOMETRY from your model.
Thanks. This is much nicer.