damn, my bad english...
...i just read the article about the matrices, it is fine, but hard to understand at the first reading, espacially if your english isn't that good. but it helped, thanks to halifax.
Code: Select all
// Copyright (c) 2007-2008 Tomer Nosrati
// This file is part of the "NUSoftware Game Engine".
// For conditions of distribution and use, see copyright notice in nge.hpp
#pragma once
#ifndef __I_SCENE_NODE_CONTROLLER_ANIMATOR_H_
#define __I_SCENE_NODE_CONTROLLER_ANIMATOR_H_
#include "irrlicht.h"
using namespace irr;
using namespace irr::core;
using namespace irr::gui;
using namespace irr::io;
using namespace irr::scene;
//! Special scene node animator for doing automatic movement in 3D space.
/*! This scene node animator can be attached to any scene node modifying it in that
way, that it can move freely in 3D space, rotate with mouse input and move/strafe with
keyboard input. */
class ISceneNodeControllerAnimator : public ISceneNodeAnimator, public IEventReceiver
{
public:
//! Destructor
virtual ~ISceneNodeControllerAnimator() {}
//! Animates a scene node.
//! \param node: Node to animate.
//! \param timeMs: Current time in milli seconds.
virtual void animateNode(ISceneNode* node, u32 timeMs) = 0;
//! called if an event happened.
virtual bool OnEvent(const SEvent& event) = 0;
virtual void lockMouseCursor() = 0;
virtual void unlockMouseCursor() = 0;
//! Returns if the input receiver of the animator is currently enabled.
virtual bool isInputReceiverEnabled() = 0;
//! Disables or enables the animator to get key or mouse inputs.
virtual void setInputReceiverEnabled(bool enabled) = 0;
//! Returns if the scene node could move vertically or not
virtual bool isVerticalMovementEnabled() = 0;
//! Sets if the scene node could move vertically or not
virtual void setVerticalMovementEnabled(bool enabled) = 0;
//! Get the animator's movement speed
virtual f32 getMoveSpeed() const = 0;
//! Get the animator's rotation speed
virtual f32 getRotateSpeed() const = 0;
//! Set the animator's movement speed
virtual void setMoveSpeed(f32 speed) = 0;
//! Set the animator's rotation speed
virtual void setRotateSpeed(f32 speed) = 0;
//! Set should the rotation on both X and Y axes be inverted
virtual void invertRotation(bool X, bool Y) = 0;
//! Set should the rotation on the X axis be inverted
virtual void invertXRotation(bool isInvert) = 0;
//! Set should the rotation on the Y axis be inverted
virtual void invertYRotation(bool isInvert) = 0;
//! Returns whether the rotation on the X axis is inverted or not
virtual bool isXRotationInverted() const = 0;
//! Returns whether the rotation on the Y axis is inverted or not
virtual bool isYRotationInverted() const = 0;
};
#endif // __I_SCENE_NODE_CONTROLLER_ANIMATOR_H_
Code: Select all
// Copyright (c) 2007-2008 Tomer Nosrati
// This file is part of the "NUSoftware Game Engine".
// For conditions of distribution and use, see copyright notice in nge.hpp
#pragma once
#ifndef __C_SCENE_NODE_CONTROLLER_ANIMATOR_H_
#define __C_SCENE_NODE_CONTROLLER_ANIMATOR_H_
#include "ISceneNodeControllerAnimator.hpp"
class CSceneNodeControllerAnimator : public ISceneNodeControllerAnimator
{
public:
//! Constructor
CSceneNodeControllerAnimator(ISceneManager* smgr, ICursorControl* cur,
f32 rotateSpeed = 150.f, f32 moveSpeed = 100.f,
SKeyMap* keyMapArray = 0, s32 keyMapSize = 0,
bool verticalMovement = true);
//! Destructor
~CSceneNodeControllerAnimator();
virtual void animateNode(ISceneNode* node, u32 timeMs);
virtual bool OnEvent(const SEvent& event);
virtual void lockMouseCursor();
virtual void unlockMouseCursor();
virtual bool isInputReceiverEnabled();
virtual void setInputReceiverEnabled(bool enabled);
virtual bool isVerticalMovementEnabled();
virtual void setVerticalMovementEnabled(bool enabled);
f32 getMoveSpeed() const;
f32 getRotateSpeed() const;
void setMoveSpeed(f32 speed);
void setRotateSpeed(f32 speed);
void invertRotation(bool X, bool Y);
void invertXRotation(bool isInvert);
void invertYRotation(bool isInvert);
bool isXRotationInverted() const;
bool isYRotationInverted() const;
private:
void allKeysUp();
//! Binds an action to a key
struct SCamKeyMap
{
SCamKeyMap() {};
SCamKeyMap(EKEY_ACTION a, EKEY_CODE k) : action(a), keycode(k) {}
EKEY_ACTION action;
EKEY_CODE keycode;
};
array<SCamKeyMap> m_aKeyMap;
bool m_CursorKeys[EKA_COUNT];
ISceneNode* m_pDummySceneNode;
position2df m_CenterPosition;
ISceneManager* m_pSceneManager;
ICursorControl* m_pCursorControl;
f32 m_MoveSpeed;
f32 m_RotateSpeed;
s32 m_LastAnimationTime;
bool m_RotUp, m_RotDown, m_RotLeft, m_RotRight;
s32 m_PrevMouseX, m_PrevMouseY;
bool m_IsInvertX, m_IsInvertY;
bool m_InputReceiverEnabled;
bool m_VerticalMovement;
bool m_IsLocked;
};
#endif // __C_SCENE_NODE_CONTROLLER_ANIMATOR_H_
Code: Select all
// Copyright (c) 2007-2008 Tomer Nosrati
// This file is part of the "NUSoftware Game Engine".
// For conditions of distribution and use, see copyright notice in nge.hpp
#include "CSceneNodeControllerAnimator.hpp"
CSceneNodeControllerAnimator::CSceneNodeControllerAnimator(
ISceneManager* smgr, ICursorControl* cur,
f32 rotateSpeed, f32 m_MoveSpeed, SKeyMap* keyMapArray, s32 keyMapSize,
bool verticalMovement)
: m_pSceneManager(smgr), m_pCursorControl(cur),
m_MoveSpeed(m_MoveSpeed), m_RotateSpeed(rotateSpeed), m_LastAnimationTime(0),
m_RotUp(false), m_RotDown(false), m_RotLeft(false), m_RotRight(false),
m_PrevMouseX(0), m_PrevMouseY(0),
m_IsInvertX(false), m_IsInvertY(false),
m_InputReceiverEnabled(true), m_VerticalMovement(verticalMovement), m_IsLocked(false)
{
m_pSceneManager->grab();
//m_pDummySceneNode = m_pSceneManager->addCubeSceneNode(3.f,0,12);
m_pDummySceneNode = m_pSceneManager->addEmptySceneNode();
m_pCursorControl->setPosition(0.5f,0.5f);
m_CenterPosition = m_pCursorControl->getRelativePosition();
allKeysUp();
// create key map
if (!keyMapArray || !keyMapSize)
{
// create default key map
m_aKeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, KEY_UP));
m_aKeyMap.push_back(SCamKeyMap(EKA_MOVE_BACKWARD, KEY_DOWN));
m_aKeyMap.push_back(SCamKeyMap(EKA_STRAFE_LEFT, KEY_LEFT));
m_aKeyMap.push_back(SCamKeyMap(EKA_STRAFE_RIGHT, KEY_RIGHT));
}
else
{
// create custom key map
for (s32 i = 0; i < keyMapSize; i++)
{
switch(keyMapArray[i].Action)
{
case EKA_MOVE_FORWARD:
m_aKeyMap.push_back(SCamKeyMap(EKA_MOVE_FORWARD, keyMapArray[i].KeyCode));
break;
case EKA_MOVE_BACKWARD:
m_aKeyMap.push_back(SCamKeyMap(EKA_MOVE_BACKWARD, keyMapArray[i].KeyCode));
break;
case EKA_STRAFE_LEFT:
m_aKeyMap.push_back(SCamKeyMap(EKA_STRAFE_LEFT, keyMapArray[i].KeyCode));
break;
case EKA_STRAFE_RIGHT:
m_aKeyMap.push_back(SCamKeyMap(EKA_STRAFE_RIGHT, keyMapArray[i].KeyCode));
break;
default:
break;
} // end switch
} // end for
}// end if
}
CSceneNodeControllerAnimator::~CSceneNodeControllerAnimator()
{
if(m_pSceneManager)
m_pSceneManager->drop();
}
void CSceneNodeControllerAnimator::animateNode(ISceneNode* node, u32 timeMs)
{
if (!node)
return;
f32 timeDiff = 0.f;
// for first time
if(m_LastAnimationTime)
timeDiff = (f32) ( timeMs - m_LastAnimationTime );
m_LastAnimationTime = timeMs;
m_pDummySceneNode->setParent(node);
m_pDummySceneNode->setPosition(vector3df(0,0,-8.1f));
vector3df Pos = node->getPosition();
vector3df PrevPos = Pos;
vector3df Rot = node->getRotation();
vector3df PrevRot = Rot;
vector3df Vel(Pos - m_pDummySceneNode->getAbsolutePosition());
f32 MovementSpeed = m_MoveSpeed/1000.f * timeDiff;
f32 RotationSpeed = m_RotateSpeed/100.f;
Vel.normalize();
if(m_VerticalMovement)
Vel.Y *= MovementSpeed;
else
Vel.Y = 0.f;
Vel.X *= MovementSpeed;
Vel.Z *= MovementSpeed;
if (m_CursorKeys[EKA_MOVE_FORWARD])
{
Pos += Vel;
}
if (m_CursorKeys[EKA_MOVE_BACKWARD])
{
Pos -= Vel;
}
if (m_CursorKeys[EKA_STRAFE_LEFT])
{
Pos.X -= MovementSpeed * cos((Rot.Y) * DEGTORAD);
Pos.Z += MovementSpeed * sin((Rot.Y) * DEGTORAD);
}
if (m_CursorKeys[EKA_STRAFE_RIGHT])
{
Pos.X += MovementSpeed * cos((Rot.Y) * DEGTORAD);
Pos.Z -= MovementSpeed * sin((Rot.Y) * DEGTORAD);
}
if (m_RotUp)
{
Rot.X -= RotationSpeed;
m_RotUp = false;
}
if (m_RotDown)
{
Rot.X += RotationSpeed;
m_RotDown = false;
}
if (m_RotLeft)
{
Rot.Y -= RotationSpeed;
m_RotLeft = false;
}
if (m_RotRight)
{
Rot.Y += RotationSpeed;
m_RotRight = false;
}
node->setPosition(Pos);
node->setRotation(Rot);
if(m_IsLocked)
{
m_pCursorControl->setPosition(m_CenterPosition);
m_PrevMouseX = m_pCursorControl->getPosition().X;
m_PrevMouseY = m_pCursorControl->getPosition().Y;
}
}
bool CSceneNodeControllerAnimator::OnEvent(const SEvent& event)
{
if(m_InputReceiverEnabled)
{
if(event.EventType == EET_KEY_INPUT_EVENT)
{
const u32 cnt = m_aKeyMap.size();
for(u32 i=0; i<cnt; i++)
if(m_aKeyMap[i].keycode == event.KeyInput.Key)
{
m_CursorKeys[m_aKeyMap[i].action] = event.KeyInput.PressedDown;
}
}
if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
switch(event.MouseInput.Event)
{
case EMIE_MOUSE_MOVED:
{
s32 CurrentX = event.MouseInput.X;
s32 CurrentY = event.MouseInput.Y;
if((CurrentX - m_PrevMouseX) > 0)
{
if(m_IsInvertY)
{
m_RotLeft = true;
m_RotRight = false;
}
else
{
m_RotLeft = false;
m_RotRight = true;
}
}
else if((CurrentX - m_PrevMouseX) < 0)
{
if(m_IsInvertY)
{
m_RotLeft = false;
m_RotRight = true;
}
else
{
m_RotLeft = true;
m_RotRight = false;
}
}
if((CurrentY - m_PrevMouseY) > 0)
{
if(m_IsInvertX)
{
m_RotUp = true;
m_RotDown = false;
}
else
{
m_RotUp = false;
m_RotDown = true;
}
}
else if((CurrentY - m_PrevMouseY) < 0)
{
if(m_IsInvertX)
{
m_RotUp = false;
m_RotDown = true;
}
else
{
m_RotUp = true;
m_RotDown = false;
}
}
m_PrevMouseX = CurrentX;
m_PrevMouseY = CurrentY;
break;
}
}
}
return true;
} // if(m_InputReceiverEnabled)
return false;
}
void CSceneNodeControllerAnimator::lockMouseCursor()
{
m_IsLocked = true;
}
void CSceneNodeControllerAnimator::unlockMouseCursor()
{
m_IsLocked = false;
}
bool CSceneNodeControllerAnimator::isInputReceiverEnabled()
{
return m_InputReceiverEnabled;
}
void CSceneNodeControllerAnimator::setInputReceiverEnabled(bool enabled)
{
m_InputReceiverEnabled = enabled;
}
bool CSceneNodeControllerAnimator::isVerticalMovementEnabled()
{
return m_VerticalMovement;
}
void CSceneNodeControllerAnimator::setVerticalMovementEnabled(bool enabled)
{
m_VerticalMovement = enabled;
}
f32 CSceneNodeControllerAnimator::getMoveSpeed() const
{
return m_MoveSpeed;
}
f32 CSceneNodeControllerAnimator::getRotateSpeed() const
{
return m_RotateSpeed;
}
void CSceneNodeControllerAnimator::setMoveSpeed(f32 speed)
{
m_MoveSpeed = speed;
}
void CSceneNodeControllerAnimator::setRotateSpeed(f32 speed)
{
m_RotateSpeed = speed;
}
void CSceneNodeControllerAnimator::invertRotation(bool X, bool Y)
{
m_IsInvertX = X;
m_IsInvertY = Y;
}
void CSceneNodeControllerAnimator::invertXRotation(bool isInvert)
{
m_IsInvertX = isInvert;
}
void CSceneNodeControllerAnimator::invertYRotation(bool isInvert)
{
m_IsInvertY = isInvert;
}
bool CSceneNodeControllerAnimator::isXRotationInverted() const
{
return m_IsInvertX;
}
bool CSceneNodeControllerAnimator::isYRotationInverted() const
{
return m_IsInvertY;
}
void CSceneNodeControllerAnimator::allKeysUp()
{
for (s32 i=0; i<EKA_COUNT; i++)
m_CursorKeys[i] = false;
}
Code: Select all
#include <irrlicht.h>
#include <iostream>
#include "CSceneNodeControllerAnimator.hpp"
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0;
ISceneNodeControllerAnimator* anim = 0;
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
if(anim)
return anim->OnEvent(event);
return false;
}
};
int main()
{
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 0;
}
// create device
MyEventReceiver receiver;
IrrlichtDevice* device = createDevice( driverType, core::dimension2d<s32>(640, 480),
32, false, false, false, &receiver);
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3");
scene::IAnimatedMesh* lvl_mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* lvl_node = 0;
if (lvl_mesh)
lvl_node = smgr->addOctTreeSceneNode(lvl_mesh->getMesh(0), 0, -1, 128);
if (lvl_node)
lvl_node->setPosition(core::vector3df(-1300,-144,-1249));
node = smgr->addCubeSceneNode();
node->setPosition(vector3df(15,0,25.f));
if (node)
{
node->setMaterialTexture(0, driver->getTexture("t351sml.jpg"));
node->setMaterialFlag(video::EMF_LIGHTING, false);
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;
anim = new CSceneNodeControllerAnimator(smgr, device->getCursorControl(), 150.f,100.f,keyMap,8);
anim->lockMouseCursor();
node->addAnimator(anim);
anim->drop();
}
IAnimatedMeshSceneNode* forwardArrow = smgr->addAnimatedMeshSceneNode(smgr->addArrowMesh(
"forward",
video::SColor(255,255,255,0),
video::SColor(255,255,0,0),
4,
8,
8.f,
0.3f,
0.05f,
1.3f));
forwardArrow->setMaterialFlag(video::EMF_LIGHTING, false);
forwardArrow->setParent(node);
forwardArrow->setRotation(vector3df(90.f,0.f,0.f));
forwardArrow->setPosition(vector3df(0.f,0.f,8.f));
scene::ICameraSceneNode * cam = smgr->addCameraSceneNode();
device->getCursorControl()->setVisible(true);
/*
// 3rd Person Camera
cam->setParent(node);
cam->setPosition(vector3df(0.f, 20.f, -40.f));*/
// Add a colorful irrlicht logo
device->getGUIEnvironment()->addImage(
driver->getTexture("irrlichtlogoalpha2.tga"),
core::position2d<s32>(10,10));
int lastFPS = -1;
while(device->run())
{
cam->setTarget(node->getPosition());
driver->beginScene(true, true, video::SColor(255,113,113,133));
smgr->drawAll();
device->getGUIEnvironment()->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw tmp(L"Movement Example - Irrlicht Engine [");
tmp += driver->getName();
tmp += L"] fps: ";
tmp += fps;
device->setWindowCaption(tmp.c_str());
lastFPS = fps;
}
}
device->drop();
return 0;
}