Hi everyone,
I am just trying to get my custom TerrainPage (Heightmap) into BaseGame with waterRenderPass…
/*
* Copyright (c) 2003-2007 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package prototyp1;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import jmetest.terrain.TestTerrain;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.PointLight;
import com.jme.math.Plane;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Node;
import com.jme.scene.PassNode;
import com.jme.scene.PassNodeState;
import com.jme.scene.SceneElement;
import com.jme.scene.Skybox;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
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.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.effects.water.WaterRenderPass;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.MidPointHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
import com.jmex.terrain.util.RawHeightMap;
public class TestIsland extends BaseGame {
private WaterRenderPass waterEffectRenderPass;
private Skybox skybox;
private Quad waterQuad;
private float farPlane = 10000.0f;
private float textureScale = 0.02f;
protected LightState lightState;
private Spatial splatTerrain;
protected Timer timer;
private Camera cam;
private static final Logger logger = Logger.getLogger(Main.class
.getName());
protected InputHandler input;
private float tpf;
boolean pause;
private Node rootNode;
protected BasicPassManager pManager;
private float globalSplatScale = 90.0f;
public static void main( String[] args ) {
TestIsland app = new TestIsland();
app.setDialogBehaviour( ALWAYS_SHOW_PROPS_DIALOG );
app.start();
}
protected void cleanup() {
waterEffectRenderPass.cleanup();
}
private void setVertexCoords( float x, float y, float z ) {
FloatBuffer vertBuf = waterQuad.getVertexBuffer( 0 );
vertBuf.clear();
vertBuf.put( x - farPlane ).put( y ).put( z - farPlane );
vertBuf.put( x - farPlane ).put( y ).put( z + farPlane );
vertBuf.put( x + farPlane ).put( y ).put( z + farPlane );
vertBuf.put( x + farPlane ).put( y ).put( z - farPlane );
}
private void setTextureCoords( int buffer, float x, float y, float textureScale ) {
x *= textureScale * 0.5f;
y *= textureScale * 0.5f;
textureScale = farPlane * textureScale;
FloatBuffer texBuf;
texBuf = waterQuad.getTextureBuffer( 0, buffer );
texBuf.clear();
texBuf.put( x ).put( textureScale + y );
texBuf.put( x ).put( y );
texBuf.put( textureScale + x ).put( y );
texBuf.put( textureScale + x ).put( textureScale + y );
}
private void setupFog() {
FogState fogState = display.getRenderer().createFogState();
fogState.setDensity( 1.0f );
fogState.setEnabled( true );
fogState.setColor( new ColorRGBA( 1.0f, 1.0f, 1.0f, 1.0f ) );
fogState.setEnd( farPlane );
fogState.setStart( farPlane / 10.0f );
fogState.setDensityFunction( FogState.DF_LINEAR );
fogState.setApplyFunction( FogState.AF_PER_VERTEX );
rootNode.setRenderState( fogState );
}
private void buildSkyBox() {
skybox = new Skybox( "skybox", 10, 10, 10 );
String dir = "data/skybox/";
Texture north = TextureManager.loadTexture(
TestIsland.class.getClassLoader().getResource(
dir + "1.jpg" ),
Texture.MM_LINEAR,
Texture.FM_LINEAR );
Texture south = TextureManager.loadTexture(
TestIsland.class.getClassLoader().getResource(
dir + "3.jpg" ),
Texture.MM_LINEAR,
Texture.FM_LINEAR );
Texture east = TextureManager.loadTexture(
TestIsland.class.getClassLoader().getResource(
dir + "2.jpg" ),
Texture.MM_LINEAR,
Texture.FM_LINEAR );
Texture west = TextureManager.loadTexture(
TestIsland.class.getClassLoader().getResource(
dir + "4.jpg" ),
Texture.MM_LINEAR,
Texture.FM_LINEAR );
Texture up = TextureManager.loadTexture(
TestIsland.class.getClassLoader().getResource(
dir + "6.jpg" ),
Texture.MM_LINEAR,
Texture.FM_LINEAR );
Texture down = TextureManager.loadTexture(
TestIsland.class.getClassLoader().getResource(
dir + "5.jpg" ),
Texture.MM_LINEAR,
Texture.FM_LINEAR );
skybox.setTexture( Skybox.NORTH, north );
skybox.setTexture( Skybox.WEST, west );
skybox.setTexture( Skybox.SOUTH, south );
skybox.setTexture( Skybox.EAST, east );
skybox.setTexture( Skybox.UP, up );
skybox.setTexture( Skybox.DOWN, down );
skybox.preloadTextures();
CullState cullState = display.getRenderer().createCullState();
cullState.setCullMode( CullState.CS_NONE );
cullState.setEnabled( true );
skybox.setRenderState( cullState );
ZBufferState zState = display.getRenderer().createZBufferState();
zState.setEnabled( false );
skybox.setRenderState( zState );
FogState fs = display.getRenderer().createFogState();
fs.setEnabled( false );
skybox.setRenderState( fs );
skybox.setLightCombineMode( LightState.OFF );
skybox.setCullMode( SceneElement.CULL_NEVER );
skybox.setTextureCombineMode( TextureState.REPLACE );
skybox.updateRenderState();
skybox.lockBounds();
skybox.lockMeshes();
}
private void buildTerrain(){
RawHeightMap heightMap = new RawHeightMap(Main.class.getClassLoader().getResource(
"data/terrain/heights2.raw").getFile(), 129,
RawHeightMap.FORMAT_16BITLE, false);
Vector3f terrainScale = new Vector3f(30, 0.001f, 30);
heightMap.setHeightScale(0.001f);
// create a terrainblock
TerrainPage page = new TerrainPage("Terrain", 33, heightMap.getSize(),
terrainScale, heightMap.getHeightMap(), false);
page.getLocalTranslation().set(0, 5f, 0);
page.setDetailTexture(1, 1);
// create some interesting texturestates for splatting
TextureState ts1 = createSplatTextureState(
"data/terrain/rainforest_t1.jpg", null);
TextureState ts2 = createSplatTextureState(
"data/terrain/rainforest_t1.jpg",
"data/texture/darkrockalpha.png");
TextureState ts3 = createSplatTextureState(
"data/terrain/rainforest_t1.jpg",
"data/texture/deadalpha.png");
TextureState ts4 = createSplatTextureState(
"data/terrain/rainforest_t1.jpg",
"data/texture/grassalpha.png");
TextureState ts5 = createSplatTextureState(
"data/terrain/rainforest_t1.jpg",
"data/texture/grassalpha.png");
TextureState ts6 = createLightmapTextureState("data/terrain/lightmap.jpg");
// alpha used for blending the passnodestates together
AlphaState as = display.getRenderer().createAlphaState();
as.setBlendEnabled(true);
as.setSrcFunction(AlphaState.SB_SRC_ALPHA);
as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
as.setTestEnabled(true);
as.setTestFunction(AlphaState.TF_GREATER);
as.setEnabled(true);
// alpha used for blending the lightmap
AlphaState as2 = display.getRenderer().createAlphaState();
as2.setBlendEnabled(true);
as2.setSrcFunction(AlphaState.SB_DST_COLOR);
as2.setDstFunction(AlphaState.DB_SRC_COLOR);
as2.setTestEnabled(true);
as2.setTestFunction(AlphaState.TF_GREATER);
as2.setEnabled(true);
// //////////////////// PASS STUFF START
// try out a passnode to use for splatting
PassNode splattingPassNode = new PassNode("SplatPassNode");
splattingPassNode.attachChild(page);
PassNodeState passNodeState = new PassNodeState();
passNodeState.setPassState(ts1);
splattingPassNode.addPass(passNodeState);
passNodeState = new PassNodeState();
passNodeState.setPassState(ts2);
passNodeState.setPassState(as);
splattingPassNode.addPass(passNodeState);
passNodeState = new PassNodeState();
passNodeState.setPassState(ts3);
passNodeState.setPassState(as);
splattingPassNode.addPass(passNodeState);
passNodeState = new PassNodeState();
passNodeState.setPassState(ts4);
passNodeState.setPassState(as);
splattingPassNode.addPass(passNodeState);
passNodeState = new PassNodeState();
passNodeState.setPassState(ts5);
passNodeState.setPassState(as);
splattingPassNode.addPass(passNodeState);
passNodeState = new PassNodeState();
passNodeState.setPassState(ts6);
passNodeState.setPassState(as2);
splattingPassNode.addPass(passNodeState);
// //////////////////// PASS STUFF END
// lock some things to increase the performance
splattingPassNode.lockBounds();
splattingPassNode.lockTransforms();
splattingPassNode.lockShadows();
splatTerrain = splattingPassNode;
}
private TextureState createSplatTextureState(String texture, String alpha) {
TextureState ts = display.getRenderer().createTextureState();
Texture t0 = TextureManager.loadTexture(TestIsland.class
.getClassLoader().getResource(texture),
Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
t0.setWrap(Texture.WM_WRAP_S_WRAP_T);
t0.setApply(Texture.AM_MODULATE);
t0.setScale(new Vector3f(globalSplatScale, globalSplatScale, 1.0f));
ts.setTexture(t0, 0);
if (alpha != null) {
addAlphaSplat(ts, alpha);
}
return ts;
}
private TextureState createLightmapTextureState(String texture) {
TextureState ts = display.getRenderer().createTextureState();
Texture t0 = TextureManager.loadTexture(TestIsland.class
.getClassLoader().getResource(texture),
Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
t0.setWrap(Texture.WM_WRAP_S_WRAP_T);
ts.setTexture(t0, 0);
return ts;
}
private void addAlphaSplat(TextureState ts, String alpha) {
Texture t1 = TextureManager.loadTexture(TestIsland.class
.getClassLoader().getResource(alpha), Texture.MM_LINEAR_LINEAR,
Texture.FM_LINEAR);
t1.setWrap(Texture.WM_WRAP_S_WRAP_T);
t1.setApply(Texture.AM_COMBINE);
t1.setCombineFuncRGB(Texture.ACF_REPLACE);
t1.setCombineSrc0RGB(Texture.ACS_PREVIOUS);
t1.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
t1.setCombineFuncAlpha(Texture.ACF_REPLACE);
ts.setTexture(t1, ts.getNumberOfSetTextures());
}
private void setupKeyBindings() {
KeyBindingManager.getKeyBindingManager().set( "g", KeyInput.KEY_G );
KeyBindingManager.getKeyBindingManager().set( "e", KeyInput.KEY_E );
KeyBindingManager.getKeyBindingManager().set( "lower", KeyInput.KEY_H );
KeyBindingManager.getKeyBindingManager().set( "higher", KeyInput.KEY_Y );
KeyBindingManager.getKeyBindingManager().set( "1", KeyInput.KEY_1 );
KeyBindingManager.getKeyBindingManager().set( "2", KeyInput.KEY_2 );
}
@Override
protected void initGame() {
pManager = new BasicPassManager();
rootNode = new Node( "rootNode" );
ZBufferState buf = display.getRenderer().createZBufferState();
buf.setEnabled( true );
buf.setFunction( ZBufferState.CF_LEQUAL );
rootNode.setRenderState( buf );
PointLight light = new PointLight();
light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );
light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 1.0f ) );
light.setLocation( new Vector3f( 100, 100, 100 ) );
light.setEnabled( true );
lightState = display.getRenderer().createLightState();
lightState.setEnabled( true );
lightState.attach( light );
rootNode.setRenderState( lightState );
timer.reset();
cam.setFrustumPerspective( 45.0f, (float) display.getWidth() / (float) display.getHeight(), 1f, farPlane );
cam.setLocation( new Vector3f( 100, 50, 100 ) );
cam.lookAt( new Vector3f( 0, 0, 0 ), Vector3f.UNIT_Y );
cam.update();
setupKeyBindings();
setupFog();
buildTerrain();
Node reflectedNode = new Node( "reflectNode" );
buildSkyBox();
reflectedNode.attachChild( skybox );
rootNode.attachChild( reflectedNode );
waterEffectRenderPass = new WaterRenderPass( cam, 4, false, true );
waterEffectRenderPass.setWaterPlane( new Plane( new Vector3f( 0.0f, 1.0f, 0.0f ), 0.0f ) );
waterQuad = new Quad( "waterQuad", 1, 1 );
FloatBuffer normBuf = waterQuad.getNormalBuffer( 0 );
normBuf.clear();
normBuf.put( 0 ).put( 1 ).put( 0 );
normBuf.put( 0 ).put( 1 ).put( 0 );
normBuf.put( 0 ).put( 1 ).put( 0 );
normBuf.put( 0 ).put( 1 ).put( 0 );
waterEffectRenderPass.setWaterEffectOnSpatial( waterQuad );
rootNode.attachChild( waterQuad );
waterEffectRenderPass.setReflectedScene( reflectedNode );
waterEffectRenderPass.setSkybox( skybox );
pManager.add( waterEffectRenderPass );
RenderPass rootPass = new RenderPass();
rootPass.add( rootNode );
pManager.add( rootPass );
rootNode.setCullMode( SceneElement.CULL_NEVER);
rootNode.setRenderQueueMode( Renderer.QUEUE_OPAQUE );
rootNode.updateGeometricState( 0.0f, true );
rootNode.updateRenderState();
timer.reset();
}
@Override
protected void initSystem() {
logger.info(getVersion());
try {
display = DisplaySystem.getDisplaySystem( properties.getRenderer() );
display.createWindow( properties.getWidth(), properties.getHeight(),
properties.getDepth(), properties.getFreq(), properties
.getFullscreen() );
logger.info("Running on: " + display.getAdapter()
+ "nDriver version: " + display.getDriverVersion() + "n"
+ display.getDisplayVendor() + " - "
+ display.getDisplayRenderer() + " - "
+ display.getDisplayAPIVersion());
cam = display.getRenderer().createCamera( display.getWidth(),
display.getHeight() );
} catch ( JmeException e ) {
logger.log(Level.SEVERE, "Could not create displaySystem", e);
System.exit( 1 );
}
display.getRenderer().setBackgroundColor(ColorRGBA.blue.clone());
cam.setFrustumPerspective(45.0f, (float)display.getWidth() / (float)display.getHeight(), 1, 1000);
Vector3f loc = new Vector3f(20.0f, 0.0f, 0.0f);
Vector3f left = new Vector3f(0.0f, 0.0f, -1.0f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f dir = new Vector3f(-1.0f, 0f, 0.0f);
cam.setFrame(loc, left, up, dir);
cam.update();
display.getRenderer().setCamera( cam );
FirstPersonHandler firstPersonHandler = new FirstPersonHandler( cam, 50,
1 );
input = firstPersonHandler;
timer = Timer.getTimer();
/** Sets the title of our display. */
String className = getClass().getName();
if ( className.lastIndexOf( '.' ) > 0 ) className = className.substring( className.lastIndexOf( '.' )+1 );
display.setTitle( className );
display.getRenderer().enableStatistics( true );
KeyBindingManager.getKeyBindingManager().set( "exit",
KeyInput.KEY_ESCAPE );
}
@Override
protected void reinit() {
}
@Override
protected void render(float interpolation) {
Renderer r = display.getRenderer();
r.clearStatistics();
r.clearBuffers();
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER).execute();
pManager.renderPasses(display.getRenderer());
}
@Override
protected void update(float interpolation) {
timer.update();
tpf = timer.getTimePerFrame();
input.update( tpf );
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.UPDATE).execute();
if ( KeyBindingManager.getKeyBindingManager().isValidCommand( "exit",
false ) ) {
finished = true;
}
skybox.getLocalTranslation().set( cam.getLocation() );
skybox.updateGeometricState( 0.0f, true );
Vector3f transVec = new Vector3f( cam.getLocation().x, waterEffectRenderPass.getWaterHeight(), cam.getLocation().z );
setTextureCoords( 0, transVec.x, -transVec.z, textureScale );
setVertexCoords( transVec.x, transVec.y, transVec.z );
rootNode.updateGeometricState(tpf, true);
pManager.updatePasses(tpf);
}
}
The water and skybox is working. But there is no terrain on the water. When I use TerrainBlock with this implementation is works but is all black!
Any ideas why the TerrainPage doesn't show anything?
Thanks so much, Rapidm