Here is my code so far.
package test;
import java.net.URL;
import javax.swing.ImageIcon;
import jmetest.renderer.TestSkybox;
import jmetest.terrain.TestTerrain;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
public class testTerrain extends BaseGame{
//terrain block for the terrain
private TerrainBlock tb;
//the skybox
private Skybox skybox;
//timer for the game to obtain framerate
protected Timer timer;
//camera for the game
private Camera cam;
//variables for storing display properties
private int width, height, depth, freq;
//boolean for fullscreen
private boolean fullscreen;
//the root node of the scene graph
private Node scene;
//TextureState to show the monkey on the sphere.
private TextureState ts;
//entry point
public static void main(String[] args) {
//create and initialise new application
testTerrain app = new testTerrain();
app.setConfigShowMode(ConfigShowMode.AlwaysShow);
app.start();
}
@Override
/**
* clean up the textures.
*
*/
protected void cleanup() {
ts.deleteAll();
}
@Override
protected void initGame() {
scene = new Node("Scene graph node");
/** Create a ZBuffer to display pixels closest to the camera above farther ones. */
ZBufferState buf = display.getRenderer().createZBufferState();
buf.setEnabled(true);
buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
scene.setRenderState(buf);
//Add terrain to the scene
buildTerrain();
//Light the world
buildLighting();
//Add the skybox
buildSkyBox();
// update the scene graph for rendering
scene.updateGeometricState(0.0f, true);
scene.updateRenderState();
}
@Override
protected void initSystem() {
//store the display properties information
width = this.settings.getWidth();
height = this.settings.getHeight();
depth = this.settings.getDepth();
freq = this.settings.getFrequency();
fullscreen = this.settings.isFullscreen();
//chech that display properties work, if not then exit
try {
display = DisplaySystem.getDisplaySystem(this.settings.getRenderer());
display.createWindow(width, height, depth, freq, fullscreen);
cam = display.getRenderer().createCamera(width, height);
} catch (JmeException e) {
e.printStackTrace();
System.exit(1);
}
//set the background to black
display.getRenderer().setBackgroundColor(ColorRGBA.black);
//initialize the camera
cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
Vector3f loc = new Vector3f(1.0f, 1.0f, 1.0f);
Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f dir = new Vector3f(-0.5f, 0.0f, -0.5f);
// Move our camera to a correct place and orientation.
cam.setFrame(loc, left, up, dir);
/** Signal that we've changed our camera's location/frustum. */
cam.update();
display.getRenderer().setCamera(cam);
/** Get a high resolution timer for FPS updates. */
timer = Timer.getTimer();
KeyBindingManager.getKeyBindingManager().set("exit",
KeyInput.KEY_ESCAPE);
}
@Override
/**
* will be called if the resolution changes
*
*/
protected void reinit() {
display.recreateWindow(width, height, depth, freq, fullscreen);
}
@Override
/**
* draws the scene graph
*/
protected void render(float interpolation) {
//Clear the screen
display.getRenderer().clearBuffers();
display.getRenderer().draw(scene);
}
@Override
/**
* During an update we only look for the escape button and update the timer
* to get the framerate.
*/
protected void update(float interpolation) {
//update the time to get the framerate
timer.update();
interpolation = timer.getTimePerFrame();
//if escape was pressed, we exit
if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
finished = true;
}
//we want to keep the skybox around our eyes, so move it with
//the camera
skybox.setLocalTranslation(cam.getLocation());
}
private void buildTerrain() {
URL heightMapImage = testTerrain.class.getClassLoader().getResource("data/heightmap.png");
ImageBasedHeightMap heightMap = new ImageBasedHeightMap(
new ImageIcon(heightMapImage).getImage()
);
// Scale the data
Vector3f terrainScale = new Vector3f(1000, 0.0575f, 4);
// create a terrainblock
tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
heightMap.getHeightMap(), new Vector3f(0, 0, 0));
tb.setModelBound(new BoundingBox());
tb.updateModelBound();
// generate a terrain texture with 2 textures
ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
heightMap);
pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
.getResource("jmetest/data/texture/grassb.png")), -128, 0, 128);
pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
.getResource("jmetest/data/texture/dirt.jpg")), 0, 128, 255);
pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
.getResource("jmetest/data/texture/highest.jpg")), 128, 255,
384);
pt.createTexture(32);
// assign the texture to the terrain
TextureState ts = display.getRenderer().createTextureState();
ts.setEnabled(true);
Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
ts.setTexture(t1, 0);
tb.setRenderState(ts);
}
/**
* creates a light for the terrain.
*/
private void buildLighting() {
/** Set up a basic, default light. */
DirectionalLight light = new DirectionalLight();
light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
light.setDirection(new Vector3f(1,-1,0));
light.setEnabled(true);
/** Attach the light to a lightState and the lightState to rootNode. */
LightState lightState = display.getRenderer().createLightState();
lightState.setEnabled(true);
lightState.attach(light);
scene.setRenderState(lightState);
}
/**
* buildSkyBox creates a new skybox object with all the proper textures. The
* textures used are the standard skybox textures from all the tests.
*
*/
private void buildSkyBox() {
skybox = new Skybox("skybox", 10, 10, 10);
Texture north = TextureManager.loadTexture(
TestSkybox.class.getClassLoader().getResource(
"jmetest/data/texture/north.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear);
Texture south = TextureManager.loadTexture(
TestSkybox.class.getClassLoader().getResource(
"jmetest/data/texture/south.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear);
Texture east = TextureManager.loadTexture(
TestSkybox.class.getClassLoader().getResource(
"jmetest/data/texture/east.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear);
Texture west = TextureManager.loadTexture(
TestSkybox.class.getClassLoader().getResource(
"jmetest/data/texture/west.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear);
Texture up = TextureManager.loadTexture(
TestSkybox.class.getClassLoader().getResource(
"jmetest/data/texture/top.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear);
Texture down = TextureManager.loadTexture(
TestSkybox.class.getClassLoader().getResource(
"jmetest/data/texture/bottom.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear);
skybox.setTexture(Skybox.Face.North, north);
skybox.setTexture(Skybox.Face.West, west);
skybox.setTexture(Skybox.Face.South, south);
skybox.setTexture(Skybox.Face.East, east);
skybox.setTexture(Skybox.Face.Up, up);
skybox.setTexture(Skybox.Face.Down, down);
skybox.preloadTextures();
scene.attachChild(skybox);
}
}
I cannot see the terrain! :(
I have tried playing about with the numbers but really I have no idea which number does what so I have been at a loss with it.
I tried to look through the API for clues but that thing confuses me so much.
Anyway, my ventures into the unknown have left me with a few questions.
Firstly number one!
1 - Where is my Terrain? Can anyone tell why I can't see it? I'm sure it is a scaling issue or to do with the placement of something, either the camera or the terrain, but I don't know what is placed where and with respect to which point of the object. FYI heightmap.png is a 127x127, dunno if the resolution of this makes a difference.
2 - I have been looking at the Vector3f things the next few questions are a cascade of inquiries in this vein. My first question is, what actually is a Vector3f? I would assume that they are vectors (I came up with that one myself, no help at all) but then, just a vector is a bit abstract. Vectors need starting positions, scale and icecream. Then looking at the camera settings I have loc, left, up and dir each with their own associated vectors3f. Some places they are used they seem not to be used as vectors but merely as arrays (like the scale for terrain scale) what's the deal with this?
3 - Is there a standard way that vector3f's are laid out? ie. Vector3f ( x value, y value, z value)
4 - What do the values represent here?
// Scale the data
Vector3f terrainScale = new Vector3f(1000, 0.0575f, 4);
5 - what is going on here? I'd like to think that I understand it but frankly I don't;
//initialize the camera
cam.setFrustumPerspective(45.0f, (float)width / (float)height, 1, 1000);
Vector3f loc = new Vector3f(1.0f, 1.0f, 1.0f);
Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f dir = new Vector3f(-0.5f, 0.0f, -0.5f);
// Move our camera to a correct place and orientation.
cam.setFrame(loc, left, up, dir);
/** Signal that we've changed our camera's location/frustum. */
cam.update();
I'm fairly happy with the rest of it and think that I understand it well enough to get on, but the bits I have outlined, I just don't get and they are slowing up my progress so I'd appreciate any help.
Thanks
Neilos