All basic features are there, smooth motion is still missing along with some very specific features that I'm tempted to just drop... Also added a test case git-svn-id: https://jmonkeyengine.googlecode.com/svn/branches/gradle-restructure@11102 75d07b2b-3a1a-0410-a2c5-0572b91ccdcaexperimental
parent
240b41fdf6
commit
bea196baa2
@ -0,0 +1,484 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2012 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.app; |
||||||
|
|
||||||
|
import com.jme3.app.state.AbstractAppState; |
||||||
|
import com.jme3.app.state.AppStateManager; |
||||||
|
import com.jme3.input.CameraInput; |
||||||
|
import com.jme3.input.InputManager; |
||||||
|
import com.jme3.input.MouseInput; |
||||||
|
import com.jme3.input.controls.ActionListener; |
||||||
|
import com.jme3.input.controls.AnalogListener; |
||||||
|
import com.jme3.input.controls.MouseAxisTrigger; |
||||||
|
import com.jme3.input.controls.MouseButtonTrigger; |
||||||
|
import com.jme3.input.controls.Trigger; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.CameraNode; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
import com.jme3.scene.control.CameraControl; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
|
||||||
|
/** |
||||||
|
* This class is a camera controler that allow the camera to follow a target |
||||||
|
* Spatial. |
||||||
|
* |
||||||
|
* @author Nehon |
||||||
|
*/ |
||||||
|
public class ChaseCameraAppState extends AbstractAppState implements ActionListener, AnalogListener { |
||||||
|
|
||||||
|
protected Spatial spatial; |
||||||
|
protected Node target; |
||||||
|
protected CameraNode camNode; |
||||||
|
protected InputManager inputManager; |
||||||
|
protected boolean invertYaxis = false; |
||||||
|
protected boolean invertXaxis = false; |
||||||
|
protected boolean hideCursorOnRotate = true; |
||||||
|
protected boolean canRotate; |
||||||
|
protected boolean dragToRotate = true; |
||||||
|
protected float rotationSpeed = 1.0f; |
||||||
|
protected float zoomSpeed = 2.0f; |
||||||
|
//protected boolean zoomin;
|
||||||
|
protected float minDistance = 1.0f; |
||||||
|
protected float maxDistance = 40.0f; |
||||||
|
protected float distance = 20; |
||||||
|
protected float maxVerticalRotation = 1.4f; |
||||||
|
protected float verticalRotation = 0f; |
||||||
|
protected float minVerticalRotation = 0f; |
||||||
|
protected float horizontalRotation = 0f; |
||||||
|
//protected float distanceLerpFactor = 0;
|
||||||
|
protected Vector3f upVector; |
||||||
|
protected Vector3f leftVector; |
||||||
|
protected Trigger[] zoomOutTrigger = {new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true)}; |
||||||
|
protected Trigger[] zoomInTrigger = {new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false)}; |
||||||
|
protected Trigger[] toggleRotateTrigger = {new MouseButtonTrigger(MouseInput.BUTTON_LEFT), new MouseButtonTrigger(MouseInput.BUTTON_RIGHT)}; |
||||||
|
|
||||||
|
//
|
||||||
|
// protected boolean rotating = false;
|
||||||
|
// protected float rotation = 0;
|
||||||
|
// protected float targetRotation = rotation;
|
||||||
|
public ChaseCameraAppState() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppStateManager stateManager, Application app) { |
||||||
|
super.initialize(stateManager, app); |
||||||
|
this.inputManager = app.getInputManager(); |
||||||
|
target = new Node("ChaseCamTarget"); |
||||||
|
camNode = new CameraNode("ChaseCameraNode", app.getCamera()); |
||||||
|
camNode.setControlDir(CameraControl.ControlDirection.SpatialToCamera); |
||||||
|
target.attachChild(camNode); |
||||||
|
camNode.setLocalTranslation(0, 0, distance); |
||||||
|
upVector = app.getCamera().getUp().clone(); |
||||||
|
leftVector = app.getCamera().getLeft().clone(); |
||||||
|
registerWithInput(); |
||||||
|
rotateCamera(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Registers inputs with the input manager |
||||||
|
* |
||||||
|
* @param inputManager |
||||||
|
*/ |
||||||
|
public final void registerWithInput() { |
||||||
|
|
||||||
|
String[] inputs = {CameraInput.CHASECAM_TOGGLEROTATE, |
||||||
|
CameraInput.CHASECAM_DOWN, |
||||||
|
CameraInput.CHASECAM_UP, |
||||||
|
CameraInput.CHASECAM_MOVELEFT, |
||||||
|
CameraInput.CHASECAM_MOVERIGHT, |
||||||
|
CameraInput.CHASECAM_ZOOMIN, |
||||||
|
CameraInput.CHASECAM_ZOOMOUT}; |
||||||
|
initVerticalAxisInputs(); |
||||||
|
initZoomInput(); |
||||||
|
initHorizontalAxisInput(); |
||||||
|
initTogleRotateInput(); |
||||||
|
|
||||||
|
inputManager.addListener(this, inputs); |
||||||
|
} |
||||||
|
|
||||||
|
public void onAction(String name, boolean keyPressed, float tpf) { |
||||||
|
if (isEnabled()) { |
||||||
|
if (dragToRotate) { |
||||||
|
if (name.equals(CameraInput.CHASECAM_TOGGLEROTATE) && isEnabled()) { |
||||||
|
if (keyPressed) { |
||||||
|
canRotate = true; |
||||||
|
if (hideCursorOnRotate) { |
||||||
|
inputManager.setCursorVisible(false); |
||||||
|
} |
||||||
|
} else { |
||||||
|
canRotate = false; |
||||||
|
if (hideCursorOnRotate) { |
||||||
|
inputManager.setCursorVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void onAnalog(String name, float value, float tpf) { |
||||||
|
if (isEnabled()) { |
||||||
|
if (canRotate) { |
||||||
|
if (name.equals(CameraInput.CHASECAM_MOVELEFT)) { |
||||||
|
horizontalRotation -= value * rotationSpeed; |
||||||
|
rotateCamera(); |
||||||
|
} else if (name.equals(CameraInput.CHASECAM_MOVERIGHT)) { |
||||||
|
horizontalRotation += value * rotationSpeed; |
||||||
|
rotateCamera(); |
||||||
|
} else if (name.equals(CameraInput.CHASECAM_UP)) { |
||||||
|
verticalRotation += value * rotationSpeed; |
||||||
|
rotateCamera(); |
||||||
|
} else if (name.equals(CameraInput.CHASECAM_DOWN)) { |
||||||
|
verticalRotation -= value * rotationSpeed; |
||||||
|
rotateCamera(); |
||||||
|
} |
||||||
|
} |
||||||
|
if (name.equals(CameraInput.CHASECAM_ZOOMIN)) { |
||||||
|
zoomCamera(-value * zoomSpeed); |
||||||
|
} else if (name.equals(CameraInput.CHASECAM_ZOOMOUT)) { |
||||||
|
zoomCamera(+value * zoomSpeed); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* rotate the camera around the target |
||||||
|
*/ |
||||||
|
protected void rotateCamera() { |
||||||
|
verticalRotation = FastMath.clamp(verticalRotation, minVerticalRotation, maxVerticalRotation); |
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Quaternion rot = vars.quat1; |
||||||
|
Quaternion rot2 = vars.quat2; |
||||||
|
rot.fromAngleNormalAxis(verticalRotation, leftVector); |
||||||
|
rot2.fromAngleNormalAxis(horizontalRotation, upVector); |
||||||
|
rot2.multLocal(rot); |
||||||
|
target.setLocalRotation(rot2); |
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* move the camera toward or away the target |
||||||
|
*/ |
||||||
|
protected void zoomCamera(float value) { |
||||||
|
distance = FastMath.clamp(distance + value, minDistance, maxDistance); |
||||||
|
camNode.setLocalTranslation(new Vector3f(0, 0, distance)); |
||||||
|
} |
||||||
|
|
||||||
|
public void setTarget(Spatial targetSpatial) { |
||||||
|
spatial = targetSpatial; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(float tpf) { |
||||||
|
if (spatial == null) { |
||||||
|
throw new IllegalArgumentException("The spatial to follow is null, please use the setTarget method"); |
||||||
|
} |
||||||
|
target.setLocalTranslation(spatial.getWorldTranslation()); |
||||||
|
camNode.lookAt(target.getWorldTranslation(), upVector); |
||||||
|
|
||||||
|
target.updateLogicalState(tpf); |
||||||
|
target.updateGeometricState(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets custom triggers for toggleing the rotation of the cam deafult are |
||||||
|
* new MouseButtonTrigger(MouseInput.BUTTON_LEFT) left mouse button new |
||||||
|
* MouseButtonTrigger(MouseInput.BUTTON_RIGHT) right mouse button |
||||||
|
* |
||||||
|
* @param triggers |
||||||
|
*/ |
||||||
|
public void setToggleRotationTrigger(Trigger... triggers) { |
||||||
|
toggleRotateTrigger = triggers; |
||||||
|
if (inputManager != null) { |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_TOGGLEROTATE); |
||||||
|
initTogleRotateInput(); |
||||||
|
inputManager.addListener(this, CameraInput.CHASECAM_TOGGLEROTATE); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets custom triggers for zomming in the cam default is new |
||||||
|
* MouseAxisTrigger(MouseInput.AXIS_WHEEL, true) mouse wheel up |
||||||
|
* |
||||||
|
* @param triggers |
||||||
|
*/ |
||||||
|
public void setZoomInTrigger(Trigger... triggers) { |
||||||
|
zoomInTrigger = triggers; |
||||||
|
if (inputManager != null) { |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_ZOOMIN); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_ZOOMIN, zoomInTrigger); |
||||||
|
inputManager.addListener(this, CameraInput.CHASECAM_ZOOMIN); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets custom triggers for zomming out the cam default is new |
||||||
|
* MouseAxisTrigger(MouseInput.AXIS_WHEEL, false) mouse wheel down |
||||||
|
* |
||||||
|
* @param triggers |
||||||
|
*/ |
||||||
|
public void setZoomOutTrigger(Trigger... triggers) { |
||||||
|
zoomOutTrigger = triggers; |
||||||
|
if (inputManager != null) { |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_ZOOMOUT); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_ZOOMOUT, zoomOutTrigger); |
||||||
|
inputManager.addListener(this, CameraInput.CHASECAM_ZOOMOUT); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the max zoom distance of the camera (default is 40) |
||||||
|
* |
||||||
|
* @return maxDistance |
||||||
|
*/ |
||||||
|
public float getMaxDistance() { |
||||||
|
return maxDistance; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the max zoom distance of the camera (default is 40) |
||||||
|
* |
||||||
|
* @param maxDistance |
||||||
|
*/ |
||||||
|
public void setMaxDistance(float maxDistance) { |
||||||
|
this.maxDistance = maxDistance; |
||||||
|
zoomCamera(distance); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the min zoom distance of the camera (default is 1) |
||||||
|
* |
||||||
|
* @return minDistance |
||||||
|
*/ |
||||||
|
public float getMinDistance() { |
||||||
|
return minDistance; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the min zoom distance of the camera (default is 1) |
||||||
|
*/ |
||||||
|
public void setMinDistance(float minDistance) { |
||||||
|
this.minDistance = minDistance; |
||||||
|
zoomCamera(distance); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return The maximal vertical rotation angle in radian of the camera |
||||||
|
* around the target |
||||||
|
*/ |
||||||
|
public float getMaxVerticalRotation() { |
||||||
|
return maxVerticalRotation; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the maximal vertical rotation angle in radian of the camera around |
||||||
|
* the target. Default is Pi/2; |
||||||
|
* |
||||||
|
* @param maxVerticalRotation |
||||||
|
*/ |
||||||
|
public void setMaxVerticalRotation(float maxVerticalRotation) { |
||||||
|
this.maxVerticalRotation = maxVerticalRotation; |
||||||
|
rotateCamera(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @return The minimal vertical rotation angle in radian of the camera |
||||||
|
* around the target |
||||||
|
*/ |
||||||
|
public float getMinVerticalRotation() { |
||||||
|
return minVerticalRotation; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the minimal vertical rotation angle in radian of the camera around |
||||||
|
* the target default is 0; |
||||||
|
* |
||||||
|
* @param minHeight |
||||||
|
*/ |
||||||
|
public void setMinVerticalRotation(float minHeight) { |
||||||
|
this.minVerticalRotation = minHeight; |
||||||
|
rotateCamera(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* returns the zoom speed |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public float getZoomSpeed() { |
||||||
|
return zoomSpeed; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the zoom speed, the lower the value, the slower the camera will zoom |
||||||
|
* in and out. default is 2. |
||||||
|
* |
||||||
|
* @param zoomSpeed |
||||||
|
*/ |
||||||
|
public void setZoomSpeed(float zoomSpeed) { |
||||||
|
this.zoomSpeed = zoomSpeed; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the rotation speed when the mouse is moved. |
||||||
|
* |
||||||
|
* @return the rotation speed when the mouse is moved. |
||||||
|
*/ |
||||||
|
public float getRotationSpeed() { |
||||||
|
return rotationSpeed; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the rotate amount when user moves his mouse, the lower the value, |
||||||
|
* the slower the camera will rotate. default is 1. |
||||||
|
* |
||||||
|
* @param rotationSpeed Rotation speed on mouse movement, default is 1. |
||||||
|
*/ |
||||||
|
public void setRotationSpeed(float rotationSpeed) { |
||||||
|
this.rotationSpeed = rotationSpeed; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the default distance at start of applicaiton |
||||||
|
* |
||||||
|
* @param defaultDistance |
||||||
|
*/ |
||||||
|
public void setDefaultDistance(float defaultDistance) { |
||||||
|
distance = defaultDistance; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* sets the default horizontal rotation in radian of the camera at start of |
||||||
|
* the application |
||||||
|
* |
||||||
|
* @param angleInRad |
||||||
|
*/ |
||||||
|
public void setDefaultHorizontalRotation(float angleInRad) { |
||||||
|
horizontalRotation = angleInRad; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* sets the default vertical rotation in radian of the camera at start of |
||||||
|
* the application |
||||||
|
* |
||||||
|
* @param angleInRad |
||||||
|
*/ |
||||||
|
public void setDefaultVerticalRotation(float angleInRad) { |
||||||
|
verticalRotation = angleInRad; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return If drag to rotate feature is enabled. |
||||||
|
* |
||||||
|
* @see FlyByCamera#setDragToRotate(boolean) |
||||||
|
*/ |
||||||
|
public boolean isDragToRotate() { |
||||||
|
return dragToRotate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param dragToRotate When true, the user must hold the mouse button and |
||||||
|
* drag over the screen to rotate the camera, and the cursor is visible |
||||||
|
* until dragged. Otherwise, the cursor is invisible at all times and |
||||||
|
* holding the mouse button is not needed to rotate the camera. This feature |
||||||
|
* is disabled by default. |
||||||
|
*/ |
||||||
|
public void setDragToRotate(boolean dragToRotate) { |
||||||
|
this.dragToRotate = dragToRotate; |
||||||
|
this.canRotate = !dragToRotate; |
||||||
|
inputManager.setCursorVisible(dragToRotate); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* invert the vertical axis movement of the mouse |
||||||
|
* |
||||||
|
* @param invertYaxis |
||||||
|
*/ |
||||||
|
public void setInvertVerticalAxis(boolean invertYaxis) { |
||||||
|
this.invertYaxis = invertYaxis; |
||||||
|
if (inputManager != null) { |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_DOWN); |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_UP); |
||||||
|
initVerticalAxisInputs(); |
||||||
|
inputManager.addListener(this, CameraInput.CHASECAM_DOWN, CameraInput.CHASECAM_UP); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* invert the Horizontal axis movement of the mouse |
||||||
|
* |
||||||
|
* @param invertXaxis |
||||||
|
*/ |
||||||
|
public void setInvertHorizontalAxis(boolean invertXaxis) { |
||||||
|
this.invertXaxis = invertXaxis; |
||||||
|
if (inputManager != null) { |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_MOVELEFT); |
||||||
|
inputManager.deleteMapping(CameraInput.CHASECAM_MOVERIGHT); |
||||||
|
initHorizontalAxisInput(); |
||||||
|
inputManager.addListener(this, CameraInput.CHASECAM_MOVELEFT, CameraInput.CHASECAM_MOVERIGHT); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void initVerticalAxisInputs() { |
||||||
|
if (!invertYaxis) { |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_DOWN, new MouseAxisTrigger(MouseInput.AXIS_Y, true)); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_UP, new MouseAxisTrigger(MouseInput.AXIS_Y, false)); |
||||||
|
} else { |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_DOWN, new MouseAxisTrigger(MouseInput.AXIS_Y, false)); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_UP, new MouseAxisTrigger(MouseInput.AXIS_Y, true)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void initHorizontalAxisInput() { |
||||||
|
if (!invertXaxis) { |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_MOVELEFT, new MouseAxisTrigger(MouseInput.AXIS_X, true)); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_MOVERIGHT, new MouseAxisTrigger(MouseInput.AXIS_X, false)); |
||||||
|
} else { |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_MOVELEFT, new MouseAxisTrigger(MouseInput.AXIS_X, false)); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_MOVERIGHT, new MouseAxisTrigger(MouseInput.AXIS_X, true)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void initZoomInput() { |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_ZOOMIN, zoomInTrigger); |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_ZOOMOUT, zoomOutTrigger); |
||||||
|
} |
||||||
|
|
||||||
|
private void initTogleRotateInput() { |
||||||
|
inputManager.addMapping(CameraInput.CHASECAM_TOGGLEROTATE, toggleRotateTrigger); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,153 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2012 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package jme3test.input; |
||||||
|
|
||||||
|
import com.jme3.app.ChaseCameraAppState; |
||||||
|
import com.jme3.app.FlyCamAppState; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.input.KeyInput; |
||||||
|
import com.jme3.input.controls.ActionListener; |
||||||
|
import com.jme3.input.controls.AnalogListener; |
||||||
|
import com.jme3.input.controls.KeyTrigger; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.shape.Quad; |
||||||
|
|
||||||
|
/** A 3rd-person chase camera orbits a target (teapot). |
||||||
|
* Follow the teapot with WASD keys, rotate by dragging the mouse. */ |
||||||
|
public class TestChaseCameraAppState extends SimpleApplication implements AnalogListener, ActionListener { |
||||||
|
|
||||||
|
private Geometry teaGeom; |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
TestChaseCameraAppState app = new TestChaseCameraAppState(); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
|
||||||
|
public void simpleInitApp() { |
||||||
|
// Load a teapot model
|
||||||
|
teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj"); |
||||||
|
Material mat_tea = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md"); |
||||||
|
teaGeom.setMaterial(mat_tea); |
||||||
|
rootNode.attachChild(teaGeom); |
||||||
|
|
||||||
|
// Load a floor model
|
||||||
|
Material mat_ground = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat_ground.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg")); |
||||||
|
Geometry ground = new Geometry("ground", new Quad(50, 50)); |
||||||
|
ground.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X)); |
||||||
|
ground.setLocalTranslation(-25, -1, 25); |
||||||
|
ground.setMaterial(mat_ground); |
||||||
|
rootNode.attachChild(ground); |
||||||
|
|
||||||
|
//disable the flyCam
|
||||||
|
stateManager.detach(stateManager.getState(FlyCamAppState.class)); |
||||||
|
|
||||||
|
// Enable a chase cam
|
||||||
|
ChaseCameraAppState chaseCamAS = new ChaseCameraAppState(); |
||||||
|
chaseCamAS.setTarget(teaGeom); |
||||||
|
stateManager.attach(chaseCamAS); |
||||||
|
|
||||||
|
//Uncomment this to invert the camera's vertical rotation Axis
|
||||||
|
//chaseCamAS.setInvertVerticalAxis(true);
|
||||||
|
|
||||||
|
//Uncomment this to invert the camera's horizontal rotation Axis
|
||||||
|
//chaseCamAS.setInvertHorizontalAxis(true);
|
||||||
|
|
||||||
|
//Uncomment this to enable rotation when the middle mouse button is pressed (like Blender)
|
||||||
|
//WARNING : setting this trigger disable the rotation on right and left mouse button click
|
||||||
|
//chaseCamAS.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.BUTTON_MIDDLE));
|
||||||
|
|
||||||
|
//Uncomment this to set mutiple triggers to enable rotation of the cam
|
||||||
|
//Here space bar and middle mouse button
|
||||||
|
//chaseCamAS.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.BUTTON_MIDDLE),new KeyTrigger(KeyInput.KEY_SPACE));
|
||||||
|
|
||||||
|
//registering inputs for target's movement
|
||||||
|
registerInput(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void registerInput() { |
||||||
|
inputManager.addMapping("moveForward", new KeyTrigger(KeyInput.KEY_UP), new KeyTrigger(KeyInput.KEY_W)); |
||||||
|
inputManager.addMapping("moveBackward", new KeyTrigger(KeyInput.KEY_DOWN), new KeyTrigger(KeyInput.KEY_S)); |
||||||
|
inputManager.addMapping("moveRight", new KeyTrigger(KeyInput.KEY_RIGHT), new KeyTrigger(KeyInput.KEY_D)); |
||||||
|
inputManager.addMapping("moveLeft", new KeyTrigger(KeyInput.KEY_LEFT), new KeyTrigger(KeyInput.KEY_A)); |
||||||
|
inputManager.addMapping("displayPosition", new KeyTrigger(KeyInput.KEY_P)); |
||||||
|
inputManager.addListener(this, "moveForward", "moveBackward", "moveRight", "moveLeft"); |
||||||
|
inputManager.addListener(this, "displayPosition"); |
||||||
|
} |
||||||
|
|
||||||
|
public void onAnalog(String name, float value, float tpf) { |
||||||
|
if (name.equals("moveForward")) { |
||||||
|
teaGeom.move(0, 0, -5 * tpf); |
||||||
|
} |
||||||
|
if (name.equals("moveBackward")) { |
||||||
|
teaGeom.move(0, 0, 5 * tpf); |
||||||
|
} |
||||||
|
if (name.equals("moveRight")) { |
||||||
|
teaGeom.move(5 * tpf, 0, 0); |
||||||
|
} |
||||||
|
if (name.equals("moveLeft")) { |
||||||
|
teaGeom.move(-5 * tpf, 0, 0); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void onAction(String name, boolean keyPressed, float tpf) { |
||||||
|
if (name.equals("displayPosition") && keyPressed) { |
||||||
|
teaGeom.move(10, 10, 10); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
super.simpleUpdate(tpf); |
||||||
|
|
||||||
|
// teaGeom.move(new Vector3f(0.001f, 0, 0));
|
||||||
|
// pivot.rotate(0, 0.00001f, 0);
|
||||||
|
// rootNode.updateGeometricState();
|
||||||
|
} |
||||||
|
// public void update() {
|
||||||
|
// super.update();
|
||||||
|
//// render the viewports
|
||||||
|
// float tpf = timer.getTimePerFrame();
|
||||||
|
// state.getRootNode().rotate(0, 0.000001f, 0);
|
||||||
|
// stateManager.update(tpf);
|
||||||
|
// stateManager.render(renderManager);
|
||||||
|
// renderManager.render(tpf);
|
||||||
|
// }
|
||||||
|
} |
Loading…
Reference in new issue