This is my version of the “swimming” example on the site. It is actually a falling and walking on the sea bed example. I found a water.isUnderWater(); for the camera, but that doesn’t sound promising either as a character may have his/her head outside the water. How can I tell if a character is underwater and give him swimming physics and controls?
package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.renderer.RenderManager;
import com.jme3.texture.Texture;
import com.jme3.input.controls.;
import com.jme3.light.;
import com.jme3.post.FilterPostProcessor;
import com.jme3.scene.control.CameraControl;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.;
import com.jme3.water.WaterFilter;
import com.jme3.scene.;
import com.jme3.math.;
import com.jme3.util.;
import com.jme3.texture.Texture.;
import com.jme3.scene.shape.;
import com.jme3.bullet.;
import com.jme3.bullet.control.;
import com.jme3.input.*;
/**
-
test
-
@author normenhansen
*/
public class WaterSimple extends SimpleApplication implements ActionListener {
private boolean rotateLeft = false;
private boolean rotateRight = false;
private boolean forward = false;
private boolean backward = false;
private BetterCharacterControl landControl;
private BetterCharacterControl waterControl;
private Node player;
private Vector3f walkDirection = new Vector3f(0,0,0);
private Vector3f viewDirection = new Vector3f(0,0,1);
private float speed = 20;
private Vector3f lightDir = new Vector3f(-2.9f, -1.2f, -5.8f);
private WaterFilter water;
private TerrainQuad terrain;
private float time = 0.0f;
private float waterHeight = 0.0f;
private float initialWaterHeight = 0.8f;
private Node reflectedScene;
private BulletAppState landAppState;public static void main(String[] args) {
WaterSimple app = new WaterSimple();
app.start();
}@Override
public void simpleInitApp() {
setDisplayFps(false);
setDisplayStatView(false);reflectedScene=new Node("Reflected Scene"); rootNode.attachChild(reflectedScene); FilterPostProcessor fpp = new FilterPostProcessor(assetManager); viewPort.addProcessor(fpp); // add water water = new WaterFilter(reflectedScene, lightDir); water.setLightColor(ColorRGBA.White); water.setWindDirection(Vector2f.UNIT_XY); water.setLightDirection(lightDir); water.setSunScale(3); water.setWaveScale(0.005f); water.setMaxAmplitude(5); water.setWaterTransparency(.1f); water.setWaterColor(new ColorRGBA(0.1f, 0.6f, 0.9f, 1.0f)); water.setDeepWaterColor(new ColorRGBA(0.0f, 0.0f, 0.1f, 1.0f)); water.setWaterHeight(initialWaterHeight); fpp.addFilter(water); initScene(); settings.setFrameRate(60); viewPort.setBackgroundColor(ColorRGBA.Cyan); landAppState = new BulletAppState(); stateManager.attach(landAppState); RigidBodyControl scenePhy = new RigidBodyControl(0f); reflectedScene.addControl(scenePhy); landAppState.getPhysicsSpace().add(reflectedScene); rootNode.attachChild( reflectedScene ); landAppState.getPhysicsSpace().setGravity( new Vector3f(0,-9.81f,0) ); walkDirection.set(0, 0, 0); player = (Node) assetManager.loadModel("Models/RattleSnakey/RattleSnakey.mesh.j3o"); player.setLocalTranslation( new Vector3f(50,6,0) ); landControl = new BetterCharacterControl(1.5f , 4, 30f); landControl = new BetterCharacterControl(1.5f , 4, 30f); landControl.setJumpForce( new Vector3f(0,300,0) ); landControl.setGravity( new Vector3f(0,-10,0) ); landControl.setGravity( new Vector3f(0,-10,0) ); player.addControl(landControl); player.addControl(landControl); landAppState.getPhysicsSpace().add(landControl); inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W) ); inputManager.addMapping("Back", new KeyTrigger(KeyInput.KEY_S) ); inputManager.addMapping("Rotate Left", new KeyTrigger(KeyInput.KEY_A) ); inputManager.addMapping("Rotate Right", new KeyTrigger(KeyInput.KEY_D) ); inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE) ); inputManager.addListener(this, "Rotate Left", "Rotate Right" ); inputManager.addListener(this, "Forward", "Back", "Jump" ); reflectedScene.attachChild(player); // Third person camera flyCam.setEnabled(false); ChaseCamera camNode = new ChaseCamera(cam, player, inputManager); camNode.setDragToRotate(true);
}
@Override
public void simpleUpdate(float tpf) {
// Get current forward and left vectors of the player:
Vector3f modelForwardDir = player.getWorldRotation().mult(Vector3f.UNIT_Z);
Vector3f modelLeftDir = player.getWorldRotation().mult(Vector3f.UNIT_X);
// Depending on which nav keys are pressed, determine the change in directionwalkDirection.set(0, 0, 0); if (forward) { walkDirection.addLocal(modelForwardDir.mult(speed)); } else if (backward) { walkDirection.addLocal(modelForwardDir.mult(speed).negate()); } landControl.setWalkDirection(walkDirection); // Depending on which nav keys are pressed, determine the change in rotation if (rotateLeft) { Quaternion rotateL = new Quaternion().fromAngleAxis(FastMath.PI * tpf, Vector3f.UNIT_Y); rotateL.multLocal(viewDirection); } else if (rotateRight) { Quaternion rotateR = new Quaternion().fromAngleAxis(-FastMath.PI * tpf, Vector3f.UNIT_Y); rotateR.multLocal(viewDirection); } landControl.setViewDirection(viewDirection); // simulate tides by varying the height of the water plane time += tpf; waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f; water.setWaterHeight(initialWaterHeight + waterHeight);
}
private TerrainQuad createTerrain() {
Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/heightmap.png"); Material terrainMat = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md"); terrainMat.setBoolean("useTriPlanarMapping", false); terrainMat.setBoolean("WardIso", true); terrainMat.setTexture("AlphaMap", assetManager.loadTexture("Textures/Terrain/alphamap.png")); Texture grass = assetManager.loadTexture("Textures/Terrain/grass.jpg"); grass.setWrap(WrapMode.Repeat); terrainMat.setTexture("DiffuseMap_1", grass); terrainMat.setFloat("DiffuseMap_1_scale", 64); Texture normalMap1 = assetManager.loadTexture( "Textures/Terrain/grass_normal.jpg"); normalMap1.setWrap(WrapMode.Repeat); terrainMat.setTexture("NormalMap_1", normalMap1); Texture rock = assetManager.loadTexture("Textures/Terrain/rock.png"); rock.setWrap(WrapMode.Repeat); terrainMat.setTexture("DiffuseMap", rock); terrainMat.setFloat("DiffuseMap_0_scale", 64); Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/rock_normal.png"); normalMap0.setWrap(WrapMode.Repeat); terrainMat.setTexture("NormalMap", normalMap0); Texture road = assetManager.loadTexture("Textures/Terrain/road.png"); road.setWrap(WrapMode.Repeat); terrainMat.setTexture("DiffuseMap_2", road); terrainMat.setFloat("DiffuseMap_2_scale", 64); Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/road_normal.png"); normalMap2.setWrap(WrapMode.Repeat); terrainMat.setTexture("NormalMap_2", normalMap2); AbstractHeightMap heightmap = null; try { heightmap = new ImageBasedHeightMap(heightMapImage.getImage(), .5f); heightmap.load(); } catch (Exception e) { e.printStackTrace(); } heightmap.smooth(0.9f,3); terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap()); terrain.setMaterial(terrainMat); terrain.scale(4, 4, 4); terrain.move(0,-110,200); return terrain;
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}private void initScene() {
// reflectedScene node groups everything that reflects in water,
// including terrain, skyË› light, but not the water itself.
DirectionalLight sun = new DirectionalLight();
sun.setDirection(lightDir);
sun.setColor(ColorRGBA.White.clone().multLocal(1.7f));
reflectedScene.addLight(sun);AmbientLight ambientLight = new AmbientLight(); reflectedScene.addLight(ambientLight); Spatial sky = SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", false); reflectedScene.attachChild(sky); reflectedScene.attachChild(createTerrain());
}
public void onAction(String binding, boolean isPressed, float tpf) {
if (binding.equals(“Rotate Left”)) {
rotateLeft = isPressed;
} else if (binding.equals(“Rotate Right”)) {
rotateRight = isPressed;
} else
if (binding.equals(“Forward”)) {
forward = isPressed;
} else if (binding.equals(“Back”)) {
backward = isPressed;
} else
if (binding.equals(“Jump”)) {
landControl.jump();
}
}
}