cancel
Showing results for 
Search instead for 
Did you mean: 

Oculus SDK and Irrlicht Engine

Copland
Level 2
Hello,
I work on Irrlicht engine for a few years and now I try to integrate the Oculus SDK 1.19 into this engine.
The render appear ok but I have a problem for the Framerate.
Without Oculus SDK I Have a simple test scene that run at +2000 Fps and with the Oculus SDK only 45 Fps.
There is no shadows or Glow effect for the moment, just a simple terrain with BumpMapping.
I Don't understand why this is so slow...
Maybe anyone can help me a little ?

In advance thanks.
Pseudo code:
Set Irrlicht Device;
IOCulusSceneNode::GetInstance()->SetOculusAfterDevice(device);
While main Loop
{
IOCulusSceneNode::GetInstance()->UpdateOculusRender(camera, WithoutEffect);
IOCulusSceneNode::GetInstance()->SendRenderToOculus();
}

My Code .h
#ifndef _OCULUS_CV1_
#define _OCULUS_CV1_

#include "glew.h"
#include "OVR_CAPI.h"
#include "OVR_CAPI_GL.h"
#include "OVR_Math.h"
#include "Irrlicht.h"
#include "COpenGLTexture.h"

using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::io;
using namespace irr::gui;
using namespace OVR;

class IOCulusSceneNode
{
protected:
static IOCulusSceneNode* IOculus;

//le constructeur privé
IOCulusSceneNode();

//le destructeur privé
~IOCulusSceneNode();

private:
//Params for initialize OVR
ovrInitParams initParams = { ovrInit_RequestVersion, OVR_MINOR_VERSION, NULL, 0, 0 };

//Irrlicht Render texture
ITexture* eyeRenderTexture[2] = { nullptr, nullptr };

//Create  cameras: one for Left Eye, one for Right eye.
ICameraSceneNode* cam[2] = { nullptr, nullptr };

//Projection Matrix
matrix4 OculusProjectionMatrix[2];

//Texture swap chain for left and right eyes
ovrTextureSwapChain textureChainLeft = nullptr;
ovrTextureSwapChain textureChainRight = nullptr; 

//Gl Texture ID
GLuint TextureIDLeft=0;
GLuint TextureIDRight=0;

//Eye Left and Right Vars
const int EyeLeft = 0;
const int EyeRight = 1;

//Frame index
long long frameIndex = 0;

//OVR Vars
ovrSession session;
ovrGraphicsLuid luid;
ovrHmdDesc hmdDesc;
ovrSessionStatus sessionStatus;
ovrSizei texSizeL, texSizeR;
ovrPosef EyeRenderPose[2];
ovrInputState inputState;
ovrTrackingState trackingState;

int currentIndex;
double sensorSampleTime;

//Size Of Window
ovrSizei windowSize;

IrrlichtDevice* IDevice=nullptr;

public:
//Initialize the oculus
void InitOculus();

//Set params after irrlicht device is created
void SetOculusAfterDevice(IrrlichtDevice* IrrDevice);

//Update the Oculus Render
void UpdateOculusRender(ICameraSceneNode* IrrlichtCamera,bool WithEffect=false);

//Separate the two render for Effect
void PreRenderEyeLeft();
void PreRenderEyeRight();

//Send the final render to Oculus CV1
void SendRenderToOculus();

//Set the active camera for external render Effect
void SetActiveCameraLeft();
void SetActiveCameraRight();

//Get the Irrlicht render texture for eye
ITexture* GetTextureEyeLeft();
ITexture* GetTextureEyeRight();

//Get the window size
dimension2di GetIrrWindowSize();

//Convert OVR matrix to Irrlicht
matrix4 GetIRRMatrix(Matrix4f mat);

//Convert OVR Vector to Irrlicht
vector3df GetIrrVector(Vector3f Vec);

//Get the rotation of the Head
vector3df GetOculusRotation();

//Get the position of the Head
vector3df GetOculusPosition();

//Get the eye projection matrix
matrix4 GetOculusProjectionMatrixPerEye(int eye);

//Get the position of Touch Left
vector3df GetOculusTouchPositionLeft(ICameraSceneNode* CameraRelative);

//Get the rotation of Touch Left;
vector3df GetOculusTouchRotationLeft(ICameraSceneNode* CameraRelative);

//Get the position of Touch Right
vector3df GetOculusTouchPositionRight(ICameraSceneNode* CameraRelative);

//Get the rotation of Touch Right;
vector3df GetOculusTouchRotationRight(ICameraSceneNode* CameraRelative);

//Get the direction stick of left touch
vector2df GetOculusStickStateLeft();

//Get the direction stick of right touch
vector2df GetOculusStickStateRight();

//Get the Button A or B for Left touch
int GetOculusButtonLeft();

//Get the Button A or B for Right touch
int GetOculusButtonRight();

void OculusSendVibrationToLeft(int TimeInSecond);

//le constructeur public
static IOCulusSceneNode* GetInstance()
{
if (IOculus == 0)
{
IOculus = new IOCulusSceneNode;
}
return IOculus;
}

//le "destructeur" public
static void RemoveInstance()
{
if (IOculus != 0)
{
delete IOculus;
IOculus = 0;
}
}
};
#endif


