/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * 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 the 'Xith3D Project Group' 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) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.input.modules.fpih; import org.openmali.FastMath; import org.openmali.spatial.AxisIndicator; import org.openmali.vecmath2.Tuple3f; import org.openmali.vecmath2.Vector3f; import org.xith3d.input.FirstPersonInputHandler; /** * {@link FPIHMovementConstraints} defines movement constraints for a * {@link FirstPersonInputHandler}. * This includes constraints for the movement as well as constraints for the * mouse rotation or zooming. * * @author Marvin Froehlich (aka Qudus) */ public class FPIHMovementConstraints { private float maxAngleUp = FPIHConfig.DEFAULT_MAX_ANGLE_UP_DOWN; private float maxAngleDown = FPIHConfig.DEFAULT_MAX_ANGLE_UP_DOWN; private boolean fixedPlaneEnabled = false; /** * Sets the maximum up-angle (in radians), that the view can be rotated. * * @param angle */ public void setMaxAngleUp( float angle ) { this.maxAngleUp = angle; } /** * @return the maximum up-angle (in radians), that the view can be rotated. */ public final float getMaxAngleUp() { return ( maxAngleUp ); } /** * Sets the maximum down-angle (in radians), that the view can be rotated. * * @param angle */ public void setMaxAngleDown( float angle ) { this.maxAngleDown = angle; } /** * @return the maximum down-angle (in radians), that the view can be rotated. */ public final float getMaxAngleDown() { return ( maxAngleDown ); } /** * Just calls {@link #setMaxAngleUp(float)} and {@link #setMaxAngleDown(float)}. * * @param angle */ public final void setMaxAngleUpDown( float angle ) { setMaxAngleUp( angle ); setMaxAngleDown( angle ); } /** * If enabled, the Player will always move on the current y-plane. * * @param enabled enabled/disabled */ public void setFixedPlaneEnabled( boolean enabled ) { this.fixedPlaneEnabled = enabled; } /** * If enabled, the Player will always move on the current y-plane. */ public final boolean getFixedPlaneEnabled() { return ( fixedPlaneEnabled ); } /** * Applies the rotational constraints to the euler-angles. * * @param viewEuler * @param upAxis */ public void applyRotationalConstraints( Tuple3f viewEuler, AxisIndicator upAxis ) { // TODO: Fix code for x-up. float rotLeftRight = 0f; float rotUpDown = 0f; switch ( upAxis ) { case POSITIVE_X_AXIS: rotLeftRight = viewEuler.getX(); rotUpDown = viewEuler.getY(); break; case NEGATIVE_X_AXIS: rotLeftRight = viewEuler.getX(); rotUpDown = viewEuler.getY(); break; case POSITIVE_Y_AXIS: rotLeftRight = viewEuler.getY(); rotUpDown = viewEuler.getX(); break; case NEGATIVE_Y_AXIS: rotLeftRight = viewEuler.getY(); rotUpDown = viewEuler.getX(); break; case POSITIVE_Z_AXIS: rotLeftRight = viewEuler.getZ(); rotUpDown = viewEuler.getX() - FastMath.PI_HALF; break; case NEGATIVE_Z_AXIS: rotLeftRight = viewEuler.getZ(); rotUpDown = viewEuler.getX() - FastMath.PI_HALF; break; } rotLeftRight %= FastMath.TWO_PI; if ( rotUpDown > maxAngleUp ) rotUpDown = maxAngleUp; else if ( rotUpDown < -maxAngleDown ) rotUpDown = -maxAngleDown; switch ( upAxis ) { case POSITIVE_X_AXIS: viewEuler.setX( rotLeftRight ); viewEuler.setY( rotUpDown ); break; case NEGATIVE_X_AXIS: viewEuler.setX( rotLeftRight ); viewEuler.setY( rotUpDown ); break; case POSITIVE_Y_AXIS: viewEuler.setY( rotLeftRight ); viewEuler.setX( rotUpDown ); break; case NEGATIVE_Y_AXIS: viewEuler.setY( rotLeftRight ); viewEuler.setX( rotUpDown ); break; case POSITIVE_Z_AXIS: viewEuler.setZ( rotLeftRight ); viewEuler.setX( rotUpDown + FastMath.PI_HALF ); break; case NEGATIVE_Z_AXIS: viewEuler.setZ( rotLeftRight ); viewEuler.setX( rotUpDown + FastMath.PI_HALF ); break; } } public void applyMovementDeltaConstraints( Vector3f viewDeltaPosition, AxisIndicator upAxis ) { if ( fixedPlaneEnabled ) { final float speed = viewDeltaPosition.length(); if ( ( speed == 0f ) || Float.isNaN( speed ) || Float.isInfinite( speed ) ) { viewDeltaPosition.setZero(); return; } switch ( upAxis ) { case POSITIVE_X_AXIS: case NEGATIVE_X_AXIS: viewDeltaPosition.setX( 0.0f ); break; case POSITIVE_Y_AXIS: case NEGATIVE_Y_AXIS: viewDeltaPosition.setY( 0.0f ); break; case POSITIVE_Z_AXIS: case NEGATIVE_Z_AXIS: viewDeltaPosition.setZ( 0.0f ); break; } viewDeltaPosition.normalize(); viewDeltaPosition.scale( speed ); } } /** * * @param viewPosition * @param upAxis */ public void applyMovementConstraints( Tuple3f viewPosition, AxisIndicator upAxis ) { } }