From e21ef5cff24774ca85f4ab3adc27131e569be74e Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 23 Jan 2013 04:39:12 +1000 Subject: Clone CSceneNodeAnimatorCameraFPS so I can start to morph it into a real camera. --- ClientHamr/extantz/CDemo.cpp | 3 +- ClientHamr/extantz/build.sh | 3 +- ClientHamr/extantz/extantzCamera.cpp | 378 +++++++++++++++++++++++++++++++++++ ClientHamr/extantz/extantzCamera.h | 124 ++++++++++++ 4 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 ClientHamr/extantz/extantzCamera.cpp create mode 100644 ClientHamr/extantz/extantzCamera.h (limited to 'ClientHamr/extantz') diff --git a/ClientHamr/extantz/CDemo.cpp b/ClientHamr/extantz/CDemo.cpp index 5f67928..929f0db 100644 --- a/ClientHamr/extantz/CDemo.cpp +++ b/ClientHamr/extantz/CDemo.cpp @@ -3,6 +3,7 @@ #include #include "extantz.h" +#include "extantzCamera.h" #include "CDemo.h" @@ -214,7 +215,7 @@ void CDemo::switchToNextScene() keyMap[8].Action = EKA_JUMP_UP; keyMap[8].KeyCode = KEY_KEY_J; - camera = sm->addCameraSceneNodeFPS(0, 100.0f, .4f, -1, keyMap, 9, false, 3.f); + camera = addExtantzCamera(sm, 0, 100.0f, .4f, -1, keyMap, 9, false, 3.f, false, true); camera->setPosition(core::vector3df(150, 170, -160)); camera->setFarValue(5000.0f); diff --git a/ClientHamr/extantz/build.sh b/ClientHamr/extantz/build.sh index e29416c..d9c386a 100755 --- a/ClientHamr/extantz/build.sh +++ b/ClientHamr/extantz/build.sh @@ -9,4 +9,5 @@ echo "Irrlicht" g++ -O3 -ffast-math -c crappisspuke.cpp -o crappisspuke.o -I../../libraries/irrlicht-1.8/include -I/usr/X11R6/include $(pkg-config --cflags elementary) g++ -O3 -ffast-math -c CDemo.cpp -o CDemo.o -I../../libraries/irrlicht-1.8/include -I/usr/X11R6/include $(pkg-config --cflags elementary) echo "extantz" -gcc -g -DPACKAGE_BIN_DIR="\"$(pwd)\"" -DPACKAGE_DATA_DIR="\"$(pwd)\"" extantz.c crappisspuke.o CDemo.o -o extantz $(pkg-config --cflags --libs eo) $(pkg-config --cflags --libs ecore-x) $(pkg-config --cflags --libs elementary) $(pkg-config --cflags --libs ephysics) -L../../libraries/irrlicht-1.8/lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor -lpng -ljpeg -lbz2 && strip extantz +g++ -O3 -ffast-math -c extantzCamera.cpp -o extantzCamera.o -I../../libraries/irrlicht-1.8/include -I/usr/X11R6/include $(pkg-config --cflags elementary) +gcc -g -DPACKAGE_BIN_DIR="\"$(pwd)\"" -DPACKAGE_DATA_DIR="\"$(pwd)\"" extantz.c crappisspuke.o CDemo.o extantzCamera.o -o extantz $(pkg-config --cflags --libs eo) $(pkg-config --cflags --libs ecore-x) $(pkg-config --cflags --libs elementary) $(pkg-config --cflags --libs ephysics) -L../../libraries/irrlicht-1.8/lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor -lpng -ljpeg -lbz2 && strip extantz diff --git a/ClientHamr/extantz/extantzCamera.cpp b/ClientHamr/extantz/extantzCamera.cpp new file mode 100644 index 0000000..3c0ff7a --- /dev/null +++ b/ClientHamr/extantz/extantzCamera.cpp @@ -0,0 +1,378 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// The above is the copyright notice for CSceneNodeAnimatorCameraFPS.cpp, +// According to the Irrlicht docs, that's just a demo and you are supposed to use it as an example for writing your own FPS style camera. +// I'll be writing my own camera code, that includes first person, third person, and free camera styles. +// I'll start with CSceneNodeAnimatorCameraFPS.cpp and morph it until it suits me. +// As such, I expect lots of Nikolaus Gebhardt's code to go away. +// To be replaced by my code, which will be copyright and licensed under the same license as the rest of extantz. + +#include "extantzCamera.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "Keycodes.h" +#include "ICursorControl.h" +#include "ICameraSceneNode.h" +#include "ISceneNodeAnimatorCollisionResponse.h" + +namespace irr +{ +namespace scene +{ + +// Irrlicht hard codes a reference to the original FPS camera code inside it's scene manager. This is that code extracted so we can be more flexible. +// Hmmm, Where's CursorControl come from? Ah, passed to the scene manager constructor, it's a GUI thing that we need to replace with an EFL thing. +ICameraSceneNode *addExtantzCamera(ISceneManager* sm, ISceneNode* parent, f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed, bool invertMouseY, bool makeActive) +{ + ICameraSceneNode* node = sm->addCameraSceneNode(parent, core::vector3df(), core::vector3df(0, 0, 100), id, makeActive); + if (node) + { +// ISceneNodeAnimator* anm = new extantzCamera(CursorControl, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement, invertMouseY); + ISceneNodeAnimator* anm = new extantzCamera(NULL, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement, invertMouseY); + + // Bind the node's rotation to its target. This is consistent with 1.4.2 and below. + node->bindTargetAndRotation(true); + node->addAnimator(anm); + anm->drop(); + } + + return node; +} + + +//! constructor +extantzCamera::extantzCamera(gui::ICursorControl* cursorControl, f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY) + : CursorControl(cursorControl), MaxVerticalAngle(88.0f), MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), + MouseYDirection(invertY ? -1.0f : 1.0f), LastAnimationTime(0), firstUpdate(true), firstInput(true), NoVerticalMovement(noVerticalMovement) +{ + #ifdef _DEBUG + setDebugName("extantzCamera"); + #endif + +// if (CursorControl) +// CursorControl->grab(); + + allKeysUp(); + + // create key map + if (!keyMapArray || !keyMapSize) + { + // 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_JUMP_UP, irr::KEY_KEY_J)); + } + else + { + // create custom key map + setKeyMap(keyMapArray, keyMapSize); + } +} + + +//! destructor +extantzCamera::~extantzCamera() +{ +// if (CursorControl) +// CursorControl->drop(); +} + + +//! 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::addFPSCameraSceneNode, may want to get this input +//! for changing their position, look at target or whatever. +bool extantzCamera::OnEvent(const SEvent& evt) +{ + switch(evt.EventType) + { + case EET_KEY_INPUT_EVENT: + for (u32 i=0; igetRelativePosition(); + return true; + } + break; + + default: + break; + } + + return false; +} + + +void extantzCamera::animateNode(ISceneNode* node, u32 timeMs) +{ + if (!node || node->getType() != ESNT_CAMERA) + return; + + ICameraSceneNode* camera = static_cast(node); + + if (firstUpdate) + { + camera->updateAbsolutePosition(); +// if (CursorControl ) +// { +// CursorControl->setPosition(0.5f, 0.5f); +// CursorPos = CenterCursor = CursorControl->getRelativePosition(); +// } + + LastAnimationTime = timeMs; + + firstUpdate = false; + } + + // If the camera isn't the active camera, and receiving input, then don't process it. + if(!camera->isInputReceiverEnabled()) + { + firstInput = true; + return; + } + + if ( firstInput ) + { + allKeysUp(); + firstInput = false; + } + + scene::ISceneManager * smgr = camera->getSceneManager(); + if(smgr && smgr->getActiveCamera() != camera) + return; + + // get time + f32 timeDiff = (f32) ( timeMs - LastAnimationTime ); + LastAnimationTime = timeMs; + + // update position + core::vector3df pos = camera->getPosition(); + + // Update rotation + core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition()); + core::vector3df relativeRotation = target.getHorizontalAngle(); + +#if 0 + if (CursorControl) + { + 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; + } + + // Do the fix as normal, special case below + // reset cursor position to the centre of the window. + CursorControl->setPosition(0.5f, 0.5f); + CenterCursor = CursorControl->getRelativePosition(); + + // needed to avoid problems when the event receiver is disabled + CursorPos = CenterCursor; + } + + // Special case, mouse is whipped outside of window before it can update. + video::IVideoDriver* driver = smgr->getVideoDriver(); + core::vector2d mousepos(u32(CursorControl->getPosition().X), u32(CursorControl->getPosition().Y)); + core::rect screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height); + + // Only if we are moving outside quickly. + bool reset = !screenRect.isPointInside(mousepos); + + if(reset) + { + // Force a reset. + CursorControl->setPosition(0.5f, 0.5f); + CenterCursor = CursorControl->getRelativePosition(); + CursorPos = CenterCursor; + } + } +#endif + + // set target + + target.set(0,0, core::max_(1.f, pos.getLength())); + core::vector3df movedir = target; + + core::matrix4 mat; + mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0)); + mat.transformVect(target); + + if (NoVerticalMovement) + { + mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0)); + mat.transformVect(movedir); + } + else + { + movedir = target; + } + + movedir.normalize(); + + if (CursorKeys[EKA_MOVE_FORWARD]) + pos += movedir * timeDiff * MoveSpeed; + + if (CursorKeys[EKA_MOVE_BACKWARD]) + pos -= movedir * timeDiff * MoveSpeed; + + // strafing + + core::vector3df strafevect = target; + strafevect = strafevect.crossProduct(camera->getUpVector()); + + if (NoVerticalMovement) + strafevect.Y = 0.0f; + + strafevect.normalize(); + + if (CursorKeys[EKA_STRAFE_LEFT]) + pos += strafevect * timeDiff * MoveSpeed; + + if (CursorKeys[EKA_STRAFE_RIGHT]) + pos -= strafevect * timeDiff * MoveSpeed; + + // For jumping, we find the collision response animator attached to our camera + // and if it's not falling, we tell it to jump. + if (CursorKeys[EKA_JUMP_UP]) + { + const ISceneNodeAnimatorList& animators = camera->getAnimators(); + ISceneNodeAnimatorList::ConstIterator it = animators.begin(); + while(it != animators.end()) + { + if(ESNAT_COLLISION_RESPONSE == (*it)->getType()) + { + ISceneNodeAnimatorCollisionResponse * collisionResponse = + static_cast(*it); + + if(!collisionResponse->isFalling()) + collisionResponse->jump(JumpSpeed); + } + + it++; + } + } + + // write translation + camera->setPosition(pos); + + // write right target + target += pos; + camera->setTarget(target); +} + + +void extantzCamera::allKeysUp() +{ + for (u32 i=0; i& keymap) +{ + KeyMap=keymap; +} + +const core::array& extantzCamera::getKeyMap() const +{ + return KeyMap; +} + + +//! Sets whether vertical movement should be allowed. +void extantzCamera::setVerticalMovement(bool allow) +{ + NoVerticalMovement = !allow; +} + + +//! Sets whether the Y axis of the mouse should be inverted. +void extantzCamera::setInvertMouse(bool invert) +{ + if (invert) + MouseYDirection = -1.0f; + else + MouseYDirection = 1.0f; +} + + +ISceneNodeAnimator* extantzCamera::createClone(ISceneNode* node, ISceneManager* newManager) +{ + extantzCamera *newAnimator = new extantzCamera(CursorControl, RotateSpeed, MoveSpeed, JumpSpeed, 0, 0, NoVerticalMovement); + newAnimator->setKeyMap(KeyMap); + return newAnimator; +} + + +} // namespace scene +} // namespace irr + diff --git a/ClientHamr/extantz/extantzCamera.h b/ClientHamr/extantz/extantzCamera.h new file mode 100644 index 0000000..a81eb8a --- /dev/null +++ b/ClientHamr/extantz/extantzCamera.h @@ -0,0 +1,124 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __EXTANTZ_CAMERA_H_INCLUDED__ +#define __EXTANTZ_CAMERA_H_INCLUDED__ + +#include +#include +#include +#include +#include +#include + + + +namespace irr +{ +namespace gui +{ + class ICursorControl; +} + +namespace scene +{ + + ICameraSceneNode *addExtantzCamera(ISceneManager* sm, ISceneNode* parent, f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed, bool invertMouseY, bool makeActive); + + class extantzCamera : public ISceneNodeAnimator + { + public: + + //! Constructor + extantzCamera(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); + + //! Destructor + virtual ~extantzCamera(); + + //! Animates the scene node, currently only works on cameras + virtual void animateNode(ISceneNode* node, u32 timeMs); + + //! Event receiver + virtual bool OnEvent(const SEvent& event); + + //! Returns the speed of movement in units per second + virtual f32 getMoveSpeed() const; + + //! Sets the speed of movement in units per second + virtual void setMoveSpeed(f32 moveSpeed); + + //! Returns the rotation speed + virtual f32 getRotateSpeed() const; + + //! Set the rotation speed + virtual void setRotateSpeed(f32 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 + virtual void setKeyMap(SKeyMap *map, u32 count); + + //! Sets the keyboard mapping for this animator + //! \param keymap The new keymap array + virtual void setKeyMap(const core::array& keymap); + + //! Gets the keyboard mapping for this animator + virtual const core::array& getKeyMap() const; + + //! Sets whether vertical movement should be allowed. + virtual void setVerticalMovement(bool allow); + + //! Sets whether the Y axis of the mouse should be inverted. + /** If enabled then moving the mouse down will cause + the camera to look up. It is disabled by default. */ + virtual void setInvertMouse(bool invert); + + //! This animator will receive events when attached to the active camera + virtual bool isEventReceiverEnabled() const + { + return true; + } + + //! Returns the type of this animator + virtual ESCENE_NODE_ANIMATOR_TYPE getType() const + { + return ESNAT_CAMERA_FPS; + } + + //! Creates a clone of this animator. + /** Please note that you will have to drop + (IReferenceCounted::drop()) the returned pointer once you're + done with it. */ + virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); + + private: + void allKeysUp(); + + gui::ICursorControl *CursorControl; + + f32 MaxVerticalAngle; + + f32 MoveSpeed; + f32 RotateSpeed; + f32 JumpSpeed; + // -1.0f for inverted mouse, defaults to 1.0f + f32 MouseYDirection; + + s32 LastAnimationTime; + + core::array KeyMap; + core::position2d CenterCursor, CursorPos; + + bool CursorKeys[EKA_COUNT]; + + bool firstUpdate; + bool firstInput; + bool NoVerticalMovement; + }; + +} // end namespace scene +} // end namespace irr + +#endif // __EXTANTZ_CAMERA_H_INCLUDED__ + -- cgit v1.1