Translation code is highly inspired (as in "copy/paste") from the original one.
Instead of using a camera without parent, to simplify the rotation and translation, the camera is child of an empty node.
It might be improved, but it's doing the basic function of a Maya camera without having to tweak the "official" one.
LMB or Up Down Left Right arrow keys = rotate
RMB or ZQSD (AZERTY keyboard) = translate
MW or LMB+RMB = zoom in/out (left/right axis)
Code: Select all
//global vars
irr::scene::ICameraSceneNode *camera;
irr::scene::ISceneNode *camTarget;
//Event receiver
class MyEventReceiver : public irr::IEventReceiver {
private:
SAppContext & Context;
struct mouseData {
int X;
int Y;
irr::f32 wheel;
};
struct mouseData mousePos;
struct mouseData mouseLastPos;
core::vector3df camTargetPos;
core::vector3df camTargetRot;
bool leftButton;
bool rightButton;
public:
bool KeyIsDown[irr::KEY_KEY_CODES_COUNT];
core::vector3df cameraPos;
f32 cameraDistance;
MyEventReceiver(SAppContext & context) : Context(context) {
for (irr::u32 i=0; i<irr::KEY_KEY_CODES_COUNT; ++i){
KeyIsDown[i] = false;
}
leftButton=false;
rightButton=false;
}
virtual bool OnEvent(const irr::SEvent& event) {
//KEYBOARD
if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
//KeyboardProcess();
}
//MOUSE
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
if (event.MouseInput.Event == irr::EMIE_MOUSE_MOVED) {
mousePos.X=event.MouseInput.X;
mousePos.Y=event.MouseInput.Y;
}
if (event.MouseInput.Event == irr::EMIE_MOUSE_WHEEL) {
mousePos.wheel+=event.MouseInput.Wheel;
//MouseWheelProcess();
}
if (event.MouseInput.Event == irr::EMIE_LMOUSE_PRESSED_DOWN) {
leftButton=true;
mouseLastPos=mousePos;
}
if (event.MouseInput.Event == irr::EMIE_LMOUSE_LEFT_UP) {
leftButton=false;
}
if (event.MouseInput.Event == irr::EMIE_RMOUSE_PRESSED_DOWN) {
rightButton=true;
mouseLastPos=mousePos;
}
if (event.MouseInput.Event == irr::EMIE_RMOUSE_LEFT_UP) {
rightButton=false;
}
}
return false;
}
virtual bool IsKeyDown(irr::EKEY_CODE keyCode) const {
return KeyIsDown[keyCode];
}
void AllProcess() {
KeyboardProcess();
MouseProcess();
MouseWheelProcess();
}
void KeyboardProcess() {
if(IsKeyDown(irr::KEY_UP)) {
camTargetRot=camTarget->getRotation();
camTargetRot.X+=0.01;
if (camTargetRot.X>89.9) {
camTargetRot.X=89.9;
}
camTarget->setRotation(camTargetRot);
}
if(IsKeyDown(irr::KEY_DOWN)) {
camTargetRot=camTarget->getRotation();
camTargetRot.X-=0.01;
if (camTargetRot.X<-89.9) {
camTargetRot.X=-89.9;
}
camTarget->setRotation(camTargetRot);
}
if(IsKeyDown(irr::KEY_LEFT)) {
camTargetRot=camTarget->getRotation();
camTargetRot.Y+=0.01;
camTarget->setRotation(camTargetRot);
}
if(IsKeyDown(irr::KEY_RIGHT)) {
camTargetRot=camTarget->getRotation();
camTargetRot.Y-=0.01;
camTarget->setRotation(camTargetRot);
}
if (IsKeyDown(irr::KEY_KEY_Q)) {
translateCenter(-0.1,0);
}
if (IsKeyDown(irr::KEY_KEY_D)) {
translateCenter(0.1,0);
}
if (IsKeyDown(irr::KEY_KEY_Z)) {
translateCenter(0,-0.1);
}
if (IsKeyDown(irr::KEY_KEY_S)) {
translateCenter(0,0.1);
}
}
void MouseProcess() {
if (leftButton) {
if (rightButton) {
//zoom
zoom((mouseLastPos.X-mousePos.X)*0.05);
mouseLastPos=mousePos;
} else {
//rotate
camTargetRot=camTarget->getRotation();
camTargetRot.X+=(mouseLastPos.Y-mousePos.Y)*0.1;
if (camTargetRot.X<-89.0) {
camTargetRot.X=-89.0;
} else if (camTargetRot.X>89.0) {
camTargetRot.X=89.0;
}
camTargetRot.Y+=(mouseLastPos.X-mousePos.X)*0.1;
camTarget->setRotation(camTargetRot);
mouseLastPos=mousePos;
}
}
if (rightButton & !leftButton) {
if ((mousePos.X!=mouseLastPos.X) || (mousePos.Y!=mouseLastPos.Y))
translateCenter((mousePos.X-mouseLastPos.X)*0.1,(mousePos.Y-mouseLastPos.Y)*0.1);
mouseLastPos=mousePos;
}
}
void MouseWheelProcess() {
if (mousePos.wheel!=0) {
zoom(mousePos.wheel*(-1));
mousePos.wheel=0;
}
}
void zoom(irr::f32 zoomValue) {
cameraPos = camera->getPosition();
cameraDistance = cameraPos.getLength()+1.0f*zoomValue;
if (cameraDistance<1.0f) {
cameraDistance=1.0f;
}
if (cameraDistance>100.0f) {
cameraDistance=100.0f;
}
//std::cout << cameraDistance << std::endl;
cameraPos.setLength(cameraDistance);
camera->setPosition(cameraPos);
camera->setTarget(camTarget->getPosition());
}
void translateCenter(irr::f32 X, irr::f32 Y) {
core::vector3df upVector(camera->getUpVector());
core::vector3df target = camera->getTarget();
core::vector3df pos = camera->getAbsolutePosition();
core::vector3df tvectX = pos - target;
tvectX = tvectX.crossProduct(upVector);
tvectX.normalize();
const SViewFrustum* const va = camera->getViewFrustum();
core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown());
tvectY = tvectY.crossProduct(upVector.Y > 0 ? pos - target : target - pos);
tvectY.normalize();
camTargetPos=camTarget->getPosition();
camTargetPos+=tvectX*X+tvectY*Y;
camTarget->setPosition(camTargetPos);
camera->setTarget(camTarget->getPosition());
}
};
//Inside main
MyEventReceiver receiver();
//camera target
camTarget=sceneManager->addEmptySceneNode(0);
camTarget->setPosition(irr::core::vector3df(0.0f,0.0f,0.0f));
/* CAMERA */
camera=sceneManager->addCameraSceneNode(camTarget,core::vector3df(0.0f,0.0f,-(100.0f)),camTarget->getPosition());
//Inside run loop
receiver.AllProcess();