00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Win32_OculusRoomTiny.h"
00025 #include "RenderTiny_D3D1X_Device.h"
00026
00027
00028
00029
00030
00031 OculusRoomTinyApp* OculusRoomTinyApp::pApp = 0;
00032
00033
00034 OculusRoomTinyApp::OculusRoomTinyApp(HINSTANCE hinst)
00035 : pRender(0),
00036 LastUpdate(0),
00037
00038
00039 hWnd(NULL),
00040 hInstance(hinst), Quit(0), MouseCaptured(true),
00041 hXInputModule(0), pXInputGetState(0),
00042
00043
00044 EyePos(0.0f, 1.6f, -5.0f),
00045 EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
00046 LastSensorYaw(0),
00047 SConfig(),
00048 PostProcess(PostProcess_Distortion),
00049 ShiftDown(false),
00050 ControlDown(false)
00051 {
00052 pApp = this;
00053
00054 Width = 1280;
00055 Height = 800;
00056
00057 StartupTicks = OVR::Timer::GetTicks();
00058 LastPadPacketNo = 0;
00059
00060 MoveForward = MoveBack = MoveLeft = MoveRight = 0;
00061 GamepadMove = Vector3f(0);
00062 GamepadRotate = Vector3f(0);
00063 }
00064
00065 OculusRoomTinyApp::~OculusRoomTinyApp()
00066 {
00067 RemoveHandlerFromDevices();
00068 pSensor.Clear();
00069 pHMD.Clear();
00070 destroyWindow();
00071 pApp = 0;
00072 }
00073
00074
00075 int OculusRoomTinyApp::OnStartup(const char* args)
00076 {
00077 OVR_UNUSED(args);
00078
00079
00080
00081
00082
00083
00084
00085
00086 pManager = *DeviceManager::Create();
00087
00088
00089 pManager->SetMessageHandler(this);
00090
00091
00092 int detectionResult = IDCONTINUE;
00093 const char* detectionMessage;
00094
00095 do
00096 {
00097
00098 pSensor.Clear();
00099 pHMD.Clear();
00100 RenderParams.MonitorName.Clear();
00101
00102 pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
00103 if (pHMD)
00104 {
00105 pSensor = *pHMD->GetSensor();
00106
00107
00108
00109
00110
00111 if (pHMD->GetDeviceInfo(&HMDInfo))
00112 {
00113 RenderParams.MonitorName = HMDInfo.DisplayDeviceName;
00114 RenderParams.DisplayId = HMDInfo.DisplayId;
00115 SConfig.SetHMDInfo(HMDInfo);
00116 }
00117 }
00118 else
00119 {
00120
00121
00122
00123 pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
00124 }
00125
00126
00127
00128 detectionResult = IDCONTINUE;
00129
00130 if (!pHMD && !pSensor)
00131 detectionMessage = "Oculus Rift not detected.";
00132 else if (!pHMD)
00133 detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
00134 else if (!pSensor)
00135 detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
00136 else if (HMDInfo.DisplayDeviceName[0] == '\0')
00137 detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
00138 else
00139 detectionMessage = 0;
00140
00141 if (detectionMessage)
00142 {
00143 String messageText(detectionMessage);
00144 messageText += "\n\n"
00145 "Press 'Try Again' to run retry detection.\n"
00146 "Press 'Continue' to run full-screen anyway.";
00147
00148 detectionResult = ::MessageBoxA(0, messageText.ToCStr(), "Oculus Rift Detection",
00149 MB_CANCELTRYCONTINUE|MB_ICONWARNING);
00150
00151 if (detectionResult == IDCANCEL)
00152 return 1;
00153 }
00154
00155 } while (detectionResult != IDCONTINUE);
00156
00157
00158 if (HMDInfo.HResolution > 0)
00159 {
00160 Width = HMDInfo.HResolution;
00161 Height = HMDInfo.VResolution;
00162 }
00163
00164
00165 if (!setupWindow())
00166 return 1;
00167
00168 if (pSensor)
00169 {
00170
00171
00172
00173 SFusion.AttachToSensor(pSensor);
00174 SFusion.SetDelegateMessageHandler(this);
00175 SFusion.SetPredictionEnabled(true);
00176 }
00177
00178
00179
00180
00181
00182 RenderParams.Multisample = 4;
00183 RenderParams.Fullscreen = true;
00184
00185
00186 pRender = *RenderTiny::D3D10::RenderDevice::CreateDevice(RenderParams, (void*)hWnd);
00187 if (!pRender)
00188 return 1;
00189
00190
00191
00192
00193 SConfig.SetFullViewport(Viewport(0,0, Width, Height));
00194 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00195
00196
00197
00198
00199
00200 if (HMDInfo.HScreenSize > 0.0f)
00201 {
00202 if (HMDInfo.HScreenSize > 0.140f)
00203 SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
00204 else
00205 SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
00206 }
00207
00208 pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
00209
00210 SConfig.Set2DAreaFov(DegreeToRad(85.0f));
00211
00212
00213
00214
00215
00216 PopulateRoomScene(&Scene, pRender);
00217
00218
00219 LastUpdate = GetAppTime();
00220 return 0;
00221 }
00222
00223 void OculusRoomTinyApp::OnMessage(const Message& msg)
00224 {
00225 if (msg.Type == Message_DeviceAdded && msg.pDevice == pManager)
00226 {
00227 LogText("DeviceManager reported device added.\n");
00228 }
00229 else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pManager)
00230 {
00231 LogText("DeviceManager reported device removed.\n");
00232 }
00233 else if (msg.Type == Message_DeviceAdded && msg.pDevice == pSensor)
00234 {
00235 LogText("Sensor reported device added.\n");
00236 }
00237 else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pSensor)
00238 {
00239 LogText("Sensor reported device removed.\n");
00240 }
00241 }
00242
00243
00244 void OculusRoomTinyApp::OnGamepad(float padLx, float padLy, float padRx, float padRy)
00245 {
00246 GamepadMove = Vector3f(padLx * padLx * (padLx > 0 ? 1 : -1),
00247 0,
00248 padLy * padLy * (padLy > 0 ? -1 : 1));
00249 GamepadRotate = Vector3f(2 * padRx, -2 * padRy, 0);
00250 }
00251
00252 void OculusRoomTinyApp::OnMouseMove(int x, int y, int modifiers)
00253 {
00254 OVR_UNUSED(modifiers);
00255
00256
00257 int dx = x, dy = y;
00258 const float maxPitch = ((3.1415f/2)*0.98f);
00259
00260
00261
00262 EyeYaw -= (Sensitivity * dx)/ 360.0f;
00263
00264 if (!pSensor)
00265 {
00266 EyePitch -= (Sensitivity * dy)/ 360.0f;
00267
00268 if (EyePitch > maxPitch)
00269 EyePitch = maxPitch;
00270 if (EyePitch < -maxPitch)
00271 EyePitch = -maxPitch;
00272 }
00273 }
00274
00275 void OculusRoomTinyApp::OnKey(unsigned vk, bool down)
00276 {
00277 switch (vk)
00278 {
00279 case 'Q':
00280 if (down && ControlDown)
00281 Quit = true;
00282 break;
00283 case VK_ESCAPE:
00284 if (!down)
00285 Quit = true;
00286 break;
00287
00288
00289
00290
00291 case 'W': MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); break;
00292 case 'S': MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); break;
00293 case 'A': MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); break;
00294 case 'D': MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); break;
00295 case VK_UP: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); break;
00296 case VK_DOWN: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); break;
00297
00298 case 'R':
00299 SFusion.Reset();
00300 break;
00301
00302 case 'P':
00303 if (down)
00304 {
00305
00306 RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
00307
00308 if (shader == RenderDevice::PostProcessShader_Distortion)
00309 {
00310 pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
00311 }
00312 else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
00313 {
00314 pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
00315 }
00316 else
00317 OVR_ASSERT(false);
00318 }
00319 break;
00320
00321
00322 case VK_F1:
00323 SConfig.SetStereoMode(Stereo_None);
00324 PostProcess = PostProcess_None;
00325 break;
00326 case VK_F2:
00327 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00328 PostProcess = PostProcess_None;
00329 break;
00330 case VK_F3:
00331 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00332 PostProcess = PostProcess_Distortion;
00333 break;
00334
00335
00336 case VK_OEM_PLUS:
00337 case VK_INSERT:
00338 if (down)
00339 SConfig.SetIPD(SConfig.GetIPD() + 0.0005f * (ShiftDown ? 5.0f : 1.0f));
00340 break;
00341 case VK_OEM_MINUS:
00342 case VK_DELETE:
00343 if (down)
00344 SConfig.SetIPD(SConfig.GetIPD() - 0.0005f * (ShiftDown ? 5.0f : 1.0f));
00345 break;
00346
00347
00348 case VK_SHIFT:
00349 ShiftDown = down;
00350 break;
00351 case VK_CONTROL:
00352 ControlDown = down;
00353 break;
00354 }
00355 }
00356
00357
00358 void OculusRoomTinyApp::OnIdle()
00359 {
00360 double curtime = GetAppTime();
00361 float dt = float(curtime - LastUpdate);
00362 LastUpdate = curtime;
00363
00364
00365
00366
00367
00368 if (pSensor)
00369 {
00370 Quatf hmdOrient = SFusion.GetOrientation();
00371 float yaw = 0.0f;
00372
00373 hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &EyePitch, &EyeRoll);
00374
00375 EyeYaw += (yaw - LastSensorYaw);
00376 LastSensorYaw = yaw;
00377 }
00378
00379
00380
00381 EyeYaw -= GamepadRotate.x * dt;
00382
00383 if (!pSensor)
00384 {
00385
00386 EyePitch -= GamepadRotate.y * dt;
00387
00388 const float maxPitch = ((3.1415f/2)*0.98f);
00389 if (EyePitch > maxPitch)
00390 EyePitch = maxPitch;
00391 if (EyePitch < -maxPitch)
00392 EyePitch = -maxPitch;
00393 }
00394
00395
00396
00397
00398 if (MoveForward || MoveBack || MoveLeft || MoveRight)
00399 {
00400 Vector3f localMoveVector(0,0,0);
00401 Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
00402
00403 if (MoveForward)
00404 localMoveVector = ForwardVector;
00405 else if (MoveBack)
00406 localMoveVector = -ForwardVector;
00407
00408 if (MoveRight)
00409 localMoveVector += RightVector;
00410 else if (MoveLeft)
00411 localMoveVector -= RightVector;
00412
00413
00414 localMoveVector.Normalize();
00415 Vector3f orientationVector = yawRotate.Transform(localMoveVector);
00416 orientationVector *= MoveSpeed * dt * (ShiftDown ? 3.0f : 1.0f);
00417
00418 EyePos += orientationVector;
00419 }
00420
00421 else if (GamepadMove.LengthSq() > 0)
00422 {
00423 Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
00424 Vector3f orientationVector = yawRotate.Transform(GamepadMove);
00425 orientationVector *= MoveSpeed * dt;
00426 EyePos += orientationVector;
00427 }
00428
00429
00430
00431
00432 Matrix4f rollPitchYaw = Matrix4f::RotationY(EyeYaw) * Matrix4f::RotationX(EyePitch) *
00433 Matrix4f::RotationZ(EyeRoll);
00434 Vector3f up = rollPitchYaw.Transform(UpVector);
00435 Vector3f forward = rollPitchYaw.Transform(ForwardVector);
00436
00437
00438
00439 float headBaseToEyeHeight = 0.15f;
00440 float headBaseToEyeProtrusion = 0.09f;
00441
00442 Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
00443 Vector3f shiftedEyePos = EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
00444 shiftedEyePos.y -= eyeCenterInHeadFrame.y;
00445
00446 View = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
00447
00448
00449
00450
00451 switch(SConfig.GetStereoMode())
00452 {
00453 case Stereo_None:
00454 Render(SConfig.GetEyeRenderParams(StereoEye_Center));
00455 break;
00456
00457 case Stereo_LeftRight_Multipass:
00458 Render(SConfig.GetEyeRenderParams(StereoEye_Left));
00459 Render(SConfig.GetEyeRenderParams(StereoEye_Right));
00460 break;
00461 }
00462
00463 pRender->Present();
00464
00465 pRender->ForceFlushGPU();
00466 }
00467
00468
00469
00470 void OculusRoomTinyApp::Render(const StereoEyeParams& stereo)
00471 {
00472 pRender->BeginScene(PostProcess);
00473
00474
00475 pRender->ApplyStereoParams(stereo);
00476 pRender->Clear();
00477 pRender->SetDepthMode(true, true);
00478
00479 Scene.Render(pRender, stereo.ViewAdjust * View);
00480
00481 pRender->FinishScene();
00482 }
00483
00484
00485
00486
00487
00488 bool OculusRoomTinyApp::setupWindow()
00489 {
00490
00491 WNDCLASS wc;
00492 memset(&wc, 0, sizeof(wc));
00493 wc.lpszClassName = L"OVRAppWindow";
00494 wc.style = CS_OWNDC;
00495 wc.lpfnWndProc = systemWindowProc;
00496 wc.cbWndExtra = sizeof(OculusRoomTinyApp*);
00497 RegisterClass(&wc);
00498
00499
00500 RECT winSize = { 0, 0, Width, Height };
00501 AdjustWindowRect(&winSize, WS_POPUP, false);
00502 hWnd = CreateWindowA("OVRAppWindow", "OculusRoomTiny", WS_POPUP|WS_VISIBLE,
00503 HMDInfo.DesktopX, HMDInfo.DesktopY,
00504 winSize.right-winSize.left, winSize.bottom-winSize.top,
00505 NULL, NULL, hInstance, (LPVOID)this);
00506
00507
00508
00509 POINT center = { Width / 2, Height / 2 };
00510 ::ClientToScreen(hWnd, ¢er);
00511 WindowCenter = center;
00512
00513
00514 return (hWnd != NULL);
00515 }
00516
00517 void OculusRoomTinyApp::destroyWindow()
00518 {
00519 pRender.Clear();
00520
00521 if (hWnd)
00522 {
00523
00524 ::DestroyWindow(hWnd);
00525 UnregisterClass(L"OVRAppWindow", hInstance);
00526 hWnd = 0;
00527 Width = Height = 0;
00528 }
00529 }
00530
00531
00532 LRESULT CALLBACK OculusRoomTinyApp::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
00533 {
00534 if (msg == WM_NCCREATE)
00535 pApp->hWnd = hwnd;
00536 return pApp->windowProc(msg, wp, lp);
00537 }
00538
00539 void OculusRoomTinyApp::giveUsFocus(bool setFocus)
00540 {
00541 if (setFocus)
00542 {
00543 ::SetCursorPos(WindowCenter.x, WindowCenter.y);
00544
00545 MouseCaptured = true;
00546 ::SetCapture(hWnd);
00547 ::ShowCursor(FALSE);
00548
00549 }
00550 else
00551 {
00552 MouseCaptured = false;
00553 ::ReleaseCapture();
00554 ::ShowCursor(TRUE);
00555 }
00556 }
00557
00558 LRESULT OculusRoomTinyApp::windowProc(UINT msg, WPARAM wp, LPARAM lp)
00559 {
00560 switch (msg)
00561 {
00562 case WM_MOUSEMOVE:
00563 {
00564 if (MouseCaptured)
00565 {
00566
00567 POINT newPos = { LOWORD(lp), HIWORD(lp) };
00568 ::ClientToScreen(hWnd, &newPos);
00569 if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y))
00570 break;
00571 ::SetCursorPos(WindowCenter.x, WindowCenter.y);
00572
00573 LONG dx = newPos.x - WindowCenter.x;
00574 LONG dy = newPos.y - WindowCenter.y;
00575 pApp->OnMouseMove(dx, dy, 0);
00576 }
00577 }
00578 break;
00579
00580 case WM_MOVE:
00581 {
00582 RECT r;
00583 GetClientRect(hWnd, &r);
00584 WindowCenter.x = r.right/2;
00585 WindowCenter.y = r.bottom/2;
00586 ::ClientToScreen(hWnd, &WindowCenter);
00587 }
00588 break;
00589
00590 case WM_KEYDOWN:
00591 OnKey((unsigned)wp, true);
00592 break;
00593 case WM_KEYUP:
00594 OnKey((unsigned)wp, false);
00595 break;
00596
00597 case WM_SETFOCUS:
00598 giveUsFocus(true);
00599 break;
00600
00601 case WM_KILLFOCUS:
00602 giveUsFocus(false);
00603 break;
00604
00605 case WM_CREATE:
00606
00607 SetTimer(hWnd, 0, 100, NULL);
00608 break;
00609
00610 case WM_TIMER:
00611 KillTimer(hWnd, 0);
00612 giveUsFocus(true);
00613 break;
00614
00615 case WM_QUIT:
00616 case WM_CLOSE:
00617 Quit = true;
00618 return 0;
00619 }
00620
00621 return DefWindowProc(hWnd, msg, wp, lp);
00622 }
00623
00624 static inline float GamepadStick(short in)
00625 {
00626 float v;
00627 if (abs(in) < 9000)
00628 return 0;
00629 else if (in > 9000)
00630 v = (float) in - 9000;
00631 else
00632 v = (float) in + 9000;
00633 return v / (32767 - 9000);
00634 }
00635
00636 static inline float GamepadTrigger(BYTE in)
00637 {
00638 return (in < 30) ? 0.0f : (float(in-30) / 225);
00639 }
00640
00641
00642 int OculusRoomTinyApp::Run()
00643 {
00644
00645
00646
00647 while (!Quit)
00648 {
00649 MSG msg;
00650 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
00651 {
00652 TranslateMessage(&msg);
00653 DispatchMessage(&msg);
00654 }
00655 else
00656 {
00657
00658 XINPUT_STATE xis;
00659
00660 if (pXInputGetState && !pXInputGetState(0, &xis) &&
00661 (xis.dwPacketNumber != LastPadPacketNo))
00662 {
00663 OnGamepad(GamepadStick(xis.Gamepad.sThumbLX),
00664 GamepadStick(xis.Gamepad.sThumbLY),
00665 GamepadStick(xis.Gamepad.sThumbRX),
00666 GamepadStick(xis.Gamepad.sThumbRY));
00667
00668 LastPadPacketNo = xis.dwPacketNumber;
00669 }
00670
00671 pApp->OnIdle();
00672
00673
00674 if (IsIconic(hWnd))
00675 Sleep(10);
00676 }
00677 }
00678
00679 return 0;
00680 }
00681
00682
00683
00684
00685
00686 int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR inArgs, int)
00687 {
00688 int exitCode = 0;
00689
00690
00691
00692 OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
00693
00694
00695 {
00696 OculusRoomTinyApp app(hinst);
00697
00698
00699 exitCode = app.OnStartup(inArgs);
00700 if (!exitCode)
00701 {
00702
00703 exitCode = app.Run();
00704 }
00705 }
00706
00707
00708 OVR::System::Destroy();
00709
00710 OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
00711 return exitCode;
00712 }