My Code .cpp :
#include "IOculusCV1.h"
#include "glew.h"
#include "OVR_CAPI.h"
#include "OVR_CAPI_GL.h"
#include "OVR_Math.h"
#include "Irrlicht.h"
#include "COpenGLTexture.h"

using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::io;
using namespace irr::gui;
using namespace OVR;

IOCulusSceneNode *IOCulusSceneNode::IOculus = 0;

//Private constructor
IOCulusSceneNode::IOCulusSceneNode()
{
}

//Private Destructor
IOCulusSceneNode::~IOCulusSceneNode()
{
ovr_DestroyTextureSwapChain(session, textureChainLeft);
ovr_DestroyTextureSwapChain(session, textureChainRight);
ovr_Destroy(session);
IDevice->getVideoDriver()->removeTexture(eyeRenderTexture[0]);
IDevice->getVideoDriver()->removeTexture(eyeRenderTexture[1]);
cam[EyeLeft]->drop();
cam[EyeRight]->drop();
void DeleteOculus();
}

//Init the oculus here
void IOCulusSceneNode::InitOculus()
{
//Initialize the OVR with Params
ovr_Initialize(&initParams);

//Create the OVR Session
ovr_Create(&session, &luid);

//Get the HMD Description
hmdDesc = ovr_GetHmdDesc(session);

//Get the size of windows
windowSize = { hmdDesc.Resolution.w / 2, hmdDesc.Resolution.h / 2 };
}

