Using JME model as terrain

Hi All,

I used MW3D to create terrain in JME Format, however I'm not pretty clear how to use it since after I import it,I got Node. Is there easy way to transfer it as TerrainBlock or Page? Or maybe I can use Node as terrain (not clear about this).



Kind Regards,

    ches

TerrainPage objects are nodes… You are supposed to get nodes in order to add them into the Scene graph.

so I can cast it? (can't try it right now)

quote from duenez on PM:


Only if the original node is actually a TerrainPage. If you are sure you created it and then exported it, then it is safe. You can use the SceneGraphDump http://www.jmonkeyengine.com/jmeforum/index.php?topic=6500.0 or some other inspecting tool to check what your objects actually are.

You can use models as terrain. See the test class TestObjectWalking in jME (I hope I got the name right this time…)

I checked the sample(TestObjectWalking ), it still creates a TerrainBlock, however I wonder if I understand the idea correctly - loading model as node, create terrainblock  and both get attached to a parent node,which is attached to root, so if I want to achieve FPS view (I already did this in other sample)

I have to create camNode then ?

What about the input is NodeHandler ok for this (FPS)?

Should I use the same trick to simulate attach to the terran - update cam location in update according to terrain height?

so here is the deal (code), I don't know how to made it FPS view…when there is no terrain how to calculate camNode location on Y axis (in update method)?



package com.captiveimagination.jmenet.flagrush;

import com.jme.app.AbstractGame.ConfigShowMode;
import com.jme.app.BaseGame;
import com.jme.app.SimpleGame;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.NodeHandler;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jme.util.export.binary.BinaryImporter;
import java.io.IOException;
import java.net.URL;

/**
 *
 * @author vlad
 */
public class TestTerrain  extends SimpleGame {

    private CameraNode camNode;
    private Spatial jmodel;
    private Node pickNode;
   
    /**
     * initializes the scene
     *
     * @see com.jme.app.BaseGame#initGame()
     */
    protected void simpleInitGame() {
        camNode = new CameraNode( "Camera Node", cam);
       input = new NodeHandler( camNode, 20f, 5 );
buildTerrain();
        pickNode.attachChild(camNode);
    }

    protected void simpleUpdate(){            
         input.update(tpf);
         camNode.setLocalTranslation(camNode.getLocalTranslation().x,
            jmodel.getLocalTranslation().y+4,
            camNode.getLocalTranslation().z);
    }   

    /**
     * build the height map and terrain block.
     */
    private void buildTerrain() {             
        try {
            //This should be updated to the latest BinaryImporter code once the model
            //is converted.
            URL bikeFile = TestTerrain.class.getClassLoader().getResource("com/captiveimagination/jmenet/flagrush/MyTerrain2.jme");
            BinaryImporter importer = new BinaryImporter();
            jmodel = (Spatial)importer.load(bikeFile.openStream());
         Quaternion q = new Quaternion();
         q.fromAngleAxis(0.5f, new Vector3f(0,1,0));
         jmodel.setLocalRotation(q);
            TextureState treeTex = display.getRenderer().createTextureState();
            //treeTex.setEnabled(true);
            Texture tr = TextureManager.loadTexture(
                    TestTerrain.class.getClassLoader().getResource(
                        "com/captiveimagination/jmenet/flagrush/texture/terrain.jpg"), Texture.MinificationFilter.Trilinear,
                Texture.MagnificationFilter.Bilinear);
            treeTex.setTexture(tr);
            jmodel.setRenderState(treeTex);
            jmodel.setModelBound(new BoundingBox());
            jmodel.updateModelBound();

            // Attach Children

            pickNode = new Node("Pick");
            pickNode.attachChild(jmodel);

            pickNode.updateGeometricState(0, true);

            rootNode.attachChild(pickNode);  
            pickNode.lockBounds();
            pickNode.lockTransforms();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }       

    public static void main(String[] args) {
      TestTerrain app = new TestTerrain();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
      app.start();
   }
}

You will probably need to pick the 'terrain' (from 'above') to get the actual 'world' location (terrain height)…

I can understand that I need the actual world terrain height, but I don't know how to get it :slight_smile:

"pick terrain from above" ? :?

ches said:

I can understand that I need the actual world terrain height, but I don't know how to get it :)
"pick terrain from above" ? :?



See the test class TestObjectWalking.

I saw it, but there are few confusing things about it:

1.Still TerrainBlock is created and is used to calculate "above"

2.When I create terrain block and load my model it looks like two separate terrains (maybe I have to duplicate terrain?)

3.Can I do it without creating terrain block? (just load model as terrain) ?

In the update method of TestObjectWalking (which momoko_fan pointed you to)  there is this:


   // This is called every frame. Do changing of values here.
   protected void simpleUpdate() {
      //lock camera to objects
      camRay.getOrigin().set(cam.getLocation());
      camResults.clear();
      pickNode.calculatePick(camRay, camResults);
       
        if(KeyInput.get().isKeyDown(KeyInput.KEY_BACKSLASH)) {
            pickNode.detachChild(bridge);
        }
   }



You see the pickNode.calculatePick(camRay, camResults)???

Thats IMPORTANT!

(The TerrainBlock is just there to put the 'stuff' on :P)

To Sum up, you have 2 options:
IF the terrain was exported out of MW3D as a TerrainPage or TerrainBlock, then you can probably just load it (from binary data)
however if it was not, then you will need to load it as a model and do 'manual' picking to find the 'location' (as is done in the TestObjectWalking)

(Perhaps this is a question for MonkeyWorld3D forums... ) http://mw3d.org/forum/

Remember that height map terrains simplify things a lot. If you're using a model, you might have bridges, overhangs etc. so you there might be two or more heights for a given point on the ground. That's why your code has to be more complicated than if you use just a heightmap (TerrainBlock).



There is no reason to create your terrain both as a terrainblock and as a model. If it is simple terrain then don't use a model. If it is complex then don't use a heightmap. You may want to use both - use the terrainblock as a base and then add detail with models. This is quite a popular approach and what TestObjectWalking does. But you still need to use the more complex code to check where the floor is just as if you were using all models. In this case the TerrainBlock is just another model - you aren't getting the simplicity of using the heightmap to find out where the floor is.

Thank you, I know understand the case of "pin" the pick, at first place I was mislead by the line:

cam.setLocation(new Vector3f(50, terrain.getHeight(50,50)+10, 50));

be then I figured out that once I go above the terrain I will be stuck above it actually (not just hanging in the air).

I found JME more and more intriguing.