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.AmbientLight;
     16 import com.jme3.light.DirectionalLight;
     17 import com.jme3.material.Material;
     18 import com.jme3.math.ColorRGBA;
     19 import com.jme3.math.Vector2f;
     20 import com.jme3.math.Vector3f;
     21 import com.jme3.renderer.Camera;
     22 import com.jme3.scene.Geometry;
     23 import com.jme3.scene.Node;
     24 import com.jme3.scene.Spatial;
     25 import com.jme3.scene.debug.Arrow;
     26 import com.jme3.terrain.geomipmap.TerrainGrid;
     27 import com.jme3.terrain.geomipmap.TerrainGridListener;
     28 import com.jme3.terrain.geomipmap.TerrainLodControl;
     29 import com.jme3.terrain.geomipmap.TerrainQuad;
     30 import com.jme3.terrain.geomipmap.grid.FractalTileLoader;
     31 import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
     32 import com.jme3.texture.Texture;
     33 import com.jme3.texture.Texture.WrapMode;
     34 import java.io.File;
     35 import java.util.ArrayList;
     36 import java.util.List;
     37 import com.jme3.terrain.noise.ShaderUtils;
     38 import com.jme3.terrain.noise.basis.FilteredBasis;
     39 import com.jme3.terrain.noise.filter.IterativeFilter;
     40 import com.jme3.terrain.noise.filter.OptimizedErode;
     41 import com.jme3.terrain.noise.filter.PerturbFilter;
     42 import com.jme3.terrain.noise.filter.SmoothFilter;
     43 import com.jme3.terrain.noise.fractal.FractalSum;
     44 import com.jme3.terrain.noise.modulator.NoiseModulator;
     45 
     46 public class TerrainGridAlphaMapTest extends SimpleApplication {
     47 
     48     private TerrainGrid terrain;
     49     private float grassScale = 64;
     50     private float dirtScale = 16;
     51     private float rockScale = 128;
     52     private boolean usePhysics = false;
     53 
     54     public static void main(final String[] args) {
     55         TerrainGridAlphaMapTest app = new TerrainGridAlphaMapTest();
     56         app.start();
     57     }
     58     private CharacterControl player3;
     59     private FractalSum base;
     60     private PerturbFilter perturb;
     61     private OptimizedErode therm;
     62     private SmoothFilter smooth;
     63     private IterativeFilter iterate;
     64     private Material material;
     65     private Material matWire;
     66 
     67     @Override
     68     public void simpleInitApp() {
     69         DirectionalLight sun = new DirectionalLight();
     70         sun.setColor(ColorRGBA.White);
     71         sun.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
     72         rootNode.addLight(sun);
     73 
     74         AmbientLight al = new AmbientLight();
     75         al.setColor(ColorRGBA.White.mult(1.3f));
     76         rootNode.addLight(al);
     77 
     78         File file = new File("TerrainGridTestData.zip");
     79         if (!file.exists()) {
     80             assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/TerrainGridTestData.zip", HttpZipLocator.class);
     81         } else {
     82             assetManager.registerLocator("TerrainGridTestData.zip", ZipLocator.class);
     83         }
     84 
     85         this.flyCam.setMoveSpeed(100f);
     86         ScreenshotAppState state = new ScreenshotAppState();
     87         this.stateManager.attach(state);
     88 
     89         // TERRAIN TEXTURE material
     90         material = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
     91         material.setBoolean("useTriPlanarMapping", false);
     92         //material.setBoolean("isTerrainGrid", true);
     93         material.setFloat("Shininess", 0.0f);
     94 
     95         // GRASS texture
     96         Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
     97         grass.setWrap(WrapMode.Repeat);
     98         material.setTexture("DiffuseMap", grass);
     99         material.setFloat("DiffuseMap_0_scale", grassScale);
    100 
    101         // DIRT texture
    102         Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
    103         dirt.setWrap(WrapMode.Repeat);
    104         material.setTexture("DiffuseMap_1", dirt);
    105         material.setFloat("DiffuseMap_1_scale", dirtScale);
    106 
    107         // ROCK texture
    108         Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
    109         rock.setWrap(WrapMode.Repeat);
    110         material.setTexture("DiffuseMap_2", rock);
    111         material.setFloat("DiffuseMap_2_scale", rockScale);
    112 
    113         // WIREFRAME material
    114         matWire = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    115         matWire.getAdditionalRenderState().setWireframe(true);
    116         matWire.setColor("Color", ColorRGBA.Green);
    117 
    118         this.base = new FractalSum();
    119         this.base.setRoughness(0.7f);
    120         this.base.setFrequency(1.0f);
    121         this.base.setAmplitude(1.0f);
    122         this.base.setLacunarity(2.12f);
    123         this.base.setOctaves(8);
    124         this.base.setScale(0.02125f);
    125         this.base.addModulator(new NoiseModulator() {
    126 
    127             @Override
    128             public float value(float... in) {
    129                 return ShaderUtils.clamp(in[0] * 0.5f + 0.5f, 0, 1);
    130             }
    131         });
    132 
    133         FilteredBasis ground = new FilteredBasis(this.base);
    134 
    135         this.perturb = new PerturbFilter();
    136         this.perturb.setMagnitude(0.119f);
    137 
    138         this.therm = new OptimizedErode();
    139         this.therm.setRadius(5);
    140         this.therm.setTalus(0.011f);
    141 
    142         this.smooth = new SmoothFilter();
    143         this.smooth.setRadius(1);
    144         this.smooth.setEffect(0.7f);
    145 
    146         this.iterate = new IterativeFilter();
    147         this.iterate.addPreFilter(this.perturb);
    148         this.iterate.addPostFilter(this.smooth);
    149         this.iterate.setFilter(this.therm);
    150         this.iterate.setIterations(1);
    151 
    152         ground.addPreFilter(this.iterate);
    153 
    154         this.terrain = new TerrainGrid("terrain", 33, 257, new FractalTileLoader(ground, 256));
    155         this.terrain.setMaterial(this.material);
    156 
    157         this.terrain.setLocalTranslation(0, 0, 0);
    158         this.terrain.setLocalScale(2f, 1f, 2f);
    159         this.rootNode.attachChild(this.terrain);
    160 
    161         List<Camera> cameras = new ArrayList<Camera>();
    162         cameras.add(this.getCamera());
    163         TerrainLodControl control = new TerrainLodControl(this.terrain, cameras);
    164         control.setLodCalculator( new DistanceLodCalculator(33, 2.7f) ); // patch size, and a multiplier
    165         this.terrain.addControl(control);
    166 
    167         final BulletAppState bulletAppState = new BulletAppState();
    168         stateManager.attach(bulletAppState);
    169 
    170 
    171         this.getCamera().setLocation(new Vector3f(0, 256, 0));
    172 
    173         this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
    174 
    175         if (usePhysics) {
    176             CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
    177             player3 = new CharacterControl(capsuleShape, 0.5f);
    178             player3.setJumpSpeed(20);
    179             player3.setFallSpeed(10);
    180             player3.setGravity(10);
    181 
    182             player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
    183 
    184             bulletAppState.getPhysicsSpace().add(player3);
    185 
    186         }
    187         terrain.addListener(new TerrainGridListener() {
    188 
    189             public void gridMoved(Vector3f newCenter) {
    190             }
    191 
    192             public void tileAttached(Vector3f cell, TerrainQuad quad) {
    193                 Texture alpha = null;
    194                 try {
    195                     alpha = assetManager.loadTexture("TerrainAlphaTest/alpha_" + (int)cell.x+ "_" + (int)cell.z + ".png");
    196                 } catch (Exception e) {
    197                     alpha = assetManager.loadTexture("TerrainAlphaTest/alpha_default.png");
    198                 }
    199                 quad.getMaterial().setTexture("AlphaMap", alpha);
    200                 if (usePhysics) {
    201                     quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrain.getLocalScale()), 0));
    202                     bulletAppState.getPhysicsSpace().add(quad);
    203                 }
    204                 updateMarkerElevations();
    205             }
    206 
    207             public void tileDetached(Vector3f cell, TerrainQuad quad) {
    208                 if (usePhysics) {
    209                     bulletAppState.getPhysicsSpace().remove(quad);
    210                     quad.removeControl(RigidBodyControl.class);
    211                 }
    212                 updateMarkerElevations();
    213             }
    214         });
    215 
    216         this.initKeys();
    217 
    218         markers = new Node();
    219         rootNode.attachChild(markers);
    220         createMarkerPoints(1);
    221     }
    222 
    223     Node markers;
    224 
    225 
    226     private void createMarkerPoints(float count) {
    227         Node center = createAxisMarker(10);
    228         markers.attachChild(center);
    229 
    230         float xS = (count-1)*terrain.getTerrainSize() - (terrain.getTerrainSize()/2);
    231         float zS = (count-1)*terrain.getTerrainSize() - (terrain.getTerrainSize()/2);
    232         float xSi = xS;
    233         float zSi = zS;
    234         for (int x=0; x<count*2; x++) {
    235             for (int z=0; z<count*2; z++) {
    236                 Node m = createAxisMarker(5);
    237                 m.setLocalTranslation(xSi, 0, zSi);
    238                 markers.attachChild(m);
    239                 zSi += terrain.getTerrainSize();
    240             }
    241             zSi = zS;
    242             xSi += terrain.getTerrainSize();
    243         }
    244     }
    245 
    246     private void updateMarkerElevations() {
    247         for (Spatial s : markers.getChildren()) {
    248             float h = terrain.getHeight(new Vector2f(s.getLocalTranslation().x, s.getLocalTranslation().z));
    249             s.setLocalTranslation(s.getLocalTranslation().x, h+1, s.getLocalTranslation().z);
    250         }
    251     }
    252 
    253     private void initKeys() {
    254         // You can map one or several inputs to one named action
    255         this.inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A));
    256         this.inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
    257         this.inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_W));
    258         this.inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_S));
    259         this.inputManager.addMapping("Jumps", new KeyTrigger(KeyInput.KEY_SPACE));
    260         this.inputManager.addListener(this.actionListener, "Lefts");
    261         this.inputManager.addListener(this.actionListener, "Rights");
    262         this.inputManager.addListener(this.actionListener, "Ups");
    263         this.inputManager.addListener(this.actionListener, "Downs");
    264         this.inputManager.addListener(this.actionListener, "Jumps");
    265     }
    266     private boolean left;
    267     private boolean right;
    268     private boolean up;
    269     private boolean down;
    270     private final ActionListener actionListener = new ActionListener() {
    271 
    272         @Override
    273         public void onAction(final String name, final boolean keyPressed, final float tpf) {
    274             if (name.equals("Lefts")) {
    275                 if (keyPressed) {
    276                     TerrainGridAlphaMapTest.this.left = true;
    277                 } else {
    278                     TerrainGridAlphaMapTest.this.left = false;
    279                 }
    280             } else if (name.equals("Rights")) {
    281                 if (keyPressed) {
    282                     TerrainGridAlphaMapTest.this.right = true;
    283                 } else {
    284                     TerrainGridAlphaMapTest.this.right = false;
    285                 }
    286             } else if (name.equals("Ups")) {
    287                 if (keyPressed) {
    288                     TerrainGridAlphaMapTest.this.up = true;
    289                 } else {
    290                     TerrainGridAlphaMapTest.this.up = false;
    291                 }
    292             } else if (name.equals("Downs")) {
    293                 if (keyPressed) {
    294                     TerrainGridAlphaMapTest.this.down = true;
    295                 } else {
    296                     TerrainGridAlphaMapTest.this.down = false;
    297                 }
    298             } else if (name.equals("Jumps")) {
    299                 TerrainGridAlphaMapTest.this.player3.jump();
    300             }
    301         }
    302     };
    303     private final Vector3f walkDirection = new Vector3f();
    304 
    305     @Override
    306     public void simpleUpdate(final float tpf) {
    307         Vector3f camDir = this.cam.getDirection().clone().multLocal(0.6f);
    308         Vector3f camLeft = this.cam.getLeft().clone().multLocal(0.4f);
    309         this.walkDirection.set(0, 0, 0);
    310         if (this.left) {
    311             this.walkDirection.addLocal(camLeft);
    312         }
    313         if (this.right) {
    314             this.walkDirection.addLocal(camLeft.negate());
    315         }
    316         if (this.up) {
    317             this.walkDirection.addLocal(camDir);
    318         }
    319         if (this.down) {
    320             this.walkDirection.addLocal(camDir.negate());
    321         }
    322 
    323         if (usePhysics) {
    324             this.player3.setWalkDirection(this.walkDirection);
    325             this.cam.setLocation(this.player3.getPhysicsLocation());
    326         }
    327     }
    328 
    329     protected Node createAxisMarker(float arrowSize) {
    330 
    331         Material redMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    332         redMat.getAdditionalRenderState().setWireframe(true);
    333         redMat.setColor("Color", ColorRGBA.Red);
    334 
    335         Material greenMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    336         greenMat.getAdditionalRenderState().setWireframe(true);
    337         greenMat.setColor("Color", ColorRGBA.Green);
    338 
    339         Material blueMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    340         blueMat.getAdditionalRenderState().setWireframe(true);
    341         blueMat.setColor("Color", ColorRGBA.Blue);
    342 
    343         Node axis = new Node();
    344 
    345         // create arrows
    346         Geometry arrowX = new Geometry("arrowX", new Arrow(new Vector3f(arrowSize, 0, 0)));
    347         arrowX.setMaterial(redMat);
    348         Geometry arrowY = new Geometry("arrowY", new Arrow(new Vector3f(0, arrowSize, 0)));
    349         arrowY.setMaterial(greenMat);
    350         Geometry arrowZ = new Geometry("arrowZ", new Arrow(new Vector3f(0, 0, arrowSize)));
    351         arrowZ.setMaterial(blueMat);
    352         axis.attachChild(arrowX);
    353         axis.attachChild(arrowY);
    354         axis.attachChild(arrowZ);
    355 
    356         //axis.setModelBound(new BoundingBox());
    357         return axis;
    358     }
    359 }
    360