TerrainFractalGridTest.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package jme3test.terrain;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import com.jme3.app.SimpleApplication;
  5. import com.jme3.app.state.ScreenshotAppState;
  6. import com.jme3.bullet.BulletAppState;
  7. import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
  8. import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
  9. import com.jme3.bullet.control.CharacterControl;
  10. import com.jme3.bullet.control.RigidBodyControl;
  11. import com.jme3.input.KeyInput;
  12. import com.jme3.input.controls.ActionListener;
  13. import com.jme3.input.controls.KeyTrigger;
  14. import com.jme3.material.Material;
  15. import com.jme3.math.ColorRGBA;
  16. import com.jme3.math.Vector2f;
  17. import com.jme3.math.Vector3f;
  18. import com.jme3.renderer.Camera;
  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.heightmap.FractalHeightMapGrid;
  23. import com.jme3.texture.Texture;
  24. import com.jme3.texture.Texture.WrapMode;
  25. import org.novyon.noise.ShaderUtils;
  26. import org.novyon.noise.basis.FilteredBasis;
  27. import org.novyon.noise.filter.IterativeFilter;
  28. import org.novyon.noise.filter.OptimizedErode;
  29. import org.novyon.noise.filter.PerturbFilter;
  30. import org.novyon.noise.filter.SmoothFilter;
  31. import org.novyon.noise.fractal.FractalSum;
  32. import org.novyon.noise.modulator.NoiseModulator;
  33. public class TerrainFractalGridTest extends SimpleApplication {
  34. private Material mat_terrain;
  35. private TerrainGrid terrain;
  36. private float grassScale = 64;
  37. private float dirtScale = 16;
  38. private float rockScale = 128;
  39. private boolean usePhysics = true;
  40. private boolean physicsAdded = false;
  41. public static void main(final String[] args) {
  42. TerrainFractalGridTest app = new TerrainFractalGridTest();
  43. app.start();
  44. }
  45. private CharacterControl player3;
  46. private FractalSum base;
  47. private PerturbFilter perturb;
  48. private OptimizedErode therm;
  49. private SmoothFilter smooth;
  50. private IterativeFilter iterate;
  51. @Override
  52. public void simpleInitApp() {
  53. this.flyCam.setMoveSpeed(100f);
  54. ScreenshotAppState state = new ScreenshotAppState();
  55. this.stateManager.attach(state);
  56. // TERRAIN TEXTURE material
  57. this.mat_terrain = new Material(this.assetManager, "Common/MatDefs/Terrain/HeightBasedTerrain.j3md");
  58. // Parameters to material:
  59. // regionXColorMap: X = 1..4 the texture that should be appliad to state X
  60. // regionX: a Vector3f containing the following information:
  61. // regionX.x: the start height of the region
  62. // regionX.y: the end height of the region
  63. // regionX.z: the texture scale for the region
  64. // it might not be the most elegant way for storing these 3 values, but it packs the data nicely :)
  65. // slopeColorMap: the texture to be used for cliffs, and steep mountain sites
  66. // slopeTileFactor: the texture scale for slopes
  67. // terrainSize: the total size of the terrain (used for scaling the texture)
  68. // GRASS texture
  69. Texture grass = this.assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
  70. grass.setWrap(WrapMode.Repeat);
  71. this.mat_terrain.setTexture("region1ColorMap", grass);
  72. this.mat_terrain.setVector3("region1", new Vector3f(88, 200, this.grassScale));
  73. // DIRT texture
  74. Texture dirt = this.assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
  75. dirt.setWrap(WrapMode.Repeat);
  76. this.mat_terrain.setTexture("region2ColorMap", dirt);
  77. this.mat_terrain.setVector3("region2", new Vector3f(0, 90, this.dirtScale));
  78. // ROCK texture
  79. Texture rock = this.assetManager.loadTexture("Textures/Terrain/Rock2/rock.jpg");
  80. rock.setWrap(WrapMode.Repeat);
  81. this.mat_terrain.setTexture("region3ColorMap", rock);
  82. this.mat_terrain.setVector3("region3", new Vector3f(198, 260, this.rockScale));
  83. this.mat_terrain.setTexture("region4ColorMap", rock);
  84. this.mat_terrain.setVector3("region4", new Vector3f(198, 260, this.rockScale));
  85. this.mat_terrain.setTexture("slopeColorMap", rock);
  86. this.mat_terrain.setFloat("slopeTileFactor", 32);
  87. this.mat_terrain.setFloat("terrainSize", 513);
  88. this.base = new FractalSum();
  89. this.base.setRoughness(0.7f);
  90. this.base.setFrequency(1.0f);
  91. this.base.setAmplitude(1.0f);
  92. this.base.setLacunarity(2.12f);
  93. this.base.setOctaves(8);
  94. this.base.setScale(0.02125f);
  95. this.base.addModulator(new NoiseModulator() {
  96. @Override
  97. public float value(float... in) {
  98. return ShaderUtils.clamp(in[0] * 0.5f + 0.5f, 0, 1);
  99. }
  100. });
  101. FilteredBasis ground = new FilteredBasis(this.base);
  102. this.perturb = new PerturbFilter();
  103. this.perturb.setMagnitude(0.119f);
  104. this.therm = new OptimizedErode();
  105. this.therm.setRadius(5);
  106. this.therm.setTalus(0.011f);
  107. this.smooth = new SmoothFilter();
  108. this.smooth.setRadius(1);
  109. this.smooth.setEffect(0.7f);
  110. this.iterate = new IterativeFilter();
  111. this.iterate.addPreFilter(this.perturb);
  112. this.iterate.addPostFilter(this.smooth);
  113. this.iterate.setFilter(this.therm);
  114. this.iterate.setIterations(1);
  115. ground.addPreFilter(this.iterate);
  116. this.terrain = new TerrainGrid("terrain", 65, 257, new FractalHeightMapGrid(ground, "D:\\work5\\temp", 256f));
  117. this.terrain.setMaterial(this.mat_terrain);
  118. this.terrain.setLocalTranslation(0, 0, 0);
  119. this.terrain.setLocalScale(2f, 1f, 2f);
  120. this.rootNode.attachChild(this.terrain);
  121. List<Camera> cameras = new ArrayList<Camera>();
  122. cameras.add(this.getCamera());
  123. TerrainLodControl control = new TerrainLodControl(this.terrain, cameras);
  124. this.terrain.addControl(control);
  125. final BulletAppState bulletAppState = new BulletAppState();
  126. stateManager.attach(bulletAppState);
  127. this.getCamera().setLocation(new Vector3f(0, 0, 0));
  128. this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
  129. if (usePhysics) {
  130. terrain.addListener("physicsStartListener", new TerrainGridListener() {
  131. public void gridMoved(Vector3f newCenter) {
  132. terrain.removeListener("physicsStartListener");
  133. RigidBodyControl body = new RigidBodyControl(new HeightfieldCollisionShape(terrain.getHeightMap(), terrain.getLocalScale()), 0);
  134. terrain.addControl(body);
  135. bulletAppState.getPhysicsSpace().add(terrain);
  136. CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(0.5f, 1.8f, 1);
  137. player3 = new CharacterControl(capsuleShape, 0.5f);
  138. player3.setJumpSpeed(20);
  139. player3.setFallSpeed(10);
  140. player3.setGravity(10);
  141. player3.setPhysicsLocation(new Vector3f(cam.getLocation().x, 256, cam.getLocation().z));
  142. bulletAppState.getPhysicsSpace().add(player3);
  143. physicsAdded = true;
  144. }
  145. public Material tileLoaded(Material material, Vector3f cell) {
  146. return material;
  147. }
  148. });
  149. }
  150. this.terrain.initialize(cam.getLocation());
  151. this.initKeys();
  152. }
  153. private void initKeys() {
  154. // You can map one or several inputs to one named action
  155. this.inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A));
  156. this.inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D));
  157. this.inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_W));
  158. this.inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_S));
  159. this.inputManager.addMapping("Jumps", new KeyTrigger(KeyInput.KEY_SPACE));
  160. this.inputManager.addListener(this.actionListener, "Lefts");
  161. this.inputManager.addListener(this.actionListener, "Rights");
  162. this.inputManager.addListener(this.actionListener, "Ups");
  163. this.inputManager.addListener(this.actionListener, "Downs");
  164. this.inputManager.addListener(this.actionListener, "Jumps");
  165. }
  166. private boolean left;
  167. private boolean right;
  168. private boolean up;
  169. private boolean down;
  170. private final ActionListener actionListener = new ActionListener() {
  171. @Override
  172. public void onAction(final String name, final boolean keyPressed, final float tpf) {
  173. if (name.equals("Lefts")) {
  174. if (keyPressed) {
  175. TerrainFractalGridTest.this.left = true;
  176. } else {
  177. TerrainFractalGridTest.this.left = false;
  178. }
  179. } else if (name.equals("Rights")) {
  180. if (keyPressed) {
  181. TerrainFractalGridTest.this.right = true;
  182. } else {
  183. TerrainFractalGridTest.this.right = false;
  184. }
  185. } else if (name.equals("Ups")) {
  186. if (keyPressed) {
  187. TerrainFractalGridTest.this.up = true;
  188. } else {
  189. TerrainFractalGridTest.this.up = false;
  190. }
  191. } else if (name.equals("Downs")) {
  192. if (keyPressed) {
  193. TerrainFractalGridTest.this.down = true;
  194. } else {
  195. TerrainFractalGridTest.this.down = false;
  196. }
  197. } else if (name.equals("Jumps")) {
  198. TerrainFractalGridTest.this.player3.jump();
  199. }
  200. }
  201. };
  202. private final Vector3f walkDirection = new Vector3f();
  203. @Override
  204. public void simpleUpdate(final float tpf) {
  205. Vector3f camDir = this.cam.getDirection().clone().multLocal(0.6f);
  206. Vector3f camLeft = this.cam.getLeft().clone().multLocal(0.4f);
  207. this.walkDirection.set(0, 0, 0);
  208. if (this.left) {
  209. this.walkDirection.addLocal(camLeft);
  210. }
  211. if (this.right) {
  212. this.walkDirection.addLocal(camLeft.negate());
  213. }
  214. if (this.up) {
  215. this.walkDirection.addLocal(camDir);
  216. }
  217. if (this.down) {
  218. this.walkDirection.addLocal(camDir.negate());
  219. }
  220. if (usePhysics && physicsAdded) {
  221. this.player3.setWalkDirection(this.walkDirection);
  222. this.cam.setLocation(this.player3.getPhysicsLocation());
  223. }
  224. }
  225. }