Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Use WASD keys to move around, and cursor keys to look around & up/down.
- /// Dismiss the health and safety warning by tapping the headset or pressing any key.
- // DirectX
- #include "../../OculusRoomTiny_Advanced/Common/Win32_DirectXAppUtil.h"
- // Oculus SDK
- #pragma comment(lib, "Z:\\dev\\OculusSDK\\LibOVR\\Lib\\Windows\\Win32\\Release\\VS2015\\LibOVR.lib")
- #include "Z:\dev\OculusSDK\LibOVR\Include\OVR_CAPI_D3D.h"
- //------------------------------------------------------------
- // ovrSwapTextureSet wrapper class that also maintains the render target views
- // needed for D3D11 rendering.
- struct OculusTexture
- {
- ovrSession m_session;
- ovrTextureSwapChain m_texture_chain;
- std::vector<ID3D11RenderTargetView*> m_tex_rtv;
- OculusTexture() : m_session(nullptr), m_texture_chain(nullptr)
- {
- }
- bool Init(ovrSession session, int sizeW, int sizeH)
- {
- m_session = session;
- ovrTextureSwapChainDesc desc = {};
- desc.Type = ovrTexture_2D;
- desc.ArraySize = 1;
- desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
- desc.Width = sizeW;
- desc.Height = sizeH;
- desc.MipLevels = 1;
- desc.SampleCount = 1;
- desc.MiscFlags = ovrTextureMisc_DX_Typeless;
- desc.BindFlags = ovrTextureBind_DX_RenderTarget;
- desc.StaticImage = ovrFalse;
- ovrResult result = ovr_CreateTextureSwapChainDX(session, DIRECTX.Device, &desc, &m_texture_chain);
- if (!OVR_SUCCESS(result))
- return false;
- int texture_count = 0;
- ovr_GetTextureSwapChainLength(m_session, m_texture_chain, &texture_count);
- for (int i = 0; i < texture_count; ++i)
- {
- ID3D11Texture2D* tex = nullptr;
- ovr_GetTextureSwapChainBufferDX(m_session, m_texture_chain, i, IID_PPV_ARGS(&tex));
- D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
- rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- ID3D11RenderTargetView* rtv;
- DIRECTX.Device->CreateRenderTargetView(tex, &rtvd, &rtv);
- m_tex_rtv.push_back(rtv);
- tex->Release();
- }
- return true;
- }
- ~OculusTexture()
- {
- for (int i = 0; i < (int)m_tex_rtv.size(); ++i)
- {
- Release(m_tex_rtv[i]);
- }
- if (m_texture_chain)
- {
- ovr_DestroyTextureSwapChain(m_session, m_texture_chain);
- }
- }
- ID3D11RenderTargetView* GetRTV()
- {
- int index = 0;
- ovr_GetTextureSwapChainCurrentIndex(m_session, m_texture_chain, &index);
- return m_tex_rtv[index];
- }
- // Commit changes
- void Commit()
- {
- ovr_CommitTextureSwapChain(m_session, m_texture_chain);
- }
- };
- class HMD
- {
- public:
- HMD() :
- m_mirror_texture(nullptr),
- m_mirror_desc{},
- m_hmd_desc{},
- m_viewport_eye{},
- m_is_visible(true),
- m_frame_index(0)
- {
- m_eye_texture[0] = nullptr;
- m_eye_texture[1] = nullptr;
- m_eye_depth_buffer[0] = nullptr;
- m_eye_depth_buffer[1] = nullptr;
- }
- bool Create();
- void Release();
- void Update();
- bool Present();
- void PrepareViewport(int eye);
- XMMATRIX GetProjection(int eye, const XMVECTOR &observor_rotation_q, const XMVECTOR &observor_position, bool coord_sys_left);
- OculusTexture *m_eye_texture[2];
- DepthBuffer *m_eye_depth_buffer[2];
- ovrMirrorTextureDesc m_mirror_desc;
- ovrMirrorTexture m_mirror_texture;
- bool m_is_visible;
- long long m_frame_index;
- ovrSession m_session;
- ovrGraphicsLuid m_luid;
- ovrHmdDesc m_hmd_desc;
- ovrRecti m_viewport_eye[2];
- ovrPosef m_eye_render_pose[2];
- ovrEyeRenderDesc m_eye_render_desc[2];
- double m_sensor_sample_time;
- };
- class Zone
- {
- public:
- Zone()
- {
- m_scene = new Scene(false);
- m_camera = new Camera(&XMVectorSet(0.0f, 0.0f, 5.0f, 0), &XMQuaternionIdentity());
- }
- void Release()
- {
- if (m_camera)
- delete m_camera;
- if (m_scene)
- delete m_scene;
- }
- Scene *m_scene;
- Camera *m_camera;
- };
- // TODO: Support Retry on ovrError_DisplayLost
- // if (result == ovrError_DisplayLost) ...
- bool HMD::Create()
- {
- ovrResult result = ovr_Create(&m_session, &m_luid);
- if (!OVR_SUCCESS(result))
- return false;
- m_hmd_desc = ovr_GetHmdDesc(m_session);
- // Setup device and graphics
- // Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution
- if (!DIRECTX.InitDevice(m_hmd_desc.Resolution.w / 2, m_hmd_desc.Resolution.h / 2, reinterpret_cast<LUID*>(&m_luid)))
- return false;
- // Make the eye render buffers (caution if actual size < requested due to HW limits).
- for (int eye = 0; eye < 2; ++eye)
- {
- ovrSizei ideal_size = ovr_GetFovTextureSize(m_session, (ovrEyeType)eye, m_hmd_desc.DefaultEyeFov[eye], 1.0f);
- m_eye_texture[eye] = new OculusTexture();
- if (!m_eye_texture[eye]->Init(m_session, ideal_size.w, ideal_size.h))
- {
- VALIDATE(false, "Failed to create eye texture.");
- return false;
- }
- m_eye_depth_buffer[eye] = new DepthBuffer(DIRECTX.Device, ideal_size.w, ideal_size.h);
- m_viewport_eye[eye].Pos.x = 0;
- m_viewport_eye[eye].Pos.y = 0;
- m_viewport_eye[eye].Size = ideal_size;
- if (!m_eye_texture[eye]->m_texture_chain)
- {
- VALIDATE(false, "Failed to create texture.");
- return false;
- }
- }
- // Create a mirror to see on the monitor.
- m_mirror_desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
- m_mirror_desc.Width = DIRECTX.WinSizeW;
- m_mirror_desc.Height = DIRECTX.WinSizeH;
- result = ovr_CreateMirrorTextureDX(m_session, DIRECTX.Device, &m_mirror_desc, &m_mirror_texture);
- if (!OVR_SUCCESS(result))
- {
- VALIDATE(false, "Failed to create mirror texture.");
- return false;
- }
- // FloorLevel will give tracking poses where the floor height is 0
- ovr_SetTrackingOriginType(m_session, ovrTrackingOrigin_FloorLevel);
- return true;
- }
- HWND Rift_GetWindow()
- {
- return DIRECTX.Window;
- }
- ID3D11Device *Rift_GetDevice()
- {
- return DIRECTX.Device;
- }
- ID3D11DeviceContext *Rift_GetDeviceContext()
- {
- return DIRECTX.Context;
- }
- void Input_Processing(Zone &z)
- {
- XMVECTOR forward = XMVector3Rotate(XMVectorSet(0, 0, -0.05f, 0), z.m_camera->Rot);
- XMVECTOR right = XMVector3Rotate(XMVectorSet(0.05f, 0, 0, 0), z.m_camera->Rot);
- if (DIRECTX.Key['W'])
- z.m_camera->Pos = XMVectorAdd(z.m_camera->Pos, forward);
- if (DIRECTX.Key['S'])
- z.m_camera->Pos = XMVectorSubtract(z.m_camera->Pos, forward);
- if (DIRECTX.Key['D'])
- z.m_camera->Pos = XMVectorAdd(z.m_camera->Pos, right);
- if (DIRECTX.Key['A'])
- z.m_camera->Pos = XMVectorSubtract(z.m_camera->Pos, right);
- static float yaw = 0;
- static float pitch = 0;
- if (DIRECTX.Key[VK_LEFT])
- yaw += 0.02f;
- if (DIRECTX.Key[VK_RIGHT])
- yaw -= 0.02f;
- if (DIRECTX.Key[VK_UP])
- {
- pitch += 0.02f;
- // Clamp
- if (pitch > 0.8f)
- pitch = 0.4f;
- }
- if (DIRECTX.Key[VK_DOWN])
- {
- pitch -= 0.02f;
- // Clamp
- if (pitch < -0.8f)
- pitch = -0.4f;
- }
- z.m_camera->Rot = XMQuaternionRotationRollPitchYaw(pitch, yaw, 0);
- }
- void Animate(Scene *s)
- {
- // Animate the cube
- static float cube_clock = 0;
- s->Models[0]->Pos = XMFLOAT3(9 * sin(cube_clock), 3, 9 * cos(cube_clock += 0.015f));
- }
- void HMD::Update()
- {
- // Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc,
- // as the returned values (e.g. hmd_to_eye_offset) may change at runtime.
- m_eye_render_desc[0] = ovr_GetRenderDesc(m_session, ovrEye_Left, m_hmd_desc.DefaultEyeFov[0]);
- m_eye_render_desc[1] = ovr_GetRenderDesc(m_session, ovrEye_Right, m_hmd_desc.DefaultEyeFov[1]);
- // Get both eye poses simultaneously, with IPD offset already included.
- ovrVector3f hmd_to_eye_offset[2] = { m_eye_render_desc[0].HmdToEyeOffset,
- m_eye_render_desc[1].HmdToEyeOffset };
- ovr_GetEyePoses(m_session, m_frame_index, ovrTrue, hmd_to_eye_offset, m_eye_render_pose, &m_sensor_sample_time);
- // sensor_sample_time is fed into the layer later
- }
- void HMD::PrepareViewport(int eye)
- {
- // Clear and set up rendertarget
- DIRECTX.SetAndClearRenderTarget(m_eye_texture[eye]->GetRTV(), m_eye_depth_buffer[eye]);
- DIRECTX.SetViewport((float)m_viewport_eye[eye].Pos.x, (float)m_viewport_eye[eye].Pos.y,
- (float)m_viewport_eye[eye].Size.w, (float)m_viewport_eye[eye].Size.h);
- }
- OVR_PUBLIC_FUNCTION(void) __ovrPosef_FlipHandedness(const ovrPosef* inPose, ovrPosef* outPose)
- {
- outPose->Orientation.x = -inPose->Orientation.x;
- outPose->Orientation.y = -inPose->Orientation.y;
- outPose->Orientation.z = inPose->Orientation.z;
- outPose->Orientation.w = inPose->Orientation.w;
- outPose->Position.x = -inPose->Position.x;
- outPose->Position.y = inPose->Position.y;
- outPose->Position.z = inPose->Position.z;
- }
- XMMATRIX HMD::GetProjection(int eye, const XMVECTOR &observor_rotation_q, const XMVECTOR &observor_position, bool coord_sys_left)
- {
- ovrPosef eye_pose;
- if (coord_sys_left)
- {
- // Current rift SDK flip function appears to have a bug, resulting in up/down reversed.
- // Hence the above, which resolves the problem.
- __ovrPosef_FlipHandedness(&(m_eye_render_pose[eye]), &eye_pose);
- }
- else
- eye_pose = m_eye_render_pose[eye];
- // Get the pose information in XM format
- XMVECTOR eye_quat = XMVectorSet(eye_pose.Orientation.x, eye_pose.Orientation.y,
- eye_pose.Orientation.z, eye_pose.Orientation.w);
- XMVECTOR eye_pos = XMVectorSet(eye_pose.Position.x, eye_pose.Position.y, eye_pose.Position.z, 0);
- // Get view and projection matrices for the Rift camera
- XMVECTOR combined_pos = XMVectorAdd(observor_position, XMVector3Rotate(eye_pos, observor_rotation_q));
- // BUG: Look up/down rolls rather than pitches when combined here.
- // TODO: What's the correct means of combining these two quats, please.
- XMVECTOR combined_rot = XMQuaternionMultiply(eye_quat, observor_rotation_q);
- // DBG: use this to verify observor rotation is correct.
- //XMVECTOR combined_rot = observor_rotation_q;
- Camera final_cam(&combined_pos, &combined_rot);
- XMMATRIX view = final_cam.GetViewMatrix();
- ovrMatrix4f p = ovrMatrix4f_Projection(m_eye_render_desc[eye].Fov, 0.2f, 1000.0f, coord_sys_left ? ovrProjection_LeftHanded : ovrProjection_None);
- XMMATRIX proj = XMMatrixSet(p.M[0][0], p.M[1][0], p.M[2][0], p.M[3][0],
- p.M[0][1], p.M[1][1], p.M[2][1], p.M[3][1],
- p.M[0][2], p.M[1][2], p.M[2][2], p.M[3][2],
- p.M[0][3], p.M[1][3], p.M[2][3], p.M[3][3]);
- return XMMatrixMultiply(view, proj);
- }
- bool HMD::Present()
- {
- for (int eye = 0; eye < 2; eye++)
- m_eye_texture[eye]->Commit();
- // Initialize our single full screen Fov layer.
- ovrLayerEyeFov ld = {};
- ld.Header.Type = ovrLayerType_EyeFov;
- ld.Header.Flags = 0;
- for (int eye = 0; eye < 2; ++eye)
- {
- ld.ColorTexture[eye] = m_eye_texture[eye]->m_texture_chain;
- ld.Viewport[eye] = m_viewport_eye[eye];
- ld.Fov[eye] = m_hmd_desc.DefaultEyeFov[eye];
- ld.RenderPose[eye] = m_eye_render_pose[eye];
- ld.SensorSampleTime = m_sensor_sample_time;
- }
- ovrLayerHeader* layers = &ld.Header;
- ovrResult result = ovr_SubmitFrame(m_session, m_frame_index, nullptr, &layers, 1);
- // Exit the rendering loop if submit returns an error. TODO: retry on ovrError_DisplayLost
- if (!OVR_SUCCESS(result))
- return false;
- m_is_visible = (result == ovrSuccess);
- ovrSessionStatus session_status;
- ovr_GetSessionStatus(m_session, &session_status);
- if (session_status.ShouldQuit)
- return false;
- if (session_status.ShouldRecenter)
- ovr_RecenterTrackingOrigin(m_session);
- // Render mirror
- ID3D11Texture2D* tex = nullptr;
- ovr_GetMirrorTextureBufferDX(m_session, m_mirror_texture, IID_PPV_ARGS(&tex));
- DIRECTX.Context->CopyResource(DIRECTX.BackBuffer, tex);
- tex->Release();
- DIRECTX.SwapChain->Present(0, 0);
- m_frame_index++;
- return true;
- }
- HMD __hmd;
- Zone *__zone = nullptr;
- bool Rift_Init(HINSTANCE hinst)
- {
- // Initializes LibOVR, and the Rift
- ovrResult result = ovr_Initialize(nullptr);
- VALIDATE(OVR_SUCCESS(result), "Failed to initialize libOVR.");
- VALIDATE(DIRECTX.InitWindow(hinst, L"<><> Infinity for Oculus"), "Failed to open window.");
- return __hmd.Create();
- }
- void Rift_GetRenderTarget(void *&render_target, void *&depth, int eye)
- {
- render_target = (void*)__hmd.m_eye_texture[eye]->GetRTV();
- depth = (void*)__hmd.m_eye_depth_buffer[eye]->TexDsv;
- }
- void Rift_GetViewport(float &x, float &y, float &w, float &h, int eye)
- {
- x = (float)__hmd.m_viewport_eye[eye].Pos.x;
- y = (float)__hmd.m_viewport_eye[eye].Pos.y;
- w = (float)__hmd.m_viewport_eye[eye].Size.w;
- h = (float)__hmd.m_viewport_eye[eye].Size.h;
- }
- void Rift_Present()
- {
- __hmd.Present();
- }
- void Rift_Update()
- {
- __hmd.Update();
- }
- XMMATRIX Rift_Get_Projection(int eye, const XMFLOAT4 &rot, const XMFLOAT3 &pos, bool projection_lh)
- {
- XMVECTOR xpos = XMVectorSet(pos.x, pos.y, pos.z, 0);
- XMVECTOR xrot = XMVectorSet(rot.x, rot.y, rot.z, rot.w);
- return __hmd.GetProjection(eye, xrot, xpos, projection_lh);
- }
- #if 1
- bool Perform_Processing(HMD &hmd, Zone &z)
- {
- Input_Processing(z);
- Animate(z.m_scene);
- hmd.Update();
- // Render scene to the eye buffers ...
- if (hmd.m_is_visible)
- {
- for (int eye = 0; eye < 2; ++eye)
- {
- hmd.PrepareViewport(eye);
- const XMVECTOR &observor_rotation = z.m_camera->Rot;
- const XMVECTOR &observor_position = z.m_camera->Pos;
- // Oculus sample scene uses right handed coord system
- XMMATRIX cam_to_clip = hmd.GetProjection(eye, observor_rotation, observor_position, false); // false);
- z.m_scene->Render(&cam_to_clip, 1, 1, 1, 1, true);
- }
- }
- hmd.Present();
- return true;
- }
- #else
- // Absolute minimal implementation
- bool Perform_Processing(HMD &hmd, Zone &z)
- {
- Rift_Update();
- float green[4] = { 0, 1, 0, 1.0f };
- float blue[4] = { 0, 0, 1, 1.0f };
- ID3D11DeviceContext *ctx = Rift_GetDeviceContext();
- if (!ctx)
- return false;
- // Left
- void *rtv = nullptr, *depth = nullptr;
- Rift_GetRenderTarget(rtv, depth, 0);
- if (rtv)
- ctx->ClearRenderTargetView((ID3D11RenderTargetView *)rtv, green);
- // Right
- rtv = nullptr; depth = nullptr;
- Rift_GetRenderTarget(rtv, depth, 1);
- if (rtv)
- ctx->ClearRenderTargetView((ID3D11RenderTargetView *)rtv, blue);
- Rift_Present();
- return true;
- }
- #endif
- void HMD::Release()
- {
- if (m_mirror_texture)
- ovr_DestroyMirrorTexture(m_session, m_mirror_texture);
- for (int eye = 0; eye < 2; ++eye)
- {
- delete m_eye_texture[eye];
- delete m_eye_depth_buffer[eye];
- }
- DIRECTX.ReleaseDevice();
- ovr_Destroy(m_session);
- }
- //-------------------------------------------------------------------------------------
- int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int)
- {
- bool ok = Rift_Init(hinst);
- __zone = new Zone;
- if (ok)
- {
- // TODO: need to reconnect ovrError_DisplayLost functionality.
- while (DIRECTX.HandleMessages())
- {
- if (!Perform_Processing(__hmd, *__zone))
- break;
- }
- }
- if (__zone)
- {
- __zone->Release();
- delete __zone;
- }
- __hmd.Release();
- ovr_Shutdown();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment