1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32package jme3test.material;
33
34import com.jme3.app.SimpleApplication;
35import com.jme3.input.KeyInput;
36import com.jme3.input.controls.ActionListener;
37import com.jme3.input.controls.AnalogListener;
38import com.jme3.input.controls.KeyTrigger;
39import com.jme3.light.DirectionalLight;
40import com.jme3.material.Material;
41import com.jme3.math.*;
42import com.jme3.post.FilterPostProcessor;
43import com.jme3.post.filters.FXAAFilter;
44import com.jme3.renderer.queue.RenderQueue.ShadowMode;
45import com.jme3.scene.Geometry;
46import com.jme3.scene.Node;
47import com.jme3.scene.Spatial;
48import com.jme3.scene.shape.Quad;
49import com.jme3.texture.Texture.WrapMode;
50import com.jme3.util.SkyFactory;
51import com.jme3.util.TangentBinormalGenerator;
52
53public class TestParallax extends SimpleApplication {
54
55    private Vector3f lightDir = new Vector3f(-1, -1, .5f).normalizeLocal();
56
57    public static void main(String[] args) {
58        TestParallax app = new TestParallax();
59        app.start();
60    }
61
62    public void setupSkyBox() {
63        rootNode.attachChild(SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false));
64    }
65    DirectionalLight dl;
66
67    public void setupLighting() {
68
69        dl = new DirectionalLight();
70        dl.setDirection(lightDir);
71        dl.setColor(new ColorRGBA(.9f, .9f, .9f, 1));
72        rootNode.addLight(dl);
73    }
74    Material mat;
75
76    public void setupFloor() {
77        mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall2.j3m");
78        mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat);
79        mat.getTextureParam("NormalMap").getTextureValue().setWrap(WrapMode.Repeat);
80        mat.setFloat("Shininess", 0);
81
82       // Node floorGeom = (Node) assetManager.loadAsset("Models/WaterTest/WaterTest.mesh.xml");
83        //Geometry g = ((Geometry) floorGeom.getChild(0));
84        //g.getMesh().scaleTextureCoordinates(new Vector2f(10, 10));
85
86        Node floorGeom = new Node("floorGeom");
87        Quad q = new Quad(100, 100);
88        q.scaleTextureCoordinates(new Vector2f(10, 10));
89        Geometry g = new Geometry("geom", q);
90        g.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
91        floorGeom.attachChild(g);
92
93
94        TangentBinormalGenerator.generate(floorGeom);
95        floorGeom.setLocalTranslation(-50, 22, 60);
96        //floorGeom.setLocalScale(100);
97
98        floorGeom.setMaterial(mat);
99        rootNode.attachChild(floorGeom);
100    }
101
102    public void setupSignpost() {
103        Spatial signpost = assetManager.loadModel("Models/Sign Post/Sign Post.mesh.xml");
104        Material mat = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m");
105        TangentBinormalGenerator.generate(signpost);
106        signpost.setMaterial(mat);
107        signpost.rotate(0, FastMath.HALF_PI, 0);
108        signpost.setLocalTranslation(12, 23.5f, 30);
109        signpost.setLocalScale(4);
110        signpost.setShadowMode(ShadowMode.CastAndReceive);
111        rootNode.attachChild(signpost);
112    }
113
114    @Override
115    public void simpleInitApp() {
116        cam.setLocation(new Vector3f(-15.445636f, 30.162927f, 60.252777f));
117        cam.setRotation(new Quaternion(0.05173137f, 0.92363626f, -0.13454558f, 0.35513034f));
118
119        flyCam.setMoveSpeed(30);
120
121
122        setupLighting();
123        setupSkyBox();
124        setupFloor();
125        setupSignpost();
126
127        inputManager.addListener(new AnalogListener() {
128
129            public void onAnalog(String name, float value, float tpf) {
130                if ("heightUP".equals(name)) {
131                    parallaxHeigh += 0.0001;
132                    mat.setFloat("ParallaxHeight", parallaxHeigh);
133                }
134                if ("heightDown".equals(name)) {
135                    parallaxHeigh -= 0.0001;
136                    parallaxHeigh = Math.max(parallaxHeigh, 0);
137                    mat.setFloat("ParallaxHeight", parallaxHeigh);
138                }
139
140            }
141        }, "heightUP", "heightDown");
142        inputManager.addMapping("heightUP", new KeyTrigger(KeyInput.KEY_I));
143        inputManager.addMapping("heightDown", new KeyTrigger(KeyInput.KEY_K));
144
145        inputManager.addListener(new ActionListener() {
146
147            public void onAction(String name, boolean isPressed, float tpf) {
148                if (isPressed && "toggleSteep".equals(name)) {
149                    steep = !steep;
150                    mat.setBoolean("SteepParallax", steep);
151                }
152            }
153        }, "toggleSteep");
154        inputManager.addMapping("toggleSteep", new KeyTrigger(KeyInput.KEY_SPACE));
155        FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
156        FXAAFilter fxaa = new FXAAFilter();
157        fxaa.setReduceMul(0.08f);
158        fpp.addFilter(fxaa);
159        viewPort.addProcessor(fpp);
160    }
161    float parallaxHeigh = 0.05f;
162    float time = 0;
163    boolean steep = false;
164
165    @Override
166    public void simpleUpdate(float tpf) {
167//        time+=tpf;
168//        lightDir.set(FastMath.sin(time), -1, FastMath.cos(time));
169//        bsr.setDirection(lightDir);
170//        dl.setDirection(lightDir);
171    }
172}
173