Camera Animator
Camera Animator
Hey guys.
I am working on a custom camera animator that will basically handle first and third person, and the transition between them. Does anyone know of any good resources that will help with how to go about this?
I have seen some of the other 1st and 3rd person cameras, but they don't use an animator, which is the route I want to go.
Thanks
I am working on a custom camera animator that will basically handle first and third person, and the transition between them. Does anyone know of any good resources that will help with how to go about this?
I have seen some of the other 1st and 3rd person cameras, but they don't use an animator, which is the route I want to go.
Thanks
-
- Posts: 105
- Joined: Mon Jul 27, 2009 4:06 pm
- Location: Cambridge, MA
I just posted this, it may help you figure out your problem. I created an animator for a scene node that had a camera attached to it. You could just as well use the animator with the camera itself.
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=34567
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=34567
-
- Posts: 105
- Joined: Mon Jul 27, 2009 4:06 pm
- Location: Cambridge, MA
-
- Posts: 105
- Joined: Mon Jul 27, 2009 4:06 pm
- Location: Cambridge, MA
Sure. You can still calculate the rotation usingDo you happen to know how to rotate camera based on current mouse position and not resetting it to the middle of the screen?
Code: Select all
device->getCursorControl()->getRelativePosition();
Code: Select all
device->getCursorControl()->setPosition(0.5f, 0.5f);
If you want to hide it you should set visible to "false"; is that what you're doing?why does my cursor not hide when I set it to visible
Code: Select all
device->getCursorControl()->setVisible(false);
I'm working on windows and I don't have a problem with the cursor.I was some things about a bug in irrlicht and MS about it, is that true
I can set it to false using the method you shown, but it doesnt disappear.
Here is my current implementation:
Here is my current implementation:
Code: Select all
#ifndef __CSCENENODECAMERAANIMATOR_H__
#define __CSCENENODECAMERAANIMATOR_H__
#include <iostream>
#include <irrlicht.h>
using namespace std;
namespace irr
{
namespace gui
{
class ICursorControl;
}
namespace scene
{
class CSceneNodeCameraAnimator : public ISceneNodeAnimator
{
public:
CSceneNodeCameraAnimator(gui::ICursorControl* cursorControl,
f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, f32 jumpSpeed=0.f,
SKeyMap* keyMapArray=0, u32 keyMapSize=0, bool noVerticalMovement=false);
virtual ~CSceneNodeCameraAnimator(void);
virtual void animateNode(ISceneNode *node, u32 timeMs);
virtual bool OnEvent(const SEvent &);
virtual ISceneNodeAnimator *createClone (ISceneNode *node, ISceneManager *newManager=0)
{
return new CSceneNodeCameraAnimator(CursorControl);
}
virtual void setKeyMap(SKeyMap *map, u32 count);
struct SCamKeyMap
{
SCamKeyMap() {};
SCamKeyMap(s32 a, EKEY_CODE k) : action(a), keycode(k) {}
s32 action;
EKEY_CODE keycode;
};
virtual bool isEventReceiverEnabled() const
{
return true;
}
virtual ESCENE_NODE_ANIMATOR_TYPE getType() const
{
return ESNAT_CAMERA_FPS;
}
void setKeyMap(const core::array<SCamKeyMap>& keymap);
private:
void allKeysUp();
gui::ICursorControl *CursorControl;
f32 MaxVerticalAngle;
f32 MoveSpeed;
f32 RotateSpeed;
f32 JumpSpeed;
s32 LastAnimationTime;
core::vector3df TargetVector;
core::array<SCamKeyMap> KeyMap;
core::position2d<f32> CenterCursor, CursorPos, OldCursor;
bool CursorKeys[6];
bool firstUpdate;
bool NoVerticalMovement;
bool leftMouseDown;
bool rightMouseDown;
};
}
}
#endif
Code: Select all
#include "CSceneNodeCameraAnimator.h"
namespace irr
{
namespace scene
{
CSceneNodeCameraAnimator::CSceneNodeCameraAnimator(gui::ICursorControl* cursorControl,
f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed,
SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement)
: CursorControl(cursorControl), MaxVerticalAngle(88.0f),
MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed),
LastAnimationTime(0), firstUpdate(true), NoVerticalMovement(noVerticalMovement)
{
if (CursorControl)
CursorControl->grab();
allKeysUp();
// create key map
if (!keyMapArray || !keyMapSize)
{
// create default key map
KeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, irr::KEY_KEY_W));
KeyMap.push_back(SCamKeyMap(EKA_MOVE_BACKWARD, irr::KEY_KEY_S));
KeyMap.push_back(SCamKeyMap(EKA_STRAFE_LEFT, irr::KEY_KEY_A));
KeyMap.push_back(SCamKeyMap(EKA_STRAFE_RIGHT, irr::KEY_KEY_D));
KeyMap.push_back(SCamKeyMap(EKA_JUMP_UP, irr::KEY_KEY_J));
}
else
{
// create custom key map
setKeyMap(keyMapArray, keyMapSize);
}
}
CSceneNodeCameraAnimator::~CSceneNodeCameraAnimator(void)
{
if (CursorControl)
CursorControl->drop();
}
void CSceneNodeCameraAnimator::animateNode(ISceneNode *node, u32 timeMs)
{
if (node->getType() != ESNT_CAMERA)
return;
ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
if (firstUpdate)
{
camera->updateAbsolutePosition();
if (CursorControl && camera)
{
CursorControl->setPosition(0.5f, 0.5f);
CursorPos = CenterCursor = CursorControl->getRelativePosition();
}
LastAnimationTime = timeMs;
firstUpdate = false;
leftMouseDown = false;
rightMouseDown = false;
}
// 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 (CursorControl && rightMouseDown)
{
if (CursorPos != CenterCursor)
{
relativeRotation.Y -= (0.5f - CursorPos.X) * RotateSpeed;
relativeRotation.X -= (0.5f - CursorPos.Y) * RotateSpeed;
// 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;
}
// reset cursor position
CursorControl->setPosition(0.5f, 0.5f);
CenterCursor = CursorControl->getRelativePosition();
// needed to avoid problems when the ecent receiver is
// disabled
CursorPos = CenterCursor;
}
}
// 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 core::list<ISceneNodeAnimator*> & animators = camera->getAnimators();
core::list<ISceneNodeAnimator*>::ConstIterator it = animators.begin();
while(it != animators.end())
{
if(ESNAT_COLLISION_RESPONSE == (*it)->getType())
{
ISceneNodeAnimatorCollisionResponse * collisionResponse =
static_cast<ISceneNodeAnimatorCollisionResponse *>(*it);
if(!collisionResponse->isFalling())
collisionResponse->jump(JumpSpeed);
}
it++;
}
}
// write translation
camera->setPosition(pos);
// write right target
TargetVector = target;
target += pos;
camera->setTarget(target);
}
bool CSceneNodeCameraAnimator::OnEvent(const SEvent &event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
for (u32 i=0; i<KeyMap.size(); ++i)
{
if (KeyMap[i].keycode == event.KeyInput.Key)
{
CursorKeys[KeyMap[i].action] = event.KeyInput.PressedDown;
return true;
}
}
}
if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
switch (event.MouseInput.Event)
{
case EMIE_MOUSE_WHEEL: // zooming
break;
case EMIE_LMOUSE_PRESSED_DOWN:
leftMouseDown = true;
break;
case EMIE_RMOUSE_PRESSED_DOWN:
//OldCursor = CursorControl->getRelativePosition();
rightMouseDown = true;
break;
case EMIE_MOUSE_MOVED:
CursorPos = CursorControl->getRelativePosition();
return true;
break;
case EMIE_MMOUSE_PRESSED_DOWN:
break;
case EMIE_LMOUSE_LEFT_UP:
leftMouseDown = false;
break;
case EMIE_RMOUSE_LEFT_UP:
//CursorControl->setPosition( OldCursor );
rightMouseDown = false;
break;
}
}
return false;
}
void CSceneNodeCameraAnimator::allKeysUp()
{
for (u32 i=0; i<6; ++i)
CursorKeys[i] = false;
}
void CSceneNodeCameraAnimator::setKeyMap(SKeyMap *map, u32 count)
{
// clear the keymap
KeyMap.clear();
// add actions
for (u32 i=0; i<count; ++i)
{
switch(map[i].Action)
{
case EKA_MOVE_FORWARD: KeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, map[i].KeyCode));
break;
case EKA_MOVE_BACKWARD: KeyMap.push_back(SCamKeyMap(EKA_MOVE_BACKWARD, map[i].KeyCode));
break;
case EKA_STRAFE_LEFT: KeyMap.push_back(SCamKeyMap(EKA_STRAFE_LEFT, map[i].KeyCode));
break;
case EKA_STRAFE_RIGHT: KeyMap.push_back(SCamKeyMap(EKA_STRAFE_RIGHT, map[i].KeyCode));
break;
case EKA_JUMP_UP: KeyMap.push_back(SCamKeyMap(EKA_JUMP_UP, map[i].KeyCode));
break;
default:
break;
}
}
}
}
}
-
- Posts: 105
- Joined: Mon Jul 27, 2009 4:06 pm
- Location: Cambridge, MA
The main is a normal main. I do not have the code in front of moment but it goes like this (very psuedo-ish):
Code: Select all
camera = new CameraSceneNode(...);
animator = new MyAnimator(...);
camera->addAnimator(animator);
animator->drop();
while(device->run())
{
driver->beginscene(...);
smgr->drawAll();
driver->endscene(...);
}
-
- Posts: 105
- Joined: Mon Jul 27, 2009 4:06 pm
- Location: Cambridge, MA
Oh sorry, I took the call out of my code.
Originally I had it here:
This would have no effect, but if i put an additional call in the main, the wouldn't show up to start. Once I held down the right mouse key though, it would appear, even when telling it not to.
Originally I had it here:
Code: Select all
case EMIE_RMOUSE_LEFT_UP:
CursorControl->setVisible(true);
//CursorControl->setPosition( OldCursor );
rightMouseDown = false;
break;
case EMIE_RMOUSE_PRESSED_DOWN:
CursorControl->setVisible(false);
//OldCursor = CursorControl->getRelativePosition();
rightMouseDown = true;
break;
-
- Posts: 105
- Joined: Mon Jul 27, 2009 4:06 pm
- Location: Cambridge, MA
So it seems the setVisible() method is probably working as expected, and the problem lies somewhere else. What happens if you just remove the "CursorControl->setVisible(true)" from the "case EMIE_RMOUSE_LEFT_UP" block. I imagine it will stay hidden.
Once you try the above, but the statement to make it visible back in, then remove the "CursorConstrol->setVisible(false)" from the "case EMIE_RMOUSE_PRESSED_DOWN" block. Then run your program and pay careful attention to when the cursor appears. When you click down with the right mouse button, does it stay hidden until you lift up? or does it become visible as soon as you click down?
Once you try the above, but the statement to make it visible back in, then remove the "CursorConstrol->setVisible(false)" from the "case EMIE_RMOUSE_PRESSED_DOWN" block. Then run your program and pay careful attention to when the cursor appears. When you click down with the right mouse button, does it stay hidden until you lift up? or does it become visible as soon as you click down?