//Set oculus after Irrlicht Device is created
void IOCulusSceneNode::SetOculusAfterDevice(IrrlichtDevice* IrrDevice)
{
//Set the pointer device
IDevice = IrrDevice;

//Initialize glew
glewInit();

//get texture sizes
texSizeL = ovr_GetFovTextureSize(session, ovrEyeType(EyeLeft), hmdDesc.DefaultEyeFov[EyeLeft], 2);
texSizeR = ovr_GetFovTextureSize(session, ovrEyeType(EyeRight), hmdDesc.DefaultEyeFov[EyeRight], 2);

//Create the texture swap chain description
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Width = texSizeL.w;
desc.Height = texSizeL.h;
desc.MipLevels = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.SampleCount = 1;
desc.StaticImage = ovrFalse;

//texture swap chain type openGL
ovr_CreateTextureSwapChainGL(session, &desc, &textureChainLeft);
ovr_CreateTextureSwapChainGL(session, &desc, &textureChainRight);
//Create the Irrlicht render texture
eyeRenderTexture[EyeLeft] = IrrDevice->getVideoDriver()->addRenderTargetTexture(dimension2d<u32>(texSizeL.w, texSizeL.h), "LeftEye", ECF_A8R8G8B8);
eyeRenderTexture[EyeRight] = IrrDevice->getVideoDriver()->addRenderTargetTexture(dimension2d<u32>(texSizeR.w, texSizeR.h), "RightEye", ECF_A8R8G8B8);

//Get the GLid of irrlicht render texture
video::COpenGLTexture*  TexLeft = reinterpret_cast<video::COpenGLTexture*>(eyeRenderTexture[EyeLeft]);
video::COpenGLTexture*  TexRight = reinterpret_cast<video::COpenGLTexture*>(eyeRenderTexture[EyeRight]);
TextureIDLeft = TexLeft->getOpenGLTextureName();
TextureIDRight = TexRight->getOpenGLTextureName();

// FloorLevel will give tracking poses where the floor height is 0
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
ovr_RecenterTrackingOrigin(session);

//Create the Camera for Left Eye and Right Eye
cam[EyeLeft] = IrrDevice->getSceneManager()->addCameraSceneNode();
cam[EyeRight] = IrrDevice->getSceneManager()->addCameraSceneNode();

//Set the value of Cameras Eyes
cam[EyeLeft]->setNearValue(0.2f);
cam[EyeRight]->setNearValue(0.2f);
cam[EyeLeft]->setFarValue(2000.0f);
cam[EyeRight]->setFarValue(2000.0f);
//cam[EyeLeft]->setAutomaticCulling(EAC_OFF);
//cam[EyeRight]->setAutomaticCulling(EAC_OFF);
}

void IOCulusSceneNode::UpdateOculusRender(ICameraSceneNode* IrrlichtCamera, bool WithEffect)
{
//Get the Session Status
ovr_GetSessionStatus(session, &sessionStatus);

//If the status should to recenter
if (sessionStatus.ShouldRecenter)
{
ovr_RecenterTrackingOrigin(session);
}

//If the status is visible
//if (sessionStatus.IsVisible)
//{
// Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyePose) may change at runtime.
ovrEyeRenderDesc eyeRenderDesc[2];
eyeRenderDesc[EyeLeft] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[EyeLeft]);
eyeRenderDesc[EyeRight] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[EyeRight]);

// Get eye poses, feeding in correct IPD offset
ovrPosef HmdToEyePose[2] = { eyeRenderDesc[EyeLeft].HmdToEyePose,eyeRenderDesc[EyeRight].HmdToEyePose };

//Get the eyes Position and rotation
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyePose, EyeRenderPose, &sensorSampleTime);

//Get the input state of controller
double ftiming = ovr_GetPredictedDisplayTime(session, 0);
trackingState = ovr_GetTrackingState(session, ftiming, ovrTrue);

ovr_CalcEyePoses(trackingState.HeadPose.ThePose, HmdToEyePose, EyeRenderPose);
ovr_GetInputState(session, ovrControllerType_Touch, &inputState);

//Get the camera Scene of Irrlicht
vector3df PosCam = IrrlichtCamera->getPosition();

//Convert Irrlicht camera to OVR camera
Vector3f Pos2(PosCam.X, PosCam.Y, -PosCam.Z);

