1package jme3test.water;
2
3import com.jme3.app.SimpleApplication;
4import com.jme3.audio.AudioNode;
5import com.jme3.audio.LowPassFilter;
6import com.jme3.effect.ParticleEmitter;
7import com.jme3.effect.ParticleMesh;
8import com.jme3.input.controls.ActionListener;
9import com.jme3.input.controls.KeyTrigger;
10import com.jme3.light.DirectionalLight;
11import com.jme3.material.Material;
12import com.jme3.material.RenderState.BlendMode;
13import com.jme3.math.ColorRGBA;
14import com.jme3.math.FastMath;
15import com.jme3.math.Quaternion;
16import com.jme3.math.Vector3f;
17import com.jme3.post.FilterPostProcessor;
18import com.jme3.post.filters.BloomFilter;
19import com.jme3.post.filters.DepthOfFieldFilter;
20import com.jme3.post.filters.LightScatteringFilter;
21import com.jme3.renderer.Camera;
22import com.jme3.renderer.queue.RenderQueue.Bucket;
23import com.jme3.renderer.queue.RenderQueue.ShadowMode;
24import com.jme3.scene.Geometry;
25import com.jme3.scene.Node;
26import com.jme3.scene.Spatial;
27import com.jme3.scene.shape.Box;
28import com.jme3.terrain.geomipmap.TerrainQuad;
29import com.jme3.terrain.heightmap.AbstractHeightMap;
30import com.jme3.terrain.heightmap.ImageBasedHeightMap;
31import com.jme3.texture.Texture;
32import com.jme3.texture.Texture.WrapMode;
33import com.jme3.texture.Texture2D;
34import com.jme3.util.SkyFactory;
35import com.jme3.water.WaterFilter;
36import java.util.ArrayList;
37import java.util.List;
38
39/**
40 * test
41 * @author normenhansen
42 */
43public class TestPostWater extends SimpleApplication {
44
45    private Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f);
46    private WaterFilter water;
47    TerrainQuad terrain;
48    Material matRock;
49    AudioNode waves;
50    LowPassFilter underWaterAudioFilter = new LowPassFilter(0.5f, 0.1f);
51    LowPassFilter underWaterReverbFilter = new LowPassFilter(0.5f, 0.1f);
52    LowPassFilter aboveWaterAudioFilter = new LowPassFilter(1, 1);
53
54    public static void main(String[] args) {
55        TestPostWater app = new TestPostWater();
56        app.start();
57    }
58
59    @Override
60    public void simpleInitApp() {
61
62      setDisplayFps(false);
63      setDisplayStatView(false);
64
65        Node mainScene = new Node("Main Scene");
66        rootNode.attachChild(mainScene);
67
68        createTerrain(mainScene);
69        DirectionalLight sun = new DirectionalLight();
70        sun.setDirection(lightDir);
71        sun.setColor(ColorRGBA.White.clone().multLocal(1.7f));
72        mainScene.addLight(sun);
73
74        DirectionalLight l = new DirectionalLight();
75        l.setDirection(Vector3f.UNIT_Y.mult(-1));
76        l.setColor(ColorRGBA.White.clone().multLocal(0.3f));
77//        mainScene.addLight(l);
78
79        flyCam.setMoveSpeed(50);
80
81        //cam.setLocation(new Vector3f(-700, 100, 300));
82         //cam.setRotation(new Quaternion().fromAngleAxis(0.5f, Vector3f.UNIT_Z));
83        cam.setLocation(new Vector3f(-327.21957f, 61.6459f, 126.884346f));
84        cam.setRotation(new Quaternion(0.052168474f, 0.9443102f, -0.18395276f, 0.2678024f));
85
86
87        cam.setRotation(new Quaternion().fromAngles(new float[]{FastMath.PI * 0.06f, FastMath.PI * 0.65f, 0}));
88
89
90        Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false);
91        sky.setLocalScale(350);
92
93        mainScene.attachChild(sky);
94        cam.setFrustumFar(4000);
95        //cam.setFrustumNear(100);
96
97
98
99        //private FilterPostProcessor fpp;
100
101
102        water = new WaterFilter(rootNode, lightDir);
103
104        FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
105
106        fpp.addFilter(water);
107        BloomFilter bloom=new BloomFilter();
108        //bloom.getE
109        bloom.setExposurePower(55);
110        bloom.setBloomIntensity(1.0f);
111        fpp.addFilter(bloom);
112        LightScatteringFilter lsf = new LightScatteringFilter(lightDir.mult(-300));
113        lsf.setLightDensity(1.0f);
114        fpp.addFilter(lsf);
115        DepthOfFieldFilter dof=new DepthOfFieldFilter();
116        dof.setFocusDistance(0);
117        dof.setFocusRange(100);
118        fpp.addFilter(dof);
119//
120
121     //   fpp.addFilter(new TranslucentBucketFilter());
122 //
123
124         // fpp.setNumSamples(4);
125
126
127        water.setWaveScale(0.003f);
128        water.setMaxAmplitude(2f);
129        water.setFoamExistence(new Vector3f(1f, 4, 0.5f));
130        water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
131        //water.setNormalScale(0.5f);
132
133        //water.setRefractionConstant(0.25f);
134        water.setRefractionStrength(0.2f);
135        //water.setFoamHardness(0.6f);
136
137        water.setWaterHeight(initialWaterHeight);
138      uw=cam.getLocation().y<waterHeight;
139
140        waves = new AudioNode(audioRenderer, assetManager, "Sound/Environment/Ocean Waves.ogg", false);
141        waves.setLooping(true);
142        waves.setReverbEnabled(true);
143        if(uw){
144            waves.setDryFilter(new LowPassFilter(0.5f, 0.1f));
145        }else{
146            waves.setDryFilter(aboveWaterAudioFilter);
147        }
148        audioRenderer.playSource(waves);
149        //
150        viewPort.addProcessor(fpp);
151
152        inputManager.addListener(new ActionListener() {
153
154            public void onAction(String name, boolean isPressed, float tpf) {
155                if (isPressed) {
156                    if (name.equals("foam1")) {
157                        water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"));
158                    }
159                    if (name.equals("foam2")) {
160                        water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
161                    }
162                    if (name.equals("foam3")) {
163                        water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam3.jpg"));
164                    }
165                }
166            }
167        }, "foam1", "foam2", "foam3");
168        inputManager.addMapping("foam1", new KeyTrigger(keyInput.KEY_1));
169        inputManager.addMapping("foam2", new KeyTrigger(keyInput.KEY_2));
170        inputManager.addMapping("foam3", new KeyTrigger(keyInput.KEY_3));
171//        createBox();
172      //  createFire();
173    }
174    Geometry box;
175
176    private void createBox() {
177        //creating a transluscent box
178        box = new Geometry("box", new Box(new Vector3f(0, 0, 0), 50, 50, 50));
179        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
180        mat.setColor("Color", new ColorRGBA(1.0f, 0, 0, 0.3f));
181        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
182        //mat.getAdditionalRenderState().setDepthWrite(false);
183        //mat.getAdditionalRenderState().setDepthTest(false);
184        box.setMaterial(mat);
185        box.setQueueBucket(Bucket.Translucent);
186
187
188        //creating a post view port
189//        ViewPort post=renderManager.createPostView("transpPost", cam);
190//        post.setClearFlags(false, true, true);
191
192
193        box.setLocalTranslation(-600, 0, 300);
194
195        //attaching the box to the post viewport
196        //Don't forget to updateGeometricState() the box in the simpleUpdate
197        //  post.attachScene(box);
198
199        rootNode.attachChild(box);
200    }
201
202    private void createFire() {
203        /** Uses Texture from jme3-test-data library! */
204        ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
205        Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
206        mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
207
208        fire.setMaterial(mat_red);
209        fire.setImagesX(2);
210        fire.setImagesY(2); // 2x2 texture animation
211        fire.setEndColor(new ColorRGBA(1f, 0f, 0f, 1f));   // red
212        fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
213        fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 2, 0));
214        fire.setStartSize(10f);
215        fire.setEndSize(1f);
216        fire.setGravity(0, 0, 0);
217        fire.setLowLife(0.5f);
218        fire.setHighLife(1.5f);
219        fire.getParticleInfluencer().setVelocityVariation(0.3f);
220        fire.setLocalTranslation(-350, 40, 430);
221
222        fire.setQueueBucket(Bucket.Transparent);
223        rootNode.attachChild(fire);
224    }
225
226    private void createTerrain(Node rootNode) {
227        matRock = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
228        matRock.setBoolean("useTriPlanarMapping", false);
229        matRock.setBoolean("WardIso", true);
230        matRock.setTexture("AlphaMap", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
231        Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
232        Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
233        grass.setWrap(WrapMode.Repeat);
234        matRock.setTexture("DiffuseMap", grass);
235        matRock.setFloat("DiffuseMap_0_scale", 64);
236        Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
237        dirt.setWrap(WrapMode.Repeat);
238        matRock.setTexture("DiffuseMap_1", dirt);
239        matRock.setFloat("DiffuseMap_1_scale", 16);
240        Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
241        rock.setWrap(WrapMode.Repeat);
242        matRock.setTexture("DiffuseMap_2", rock);
243        matRock.setFloat("DiffuseMap_2_scale", 128);
244        Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
245        normalMap0.setWrap(WrapMode.Repeat);
246        Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
247        normalMap1.setWrap(WrapMode.Repeat);
248        Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
249        normalMap2.setWrap(WrapMode.Repeat);
250        matRock.setTexture("NormalMap", normalMap0);
251        matRock.setTexture("NormalMap_1", normalMap2);
252        matRock.setTexture("NormalMap_2", normalMap2);
253
254        AbstractHeightMap heightmap = null;
255        try {
256            heightmap = new ImageBasedHeightMap(heightMapImage.getImage(), 0.25f);
257            heightmap.load();
258        } catch (Exception e) {
259            e.printStackTrace();
260        }
261        terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
262        List<Camera> cameras = new ArrayList<Camera>();
263        cameras.add(getCamera());
264        terrain.setMaterial(matRock);
265        terrain.setLocalScale(new Vector3f(5, 5, 5));
266        terrain.setLocalTranslation(new Vector3f(0, -30, 0));
267        terrain.setLocked(false); // unlock it so we can edit the height
268
269        terrain.setShadowMode(ShadowMode.Receive);
270        rootNode.attachChild(terrain);
271
272    }
273    //This part is to emulate tides, slightly varrying the height of the water plane
274    private float time = 0.0f;
275    private float waterHeight = 0.0f;
276    private float initialWaterHeight = 0.8f;
277private boolean uw=false;
278    @Override
279    public void simpleUpdate(float tpf) {
280        super.simpleUpdate(tpf);
281        //     box.updateGeometricState();
282        time += tpf;
283        waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f;
284        water.setWaterHeight(initialWaterHeight + waterHeight);
285        if(water.isUnderWater() && !uw){
286
287            waves.setDryFilter(new LowPassFilter(0.5f, 0.1f));
288            uw=true;
289        }
290        if(!water.isUnderWater() && uw){
291            uw=false;
292             //waves.setReverbEnabled(false);
293             waves.setDryFilter(new LowPassFilter(1, 1f));
294             //waves.setDryFilter(new LowPassFilter(1,1f));
295
296        }
297    }
298}
299