once again I realize how much I know about math - close to ... uhm ... not much . I got my Oculus Rift DevKit a week ago, and after some simulator sickness from playing Portal and Half Life 2 I decided I want to start Irrlicht integration. Works fine so far, I get the necessary values from the SDK. The orientation is returned as a quaternion. I convert the quaternion to a matrix and then I transform the lookat vector with this matrix. Works fine except for one thing - the rotation is exactly the other direction (turning Rift right -> Irrlicht turns left, turning Rift down -> Irrlicht turns up). Anyone got an idea how to fix this? I tried the CMatrix4.getInverse method, but this screws rotation up quite a bit - if I look 90 degrees to the right and then down the camera rotates. Here is my code (the problem is located in CCameraController::update)
Code: Select all
#include <irrlicht.h>
#include <iostream>
#include <OVR.h>
#include <math.h>
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
#define M_PI 3.14159265358979323846f
using namespace OVR;
class CRiftTest : public irr::IEventReceiver {
private:
class CCameraController {
protected:
irr::scene::ICameraSceneNode *m_pCam;
irr::gui::ICursorControl *m_pCursor;
irr::f32 m_fAngleH,
m_fAngleV;
Ptr<DeviceManager> m_pRiftManager;
Ptr<HMDDevice > m_pRiftHMD;
Ptr<SensorDevice > m_pRiftSensor;
SensorFusion m_cRiftFusion;
public:
CCameraController(irr::scene::ICameraSceneNode *pCam, irr::gui::ICursorControl *pCursor) {
m_pCam = pCam;
m_fAngleH = 0.0f;
m_fAngleV = 0.0f;
m_pCursor = pCursor;
update(0, 0);
System::Init(Log::ConfigureDefaultLog(LogMask_All));
m_pRiftManager = *DeviceManager::Create();
m_pRiftHMD = *m_pRiftManager->EnumerateDevices<HMDDevice>().CreateDevice();
m_pRiftSensor = *m_pRiftHMD->GetSensor();
if (m_pRiftSensor) m_cRiftFusion.AttachToSensor(m_pRiftSensor);
}
void update(irr::s32 iMove, irr::s32 iStrafe) {
irr::core::position2di cDiff = m_pCursor->getPosition() - irr::core::vector2di(640, 400);
m_pCursor->setPosition(640, 400);
m_fAngleH -= ((irr::f32)cDiff.X) / 15.0f;
m_fAngleV -= ((irr::f32)cDiff.Y) / 15.0f;
if (m_fAngleV > 90.0f) m_fAngleV = 90.0f;
if (m_fAngleV < -90.0f) m_fAngleV = -90.0f;
irr::core::vector2df vRotH = irr::core::vector2df(-1.0f, 0.0f).rotateBy(m_fAngleH),
vRotV = irr::core::vector2df( 1.0f, 0.0f).rotateBy(m_fAngleV);
irr::core::vector3df vPos = m_pCam->getPosition(),
vTgt = irr::core::vector3df(0, 0, 1),
vUp = irr::core::vector3df(0, 1, 0),
vSide = vTgt.crossProduct(vUp);
Quatf hmdOrient = m_cRiftFusion.GetOrientation();
irr::core::quaternion cQuat(hmdOrient.x, hmdOrient.y, hmdOrient.z, hmdOrient.w);
irr::core::CMatrix4<irr::f32> cMat;
cQuat.getMatrix(cMat);
//cMat.getInverse(cMat2);
cMat.transformVect(vTgt, irr::core::vector3df(0, 0, 1));
cMat.transformVect(vUp , irr::core::vector3df(0, 1, 0));
vPos += iMove * vTgt / 25.0f + iStrafe * vSide / 25.0f;
m_pCam->setPosition(vPos);
m_pCam->setTarget (vPos + vTgt);
m_pCam->setUpVector( vUp );
}
};
irr::IrrlichtDevice *m_pDevice;
irr::scene::ISceneManager *m_pSmgr;
irr::video::IVideoDriver *m_pDrv;
irr::gui::IGUIEnvironment *m_pGui;
irr::s32 m_iMove,
m_iStrafe;
irr::gui::ICursorControl *m_pCursor;
irr::scene::ICameraSceneNode *m_pCam;
CCameraController *m_pCamCtrl;
irr::core::position2di m_cMousePos;
bool m_bLeftBtn,
m_bRghtBtn;
public:
CRiftTest(irr::IrrlichtDevice *pDevice) {
m_pDevice = pDevice;
m_pDevice->setWindowCaption(L"Oculus Rift Test");
m_pDevice->setEventReceiver(this);
m_pDrv = m_pDevice->getVideoDriver();
m_pSmgr = m_pDevice->getSceneManager();
m_pGui = m_pDevice->getGUIEnvironment();
m_pCursor = m_pDevice->getCursorControl();
m_pCam = m_pSmgr->addCameraSceneNode();
m_pCamCtrl = new CCameraController(m_pCam, m_pCursor);
m_pCam->setTarget(irr::core::vector3df(0, 0, 1));
m_iMove = 0;
m_iStrafe = 0;
}
~CRiftTest() {
}
void run() {
m_pDevice->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");
irr::u32 iFrameCnt = 0;
irr::u32 iStartTime = m_pDevice->getTimer()->getTime();
irr::scene::IAnimatedMesh *pMesh = m_pSmgr->getMesh("20kdm2.bsp");
irr::scene::ISceneNode *pNode = 0;
if (pMesh) {
pNode = m_pSmgr->addOctreeSceneNode(pMesh->getMesh(0), 0, -1, 1024);
pNode->setPosition(irr::core::vector3df(-1500.0f, -500.0f, -500.0f));
}
while(m_pDevice->run()) {
m_cMousePos = m_pCursor->getPosition();
if (m_pCamCtrl != NULL) m_pCamCtrl->update(m_iMove, m_iStrafe);
m_pDrv->beginScene(true, true, irr::video::SColor(0,200,200,200));
m_pSmgr->drawAll();
m_pGui->drawAll();
m_pDrv->endScene();
}
printf("Ready.\n");
}
virtual bool OnEvent(const irr::SEvent &event) {
if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
if (event.KeyInput.PressedDown) {
switch (event.KeyInput.Key) {
case irr::KEY_KEY_W: m_iMove = 1; break;
case irr::KEY_KEY_S: m_iMove = -1; break;
case irr::KEY_KEY_A: m_iStrafe = 1; break;
case irr::KEY_KEY_D: m_iStrafe = -1; break;
}
}
else {
switch (event.KeyInput.Key) {
case irr::KEY_KEY_W: if (m_iMove == 1) m_iMove = 0; break;
case irr::KEY_KEY_S: if (m_iMove == -1) m_iMove = 0; break;
case irr::KEY_KEY_A: if (m_iStrafe == 1) m_iStrafe = 0; break;
case irr::KEY_KEY_D: if (m_iStrafe == -1) m_iStrafe = 0; break;
}
}
}
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
m_bLeftBtn = event.MouseInput.isLeftPressed ();
m_bRghtBtn = event.MouseInput.isRightPressed();
}
return false;
}
};
int main()
{
irr::IrrlichtDevice *device = irr::createDevice(irr::video::EDT_DIRECT3D9, irr::core::dimension2d<irr::u32>(1280, 800));
if (device == 0) return 1; // could not create selected driver.
CRiftTest cRunner(device);
cRunner.run();
device->drop();
return 0;
}