// Render Scene to Eye Buffers
for (int eye = 0; eye < 2; eye++)
{
//Get the Irrlicht camera rotation
float Yaw = (IrrlichtCamera->getRotation().Y*PI / 180.0f) *-1.0f;

//Eye render pose for left and right
ovrPosef EyeRenderPosesF[2] = { EyeRenderPose[EyeLeft], EyeRenderPose[EyeRight] };

// Calc the view matrix
Matrix4f rollPitchYaw = Matrix4f::RotationY(Yaw);
Matrix4f finalRollPitchYaw = rollPitchYaw * (Matrix4f(EyeRenderPosesF[eye].Orientation));

//Scale the matrix for correct orientation
Matrix4f s = Matrix4f::Scaling(1.0f, 1.0f, -1.0f);
finalRollPitchYaw = s * finalRollPitchYaw * s;

Vector3f finalUp = finalRollPitchYaw.Transform(Vector3f(0, 1, 0));
Vector3f finalForward = finalRollPitchYaw.Transform(Vector3f(0, 0, -1));

Vector3f shiftedEyePos = Pos2 + rollPitchYaw.Transform(EyeRenderPosesF[eye].Position);
shiftedEyePos.z *= -1.0f;

//Left hand coordinate view Matrix
Matrix4f view = Matrix4f::LookAtLH(shiftedEyePos, shiftedEyePos + finalForward, finalUp);

//Projection Matrix
Matrix4f proj = ovrMatrix4f_Projection(hmdDesc.DefaultEyeFov[eye], 0.2f, 900.0f, ovrProjection_None);

//Get the Irrlicht Matrix
matrix4 MatrixProj, MatrixView;
MatrixProj = GetIRRMatrix(proj);
MatrixView = GetIRRMatrix(view);

MatrixProj(0, 0) *= -1.0f;

//Projection matrix is OK
matrix4 final = MatrixProj*MatrixView;

//Apply the Projection matrix to the cameras eye
cam[eye]->setProjectionMatrix(final, false);

cam[eye]->updateMatrices();
cam[eye]->updateAbsolutePosition();
OculusProjectionMatrix[eye] = final;

if (WithEffect == false)
{
IDevice->getSceneManager()->setActiveCamera(cam[eye]);
IDevice->getVideoDriver()->setRenderTarget(eyeRenderTexture[eye], true, true, video::SColor(0, 0, 0, 0));
IDevice->getSceneManager()->drawAll();
}
}
IDevice->getSceneManager()->setActiveCamera(IrrlichtCamera);
//}
}

//Set the active camera to the Left eye
void IOCulusSceneNode::SetActiveCameraLeft()
{
IDevice->getSceneManager()->setActiveCamera(cam[EyeLeft]);
}

//Set the active camera to the Right eye
void IOCulusSceneNode::SetActiveCameraRight()
{
IDevice->getSceneManager()->setActiveCamera(cam[EyeRight]);
}

//Get the left render texture
ITexture* IOCulusSceneNode::GetTextureEyeLeft()
{
return eyeRenderTexture[EyeLeft];
}

//Get the right render texture
ITexture* IOCulusSceneNode::GetTextureEyeRight()
{
return eyeRenderTexture[EyeRight];
}

//Update the Left eye render
void IOCulusSceneNode::PreRenderEyeLeft()
{
if (sessionStatus.IsVisible)
{
//IDevice->getSceneManager()->setActiveCamera(cam[EyeLeft]);
IDevice->getVideoDriver()->setRenderTarget(eyeRenderTexture[EyeLeft], true, true, video::SColor(0, 0, 0, 0));
//cam[EyeLeft]->render();
IDevice->getSceneManager()->drawAll();
}
}

//Update the Right eye render
void IOCulusSceneNode::PreRenderEyeRight()
{
if (sessionStatus.IsVisible)
{
//IDevice->getSceneManager()->setActiveCamera(cam[EyeRight]);
IDevice->getVideoDriver()->setRenderTarget(eyeRenderTexture[EyeRight], true, true, video::SColor(0, 0, 0, 0));
//cam[EyeRight]->render();
IDevice->getSceneManager()->drawAll();
}
}

