Home | History | Annotate | Download | only in terrain
      1 package jme3test.terrain;
      2 
      3 import com.jme3.app.SimpleApplication;
      4 import com.jme3.app.state.ScreenshotAppState;
      5 import com.jme3.asset.plugins.HttpZipLocator;
      6 import com.jme3.asset.plugins.ZipLocator;
      7 import com.jme3.bullet.BulletAppState;
      8 import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
      9 import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
     10 import com.jme3.bullet.control.CharacterControl;
     11 import com.jme3.bullet.control.RigidBodyControl;
     12 import com.jme3.input.KeyInput;
     13 import com.jme3.input.controls.ActionListener;
     14 import com.jme3.input.controls.KeyTrigger;
     15 import com.jme3.light.DirectionalLight;
     16 import com.jme3.material.Material;
     17 import com.jme3.math.ColorRGBA;
     18 import com.jme3.math.Vector3f;
     19 import com.jme3.terrain.geomipmap.TerrainGrid;
     20 import com.jme3.terrain.geomipmap.TerrainGridListener;
     21 import com.jme3.terrain.geomipmap.TerrainLodControl;
     22 import com.jme3.terrain.geomipmap.TerrainQuad;
     23 import com.jme3.terrain.geomipmap.grid.ImageTileLoader;
     24 import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
     25 import com.jme3.terrain.heightmap.Namer;
     26 import com.jme3.texture.Texture;
     27 import com.jme3.texture.Texture.WrapMode;
     28 import java.io.File;
     29 
     30 public class TerrainGridTest extends SimpleApplication {
     31 
     32     private Material mat_terrain;
     33     private TerrainGrid terrain;
     34     private float grassScale = 64;
     35     private float dirtScale = 16;
     36     private float rockScale = 128;
     37     private boolean usePhysics = false;
     38     private boolean physicsAdded = false;
     39 
     40     public static void main(final String[] args) {
     41         TerrainGridTest app = new TerrainGridTest();
     42         app.start();
     43     }
     44     private CharacterControl player3;
     45 
     46     @Override
     47     public void simpleInitApp() {
     48         File file = new File("TerrainGridTestData.zip");
     49         if (!file.exists()) {
     50             assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
     51         } else {
     52             assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
     53         }
     54 
     55         this.flyCam.setMoveSpeed(100f);
     56         ScreenshotAppState state = new ScreenshotAppState();
     57         this.stateManager.attach(state);
     58 
     59         // TERRAIN TEXTURE material
     60         this.mat_terrain = new Material(this.assetManager, "Common/MatDefs/Terrain/HeightBasedTerrain.j3md");
     61 
     62         // Parameters to material:
     63         // regionXColorMap: X = 1..4 the texture that should be appliad to state X
     64         // regionX: a Vector3f containing the following information:
     65         //      regionX.x: the start height of the region
     66         //      regionX.y: the end height of the region
     67         //      regionX.z: the texture scale for the region
     68         //  it might not be the most elegant way for storing these 3 values, but it packs the data nicely :)
     69         // slopeColorMap: the texture to be used for cliffs, and steep mountain sites
     70         // slopeTileFactor: the texture scale for slopes
     71         // terrainSize: the total size of the terrain (used for scaling the texture)
     72         // GRASS texture
     73         Texture grass = this.assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
     74         grass.setWrap(WrapMode.Repeat);
     75         this.mat_terrain.setTexture("region1ColorMap", grass);
     76         this.mat_terrain.setVector3("region1", new Vector3f(88, 200, this.grassScale));
     77 
     78         // DIRT texture
     79         Texture dirt = this.assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
     80         dirt.setWrap(WrapMode.Repeat);
     81         this.mat_terrain.setTexture("region2ColorMap", dirt);
     82         this.mat_terrain.setVector3("region2", new Vector3f(0, 90, this.dirtScale));
     83 
     84         // ROCK texture
     85         Texture rock = this.assetManager.loadTexture("Textures/Terrain/Rock2/rock.jpg");
     86         rock.setWrap(WrapMode.Repeat);
     87         this.mat_terrain.setTexture("region3ColorMap", rock);
     88         this.mat_terrain.setVector3("region3", new Vector3f(198, 260, this.rockScale));
     89 
     90         this.mat_terrain.setTexture("region4ColorMap", rock);
     91         this.mat_terrain.setVector3("region4", new Vector3f(198, 260, this.rockScale));
     92 
     93         this.mat_terrain.setTexture("slopeColorMap", rock);
     94         this.mat_terrain.setFloat("slopeTileFactor", 32);
     95 
     96         this.mat_terrain.setFloat("terrainSize", 129);
     97 
     98         this.terrain = new TerrainGrid("terrain", 65, 257, new ImageTileLoader(assetManager, new Namer() {
     99 
    100             public String getName(int x, int y) {
    101                 return "Scenes/TerrainMountains/terrain_" + x + "_" + y + ".png";
    102             }
    103         }));
    104 
    105         this.terrain.setMaterial(mat_terrain);
    106         this.terrain.setLocalTranslation(0, 0, 0);
    107         this.terrain.setLocalScale(1f, 1f, 1f);
    108         this.rootNode.attachChild(this.terrain);
    109 
    110         TerrainLodControl control = new TerrainLodControl(this.terrain, getCamera());
    111         control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier
    112         this.terrain.addControl(control);
    113 
    114         final BulletAppState bulletAppState = new BulletAppState();
    115         stateManager.attach(bulletAppState);
    116 
    117         this.getCamera().setLocation(new Vector3f(0, 200, 0));
    118 
    119         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
    120 
    121         DirectionalLight light = new DirectionalLight();
    122         light.setDirection((new Vector3f(-0.5f, -1f, -0.5f)).normalize());
    123         rootNode.addLight(light);
    124 
    125         if (usePhysics) {
    126             CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
    127             player3 = new CharacterControl(capsuleShape, 0.5f);
    128             player3.setJumpSpeed(20);
    129             player3.setFallSpeed(10);
    130             player3.setGravity(10);
    131 
    132             player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
    133 
    134             bulletAppState.getPhysicsSpace().add(player3);
    135 
    136             terrain.addListener(new TerrainGridListener() {
    137 
    138                 public void gridMoved(Vector3f newCenter) {
    139                 }
    140 
    141                 public Material tileLoaded(Material material, Vector3f cell) {
    142                     return material;
    143                 }
    144 
    145                 public void tileAttached(Vector3f cell, TerrainQuad quad) {
    146                     while(quad.getControl(RigidBodyControl.class)!=null){
    147                         quad.removeControl(RigidBodyControl.class);
    148                     }
    149                     quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
    150                     bulletAppState.getPhysicsSpace().add(quad);
    151                 }
    152 
    153                 public void tileDetached(Vector3f cell, TerrainQuad quad) {
    154                     bulletAppState.getPhysicsSpace().remove(quad);
    155                     quad.removeControl(RigidBodyControl.class);
    156                 }
    157 
    158             });
    159         }
    160 
    161         this.initKeys();
    162     }
    163 
    164     private void initKeys() {
    165         // You can map one or several inputs to one named action
    166         this.inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A));
    167         this.inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
    168         this.inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_W));
    169         this.inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_S));
    170         this.inputManager.addMapping("Jumps", new KeyTrigger(KeyInput.KEY_SPACE));
    171         this.inputManager.addListener(this.actionListener, "Lefts");
    172         this.inputManager.addListener(this.actionListener, "Rights");
    173         this.inputManager.addListener(this.actionListener, "Ups");
    174         this.inputManager.addListener(this.actionListener, "Downs");
    175         this.inputManager.addListener(this.actionListener, "Jumps");
    176     }
    177     private boolean left;
    178     private boolean right;
    179     private boolean up;
    180     private boolean down;
    181     private final ActionListener actionListener = new ActionListener() {
    182 
    183         @Override
    184         public void onAction(final String name, final boolean keyPressed, final float tpf) {
    185             if (name.equals("Lefts")) {
    186                 if (keyPressed) {
    187                     TerrainGridTest.this.left = true;
    188                 } else {
    189                     TerrainGridTest.this.left = false;
    190                 }
    191             } else if (name.equals("Rights")) {
    192                 if (keyPressed) {
    193                     TerrainGridTest.this.right = true;
    194                 } else {
    195                     TerrainGridTest.this.right = false;
    196                 }
    197             } else if (name.equals("Ups")) {
    198                 if (keyPressed) {
    199                     TerrainGridTest.this.up = true;
    200                 } else {
    201                     TerrainGridTest.this.up = false;
    202                 }
    203             } else if (name.equals("Downs")) {
    204                 if (keyPressed) {
    205                     TerrainGridTest.this.down = true;
    206                 } else {
    207                     TerrainGridTest.this.down = false;
    208                 }
    209             } else if (name.equals("Jumps")) {
    210                 TerrainGridTest.this.player3.jump();
    211             }
    212         }
    213     };
    214     private final Vector3f walkDirection = new Vector3f();
    215 
    216     @Override
    217     public void simpleUpdate(final float tpf) {
    218         Vector3f camDir = this.cam.getDirection().clone().multLocal(0.6f);
    219         Vector3f camLeft = this.cam.getLeft().clone().multLocal(0.4f);
    220         this.walkDirection.set(0, 0, 0);
    221         if (this.left) {
    222             this.walkDirection.addLocal(camLeft);
    223         }
    224         if (this.right) {
    225             this.walkDirection.addLocal(camLeft.negate());
    226         }
    227         if (this.up) {
    228             this.walkDirection.addLocal(camDir);
    229         }
    230         if (this.down) {
    231             this.walkDirection.addLocal(camDir.negate());
    232         }
    233 
    234         if (usePhysics) {
    235             this.player3.setWalkDirection(this.walkDirection);
    236             this.cam.setLocation(this.player3.getPhysicsLocation());
    237         }
    238     }
    239 }
    240