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 */ 32 package jme3test.material; 33 34 import com.jme3.app.SimpleApplication; 35 import com.jme3.input.KeyInput; 36 import com.jme3.input.controls.ActionListener; 37 import com.jme3.input.controls.AnalogListener; 38 import com.jme3.input.controls.KeyTrigger; 39 import com.jme3.light.DirectionalLight; 40 import com.jme3.material.Material; 41 import com.jme3.math.*; 42 import com.jme3.post.FilterPostProcessor; 43 import com.jme3.post.filters.FXAAFilter; 44 import com.jme3.renderer.queue.RenderQueue.ShadowMode; 45 import com.jme3.scene.Geometry; 46 import com.jme3.scene.Node; 47 import com.jme3.scene.Spatial; 48 import com.jme3.scene.shape.Quad; 49 import com.jme3.texture.Texture.WrapMode; 50 import com.jme3.util.SkyFactory; 51 import com.jme3.util.TangentBinormalGenerator; 52 53 public 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