Help with Oculus Rift Rotation

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Brainsaw
Posts: 1176
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Help with Oculus Rift Rotation

Post by Brainsaw »

Hi there,

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;
}
 
Apart from that I'm totally blown away by the rift, and it's easy to program with - apart from math. Thanks for the answer.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Help with Oculus Rift Rotation

Post by mongoose7 »

Replace the 'angle' in the quaternion with its negative?
Brainsaw
Posts: 1176
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Post by Brainsaw »

Did already try that, it didn't work. When I turn the Rift around the Y-Axis by 90 degrees it converts pitch to roll. I uploaded a video to youtube showing the problem: http://www.youtube.com/watch?v=WyKA-yfW ... e=youtu.be. Still searching for the answer.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Help with Oculus Rift Rotation

Post by mongoose7 »

Firstly, you should find out which of Y and Z is "up". Then you will have to see if it is a right-handed or left-handed system. But the first thing is, which way is up.
CuteAlien
Admin
Posts: 9629
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Help with Oculus Rift Rotation

Post by CuteAlien »

Try multiplying by a scale (1,1,-1) matrix (so it flips one axis).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Re: Help with Oculus Rift Rotation

Post by devsh »

remember that the rift introduces some serious amount of distortion and you need to make your renderer correct for that, either by rendering onto a bigger render target and anti-distorting (i.e. if your rift turns a square into a paraboloid surface {convex sides}, then you need to render a square with 'sunken'/concave sides) or by rendering in non-linear ways (some tessellation of triangles to achieve anti-curved triangle lines)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Help with Oculus Rift Rotation

Post by hybrid »

Well, this is indeed true to some extent, but has nothing to do with the problem mentioned originally. So not really helpful...
Brainsaw
Posts: 1176
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Post by Brainsaw »

Thanks. I'll try the scaling once I get home after work.

@devsh: I am well aware of the necessary distortion, but I want to take this step by step. First step: get headtracking. There is already a code snippet somewhere here in the forum that distorts the rendering, and, according to the Rift forums, it works quite well.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Suvi
Competition winner
Posts: 45
Joined: Mon Oct 01, 2007 11:24 am
Location: Finland
Contact:

Re: Help with Oculus Rift Rotation

Post by Suvi »

To get the head tracking work with the Rift I simply added empty scenenodes and then just applied the values from the SensorFusion.

Code: Select all

 
headX_ = getSceneManager()->addEmptySceneNode(0, 0);
headY_ = getSceneManager()->addEmptySceneNode(headX_, 0);
headZ_ = getSceneManager()->addEmptySceneNode(headY_, 0);
 
...
 
// Read sensor fusion 
OVR::Quatf qua = m_sensorFusion.GetOrientation();
irr::core::vector3df p;
qua.GetEulerAngles<OVR::Axis_X, OVR::Axis_Y, OVR::Axis_Z>(&p.X, &p.Y, &p.Z);
 
p.X *= -irr::core::RADTODEG;
p.Y *= -irr::core::RADTODEG;
p.Z *= irr::core::RADTODEG;
 
// Set empty node rotations
headY_->setRotation(irr::core::vector3df(0.0f, p.Y, 0.0f));
headX_->setRotation(irr::core::vector3df(p.X, 0.0f, 0.0f));
headZ_->setRotation(irr::core::vector3df(0.0f, 0.0f, p.Z));
 
// Apply to camera
irr::core::matrix4 m;
m.setRotationDegrees(headZ_->getAbsoluteTransformation().getRotationDegrees());
 
// Forward
irr::core::vector3df frv = irr::core::vector3df (0.0f, 0.0f, 1.0f);
m.transformVect(frv);
   
// Up
irr::core::vector3df upv = irr::core::vector3df (0.0f, 1.0f, 0.0f);
m.transformVect(upv);
 
camera->setTarget(camera->getPosition() + frv);
camera->setUpVector(upv); //set up vector of camera
 
I'm sure you can do it with less nodes or simply with math but if you're bad at maths like me then this is one way to do it. I had some other issues messing up the camera positioning (gimbal lock or something) while I was implementing the tracking so it's possible that most of the code here is not needed x)

The script posted here in the forums earlier does pretty good job with the rendering but at least for me it was missing depth in some angles so I had to adjust the eye positions. This screen is taken using the script (with the eye positions fixed): http://www.indiedb.com/games/gekkeiju-o ... d-tracking
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Help with Oculus Rift Rotation

Post by hendu »

/OT

How come nearly everyone here has one, when the tech makes 30% of people puke? It's like 3d cinema, if it is unusable for a significant proportion of people, it will never be a huge success.

(30% figure comes from a Remedy presentation about two months ago I was at)
Brainsaw
Posts: 1176
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Post by Brainsaw »

Thanks. I'll try that when I get home after work.
Suvi wrote:To get the head tracking work with the Rift I simply added empty scenenodes and then just applied the values from the SensorFusion.

Code: Select all

 
headX_ = getSceneManager()->addEmptySceneNode(0, 0);
headY_ = getSceneManager()->addEmptySceneNode(headX_, 0);
headZ_ = getSceneManager()->addEmptySceneNode(headY_, 0);
 
...
 
// Read sensor fusion 
OVR::Quatf qua = m_sensorFusion.GetOrientation();
irr::core::vector3df p;
qua.GetEulerAngles<OVR::Axis_X, OVR::Axis_Y, OVR::Axis_Z>(&p.X, &p.Y, &p.Z);
 
p.X *= -irr::core::RADTODEG;
p.Y *= -irr::core::RADTODEG;
p.Z *= irr::core::RADTODEG;
 
// Set empty node rotations
headY_->setRotation(irr::core::vector3df(0.0f, p.Y, 0.0f));
headX_->setRotation(irr::core::vector3df(p.X, 0.0f, 0.0f));
headZ_->setRotation(irr::core::vector3df(0.0f, 0.0f, p.Z));
 
// Apply to camera
irr::core::matrix4 m;
m.setRotationDegrees(headZ_->getAbsoluteTransformation().getRotationDegrees());
 
// Forward
irr::core::vector3df frv = irr::core::vector3df (0.0f, 0.0f, 1.0f);
m.transformVect(frv);
   
// Up
irr::core::vector3df upv = irr::core::vector3df (0.0f, 1.0f, 0.0f);
m.transformVect(upv);
 
camera->setTarget(camera->getPosition() + frv);
camera->setUpVector(upv); //set up vector of camera
 
I'm sure you can do it with less nodes or simply with math but if you're bad at maths like me then this is one way to do it. I had some other issues messing up the camera positioning (gimbal lock or something) while I was implementing the tracking so it's possible that most of the code here is not needed x)

The script posted here in the forums earlier does pretty good job with the rendering but at least for me it was missing depth in some angles so I had to adjust the eye positions. This screen is taken using the script (with the eye positions fixed): http://www.indiedb.com/games/gekkeiju-o ... d-tracking
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Brainsaw
Posts: 1176
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Post by Brainsaw »

@Suvi: Thanx, this does the job. I'll try to get the code more compact sometime, but for the moment it's OK.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Post Reply