• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
main(final String[] args)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
simpleInitApp()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 
createMarkerPoints(float count)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 
updateMarkerElevations()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 
initKeys()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
simpleUpdate(final float tpf)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 
createAxisMarker(float arrowSize)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