|
- package roadtrip.view;
-
- import com.jme3.asset.AssetManager;
- import com.jme3.bullet.PhysicsSpace;
- import com.jme3.bullet.collision.shapes.BoxCollisionShape;
- import com.jme3.bullet.collision.shapes.ConeCollisionShape;
- import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
- import com.jme3.bullet.control.RigidBodyControl;
- import com.jme3.light.AmbientLight;
- import com.jme3.light.DirectionalLight;
- import com.jme3.material.Material;
- import com.jme3.math.ColorRGBA;
- import com.jme3.math.Vector2f;
- import com.jme3.math.Vector3f;
- import com.jme3.post.FilterPostProcessor;
- import com.jme3.post.filters.DepthOfFieldFilter;
- import com.jme3.renderer.Camera;
- import com.jme3.scene.Geometry;
- import com.jme3.scene.Node;
- import com.jme3.scene.Spatial;
- import com.jme3.scene.shape.Box;
- import com.jme3.terrain.geomipmap.*;
- import com.jme3.terrain.geomipmap.grid.FractalTileLoader;
- import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
- import com.jme3.terrain.geomipmap.lodcalc.LodCalculator;
- import com.jme3.terrain.noise.ShaderUtils;
- import com.jme3.terrain.noise.basis.FilteredBasis;
- import com.jme3.terrain.noise.filter.IterativeFilter;
- import com.jme3.terrain.noise.filter.OptimizedErode;
- import com.jme3.terrain.noise.filter.PerturbFilter;
- import com.jme3.terrain.noise.filter.SmoothFilter;
- import com.jme3.terrain.noise.fractal.FractalSum;
- import com.jme3.terrain.noise.modulator.NoiseModulator;
- import com.jme3.texture.Texture;
- import java.util.Random;
- import roadtrip.model.MapObjectInstance;
- import roadtrip.model.ProceduralMapQuadBlock;
- import roadtrip.model.TerrainDataProvider;
- import roadtrip.view.model.GameWorldState;
- import roadtrip.view.model.Player;
-
- /**
- * Created by dejvino on 14.01.2017.
- */
- public class GameWorldView {
-
- public static boolean DEBUG = false;//true;
-
- private final GameWorldState state;
-
- private final AssetManager assetManager;
- private final Camera camera;
- private final Node rootNode;
- private final PhysicsSpace physicsSpace;
- private final HideControl.TargetProvider targetProvider;
-
- public TerrainView terrain = new TerrainView(new TerrainDataProvider());
-
- public GameWorldView(GameWorldState gameWorldState, AssetManager assetManager,
- Camera camera, Node rootNode, PhysicsSpace physicsSpace,
- HideControl.TargetProvider targetProvider) {
- this.state = gameWorldState;
- this.assetManager = assetManager;
- this.camera = camera;
- this.rootNode = rootNode;
- this.physicsSpace = physicsSpace;
- this.targetProvider = targetProvider;
- }
-
- public static GameWorldView create(GameWorldState gameWorldState,
- AssetManager assetManager, Camera camera, Node rootNode,
- PhysicsSpace physicsSpace, HideControl.TargetProvider targetProvider) {
- GameWorldView gameWorldView = new GameWorldView(gameWorldState, assetManager, camera, rootNode, physicsSpace, targetProvider);
- gameWorldView.initialize();
- return gameWorldView;
- }
-
- private void initialize()
- {
- // Environment
- DirectionalLight dl = new DirectionalLight();
- dl.setColor(ColorRGBA.LightGray);
- dl.setDirection(new Vector3f(1, -1, 1));
- rootNode.addLight(dl);
- AmbientLight al = new AmbientLight();
- al.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
- rootNode.addLight(al);
-
- // TERRAIN TEXTURE material
- terrain.mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/HeightBasedTerrain.j3md");
- if (DEBUG) {
- terrain.mat_terrain.getAdditionalRenderState().setWireframe(true);
- }
-
- float heightScale = 400f;
-
- // Parameters to material:
- // regionXColorMap: X = 1..4 the texture that should be appliad to state X
- // regionX: a Vector3f containing the following information:
- // regionX.x: the start height of the region
- // regionX.y: the end height of the region
- // regionX.z: the texture scale for the region
- // it might not be the most elegant way for storing these 3 values, but it packs the data nicely :)
- // slopeColorMap: the texture to be used for cliffs, and steep mountain sites
- // slopeTileFactor: the texture scale for slopes
- // terrainSize: the total size of the terrain (used for scaling the texture)
- Texture textureMid = this.assetManager.loadTexture("Textures/map-mid.png");
- textureMid.setWrap(Texture.WrapMode.Repeat);
- Texture textureLow = this.assetManager.loadTexture("Textures/map-low.png");
- textureLow.setWrap(Texture.WrapMode.Repeat);
- Texture textureHigh = this.assetManager.loadTexture("Textures/map-high.png");
- textureHigh.setWrap(Texture.WrapMode.Repeat);
-
- float modif = (heightScale / 100f) / 3f;
- terrain.mat_terrain.setTexture("region1ColorMap", textureLow);
- terrain.mat_terrain.setVector3("region1", new Vector3f(0, 80 * modif, terrain.texLowScale));
-
- terrain.mat_terrain.setTexture("region2ColorMap", textureMid);
- terrain.mat_terrain.setVector3("region2", new Vector3f(100 * modif, 160 * modif, terrain.texMidScale));
-
- terrain.mat_terrain.setTexture("region3ColorMap", textureHigh);
- terrain.mat_terrain.setVector3("region3", new Vector3f(190 * modif, 240 * modif, terrain.texHighScale));
-
- terrain.mat_terrain.setTexture("region4ColorMap", textureLow);
- terrain.mat_terrain.setVector3("region4", new Vector3f(250 * modif, 350 * modif, terrain.texLowScale));
-
- terrain.mat_terrain.setTexture("slopeColorMap", textureHigh);
- terrain.mat_terrain.setFloat("slopeTileFactor", 32);
-
- terrain.mat_terrain.setFloat("terrainSize", 513);
-
- terrain.terrainDataProvider.base = new FractalSum();
- terrain.terrainDataProvider.base.setRoughness(0.6f);
- terrain.terrainDataProvider.base.setFrequency(1.0f);
- terrain.terrainDataProvider.base.setAmplitude(1.0f);
- terrain.terrainDataProvider.base.setLacunarity(4.12f);
- terrain.terrainDataProvider.base.setOctaves(8);
- terrain.terrainDataProvider.base.setScale(0.02125f);
- terrain.terrainDataProvider.base.addModulator(new NoiseModulator() {
-
- @Override
- public float value(float... in) {
- return ShaderUtils.clamp(in[0] * 0.5f + 0.5f, 0, 1);
- }
- });
-
- FilteredBasis ground = new FilteredBasis(terrain.terrainDataProvider.base);
-
- terrain.terrainDataProvider.perturb = new PerturbFilter();
- terrain.terrainDataProvider.perturb.setMagnitude(0.119f);
-
- terrain.terrainDataProvider.therm = new OptimizedErode();
- terrain.terrainDataProvider.therm.setRadius(5);
- terrain.terrainDataProvider.therm.setTalus(0.011f);
-
- terrain.terrainDataProvider.smooth = new SmoothFilter();
- terrain.terrainDataProvider.smooth.setRadius(1);
- terrain.terrainDataProvider.smooth.setEffect(0.3f);
-
- terrain.terrainDataProvider.iterate = new IterativeFilter();
- terrain.terrainDataProvider.iterate.addPreFilter(terrain.terrainDataProvider.perturb);
- terrain.terrainDataProvider.iterate.addPostFilter(terrain.terrainDataProvider.smooth);
- terrain.terrainDataProvider.iterate.setFilter(terrain.terrainDataProvider.therm);
- terrain.terrainDataProvider.iterate.setIterations(2);
-
- ground.addPreFilter(terrain.terrainDataProvider.iterate);
-
- int patchSize = 16;
- Vector3f terrainScale = new Vector3f(8f, 1f, 8f);
- //terrain.terrainGrid = new TerrainGrid("terrain", 16 + 1, 512 + 1, new FractalTileLoader(ground, 300f));
- terrain.terrainGrid = new FineTerrainGrid("terrain", patchSize + 1, 128 + 1, terrainScale, new FractalTileLoader(ground, heightScale));
-
- terrain.terrainGrid.setMaterial(terrain.mat_terrain);
- //terrain.terrainGrid.setLocalTranslation(0, -200, 0);
- terrain.terrainGrid.setLocalScale(terrainScale);
- this.rootNode.attachChild(terrain.terrainGrid);
-
- final TerrainLodControl lodControl = new FineTerrainGridLodControl(terrain.terrainGrid, camera);
- lodControl.setLodCalculator(new DistanceLodCalculator(patchSize + 1, 3.7f)); // patch size, and a multiplier
- terrain.terrainGrid.addControl(lodControl);
-
- final Spatial treeModel = assetManager.loadModel("Models/tree.j3o");
- final Spatial houseModel = assetManager.loadModel("Models/house1.j3o");
- final Spatial grassModel = assetManager.loadModel("Models/grass.j3o");
-
- Material rockMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
- rockMat.setColor("Color", ColorRGBA.Gray);
- Geometry rockGeom = new Geometry("rock", new Box(1f, 1f, 1f));
- rockGeom.setMaterial(rockMat);
- final Node rockModel = new Node("rockNode");
- rockModel.attachChild(rockGeom);
-
- final FineTerrainGrid terrainGrid = terrain.terrainGrid;
- terrainGrid.addListener(new TerrainGridListener() {
-
- @Override
- public void gridMoved(Vector3f newCenter) {
- }
-
- @Override
- public void tileAttached(Vector3f cell, TerrainQuad quad) {
- lodControl.forceUpdate();
- while(quad.getControl(RigidBodyControl.class)!=null){
- quad.removeControl(RigidBodyControl.class);
- }
- quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrainGrid.getLocalScale()), 0));
- physicsSpace.add(quad);
-
- removeQuadObjectsNode(quad);
-
- String quadObjectsNodeKey = getQuadObjectsNodeKey(quad);
- Node objects = new Node(quadObjectsNodeKey);
- populateQuadObjectsNode(quad, objects);
- rootNode.attachChild(objects);
- }
-
- protected void populateQuadObjectsNode(TerrainQuad quad, Node objects)
- {
- ProceduralMapQuadBlock mapQuadBlock = state.proceduralMap.getMapQuadBlock(quad);
-
- /*/ DEBUG pole in the middle of a quad
- Spatial m = treeModel.clone();
- m.setLocalTranslation(quad.getWorldTranslation().add(new Vector3f(0f, getHeight(quad, quad.getWorldTranslation()), 0f)));
- m.setLocalScale(new Vector3f(1f, 20f, 1f));
- objects.attachChild(m);
- /**/
-
- // Add map objects
- Random rand = mapQuadBlock.getBlockRandom();
- for (MapObjectInstance mapObject : mapQuadBlock.getMapObjects()) {
- Vector3f pos = mapObject.getPosition();
- Vector3f scale = Vector3f.UNIT_XYZ;
- Vector3f boxHalf = Vector3f.UNIT_XYZ;
- Spatial modelInstance;
- RigidBodyControl modelPhysics;
- switch (mapObject.getType()) {
- case "tree":
- modelInstance = treeModel.clone();
- float s = 0.2f + rand.nextFloat() * 5f;
- scale = new Vector3f(s, s, s);
- boxHalf = new Vector3f(s * 0.2f, s * 3f, s * 0.2f);
- modelPhysics = new RigidBodyControl(new BoxCollisionShape(boxHalf), 0f);
- break;
- case "house":
- modelInstance = houseModel.clone();
- boxHalf = new Vector3f(2f + rand.nextFloat() * 10f, 2f + rand.nextFloat() * 10f, 2f + rand.nextFloat() * 10f);
- scale = boxHalf;
- modelPhysics = new RigidBodyControl(new BoxCollisionShape(boxHalf), 0f);
- break;
- default:
- throw new RuntimeException("Unhandled object type: " + mapObject.getType());
- }
- modelInstance.setLocalTranslation(pos);
- modelInstance.setLocalScale(scale);
- // TODO: physics from the model and not hard-coded
- //RigidBodyControl control = treeInstance.getControl(RigidBodyControl.class);
- if (modelPhysics != null) {
- modelPhysics.isActive();
- modelInstance.addControl(modelPhysics);
- modelPhysics.setPhysicsLocation(pos);
- physicsSpace.add(modelPhysics);
- }
- objects.attachChild(modelInstance);
- }
-
- int w = 128;
- for (int i = 0; i < w*w; i++) {
- int x = i % w;
- int z = i / w;
- if (((x % 8) + (z % 8)) != 0) continue;
- Vector3f pos = new Vector3f(x - w/2f + 0.25f*terrainGrid.getLocalScale().x, 0f, z - w/2f + 0.25f*terrainGrid.getLocalScale().z).addLocal(quad.getWorldTranslation());
- pos.addLocal(0f, getHeight(quad, pos), 0f);
- Vector3f scale = Vector3f.UNIT_XYZ;
- Spatial modelInstance;
- float s = 0.1f;
- if (i == 0) {
- s = 0.4f;
- } else if ((x % 16) + (z % 16) == 0) {
- s = 0.2f;
- }
- switch ("grass") {
- case "grass":
- modelInstance = rockModel.clone();
- scale = new Vector3f(s, s, s);
- break;
- default:
- throw new RuntimeException("Unhandled object type");
- }
- modelInstance.setLocalTranslation(pos);
- modelInstance.setLocalScale(scale);
- modelInstance.addControl(new HideControl(20f + 140f * s, targetProvider));
- objects.attachChild(modelInstance);
- }
- }
-
- @Override
- public void tileDetached(Vector3f cell, TerrainQuad quad) {
- if (quad.getControl(RigidBodyControl.class) != null) {
- physicsSpace.remove(quad);
- quad.removeControl(RigidBodyControl.class);
- }
- removeQuadObjectsNode(quad);
- }
-
- protected void removeQuadObjectsNode(TerrainQuad quad)
- {
- Spatial quadObjectsNodeOld = rootNode.getChild(getQuadObjectsNodeKey(quad));
- if (quadObjectsNodeOld != null) {
- physicsSpace.removeAll(quadObjectsNodeOld);
- quadObjectsNodeOld.removeFromParent();
- }
- }
-
- private String getQuadObjectsNodeKey(TerrainQuad quad)
- {
- return "Objects-" + quad.getName();
- }
-
- private float getHeight(TerrainQuad quad, Vector3f pos)
- {
- return quad.getHeight(new Vector2f(pos.x, pos.z));
- }
- });
- /**/
-
- }
-
- }
|