thirdpersonmouselook.java
来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 610 行 · 第 1/2 页
JAVA
610 行
/*
* Copyright (c) 2003-2009 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.jme.input.thirdperson;
import java.util.HashMap;
import com.jme.input.ChaseCamera;
import com.jme.input.InputHandler;
import com.jme.input.MouseInput;
import com.jme.input.RelativeMouse;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.MouseInputAction;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Spatial;
public class ThirdPersonMouseLook extends MouseInputAction {
public static final String PROP_MAXASCENT = "maxAscent";
public static final String PROP_MINASCENT = "minAscent";
public static final String PROP_MAXROLLOUT = "maxRollOut";
public static final String PROP_MINROLLOUT = "minRollOut";
public static final String PROP_MOUSEXMULT = "mouseXMult";
public static final String PROP_MOUSEYMULT = "mouseYMult";
public static final String PROP_MOUSEROLLMULT = "mouseRollMult";
public static final String PROP_INVERTEDY = "invertedY";
public static final String PROP_LOCKASCENT = "lockAscent";
public static final String PROP_ROTATETARGET = "rotateTarget";
public static final String PROP_ENABLED = "lookEnabled";
public static final String PROP_TARGETTURNSPEED = "targetTurnSpeed";
public static final String PROP_MOUSEBUTTON_FOR_LOOKING = "lookButton";
public static final String PROP_INVERTROTATE = "invertRotate";
public static final float DEFAULT_MOUSEXMULT = 2;
public static final float DEFAULT_MOUSEYMULT = 30;
public static final float DEFAULT_MOUSEROLLMULT = 50;
public static final float DEFAULT_MAXASCENT = 45 * FastMath.DEG_TO_RAD;
public static final float DEFAULT_MINASCENT = -15 * FastMath.DEG_TO_RAD;
public static final float DEFAULT_MAXROLLOUT = 240;
public static final float DEFAULT_MINROLLOUT = 20;
public static final float DEFAULT_TARGETTURNSPEED = FastMath.TWO_PI;
public static final boolean DEFAULT_INVERTEDY = false;
public static final boolean DEFAULT_LOCKASCENT = false;
public static final boolean DEFAULT_ENABLED = true;
public static final boolean DEFAULT_ROTATETARGET = false;
public static final boolean DEFAULT_INVERTROTATE = false;
public static final int DEFAULT_MOUSEBUTTON_FOR_LOOKING = -1;
protected float maxAscent = DEFAULT_MAXASCENT;
protected float minAscent = DEFAULT_MINASCENT;
protected float maxRollOut = DEFAULT_MAXROLLOUT;
protected float minRollOut = DEFAULT_MINROLLOUT;
protected float mouseXMultiplier = DEFAULT_MOUSEXMULT;
protected float mouseYMultiplier = DEFAULT_MOUSEYMULT;
protected float mouseRollMultiplier = DEFAULT_MOUSEROLLMULT;
protected float mouseXSpeed = DEFAULT_MOUSEXMULT;
protected float mouseYSpeed = DEFAULT_MOUSEYMULT;
protected float rollInSpeed = DEFAULT_MOUSEROLLMULT;
protected float targetTurnSpeed = DEFAULT_TARGETTURNSPEED;
protected ChaseCamera camera;
protected Spatial target;
protected boolean updated = false;
protected boolean invertedY = DEFAULT_INVERTEDY;
protected boolean lockAscent = DEFAULT_LOCKASCENT;
protected boolean enabled = DEFAULT_ENABLED;
protected boolean rotateTarget = DEFAULT_ROTATETARGET;
protected boolean invertRotate = DEFAULT_INVERTROTATE;
protected int lookMouse = DEFAULT_MOUSEBUTTON_FOR_LOOKING;
protected Vector3f difTemp = new Vector3f();
protected Vector3f sphereTemp = new Vector3f();
protected Vector3f rightTemp = new Vector3f();
protected Quaternion rotTemp = new Quaternion();
protected Vector3f worldUpVec = new Vector3f(ChaseCamera.DEFAULT_WORLDUPVECTOR);
protected ThirdPersonJoystickPlugin plugin = null;
/**
* Constructor creates a new <code>MouseLook</code> object. It takes the
* mouse, camera and speed of the looking.
*
* @param mouse
* the mouse to calculate view changes.
* @param camera
* the camera to move.
*/
public ThirdPersonMouseLook(RelativeMouse mouse, ChaseCamera camera, Spatial target) {
this.mouse = mouse;
this.camera = camera;
this.target = target;
// force update of the 3 speeds.
setSpeed(1);
}
/**
*
* <code>updateProperties</code>
* @param props
*/
public void updateProperties(HashMap<String, Object> props) {
maxAscent = InputHandler.getFloatProp(props, PROP_MAXASCENT, DEFAULT_MAXASCENT);
minAscent = InputHandler.getFloatProp(props, PROP_MINASCENT, DEFAULT_MINASCENT);
maxRollOut = InputHandler.getFloatProp(props, PROP_MAXROLLOUT, DEFAULT_MAXROLLOUT);
minRollOut = InputHandler.getFloatProp(props, PROP_MINROLLOUT, DEFAULT_MINROLLOUT);
targetTurnSpeed = InputHandler.getFloatProp(props, PROP_TARGETTURNSPEED, DEFAULT_TARGETTURNSPEED);
setMouseXMultiplier(InputHandler.getFloatProp(props, PROP_MOUSEXMULT, DEFAULT_MOUSEXMULT));
setMouseYMultiplier(InputHandler.getFloatProp(props, PROP_MOUSEYMULT, DEFAULT_MOUSEYMULT));
setMouseRollMultiplier(InputHandler.getFloatProp(props, PROP_MOUSEROLLMULT, DEFAULT_MOUSEROLLMULT));
invertedY = InputHandler.getBooleanProp(props, PROP_INVERTEDY, DEFAULT_INVERTEDY);
lockAscent = InputHandler.getBooleanProp(props, PROP_LOCKASCENT, DEFAULT_LOCKASCENT);
rotateTarget = InputHandler.getBooleanProp(props, PROP_ROTATETARGET, DEFAULT_ROTATETARGET);
invertRotate = InputHandler.getBooleanProp(props, PROP_INVERTROTATE, DEFAULT_INVERTROTATE);
enabled = InputHandler.getBooleanProp(props, PROP_ENABLED, DEFAULT_ENABLED);
lookMouse = InputHandler.getIntProp(props, PROP_MOUSEBUTTON_FOR_LOOKING, DEFAULT_MOUSEBUTTON_FOR_LOOKING);
worldUpVec = (Vector3f)InputHandler.getObjectProp(props, ChaseCamera.PROP_WORLDUPVECTOR, ChaseCamera.DEFAULT_WORLDUPVECTOR);
}
/**
*
* <code>setSpeed</code> sets the speed of the mouse look.
*
* @param speed
* the speed of the mouse look.
*/
public void setSpeed(float speed) {
super.setSpeed( speed );
mouseXSpeed = mouseXMultiplier * speed;
mouseYSpeed = mouseYMultiplier * speed;
rollInSpeed = mouseRollMultiplier * speed;
}
/**
* <code>performAction</code> checks for any movement of the mouse, and
* calls the appropriate method to alter the camera's orientation when
* applicable.
*
* @see com.jme.input.action.InputActionInterface#performAction(InputActionEvent)
*/
public void performAction(InputActionEvent event) {
if (!enabled)
return;
float time = 0.01f;
if (lookMouse == -1 || MouseInput.get().isButtonDown(lookMouse)) {
camera.setLooking(true);
if (mouse.getLocalTranslation().x != 0) {
float amount;
if(invertRotate) {
amount = -time * mouse.getLocalTranslation().x;
} else {
amount = time * mouse.getLocalTranslation().x;
}
rotateRight(amount, time);
updated = true;
} else if (rotateTarget)
rotateRight(0, time);
if (!lockAscent && mouse.getLocalTranslation().y != 0) {
float amount = time * mouse.getLocalTranslation().y;
rotateUp(amount);
updated = true;
}
} else camera.setLooking(false);
updateFromJoystick(time);
int wdelta = MouseInput.get().getWheelDelta();
if (wdelta != 0) {
float amount = time * -wdelta;
rollIn(amount);
updated = true;
}
if (updated)
camera.getCamera().onFrameChange();
}
protected void updateFromJoystick(float time) {
//XXX: Get the evil constants out of this method...
if (plugin != null) {
float xAmnt = plugin.getJoystick().getAxisValue(plugin.getRotateAxis());
float yAmnt = plugin.getJoystick().getAxisValue(plugin.getAscentAxis());
if (xAmnt != 0) {
rotateRight(xAmnt*.02f, time);
updated = true;
}
if (!lockAscent && yAmnt != 0) {
rotateUp(-yAmnt*.02f);
updated = true;
}
}
}
/**
* <code>rotateRight</code> updates the azimuth value of the camera's
* spherical coordinates.
*
* @param amount
*/
private void rotateRight(float amount, float time) {
Vector3f camPos = camera.getCamera().getLocation();
Vector3f targetPos = target.getWorldTranslation();
float azimuthAccel = (amount * mouseXSpeed);
difTemp.set(camPos).subtractLocal(targetPos);
if (worldUpVec.z == 1) {
float y = difTemp.y;
difTemp.y = difTemp.z;
difTemp.z = y;
}
FastMath.cartesianToSpherical(difTemp, sphereTemp);
sphereTemp.y = FastMath.normalize(sphereTemp.y + (azimuthAccel),
-FastMath.TWO_PI, FastMath.TWO_PI);
FastMath.sphericalToCartesian(sphereTemp, rightTemp);
if (worldUpVec.z == 1) {
float y = rightTemp.y;
rightTemp.y = rightTemp.z;
rightTemp.z = y;
}
rightTemp.addLocal(targetPos);
camPos.set(rightTemp);
if (camera.isMaintainAzimuth()) {
camera.setForceAzimuthUpdate(true);
}
if (rotateTarget) {
//First figure out the current facing vector.
target.getLocalRotation().getRotationColumn(0, rightTemp);
// get angle between vectors
rightTemp.normalizeLocal();
difTemp.y = 0;
difTemp.negateLocal().normalizeLocal();
float angle = rightTemp.angleBetween(difTemp);
// calc how much angle we'll do
float maxAngle = targetTurnSpeed * time;
if (angle < 0 && -maxAngle > angle) {
angle = -maxAngle;
} else if (angle > 0 && maxAngle < angle) {
angle = maxAngle;
}
//figure out rotation axis by taking cross product
Vector3f rotAxis = rightTemp.crossLocal(difTemp).normalizeLocal();
// Build a rotation quat and apply current local rotation.
Quaternion q = rotTemp;
q.fromAngleNormalAxis(angle, rotAxis);
q.mult(target.getLocalRotation(), target.getLocalRotation());
}
}
/**
* <code>rotateRight</code> updates the altitude/polar value of the
* camera's spherical coordinates.
*
* @param amount
*/
private void rotateUp(float amount) {
if (invertedY)
amount *= -1;
Vector3f camPos = camera.getCamera().getLocation();
Vector3f targetPos = target.getWorldTranslation();
float thetaAccel = (amount * mouseYSpeed);
difTemp.set(camPos).subtractLocal(targetPos).subtractLocal(
camera.getTargetOffset());
if (worldUpVec.z == 1) {
float y = difTemp.y;
difTemp.y = difTemp.z;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?