//Send the final render to Oculus
void IOCulusSceneNode::SendRenderToOculus()
{
if (sessionStatus.IsVisible)
{
//Get the index of texture swap chain
ovr_GetTextureSwapChainCurrentIndex(session, textureChainLeft, &currentIndex);
unsigned int TexID;
ovr_GetTextureSwapChainBufferGL(session, textureChainLeft, currentIndex, &TexID);
//Copy the Irrlicht render texture to the GL context for render to oculus
glCopyImageSubData(TextureIDLeft, GL_TEXTURE_2D, 0, 0, 0, 0, TexID, GL_TEXTURE_2D, 0, 0, 0, 0, texSizeL.w, texSizeL.h, 1);

ovr_GetTextureSwapChainCurrentIndex(session, textureChainRight, &currentIndex);
unsigned int TexID2;
ovr_GetTextureSwapChainBufferGL(session, textureChainRight, currentIndex, &TexID2);
glCopyImageSubData(TextureIDRight, GL_TEXTURE_2D, 0, 0, 0, 0, TexID2, GL_TEXTURE_2D, 0, 0, 0, 0, texSizeL.w, texSizeL.h, 1);

//Send the render to the Oculus
ovr_CommitTextureSwapChain(session, textureChainLeft);
ovr_CommitTextureSwapChain(session, textureChainRight);

// Do distortion rendering, Present and flush/sync
ovrLayerEyeFov ld;
ld.Header.Type = ovrLayerType_EyeFov;
ld.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;   // Because OpenGL.

//Update the render layers
for (int eye = 0; eye < 2; ++eye)
{
ld.ColorTexture[EyeLeft] = textureChainLeft;
ld.ColorTexture[EyeRight] = textureChainRight;

Recti Dim;
Dim.w = eyeRenderTexture[eye]->getSize().Width;
Dim.h = eyeRenderTexture[eye]->getSize().Height;
Dim.x = 0;
Dim.y = 0;

ld.Viewport[eye] = Dim;

ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
ld.RenderPose[eye] = EyeRenderPose[eye];
ld.SensorSampleTime = sensorSampleTime;
}

ovrLayerHeader* layers = &ld.Header;

//Submit the final render
ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);

//increment the frame index
frameIndex++;
}
}

vector3df IOCulusSceneNode::GetOculusRotation()
{
vector3df Orient;
quaternion Quat;
Quat.W = EyeRenderPose[0].Orientation.w;
Quat.X = EyeRenderPose[0].Orientation.x;
Quat.Y = EyeRenderPose[0].Orientation.y;
Quat.Z = EyeRenderPose[0].Orientation.z;

Quat.toEuler(Orient);

Orient *= 180.0f / PI;

Orient.Y *= -1;
Orient.X *= -1;

return Orient;
}

vector3df IOCulusSceneNode::GetOculusPosition()
{
vector3df Position;
Position.X = EyeRenderPose[0].Position.x;
Position.Y = -EyeRenderPose[0].Position.y;
Position.Z = -EyeRenderPose[0].Position.z;
return Position;
}

matrix4 IOCulusSceneNode::GetOculusProjectionMatrixPerEye(int eye)
{
return OculusProjectionMatrix[eye];
}

//Get the window dimension
dimension2di IOCulusSceneNode::GetIrrWindowSize()
{
dimension2di SizeOfWindow;
SizeOfWindow.Width = windowSize.w;
SizeOfWindow.Height = windowSize.h;
return SizeOfWindow;
}

//Get the position of Touch Left
vector3df IOCulusSceneNode::GetOculusTouchPositionLeft(ICameraSceneNode* CameraRelative)
{
vector3df PosReturn;
PosReturn.X = trackingState.HandPoses[0].ThePose.Position.x;
PosReturn.Y = trackingState.HandPoses[0].ThePose.Position.y;
PosReturn.Z = -trackingState.HandPoses[0].ThePose.Position.z;

core::matrix4 Mat;
Mat.setRotationDegrees(CameraRelative->getRotation());
Mat.transformVect(PosReturn);

return PosReturn;
}

//Get the rotation of Touch Left;
vector3df IOCulusSceneNode::GetOculusTouchRotationLeft(ICameraSceneNode* CameraRelative)
{
vector3df RotReturn;

Matrix4f rollPitchYaw = Matrix4f::RotationY(CameraRelative->getRotation().Y*PI / 180.0f *-1.0f);
Matrix4f finalRollPitchYaw = rollPitchYaw * (Matrix4f(trackingState.HandPoses[0].ThePose.Orientation));

//Scale the matrix for correct orientation
Matrix4f s = Matrix4f::Scaling(1.0f, 1.0f, -1.0f);
finalRollPitchYaw = s * finalRollPitchYaw * s;
matrix4 Mat = GetIRRMatrix(finalRollPitchYaw);
RotReturn = Mat.getRotationDegrees();

return RotReturn;
}

