159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine All rights reserved. 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p/> 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are met: 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright notice, 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this list of conditions and the following disclaimer. 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p/> 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p/> 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p/> 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * POSSIBILITY OF SUCH DAMAGE. 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage jme3test.input; 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.app.SimpleApplication; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.input.MouseInput; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.input.controls.*; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.Material; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Quaternion; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.CameraNode; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Geometry; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Node; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.control.CameraControl.ControlDirection; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.shape.Quad; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.system.AppSettings; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A 3rd-person camera node follows a target (teapot). Follow the teapot with 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * WASD keys, rotate by dragging the mouse. 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class TestCameraNode extends SimpleApplication implements AnalogListener, ActionListener { 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Geometry teaGeom; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Node teaNode; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CameraNode camNode; 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean rotate = false; 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f direction = new Vector3f(); 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static void main(String[] args) { 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TestCameraNode app = new TestCameraNode(); 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AppSettings s = new AppSettings(true); 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta s.setFrameRate(100); 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta app.setSettings(s); 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta app.start(); 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void simpleInitApp() { 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // load a teapot model 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj"); 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md"); 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaGeom.setMaterial(mat); 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //create a node to attach the geometry and the camera node 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode = new Node("teaNode"); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.attachChild(teaGeom); 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rootNode.attachChild(teaNode); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create a floor 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg")); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry ground = new Geometry("ground", new Quad(50, 50)); 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ground.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X)); 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ground.setLocalTranslation(-25, -1, 25); 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ground.setMaterial(mat); 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rootNode.attachChild(ground); 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //creating the camera Node 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta camNode = new CameraNode("CamNode", cam); 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //Setting the direction to Spatial to camera, this means the camera will copy the movements of the Node 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta camNode.setControlDir(ControlDirection.SpatialToCamera); 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //attaching the camNode to the teaNode 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.attachChild(camNode); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //setting the local translation of the cam node to move it away from the teanNode a bit 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta camNode.setLocalTranslation(new Vector3f(-10, 0, 0)); 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //setting the camNode to look at the teaNode 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta camNode.lookAt(teaNode.getLocalTranslation(), Vector3f.UNIT_Y); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //disable the default 1st-person flyCam (don't forget this!!) 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta flyCam.setEnabled(false); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta registerInput(); 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void registerInput() { 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("moveForward", new KeyTrigger(keyInput.KEY_UP), new KeyTrigger(keyInput.KEY_W)); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("moveBackward", new KeyTrigger(keyInput.KEY_DOWN), new KeyTrigger(keyInput.KEY_S)); 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("moveRight", new KeyTrigger(keyInput.KEY_RIGHT), new KeyTrigger(keyInput.KEY_D)); 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("moveLeft", new KeyTrigger(keyInput.KEY_LEFT), new KeyTrigger(keyInput.KEY_A)); 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("toggleRotate", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("rotateRight", new MouseAxisTrigger(MouseInput.AXIS_X, true)); 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("rotateLeft", new MouseAxisTrigger(MouseInput.AXIS_X, false)); 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addListener(this, "moveForward", "moveBackward", "moveRight", "moveLeft"); 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addListener(this, "rotateRight", "rotateLeft", "toggleRotate"); 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void onAnalog(String name, float value, float tpf) { 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //computing the normalized direction of the cam to move the teaNode 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.set(cam.getDirection()).normalizeLocal(); 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("moveForward")) { 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.multLocal(5 * tpf); 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.move(direction); 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("moveBackward")) { 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.multLocal(-5 * tpf); 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.move(direction); 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("moveRight")) { 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.crossLocal(Vector3f.UNIT_Y).multLocal(5 * tpf); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.move(direction); 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("moveLeft")) { 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.crossLocal(Vector3f.UNIT_Y).multLocal(-5 * tpf); 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.move(direction); 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("rotateRight") && rotate) { 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.rotate(0, 5 * tpf, 0); 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("rotateLeft") && rotate) { 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta teaNode.rotate(0, -5 * tpf, 0); 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void onAction(String name, boolean keyPressed, float tpf) { 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //toggling rotation on or off 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("toggleRotate") && keyPressed) { 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotate = true; 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.setCursorVisible(false); 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (name.equals("toggleRotate") && !keyPressed) { 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotate = false; 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.setCursorVisible(true); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 154