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!

Help with Oculus Rift Rotation

Postby Brainsaw » Sat Jun 22, 2013 3:55 pm

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)

cpp 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
Brainsaw
 
Posts: 1153
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Postby mongoose7 » Sun Jun 23, 2013 1:08 am

Replace the 'angle' in the quaternion with its negative?
mongoose7
 
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Help with Oculus Rift Rotation

Postby Brainsaw » Sun Jun 23, 2013 11:16 am

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-yfW00Q&feature=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
Brainsaw
 
Posts: 1153
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Postby mongoose7 » Sun Jun 23, 2013 3:02 pm

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.
mongoose7
 
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Help with Oculus Rift Rotation

Postby CuteAlien » Sun Jun 23, 2013 3:52 pm

Try multiplying by a scale (1,1,-1) matrix (so it flips one axis).
IRC: #irrlicht on irc.freenode.net
Code snippets, patches&stuff: http://www.michaelzeilfelder.de/irrlicht.htm
Free racer created with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
User avatar
CuteAlien
Admin
 
Posts: 8402
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany

Re: Help with Oculus Rift Rotation

Postby devsh » Sun Jun 23, 2013 4:32 pm

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)
User avatar
devsh
Competition winner
 
Posts: 1784
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK

Re: Help with Oculus Rift Rotation

Postby hybrid » Sun Jun 23, 2013 11:22 pm

Well, this is indeed true to some extent, but has nothing to do with the problem mentioned originally. So not really helpful...
hybrid
Admin
 
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Re: Help with Oculus Rift Rotation

Postby Brainsaw » Mon Jun 24, 2013 5:40 am

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
Brainsaw
 
Posts: 1153
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Postby Suvi » Mon Jun 24, 2013 7:56 am

To get the head tracking work with the Rift I simply added empty scenenodes and then just applied the values from the SensorFusion.
cpp 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
User avatar
Suvi
Competition winner
 
Posts: 45
Joined: Mon Oct 01, 2007 11:24 am
Location: Finland

Re: Help with Oculus Rift Rotation

Postby hendu » Mon Jun 24, 2013 10:16 am

/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)
hendu
 
Posts: 2589
Joined: Sat Dec 18, 2010 12:53 pm

Re: Help with Oculus Rift Rotation

Postby Brainsaw » Mon Jun 24, 2013 10:22 am

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.
cpp 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: 1153
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Re: Help with Oculus Rift Rotation

Postby Brainsaw » Mon Jun 24, 2013 3:28 pm

@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
Brainsaw
 
Posts: 1153
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria


Return to Advanced Help

Who is online

Users browsing this forum: No registered users and 1 guest