//Get the position of Touch Right
vector3df IOCulusSceneNode::GetOculusTouchPositionRight(ICameraSceneNode* CameraRelative)
{
vector3df PosReturn;
PosReturn.X = trackingState.HandPoses[1].ThePose.Position.x;
PosReturn.Y = trackingState.HandPoses[1].ThePose.Position.y;
PosReturn.Z = -trackingState.HandPoses[1].ThePose.Position.z;

core::matrix4 Mat;
Mat.setRotationDegrees(CameraRelative->getRotation());
Mat.transformVect(PosReturn);

return PosReturn;
}

//Get the rotation of Touch Right;
vector3df IOCulusSceneNode::GetOculusTouchRotationRight(ICameraSceneNode* CameraRelative)
{
vector3df RotReturn;

Matrix4f rollPitchYaw = Matrix4f::RotationY(CameraRelative->getRotation().Y*PI / 180.0f *-1.0f);
Matrix4f finalRollPitchYaw = rollPitchYaw * (Matrix4f(trackingState.HandPoses[1].ThePose.Orientation));

//Scale the matrix for correct orientation
Matrix4f s = Matrix4f::Scaling(1.0f, 1.0f, -1.0f);
finalRollPitchYaw = s * finalRollPitchYaw * s;
matrix4 Mat = GetIRRMatrix(finalRollPitchYaw);
RotReturn = Mat.getRotationDegrees();

return RotReturn;
}

vector2df IOCulusSceneNode::GetOculusStickStateLeft()
{
vector2df ValueToreturn;
ValueToreturn.X=inputState.Thumbstick[0].x;
ValueToreturn.Y = inputState.Thumbstick[0].y;
return ValueToreturn;
}

vector2df IOCulusSceneNode::GetOculusStickStateRight()
{
vector2df ValueToreturn;
ValueToreturn.X = inputState.Thumbstick[1].x;
ValueToreturn.Y = inputState.Thumbstick[1].y;
return ValueToreturn;
}

int IOCulusSceneNode::GetOculusButtonLeft()
{
int ValueReturn = 0;
if (inputState.Buttons==256)
{
ValueReturn= 1;
}
if (inputState.Buttons == 512)
{
ValueReturn= 2;
}

return ValueReturn;
}

int IOCulusSceneNode::GetOculusButtonRight()
{
return inputState.Buttons;
}

void IOCulusSceneNode::OculusSendVibrationToLeft(int TimeInSecond)
{
/*ovrAudioChannelData SoundData;
ovrHapticsClip clip;*/
}

//Convert the OVR Matrix to Irrlicht Matrix
matrix4 IOCulusSceneNode::GetIRRMatrix(Matrix4f mat)
{
int idx = 0;
matrix4 ReturnMatrix;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
ReturnMatrix[idx] = mat.M;
++idx;
}
return ReturnMatrix;
}

vector3df IOCulusSceneNode::GetIrrVector(Vector3f Vec)
{
vector3df Vecreturn;
Vecreturn.X = Vec.x;
Vecreturn.Y = Vec.y;
Vecreturn.Z = Vec.z;
return Vecreturn;
}

//! return open gl texture name
GLuint COpenGLTexture::getOpenGLTextureName() const
{
return TextureName;
}
2 REPLIES 2

Copland
Level 2
Hello,
I Have found one problem. If I compile my application in 64 bits mode with 64 bits lib that work at 90 Fps.
If I compile my app in 32 bits with 32 bits lib the fps drop down dramaticly.

Copland
Level 2
@imperativity
Thank for your interest.
Maybe you can explain why this is diferent with 32 bits or 64 bits mode only with oculus lib ?
Many thanks for the last link :smile: