diff -Naurw Irrlicht/C3rdPersonCameraSceneNode.cpp Irrlicht/C3rdPersonCameraSceneNode.cpp --- Irrlicht/C3rdPersonCameraSceneNode.cpp 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/C3rdPersonCameraSceneNode.cpp 2005-11-25 12:00:42.000000000 +0100 @@ -0,0 +1,291 @@ +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "C3rdPersonCameraSceneNode.h" +#include "ISceneManager.h" +#include "IVideoDriver.h" +#include "os.h" +#include "stdio.h" + +namespace irr +{ +namespace scene +{ + + +const f32 MAX_VERTICAL_ANGLE = 89.0f; + +//! constructor +C3rdPersonCameraSceneNode::C3rdPersonCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, + gui::ICursorControl* cursorControl, s32 id, f32 rotateSpeed , f32 moveSpeed, + SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement) +: CCameraSceneNode(parent, mgr, id), CursorControl(cursorControl), + MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), firstUpdate(true), + NoVerticalMovement(noVerticalMovement) +{ + #ifdef _DEBUG + setDebugName("CCameraFPSSceneNode"); + #endif + + if (CursorControl) + CursorControl->grab(); + + MoveSpeed /= 1000.0f; + + recalculateViewArea(); + + allKeysUp(); + + // create default key map + SEvent event; + event.EventType = EET_KEY_INPUT_EVENT; + event.KeyInput.PressedDown = true; + + event.KeyInput.Key = KEY_KEY_W; + EventMap[EKA_MOVE_FORWARD] = event; + event.KeyInput.Key = KEY_KEY_S; + EventMap[EKA_MOVE_BACKWARD] = event; + event.KeyInput.Key = KEY_KEY_A; + EventMap[EKA_STRAFE_LEFT] = event; + event.KeyInput.Key = KEY_KEY_D; + EventMap[EKA_STRAFE_RIGHT] = event; + event.KeyInput.Key = KEY_KEY_J; + EventMap[EKA_ROTATE_LEFT] = event; + event.KeyInput.Key = KEY_KEY_L; + EventMap[EKA_ROTATE_RIGHT] = event; + event.KeyInput.Key = KEY_KEY_I; + EventMap[EKA_ROTATE_UP] = event; + event.KeyInput.Key = KEY_KEY_K; + EventMap[EKA_ROTATE_DOWN] = event; + event.KeyInput.Key = KEY_KEY_O; + EventMap[EKA_ROLL_RIGHT] = event; + event.KeyInput.Key = KEY_KEY_U; + EventMap[EKA_ROLL_LEFT] = event; + + // create custom key map + if( keyMapArray || keyMapSize ) + { + for (s32 i=0; i::iterator it = EventMap.begin(); + for( ; it != EventMap.end(); ++it ) + { + if( it->second.EventType == event.EventType ) + { + switch( event.EventType ) + { + case EET_KEY_INPUT_EVENT: + if( event.KeyInput.Key == it->second.KeyInput.Key ) + { + Keys[it->first] = event.KeyInput.PressedDown; + return true; + } + break; + case EET_MOUSE_INPUT_EVENT: + if( event.MouseInput.Event == it->second.MouseInput.Event ) + { + return true; + } + break; + } + } + } + + return false; +} + + + +//! onPostRender is called just after rendering the whole scene. +//! nodes may calculate or store animations here, and may do other useful things, +//! dependent on what they are. +void C3rdPersonCameraSceneNode::OnPostRender(u32 timeMs) +{ + animate(); + + core::list::Iterator ait = Animators.begin(); + for (; ait != Animators.end(); ++ait) + (*ait)->animateNode(this, timeMs); + + updateAbsolutePosition(); + Target = getPosition() + TargetVector; + + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->OnPostRender(timeMs); +} + + +void C3rdPersonCameraSceneNode::animate() +{ + if (SceneManager->getActiveCamera() != this) + return; + + if (firstUpdate) + { + if (CursorControl) + CursorControl->setPosition(0.5f, 0.5f); + + LastAnimationTime = os::Timer::getTime(); + + firstUpdate = false; + return; + } + + // get time + s32 now = os::Timer::getTime(); + s32 timeDiff = now - LastAnimationTime; + LastAnimationTime = now; + + // Update rotation + Target.set(0,0,1); + + if (!CursorControl) + return; + + RelativeRotation.X *= -1.0f; + RelativeRotation.Y *= -1.0f; + RelativeRotation.Z *= -1.0f; + + if( Keys[EKA_ROTATE_LEFT] ) + RelativeRotation.Y += RotateSpeed; + if( Keys[EKA_ROTATE_RIGHT] ) + RelativeRotation.Y -= RotateSpeed; + if( Keys[EKA_ROTATE_UP] ) + RelativeRotation.X += RotateSpeed; + if( Keys[EKA_ROTATE_DOWN] ) + RelativeRotation.X -= RotateSpeed; + if( Keys[EKA_ROLL_RIGHT] ) + RelativeRotation.Z += RotateSpeed; + if( Keys[EKA_ROLL_LEFT] ) + RelativeRotation.Z -= RotateSpeed; + + //if( EventMap[EKA_ROLL_LEFT].Value.MouseInput.Event == + // core::position2d cursorpos = CursorControl->getRelativePosition(); + + // if (!core::equals(cursorpos.X, 0.5f) || + // !core::equals(cursorpos.Y, 0.5f)) + // { + // RelativeRotation.Y += (0.5f - cursorpos.X) * RotateSpeed; + // RelativeRotation.X += (0.5f - cursorpos.Y) * RotateSpeed; + // CursorControl->setPosition(0.5f, 0.5f); + + // if (RelativeRotation.X > MAX_VERTICAL_ANGLE) RelativeRotation.X = MAX_VERTICAL_ANGLE; + // if (RelativeRotation.X < -MAX_VERTICAL_ANGLE) RelativeRotation.X = -MAX_VERTICAL_ANGLE; + // } + + if (RelativeRotation.X > MAX_VERTICAL_ANGLE) + RelativeRotation.X = MAX_VERTICAL_ANGLE; + if (RelativeRotation.X < -MAX_VERTICAL_ANGLE) + RelativeRotation.X = -MAX_VERTICAL_ANGLE; + if (RelativeRotation.Z > MAX_VERTICAL_ANGLE) + RelativeRotation.Z = MAX_VERTICAL_ANGLE; + if (RelativeRotation.Z < -MAX_VERTICAL_ANGLE) + RelativeRotation.Z = -MAX_VERTICAL_ANGLE; + + // set target + core::matrix4 mat; + mat.setRotationDegrees(core::vector3df(-RelativeRotation.X, -RelativeRotation.Y, -RelativeRotation.Z)); + mat.transformVect(Target); + + // update position + core::vector3df pos = getPosition(); + core::vector3df movedir = Target; + + //if (NoVerticalMovement) + // movedir.Y = 0.0f; + + movedir.normalize(); + + if( Keys[EKA_MOVE_FORWARD] ) + pos += movedir * (f32)timeDiff * MoveSpeed; + + if( Keys[EKA_MOVE_BACKWARD] ) + pos -= movedir * (f32)timeDiff * MoveSpeed; + + // strafing + core::vector3df strafevect = Target; + strafevect = strafevect.crossProduct(UpVector); + + //if (NoVerticalMovement) + // strafevect.Y = 0.0f; + + strafevect.normalize(); + + if (Keys[EKA_STRAFE_LEFT]) + pos += strafevect * (f32)timeDiff * MoveSpeed; + + if (Keys[EKA_STRAFE_RIGHT]) + pos -= strafevect * (f32)timeDiff * MoveSpeed; + + // write translation + setPosition(pos); + + // set up vector + UpVector = movedir.crossProduct( strafevect ); + + // write right target + TargetVector = Target; + Target += pos; + + RelativeRotation.X *= -1.0f; + RelativeRotation.Y *= -1.0f; + RelativeRotation.Z *= -1.0f; +} + + +void C3rdPersonCameraSceneNode::allKeysUp() +{ + for (s32 i=0; i MAX_VERTICAL_ANGLE) + RelativeRotation.X -= 360.0f; + if (RelativeRotation.Z > MAX_VERTICAL_ANGLE) + RelativeRotation.Z -= 360.0f; +} + + +} // end namespace +} // end namespace + diff -Naurw Irrlicht/C3rdPersonCameraSceneNode.h Irrlicht/C3rdPersonCameraSceneNode.h --- Irrlicht/C3rdPersonCameraSceneNode.h 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/C3rdPersonCameraSceneNode.h 2005-11-25 11:59:12.000000000 +0100 @@ -0,0 +1,77 @@ +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_3RD_PERSON_CAMERA_SCENE_NODE_H_INCLUDED__ +#define __C_3RD_PERSON_CAMERA_SCENE_NODE_H_INCLUDED__ + +#include "ICursorControl.h" +#include "CCameraSceneNode.h" +#include "vector2d.h" +#include "SKeyMap.h" +#include "irrArray.h" +#include + +namespace irr +{ +namespace scene +{ + + class C3rdPersonCameraSceneNode : public CCameraSceneNode + { + public: + + //! constructor + C3rdPersonCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, + gui::ICursorControl* cursorControl, s32 id, + f32 rotateSpeed, f32 moveSpeed, + SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement = false ); + + //! destructor + virtual ~C3rdPersonCameraSceneNode(); + + //! It is possible to send mouse and key events to the camera. Most cameras + //! may ignore this input, but camera scene nodes which are created for + //! example with scene::ISceneManager::addMayaCameraSceneNode or + //! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input + //! for changing their position, look at target or whatever. + virtual bool OnEvent(SEvent event); + + //! onPostRender is called just after rendering the whole scene. + //! nodes may calculate or store animations here, and may do other useful things, + //! dependent on what they are. + virtual void OnPostRender(u32 timeMs); + + //! sets the look at target of the camera + //! \param pos: Look at target of the camera. + virtual void setTarget(const core::vector3df& pos); + + private: + + void allKeysUp(); + void animate(); + + f32 MoveSpeed; + f32 RotateSpeed; + + //f32 RotationX; + //f32 RotationY; + + gui::ICursorControl* CursorControl; + + bool firstUpdate; + s32 LastAnimationTime; + + core::vector3df TargetVector; + + bool Keys[EKA_COUNT]; + std::map EventMap; + + bool NoVerticalMovement; + }; + +} // end namespace +} // end namespace + +#endif // __C_3RD_PERSON_CAMERA_SCENE_NODE_H_INCLUDED__ + diff -Naurw Irrlicht/CSceneManager.cpp Irrlicht/CSceneManager.cpp --- Irrlicht/CSceneManager.cpp 2005-09-27 15:50:08.000000000 +0200 +++ Irrlicht/CSceneManager.cpp 2005-10-27 17:00:52.000000000 +0200 @@ -28,6 +28,7 @@ #include "CCameraSceneNode.h" #include "CCameraMayaSceneNode.h" #include "CCameraFPSSceneNode.h" +#include "C3rdPersonCameraSceneNode.h" #include "CLightSceneNode.h" #include "CBillboardSceneNode.h" #include "CMeshSceneNode.h" @@ -381,6 +402,24 @@ } +//! Adds a camera scene node which is able to be controled with the mouse and keys +//! like in most first person shooters (FPS): +ICameraSceneNode* CSceneManager::addCameraSceneNode3rdPerson(ISceneNode* parent, + f32 rotateSpeed, f32 moveSpeed, s32 id, + SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement) +{ + if (!parent) + parent = this; + + ICameraSceneNode* node = new C3rdPersonCameraSceneNode(parent, this, CursorControl, + id, rotateSpeed, moveSpeed, keyMapArray, keyMapSize, noVerticalMovement); + node->drop(); + + setActiveCamera(node); + + return node; +} + //! Adds a dynamic light scene node. The light will cast dynamic light on all //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING diff -Naurw Irrlicht/CSceneManager.h Irrlicht/CSceneManager.h --- Irrlicht/CSceneManager.h 2005-09-27 15:46:54.000000000 +0200 +++ Irrlicht/CSceneManager.h 2005-11-23 23:23:16.000000000 +0100 @@ -108,6 +116,12 @@ f32 rotateSpeed = 1500.0f, f32 moveSpeed = 200.0f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false); + //! Adds a camera scene node which is able to be controled with the mouse and keys + //! like in most first person shooters (FPS): + virtual ICameraSceneNode* addCameraSceneNode3rdPerson(ISceneNode* parent = 0, + f32 rotateSpeed = 1500.0f, f32 moveSpeed = 200.0f, s32 id=-1, + SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false); + //! Adds a dynamic light scene node. The light will cast dynamic light on all //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING //! turned on. (This is the default setting in most scene nodes). diff -Naurw Irrlicht/include/ISceneManager.h Irrlicht/include/ISceneManager.h --- Irrlicht/include/ISceneManager.h 2005-09-27 15:46:10.000000000 +0200 +++ Irrlicht/include/ISceneManager.h 2005-11-23 23:22:50.000000000 +0100 @@ -514,6 +523,55 @@ f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false) = 0; + //! Adds a camera scene node which is able to be controlled with the mouse and keys like in most first person shooters (FPS). + /** Look with the mouse, move with cursor keys. If you do not like the default + key layout, you may want to specify your own. For example to make the camera + be controlled by the cursor keys AND the keys W,A,S, and D, do something + like this: + \code + SKeyMap keyMap[8]; + keyMap[0].Action = EKA_MOVE_FORWARD; + keyMap[0].KeyCode = KEY_UP; + keyMap[1].Action = EKA_MOVE_FORWARD; + keyMap[1].KeyCode = KEY_KEY_W; + + keyMap[2].Action = EKA_MOVE_BACKWARD; + keyMap[2].KeyCode = KEY_DOWN; + keyMap[3].Action = EKA_MOVE_BACKWARD; + keyMap[3].KeyCode = KEY_KEY_S; + + keyMap[4].Action = EKA_STRAFE_LEFT; + keyMap[4].KeyCode = KEY_LEFT; + keyMap[5].Action = EKA_STRAFE_LEFT; + keyMap[5].KeyCode = KEY_KEY_A; + + keyMap[6].Action = EKA_STRAFE_RIGHT; + keyMap[6].KeyCode = KEY_RIGHT; + keyMap[7].Action = EKA_STRAFE_RIGHT; + keyMap[7].KeyCode = KEY_KEY_D; + + camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); + \endcode + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Speed with wich the camera is rotated. This can be done + only with the mouse. + \param movespeed: Speed with which the camera is moved. Movement is done with + the cursor keys. + \param id: id of the camera. This id can be used to identify the camera. + \param keyMapArray: Optional pointer to an array of a keymap, specifying what + keys should be used to move the camera. If this is null, the default keymap + is used. You can define actions more then one time in the array, to bind + multiple keys to the same action. + \param keyMapSize: Amount of items in the keymap array. + \param noVerticalMovement: Setting this to true makes the camera only move within a + horizontal plane, and disables vertical movement as known from most ego shooters. Default + is 'false', with which it is possible to fly around in space, if no gravity is there. + \return Returns a pointer to the interface of the camera if successful, otherwise 0. + This pointer should not be dropped. See IrrUnknown::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNode3rdPerson(ISceneNode* parent = 0, + f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, s32 id=-1, + SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false) = 0; + //! Adds a dynamic light scene node to the scene graph. /** The light will cast dynamic light on all other scene nodes in the scene, which have the material flag video::MTF_LIGHTING