diff --git a/changes.txt b/changes.txt index 2405fe8a..ba6ada35 100644 --- a/changes.txt +++ b/changes.txt @@ -1,6 +1,8 @@ -------------------------- Changes in 1.9 (not yet released) +- FPS camera now supports keyboard rotation. +- Base FPS-camera movement on last position of mouse instead of always center (works better on platforms where cursor-placement is not allowed) - Octrees with other vertex types than EVT_2TCOORDS can now also use VBO's. - Add IOctreeSceneNode interface to control parameters like VBO usage and polygon clipping checks for octree scene nodes. - Add support for different geometric primitivs to meshbuffers. Thanks @gerdb for patch proposal (http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=45999) diff --git a/include/ISceneNodeAnimatorCameraFPS.h b/include/ISceneNodeAnimatorCameraFPS.h index 5eaea817..91a00680 100644 --- a/include/ISceneNodeAnimatorCameraFPS.h +++ b/include/ISceneNodeAnimatorCameraFPS.h @@ -30,13 +30,19 @@ namespace scene //! Sets the speed of movement in units per millisecond virtual void setMoveSpeed(f32 moveSpeed) = 0; - //! Returns the rotation speed in degrees + //! Returns the rotation speed when using keyboard + virtual f32 getRotateSpeedKeyboard() const = 0; + + //! Set the rotation speed when using keyboard + virtual void setRotateSpeedKeyboard(f32 rotateSpeed) = 0; + + //! Returns the rotation speed in degrees when using mouse /** The degrees are equivalent to a half screen movement of the mouse, i.e. if the mouse cursor had been moved to the border of the screen since the last animation. */ virtual f32 getRotateSpeed() const = 0; - //! Set the rotation speed in degrees + //! Set the rotation speed in degrees when using mouse virtual void setRotateSpeed(f32 rotateSpeed) = 0; //! Sets the keyboard mapping for this animator (old style) diff --git a/include/SKeyMap.h b/include/SKeyMap.h index 793cd983..3f1b68c5 100644 --- a/include/SKeyMap.h +++ b/include/SKeyMap.h @@ -19,6 +19,8 @@ namespace irr EKA_STRAFE_RIGHT, EKA_JUMP_UP, EKA_CROUCH, + EKA_ROTATE_LEFT, + EKA_ROTATE_RIGHT, EKA_COUNT, //! This value is not used. It only forces this enumeration to compile in 32 bit. diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp index 85a27bbb..503ffb72 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp @@ -18,9 +18,10 @@ namespace scene //! constructor CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, - SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY) + SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY, float rotateSpeedKeyboard) : CursorControl(cursorControl), MaxVerticalAngle(88.0f), NoVerticalMovement(noVerticalMovement), - MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), + MoveSpeed(moveSpeed), RotateSpeedKeyboard(rotateSpeedKeyboard), RotateSpeed(rotateSpeed), + JumpSpeed(jumpSpeed), MouseYDirection(invertY ? -1.0f : 1.0f), LastAnimationTime(0), firstUpdate(true), firstInput(true) { @@ -39,9 +40,13 @@ CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cu // create default key map KeyMap.push_back(SKeyMap(EKA_MOVE_FORWARD, irr::KEY_UP)); KeyMap.push_back(SKeyMap(EKA_MOVE_BACKWARD, irr::KEY_DOWN)); - KeyMap.push_back(SKeyMap(EKA_STRAFE_LEFT, irr::KEY_LEFT)); - KeyMap.push_back(SKeyMap(EKA_STRAFE_RIGHT, irr::KEY_RIGHT)); + KeyMap.push_back(SKeyMap(EKA_MOVE_FORWARD, irr::KEY_KEY_W)); + KeyMap.push_back(SKeyMap(EKA_MOVE_BACKWARD, irr::KEY_KEY_S)); + KeyMap.push_back(SKeyMap(EKA_STRAFE_LEFT, irr::KEY_KEY_A)); + KeyMap.push_back(SKeyMap(EKA_STRAFE_RIGHT, irr::KEY_KEY_D)); KeyMap.push_back(SKeyMap(EKA_JUMP_UP, irr::KEY_KEY_J)); + KeyMap.push_back(SKeyMap(EKA_ROTATE_LEFT, irr::KEY_LEFT)); + KeyMap.push_back(SKeyMap(EKA_ROTATE_RIGHT, irr::KEY_RIGHT)); } else { @@ -149,22 +154,8 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) { if (CursorPos != CenterCursor) { - relativeRotation.Y -= (0.5f - CursorPos.X) * RotateSpeed; - relativeRotation.X -= (0.5f - CursorPos.Y) * RotateSpeed * MouseYDirection; - - // X < MaxVerticalAngle or X > 360-MaxVerticalAngle - - if (relativeRotation.X > MaxVerticalAngle*2 && - relativeRotation.X < 360.0f-MaxVerticalAngle) - { - relativeRotation.X = 360.0f-MaxVerticalAngle; - } - else - if (relativeRotation.X > MaxVerticalAngle && - relativeRotation.X < 360.0f-MaxVerticalAngle) - { - relativeRotation.X = MaxVerticalAngle; - } + relativeRotation.Y -= (CenterCursor.X - CursorPos.X) * RotateSpeed; + relativeRotation.X -= (CenterCursor.Y - CursorPos.Y) * RotateSpeed * MouseYDirection; // Do the fix as normal, special case below // reset cursor position to the centre of the window. @@ -192,6 +183,28 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) } } + // keyboard rotation + if (CursorKeys[EKA_ROTATE_LEFT]) + relativeRotation.Y -= timeDiff * RotateSpeedKeyboard; + + if (CursorKeys[EKA_ROTATE_RIGHT]) + relativeRotation.Y += timeDiff * RotateSpeedKeyboard; + + // X < MaxVerticalAngle or X > 360-MaxVerticalAngle + + if (relativeRotation.X > MaxVerticalAngle*2 && + relativeRotation.X < 360.0f-MaxVerticalAngle) + { + relativeRotation.X = 360.0f-MaxVerticalAngle; + } + else + if (relativeRotation.X > MaxVerticalAngle && + relativeRotation.X < 360.0f-MaxVerticalAngle) + { + relativeRotation.X = MaxVerticalAngle; + } + + // set target target.set(0,0, core::max_(1.f, pos.getLength())); @@ -299,7 +312,6 @@ f32 CSceneNodeAnimatorCameraFPS::getMoveSpeed() const return MoveSpeed; } - //! Sets the keyboard mapping for this animator void CSceneNodeAnimatorCameraFPS::setKeyMap(SKeyMap *map, u32 count) { @@ -358,6 +370,7 @@ void CSceneNodeAnimatorCameraFPS::serializeAttributes(io::IAttributes* out, io:: out->addFloat("MaxVerticalAngle", MaxVerticalAngle); out->addBool("NoVerticalMovement", NoVerticalMovement); out->addFloat("MoveSpeed", MoveSpeed); + out->addFloat("RotateSpeedKeyboard", RotateSpeedKeyboard); out->addFloat("RotateSpeed", RotateSpeed); out->addFloat("JumpSpeed", JumpSpeed); out->addFloat("MouseYDirection", MouseYDirection); @@ -380,6 +393,7 @@ void CSceneNodeAnimatorCameraFPS::deserializeAttributes(io::IAttributes* in, io: MaxVerticalAngle = in->getAttributeAsFloat("MaxVerticalAngle", MaxVerticalAngle); NoVerticalMovement = in->getAttributeAsBool("NoVerticalMovement", NoVerticalMovement); MoveSpeed = in->getAttributeAsFloat("MoveSpeed", MoveSpeed); + RotateSpeedKeyboard = in->getAttributeAsFloat("RotateSpeedKeyboard", RotateSpeedKeyboard); RotateSpeed = in->getAttributeAsFloat("RotateSpeed", RotateSpeed); JumpSpeed = in->getAttributeAsFloat("JumpSpeed", JumpSpeed); MouseYDirection = in->getAttributeAsFloat("MouseYDirection", MouseYDirection); diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h index 2498048f..710c3eb5 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h @@ -30,7 +30,7 @@ namespace scene CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, f32 jumpSpeed=0.f, SKeyMap* keyMapArray=0, u32 keyMapSize=0, bool noVerticalMovement=false, - bool invertY=false); + bool invertY=false, float rotateSpeedKeyboard = 0.3f); //! Destructor virtual ~CSceneNodeAnimatorCameraFPS(); @@ -47,12 +47,24 @@ namespace scene //! Sets the speed of movement in units per second virtual void setMoveSpeed(f32 moveSpeed) _IRR_OVERRIDE_; - //! Returns the rotation speed + //! Returns the rotation speed when moving mouse virtual f32 getRotateSpeed() const _IRR_OVERRIDE_; - //! Set the rotation speed + //! Set the rotation speed when moving mouse virtual void setRotateSpeed(f32 rotateSpeed) _IRR_OVERRIDE_; + //! Returns the rotation speed when using keyboard + virtual f32 getRotateSpeedKeyboard() const _IRR_OVERRIDE_ + { + return RotateSpeedKeyboard; + } + + //! Set the rotation speed when using keyboard + virtual void setRotateSpeedKeyboard(f32 rotateSpeed) _IRR_OVERRIDE_ + { + RotateSpeedKeyboard = rotateSpeed; + } + //! Sets the keyboard mapping for this animator (old style) //! \param keymap: an array of keyboard mappings, see SKeyMap //! \param count: the size of the keyboard map array @@ -107,6 +119,7 @@ namespace scene bool NoVerticalMovement; f32 MoveSpeed; + f32 RotateSpeedKeyboard; f32 RotateSpeed; f32 JumpSpeed; // -1.0f for inverted mouse, defaults to 1.0f