00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "OVR.h"
00026
00027 #include "../CommonSrc/Platform/Platform_Default.h"
00028 #include "../CommonSrc/Render/Render_Device.h"
00029 #include "../CommonSrc/Render/Render_XmlSceneLoader.h"
00030 #include "../CommonSrc/Render/Render_FontEmbed_DejaVu48.h"
00031 #include "../CommonSrc/Platform/Gamepad.h"
00032
00033 #include <Kernel/OVR_SysFile.h>
00034 #include <Kernel/OVR_Log.h>
00035 #include <Kernel/OVR_Timer.h>
00036
00037 #include "Player.h"
00038
00039
00040 #define WORLDDEMO_ASSET_FILE "Tuscany.xml"
00041 #define WORLDDEMO_ASSET_PATH1 "Assets/Tuscany/"
00042 #define WORLDDEMO_ASSET_PATH2 "../Assets/Tuscany/"
00043
00044 #define WORLDDEMO_ASSET_PATH3 "Samples/OculusWorldDemo/Assets/Tuscany/"
00045
00046
00047 using namespace OVR;
00048 using namespace OVR::Platform;
00049 using namespace OVR::Render;
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 class OculusWorldDemoApp : public Application, public MessageHandler
00088 {
00089 public:
00090 OculusWorldDemoApp();
00091 ~OculusWorldDemoApp();
00092
00093 virtual int OnStartup(int argc, const char** argv);
00094 virtual void OnIdle();
00095
00096 virtual void OnMouseMove(int x, int y, int modifiers);
00097 virtual void OnKey(OVR::KeyCode key, int chr, bool down, int modifiers);
00098 virtual void OnResize(int width, int height);
00099
00100 virtual void OnMessage(const Message& msg);
00101
00102 void Render(const StereoEyeParams& stereo);
00103
00104
00105 void SetAdjustMessage(const char* format, ...);
00106
00107
00108 void SetAdjustMessageTimeout(float timeout);
00109
00110
00111
00112 void AdjustFov(float dt);
00113 void AdjustAspect(float dt);
00114 void AdjustIPD(float dt);
00115 void AdjustEyeHeight(float dt);
00116
00117 void AdjustMotionPrediction(float dt);
00118
00119 void AdjustDistortion(float dt, int kIndex, const char* label);
00120 void AdjustDistortionK0(float dt) { AdjustDistortion(dt, 0, "K0"); }
00121 void AdjustDistortionK1(float dt) { AdjustDistortion(dt, 1, "K1"); }
00122 void AdjustDistortionK2(float dt) { AdjustDistortion(dt, 2, "K2"); }
00123 void AdjustDistortionK3(float dt) { AdjustDistortion(dt, 3, "K3"); }
00124
00125
00126 void PopulateScene(const char* fileName);
00127 void PopulatePreloadScene();
00128 void ClearScene();
00129
00130
00131 void UpdateManualMagCalibration();
00132
00133 protected:
00134 RenderDevice* pRender;
00135 RendererParams RenderParams;
00136 int Width, Height;
00137 int Screen;
00138 int FirstScreenInCycle;
00139
00140
00141 Util::MagCalibration MagCal;
00142 bool MagAwaitingForwardLook;
00143
00144
00145 Ptr<DeviceManager> pManager;
00146 Ptr<SensorDevice> pSensor;
00147 Ptr<HMDDevice> pHMD;
00148 Ptr<Profile> pUserProfile;
00149 SensorFusion SFusion;
00150 HMDInfo TheHMDInfo;
00151
00152 Ptr<LatencyTestDevice> pLatencyTester;
00153 Util::LatencyTest LatencyUtil;
00154
00155 double LastUpdate;
00156 int FPS;
00157 int FrameCounter;
00158 double NextFPSUpdate;
00159
00160 Array<Ptr<CollisionModel> > CollisionModels;
00161 Array<Ptr<CollisionModel> > GroundCollisionModels;
00162
00163
00164
00165 enum LoadingStateType
00166 {
00167 LoadingState_Frame0,
00168 LoadingState_DoLoad,
00169 LoadingState_Finished
00170 };
00171
00172
00173 Player ThePlayer;
00174 Matrix4f View;
00175 Scene MainScene;
00176 Scene LoadingScene;
00177 Scene GridScene;
00178 Scene YawMarkGreenScene;
00179 Scene YawMarkRedScene;
00180 Scene YawLinesScene;
00181
00182 LoadingStateType LoadingState;
00183
00184 Ptr<ShaderFill> LitSolid, LitTextures[4];
00185
00186
00187 StereoConfig SConfig;
00188 PostProcessType PostProcess;
00189
00190
00191 String MainFilePath;
00192 Array<String> LODFilePaths;
00193 int ConsecutiveLowFPSFrames;
00194 int CurrentLODFileIndex;
00195
00196 float DistortionK0;
00197 float DistortionK1;
00198 float DistortionK2;
00199 float DistortionK3;
00200
00201 String AdjustMessage;
00202 double AdjustMessageTimeout;
00203
00204
00205 float SavedK0, SavedK1, SavedK2, SavedK3;
00206 float SavedESD, SavedAspect, SavedEyeDistance;
00207
00208
00209 Color DistortionClearColor;
00210
00211
00212 typedef void (OculusWorldDemoApp::*AdjustFuncType)(float);
00213 bool ShiftDown;
00214 AdjustFuncType pAdjustFunc;
00215 float AdjustDirection;
00216
00217 enum SceneRenderMode
00218 {
00219 Scene_World,
00220 Scene_Grid,
00221 Scene_Both,
00222 Scene_YawView
00223 };
00224 SceneRenderMode SceneMode;
00225
00226
00227 enum TextScreen
00228 {
00229 Text_None,
00230 Text_Orientation,
00231 Text_Config,
00232 Text_Help,
00233 Text_Count
00234 };
00235 TextScreen TextScreen;
00236
00237 struct DeviceStatusNotificationDesc
00238 {
00239 DeviceHandle Handle;
00240 MessageType Action;
00241
00242 DeviceStatusNotificationDesc():Action(Message_None) {}
00243 DeviceStatusNotificationDesc(MessageType mt, const DeviceHandle& dev)
00244 : Handle(dev), Action(mt) {}
00245 };
00246 Array<DeviceStatusNotificationDesc> DeviceStatusNotificationsQueue;
00247
00248
00249 Model* CreateModel(Vector3f pos, struct SlabModel* sm);
00250 Model* CreateBoundingModel(CollisionModel &cm);
00251 void PopulateLODFileNames();
00252 void DropLOD();
00253 void RaiseLOD();
00254 void CycleDisplay();
00255 void GamepadStateChanged(const GamepadState& pad);
00256
00257
00258 Anglef FirstMagYaw;
00259 int ManualMagCalStage;
00260 int ManualMagFailures;
00261 };
00262
00263
00264
00265 OculusWorldDemoApp::OculusWorldDemoApp()
00266 : pRender(0),
00267 LastUpdate(0),
00268 LoadingState(LoadingState_Frame0),
00269
00270 SConfig(),
00271 PostProcess(PostProcess_Distortion),
00272 DistortionClearColor(0, 0, 0),
00273
00274 ShiftDown(false),
00275 pAdjustFunc(0),
00276 AdjustDirection(1.0f),
00277 SceneMode(Scene_World),
00278 TextScreen(Text_None)
00279 {
00280 Width = 1280;
00281 Height = 800;
00282 Screen = 0;
00283 FirstScreenInCycle = 0;
00284
00285 FPS = 0;
00286 FrameCounter = 0;
00287 NextFPSUpdate = 0;
00288
00289 ConsecutiveLowFPSFrames = 0;
00290 CurrentLODFileIndex = 0;
00291
00292 AdjustMessageTimeout = 0;
00293 }
00294
00295 OculusWorldDemoApp::~OculusWorldDemoApp()
00296 {
00297 RemoveHandlerFromDevices();
00298
00299 if(DejaVu.fill)
00300 {
00301 DejaVu.fill->Release();
00302 }
00303 pLatencyTester.Clear();
00304 pSensor.Clear();
00305 pHMD.Clear();
00306
00307 CollisionModels.ClearAndRelease();
00308 GroundCollisionModels.ClearAndRelease();
00309 }
00310
00311 int OculusWorldDemoApp::OnStartup(int argc, const char** argv)
00312 {
00313
00314
00315
00316
00317
00318
00319
00320 pManager = *DeviceManager::Create();
00321
00322
00323 pManager->SetMessageHandler(this);
00324
00325
00326 pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
00327 if (pHMD)
00328 {
00329 pSensor = *pHMD->GetSensor();
00330
00331
00332
00333
00334
00335 if(pHMD->GetDeviceInfo(&TheHMDInfo))
00336 {
00337
00338 SConfig.SetHMDInfo(TheHMDInfo);
00339 }
00340
00341
00342 pUserProfile = pHMD->GetProfile();
00343 if (pUserProfile)
00344 {
00345 ThePlayer.EyeHeight = pUserProfile->GetEyeHeight();
00346 ThePlayer.EyePos.y = ThePlayer.EyeHeight;
00347 }
00348 }
00349 else
00350 {
00351
00352
00353
00354 pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
00355 }
00356
00357
00358 pLatencyTester = *pManager->EnumerateDevices<LatencyTestDevice>().CreateDevice();
00359 if (pLatencyTester)
00360 {
00361 LatencyUtil.SetDevice(pLatencyTester);
00362 }
00363
00364 if(pHMD == NULL && pSensor == NULL)
00365 {
00366 SetAdjustMessage("---------------------------------\nNO HMD DETECTED\nNO SENSOR DETECTED\n---------------------------------");
00367 }
00368 else if(pHMD == NULL)
00369 {
00370 SetAdjustMessage("----------------------------\nNO HMD DETECTED\n----------------------------");
00371 }
00372 else if(pSensor == NULL)
00373 {
00374 SetAdjustMessage("---------------------------------\nNO SENSOR DETECTED\n---------------------------------");
00375 }
00376 else
00377 {
00378 SetAdjustMessage("--------------------------------------------\n"
00379 "Press F9 for Full-Screen on Rift\n"
00380 "--------------------------------------------");
00381 }
00382
00383
00384 SetAdjustMessageTimeout(10.0f);
00385
00386
00387 if(TheHMDInfo.HResolution > 0)
00388 {
00389 Width = TheHMDInfo.HResolution;
00390 Height = TheHMDInfo.VResolution;
00391 }
00392
00393 if(!pPlatform->SetupWindow(Width, Height))
00394 {
00395 return 1;
00396 }
00397
00398 String Title = "Oculus World Demo";
00399 if(TheHMDInfo.ProductName[0])
00400 {
00401 Title += " : ";
00402 Title += TheHMDInfo.ProductName;
00403 }
00404 pPlatform->SetWindowTitle(Title);
00405
00406
00407 pPlatform->SetMouseMode(Mouse_Relative);
00408
00409 if(pSensor)
00410 {
00411
00412
00413
00414 SFusion.AttachToSensor(pSensor);
00415
00416 SFusion.SetDelegateMessageHandler(this);
00417
00418 SFusion.SetPredictionEnabled(true);
00419 }
00420
00421
00422
00423
00424 const char* graphics = "d3d11";
00425
00426
00427 for(int i = 1; i < argc; i++)
00428 {
00429 if(!strcmp(argv[i], "-r") && i < argc - 1)
00430 {
00431 graphics = argv[i + 1];
00432 }
00433 else if(!strcmp(argv[i], "-fs"))
00434 {
00435 RenderParams.Fullscreen = true;
00436 }
00437 }
00438
00439
00440 RenderParams.Multisample = 4;
00441 pRender = pPlatform->SetupGraphics(OVR_DEFAULT_RENDER_DEVICE_SET,
00442 graphics, RenderParams);
00443
00444
00445
00446
00447
00448 SConfig.SetFullViewport(Viewport(0, 0, Width, Height));
00449 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00450
00451
00452
00453
00454
00455 if (TheHMDInfo.HScreenSize > 0.0f)
00456 {
00457 if (TheHMDInfo.HScreenSize > 0.140f)
00458 SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
00459 else
00460 SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
00461 }
00462
00463 pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
00464
00465
00466 SConfig.Set2DAreaFov(DegreeToRad(85.0f));
00467
00468
00469
00470
00471
00472 if (argc == 2)
00473 {
00474 MainFilePath = argv[1];
00475 PopulateLODFileNames();
00476 }
00477 else
00478 {
00479 fprintf(stderr, "Usage: OculusWorldDemo [input XML]\n");
00480 exit(1);
00481 }
00482
00483
00484 if (!SysFile(MainFilePath).IsValid())
00485 {
00486 String prefixPath1(pPlatform->GetContentDirectory() + "/" + WORLDDEMO_ASSET_PATH1),
00487 prefixPath2(WORLDDEMO_ASSET_PATH2),
00488 prefixPath3(WORLDDEMO_ASSET_PATH3);
00489 if (SysFile(prefixPath1 + MainFilePath).IsValid())
00490 MainFilePath = prefixPath1 + MainFilePath;
00491 else if (SysFile(prefixPath2 + MainFilePath).IsValid())
00492 MainFilePath = prefixPath2 + MainFilePath;
00493 else if (SysFile(prefixPath3 + MainFilePath).IsValid())
00494 MainFilePath = prefixPath3 + MainFilePath;
00495 }
00496
00497 PopulatePreloadScene();
00498
00499 LastUpdate = pPlatform->GetAppTime();
00500
00501
00502 return 0;
00503 }
00504
00505 void OculusWorldDemoApp::OnMessage(const Message& msg)
00506 {
00507 if (msg.Type == Message_DeviceAdded || msg.Type == Message_DeviceRemoved)
00508 {
00509 if (msg.pDevice == pManager)
00510 {
00511 const MessageDeviceStatus& statusMsg =
00512 static_cast<const MessageDeviceStatus&>(msg);
00513
00514 {
00515 Lock::Locker lock(pManager->GetHandlerLock());
00516 DeviceStatusNotificationsQueue.PushBack(
00517 DeviceStatusNotificationDesc(statusMsg.Type, statusMsg.Handle));
00518 }
00519
00520 switch (statusMsg.Type)
00521 {
00522 case OVR::Message_DeviceAdded:
00523 LogText("DeviceManager reported device added.\n");
00524 break;
00525
00526 case OVR::Message_DeviceRemoved:
00527 LogText("DeviceManager reported device removed.\n");
00528 break;
00529
00530 default: OVR_ASSERT(0);
00531 }
00532 }
00533 }
00534 }
00535
00536 void OculusWorldDemoApp::OnResize(int width, int height)
00537 {
00538 Width = width;
00539 Height = height;
00540 SConfig.SetFullViewport(Viewport(0, 0, Width, Height));
00541 }
00542
00543 void OculusWorldDemoApp::OnMouseMove(int x, int y, int modifiers)
00544 {
00545 if(modifiers & Mod_MouseRelative)
00546 {
00547
00548 int dx = x, dy = y;
00549
00550 const float maxPitch = ((3.1415f / 2) * 0.98f);
00551
00552
00553
00554 ThePlayer.EyeYaw -= (Sensitivity * dx) / 360.0f;
00555
00556 if(!pSensor)
00557 {
00558 ThePlayer.EyePitch -= (Sensitivity * dy) / 360.0f;
00559
00560 if(ThePlayer.EyePitch > maxPitch)
00561 {
00562 ThePlayer.EyePitch = maxPitch;
00563 }
00564 if(ThePlayer.EyePitch < -maxPitch)
00565 {
00566 ThePlayer.EyePitch = -maxPitch;
00567 }
00568 }
00569 }
00570 }
00571
00572
00573 void OculusWorldDemoApp::OnKey(OVR::KeyCode key, int chr, bool down, int modifiers)
00574 {
00575 OVR_UNUSED(chr);
00576
00577 switch(key)
00578 {
00579 case Key_Q:
00580 if (down && (modifiers & Mod_Control))
00581 {
00582 pPlatform->Exit(0);
00583 }
00584 break;
00585
00586
00587
00588
00589 case Key_W:
00590 ThePlayer.MoveForward = down ? (ThePlayer.MoveForward | 1) : (ThePlayer.MoveForward & ~1);
00591 break;
00592 case Key_S:
00593 ThePlayer.MoveBack = down ? (ThePlayer.MoveBack | 1) : (ThePlayer.MoveBack & ~1);
00594 break;
00595 case Key_A:
00596 ThePlayer.MoveLeft = down ? (ThePlayer.MoveLeft | 1) : (ThePlayer.MoveLeft & ~1);
00597 break;
00598 case Key_D:
00599 ThePlayer.MoveRight = down ? (ThePlayer.MoveRight | 1) : (ThePlayer.MoveRight & ~1);
00600 break;
00601 case Key_Up:
00602 ThePlayer.MoveForward = down ? (ThePlayer.MoveForward | 2) : (ThePlayer.MoveForward & ~2);
00603 break;
00604 case Key_Down:
00605 ThePlayer.MoveBack = down ? (ThePlayer.MoveBack | 2) : (ThePlayer.MoveBack & ~2);
00606 break;
00607 case Key_Left:
00608 ThePlayer.MoveLeft = down ? (ThePlayer.MoveLeft | 2) : (ThePlayer.MoveLeft & ~2);
00609 break;
00610 case Key_Right:
00611 ThePlayer.MoveRight = down ? (ThePlayer.MoveRight | 2) : (ThePlayer.MoveRight & ~2);
00612 break;
00613
00614 case Key_Minus:
00615 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustEyeHeight : 0;
00616 AdjustDirection = -1;
00617 break;
00618 case Key_Equal:
00619 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustEyeHeight : 0;
00620 AdjustDirection = 1;
00621 break;
00622
00623 case Key_B:
00624 if (down)
00625 {
00626 if(SConfig.GetDistortionScale() == 1.0f)
00627 {
00628 if(SConfig.GetHMDInfo().HScreenSize > 0.140f)
00629 {
00630 SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
00631 }
00632 else
00633 {
00634 SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
00635 }
00636 }
00637 else
00638 {
00639
00640 SConfig.SetDistortionFitPointVP(0, 0);
00641 }
00642 }
00643 break;
00644
00645
00646
00647 case Key_V:
00648 if (down)
00649 {
00650 if(DistortionClearColor.B == 0)
00651 {
00652 DistortionClearColor = Color(0, 128, 255);
00653 }
00654 else
00655 {
00656 DistortionClearColor = Color(0, 0, 0);
00657 }
00658
00659 pRender->SetDistortionClearColor(DistortionClearColor);
00660 }
00661 break;
00662
00663
00664 case Key_F1:
00665 SConfig.SetStereoMode(Stereo_None);
00666 PostProcess = PostProcess_None;
00667 SetAdjustMessage("StereoMode: None");
00668 break;
00669 case Key_F2:
00670 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00671 PostProcess = PostProcess_None;
00672 SetAdjustMessage("StereoMode: Stereo + No Distortion");
00673 break;
00674 case Key_F3:
00675 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00676 PostProcess = PostProcess_Distortion;
00677 SetAdjustMessage("StereoMode: Stereo + Distortion");
00678 break;
00679
00680 case Key_R:
00681 SFusion.Reset();
00682 if (MagCal.IsAutoCalibrating() || MagCal.IsManuallyCalibrating())
00683 MagCal.AbortCalibration();
00684
00685 SetAdjustMessage("Sensor Fusion Reset");
00686 break;
00687
00688 case Key_Space:
00689 if (!down)
00690 {
00691 TextScreen = (enum TextScreen)((TextScreen + 1) % Text_Count);
00692 }
00693 break;
00694
00695 case Key_F4:
00696 if (!down)
00697 {
00698 RenderParams = pRender->GetParams();
00699 RenderParams.Multisample = RenderParams.Multisample > 1 ? 1 : 4;
00700 pRender->SetParams(RenderParams);
00701 if(RenderParams.Multisample > 1)
00702 {
00703 SetAdjustMessage("Multisampling On");
00704 }
00705 else
00706 {
00707 SetAdjustMessage("Multisampling Off");
00708 }
00709 }
00710 break;
00711 case Key_F9:
00712 #ifndef OVR_OS_LINUX // On Linux F9 does the same as F11.
00713 if (!down)
00714 {
00715 CycleDisplay();
00716 }
00717 break;
00718 #endif
00719 #ifdef OVR_OS_MAC
00720 case Key_F10:
00721 #else
00722 case Key_F11:
00723 #endif
00724 if (!down)
00725 {
00726 RenderParams = pRender->GetParams();
00727 RenderParams.Display = DisplayId(SConfig.GetHMDInfo().DisplayDeviceName,SConfig.GetHMDInfo().DisplayId);
00728 pRender->SetParams(RenderParams);
00729
00730 pPlatform->SetMouseMode(Mouse_Normal);
00731 pPlatform->SetFullscreen(RenderParams, pRender->IsFullscreen() ? Display_Window : Display_FakeFullscreen);
00732 pPlatform->SetMouseMode(Mouse_Relative);
00733
00734 if(RenderParams.IsDisplaySet() && pRender->IsFullscreen())
00735 {
00736 SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
00737 PostProcess = PostProcess_Distortion;
00738 }
00739 }
00740 break;
00741
00742 case Key_Escape:
00743 if(!down)
00744 {
00745 if (MagCal.IsAutoCalibrating() || MagCal.IsManuallyCalibrating())
00746 {
00747 MagCal.AbortCalibration();
00748 SetAdjustMessage("Aborting Magnetometer Calibration");
00749 }
00750 else
00751 {
00752
00753 pPlatform->SetFullscreen(RenderParams, Display_Window);
00754 RenderParams.Display = pPlatform->GetDisplay(0);
00755 pRender->SetParams(RenderParams);
00756 Screen = 0;
00757 }
00758 }
00759 break;
00760
00761
00762 case Key_BracketLeft:
00763 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustFov : 0;
00764 AdjustDirection = 1;
00765 break;
00766 case Key_BracketRight:
00767 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustFov : 0;
00768 AdjustDirection = -1;
00769 break;
00770
00771 case Key_Insert:
00772 case Key_Num0:
00773 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustIPD : 0;
00774 AdjustDirection = 1;
00775 break;
00776 case Key_Delete:
00777 case Key_Num9:
00778 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustIPD : 0;
00779 AdjustDirection = -1;
00780 break;
00781
00782 case Key_PageUp:
00783 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustAspect : 0;
00784 AdjustDirection = 1;
00785 break;
00786 case Key_PageDown:
00787 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustAspect : 0;
00788 AdjustDirection = -1;
00789 break;
00790
00791
00792 case Key_H:
00793 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK0 : NULL;
00794 AdjustDirection = -1;
00795 break;
00796 case Key_Y:
00797 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK0 : NULL;
00798 AdjustDirection = 1;
00799 break;
00800 case Key_J:
00801 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK1 : NULL;
00802 AdjustDirection = -1;
00803 break;
00804 case Key_U:
00805 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK1 : NULL;
00806 AdjustDirection = 1;
00807 break;
00808 case Key_K:
00809 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK2 : NULL;
00810 AdjustDirection = -1;
00811 break;
00812 case Key_I:
00813 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK2 : NULL;
00814 AdjustDirection = 1;
00815 break;
00816 case Key_L:
00817 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK3 : NULL;
00818 AdjustDirection = -1;
00819 break;
00820 case Key_O:
00821 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK3 : NULL;
00822 AdjustDirection = 1;
00823 break;
00824
00825 case Key_Tab:
00826 if (down)
00827 {
00828 float t0 = SConfig.GetDistortionK(0),
00829 t1 = SConfig.GetDistortionK(1),
00830 t2 = SConfig.GetDistortionK(2),
00831 t3 = SConfig.GetDistortionK(3);
00832 float tESD = SConfig.GetEyeToScreenDistance(),
00833 taspect = SConfig.GetAspectMultiplier(),
00834 tipd = SConfig.GetIPD();
00835
00836 if(SavedK0 > 0.0f)
00837 {
00838 SConfig.SetDistortionK(0, SavedK0);
00839 SConfig.SetDistortionK(1, SavedK1);
00840 SConfig.SetDistortionK(2, SavedK2);
00841 SConfig.SetDistortionK(3, SavedK3);
00842 SConfig.SetEyeToScreenDistance(SavedESD);
00843 SConfig.SetAspectMultiplier(SavedAspect);
00844 SConfig.SetIPD(SavedEyeDistance);
00845
00846 if ( ShiftDown )
00847 {
00848
00849 SetAdjustMessage("Swapped current and saved. New settings:\n"
00850 "ESD:\t120 %.3f\t350 Eye:\t490 %.3f\n"
00851 "K0: \t120 %.4f\t350 K2: \t490 %.4f\n"
00852 "K1: \t120 %.4f\t350 K3: \t490 %.4f\n",
00853 SavedESD, SavedEyeDistance,
00854 SavedK0, SavedK2,
00855 SavedK1, SavedK3);
00856 SavedK0 = t0;
00857 SavedK1 = t1;
00858 SavedK2 = t2;
00859 SavedK3 = t3;
00860 SavedESD = tESD;
00861 SavedAspect = taspect;
00862 SavedEyeDistance = tipd;
00863 }
00864 else
00865 {
00866 SetAdjustMessage("Restored:\n"
00867 "ESD:\t120 %.3f\t350 Eye:\t490 %.3f\n"
00868 "K0: \t120 %.4f\t350 K2: \t490 %.4f\n"
00869 "K1: \t120 %.4f\t350 K3: \t490 %.4f\n",
00870 SavedESD, SavedEyeDistance,
00871 SavedK0, SavedK2,
00872 SavedK1, SavedK3);
00873 }
00874 }
00875 else
00876 {
00877 SetAdjustMessage("Setting Saved");
00878 SavedK0 = t0;
00879 SavedK1 = t1;
00880 SavedK2 = t2;
00881 SavedK3 = t3;
00882 SavedESD = tESD;
00883 SavedAspect = taspect;
00884 SavedEyeDistance = tipd;
00885 }
00886
00887 }
00888 break;
00889
00890 case Key_G:
00891 if (down)
00892 {
00893 if(SceneMode == Scene_World)
00894 {
00895 SceneMode = Scene_Grid;
00896 SetAdjustMessage("Grid Only");
00897 }
00898 else if(SceneMode == Scene_Grid)
00899 {
00900 SceneMode = Scene_Both;
00901 SetAdjustMessage("Grid Overlay");
00902 }
00903 else if(SceneMode == Scene_Both)
00904 {
00905 SceneMode = Scene_World;
00906 SetAdjustMessage("Grid Off");
00907 }
00908 }
00909 break;
00910
00911
00912 case Key_Shift:
00913 ShiftDown = down;
00914 break;
00915
00916
00917 case Key_T:
00918 ThePlayer.EyePos = Vector3f(10.0f, 1.6f, 10.0f);
00919 break;
00920
00921 case Key_F5:
00922 if (!down)
00923 {
00924 UPInt numNodes = MainScene.Models.GetSize();
00925 for(UPInt i = 0; i < numNodes; i++)
00926 {
00927 Ptr<OVR::Render::Model> nodePtr = MainScene.Models[i];
00928 Render::Model* pNode = nodePtr.GetPtr();
00929 if(pNode->IsCollisionModel)
00930 {
00931 pNode->Visible = !pNode->Visible;
00932 }
00933 }
00934 }
00935 break;
00936
00937 case Key_N:
00938 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustMotionPrediction : NULL;
00939 AdjustDirection = -1;
00940 break;
00941
00942 case Key_M:
00943 pAdjustFunc = down ? &OculusWorldDemoApp::AdjustMotionPrediction : NULL;
00944 AdjustDirection = 1;
00945 break;
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 case Key_Z:
00957 if (down)
00958 {
00959 ManualMagCalStage = 0;
00960 if (MagCal.IsManuallyCalibrating())
00961 MagAwaitingForwardLook = false;
00962 else
00963 {
00964 MagCal.BeginManualCalibration(SFusion);
00965 MagAwaitingForwardLook = true;
00966 }
00967 }
00968 break;
00969
00970 case Key_X:
00971 if (down)
00972 {
00973 MagCal.BeginAutoCalibration(SFusion);
00974 SetAdjustMessage("Starting Auto Mag Calibration");
00975 }
00976 break;
00977
00978
00979 case Key_F6:
00980 if (down)
00981 {
00982 if (SceneMode != Scene_YawView)
00983 {
00984 SceneMode = Scene_YawView;
00985 SetAdjustMessage("Magnetometer Yaw Angle Marks");
00986 }
00987 else
00988 {
00989 SceneMode = Scene_World;
00990 SetAdjustMessage("Magnetometer Marks Off");
00991 }
00992 }
00993 break;
00994
00995 case Key_C:
00996 if (down)
00997 {
00998
00999 RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
01000
01001 if (shader == RenderDevice::PostProcessShader_Distortion)
01002 {
01003 pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
01004 SetAdjustMessage("Chromatic Aberration Correction On");
01005 }
01006 else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
01007 {
01008 pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
01009 SetAdjustMessage("Chromatic Aberration Correction Off");
01010 }
01011 else
01012 OVR_ASSERT(false);
01013 }
01014 break;
01015
01016 case Key_P:
01017 if (down)
01018 {
01019
01020 if (SFusion.IsPredictionEnabled())
01021 {
01022 SFusion.SetPredictionEnabled(false);
01023 SetAdjustMessage("Motion Prediction Off");
01024 }
01025 else
01026 {
01027 SFusion.SetPredictionEnabled(true);
01028 SetAdjustMessage("Motion Prediction On");
01029 }
01030 }
01031 break;
01032 default:
01033 break;
01034 }
01035 }
01036
01037 void OculusWorldDemoApp::OnIdle()
01038 {
01039
01040 double curtime = pPlatform->GetAppTime();
01041 float dt = float(curtime - LastUpdate);
01042 LastUpdate = curtime;
01043
01044
01045 GamepadState gamepadState;
01046 if (GetPlatformCore()->GetGamepadManager()->GetGamepadState(0, &gamepadState))
01047 {
01048 GamepadStateChanged(gamepadState);
01049 }
01050
01051
01052 if (LoadingState == LoadingState_DoLoad)
01053 {
01054 PopulateScene(MainFilePath.ToCStr());
01055 LoadingState = LoadingState_Finished;
01056 return;
01057 }
01058
01059
01060 {
01061 bool queueIsEmpty = false;
01062 while (!queueIsEmpty)
01063 {
01064 DeviceStatusNotificationDesc desc;
01065
01066 {
01067 Lock::Locker lock(pManager->GetHandlerLock());
01068 if (DeviceStatusNotificationsQueue.GetSize() == 0)
01069 break;
01070 desc = DeviceStatusNotificationsQueue.Front();
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 DeviceStatusNotificationsQueue.RemoveAt(0);
01081 queueIsEmpty = (DeviceStatusNotificationsQueue.GetSize() == 0);
01082 }
01083
01084 bool wasAlreadyCreated = desc.Handle.IsCreated();
01085
01086 if (desc.Action == Message_DeviceAdded)
01087 {
01088 switch(desc.Handle.GetType())
01089 {
01090 case Device_Sensor:
01091 if (desc.Handle.IsAvailable() && !desc.Handle.IsCreated())
01092 {
01093 if (!pSensor)
01094 {
01095 pSensor = *desc.Handle.CreateDeviceTyped<SensorDevice>();
01096 SFusion.AttachToSensor(pSensor);
01097 SetAdjustMessage("---------------------------\n"
01098 "SENSOR connected\n"
01099 "---------------------------");
01100 }
01101 else if (!wasAlreadyCreated)
01102 {
01103 LogText("A new SENSOR has been detected, but it is not currently used.");
01104 }
01105 }
01106 break;
01107 case Device_LatencyTester:
01108 if (desc.Handle.IsAvailable() && !desc.Handle.IsCreated())
01109 {
01110 if (!pLatencyTester)
01111 {
01112 pLatencyTester = *desc.Handle.CreateDeviceTyped<LatencyTestDevice>();
01113 LatencyUtil.SetDevice(pLatencyTester);
01114 if (!wasAlreadyCreated)
01115 SetAdjustMessage("----------------------------------------\n"
01116 "LATENCY TESTER connected\n"
01117 "----------------------------------------");
01118 }
01119 }
01120 break;
01121 case Device_HMD:
01122 {
01123 OVR::HMDInfo info;
01124 desc.Handle.GetDeviceInfo(&info);
01125
01126
01127 if (strlen(info.DisplayDeviceName) > 0 && (!pHMD || !info.IsSameDisplay(TheHMDInfo)))
01128 {
01129 SetAdjustMessage("------------------------\n"
01130 "HMD connected\n"
01131 "------------------------");
01132 if (!pHMD || !desc.Handle.IsDevice(pHMD))
01133 pHMD = *desc.Handle.CreateDeviceTyped<HMDDevice>();
01134
01135 if (pHMD && pHMD->GetDeviceInfo(&TheHMDInfo))
01136 {
01137
01138 SConfig.SetHMDInfo(TheHMDInfo);
01139 }
01140 LogText("HMD device added.\n");
01141 }
01142 break;
01143 }
01144 default:;
01145 }
01146 }
01147 else if (desc.Action == Message_DeviceRemoved)
01148 {
01149 if (desc.Handle.IsDevice(pSensor))
01150 {
01151 LogText("Sensor reported device removed.\n");
01152 SFusion.AttachToSensor(NULL);
01153 pSensor.Clear();
01154 SetAdjustMessage("-------------------------------\n"
01155 "SENSOR disconnected.\n"
01156 "-------------------------------");
01157 }
01158 else if (desc.Handle.IsDevice(pLatencyTester))
01159 {
01160 LogText("Latency Tester reported device removed.\n");
01161 LatencyUtil.SetDevice(NULL);
01162 pLatencyTester.Clear();
01163 SetAdjustMessage("---------------------------------------------\n"
01164 "LATENCY SENSOR disconnected.\n"
01165 "---------------------------------------------");
01166 }
01167 else if (desc.Handle.IsDevice(pHMD))
01168 {
01169 if (pHMD && !pHMD->IsDisconnected())
01170 {
01171 SetAdjustMessage("---------------------------\n"
01172 "HMD disconnected\n"
01173 "---------------------------");
01174
01175
01176 pHMD = pHMD->Disconnect(pSensor);
01177
01178
01179
01180
01181
01182 if (pHMD && pHMD->GetDeviceInfo(&TheHMDInfo))
01183 {
01184
01185 SConfig.SetHMDInfo(TheHMDInfo);
01186 }
01187 LogText("HMD device removed.\n");
01188 }
01189 }
01190 }
01191 else
01192 OVR_ASSERT(0);
01193 }
01194 }
01195
01196
01197 if (pAdjustFunc)
01198 {
01199 (this->*pAdjustFunc)(dt * AdjustDirection * (ShiftDown ? 5.0f : 1.0f));
01200 }
01201
01202
01203 const char* results = LatencyUtil.GetResultsString();
01204 if (results != NULL)
01205 {
01206 LogText("LATENCY TESTER: %s\n", results);
01207 }
01208
01209
01210 LatencyUtil.ProcessInputs();
01211
01212
01213 if (MagCal.IsManuallyCalibrating())
01214 UpdateManualMagCalibration();
01215
01216 if (MagCal.IsAutoCalibrating())
01217 {
01218 MagCal.UpdateAutoCalibration(SFusion);
01219 int n = MagCal.NumberOfSamples();
01220 if (n == 1)
01221 SetAdjustMessage(" Magnetometer Calibration Has 1 Sample \n %d Remaining - Please Keep Looking Around ",4-n);
01222 else if (n < 4)
01223 SetAdjustMessage(" Magnetometer Calibration Has %d Samples \n %d Remaining - Please Keep Looking Around ",n,4-n);
01224 if (MagCal.IsCalibrated())
01225 {
01226 SFusion.SetYawCorrectionEnabled(true);
01227 Vector3f mc = MagCal.GetMagCenter();
01228 SetAdjustMessage(" Magnetometer Calibration Complete \nCenter: %f %f %f",mc.x,mc.y,mc.z);
01229 }
01230 }
01231
01232
01233
01234
01235 if(pSensor)
01236 {
01237 Quatf hmdOrient = SFusion.GetPredictedOrientation();
01238
01239 float yaw = 0.0f;
01240 hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &ThePlayer.EyePitch, &ThePlayer.EyeRoll);
01241
01242 ThePlayer.EyeYaw += (yaw - ThePlayer.LastSensorYaw);
01243 ThePlayer.LastSensorYaw = yaw;
01244
01245
01246
01247
01248
01249
01250
01251 }
01252
01253
01254 if(curtime >= NextFPSUpdate)
01255 {
01256 NextFPSUpdate = curtime + 1.0;
01257 FPS = FrameCounter;
01258 FrameCounter = 0;
01259 }
01260 FrameCounter++;
01261
01262 if(FPS < 40)
01263 {
01264 ConsecutiveLowFPSFrames++;
01265 }
01266 else
01267 {
01268 ConsecutiveLowFPSFrames = 0;
01269 }
01270
01271 if(ConsecutiveLowFPSFrames > 200)
01272 {
01273 DropLOD();
01274 ConsecutiveLowFPSFrames = 0;
01275 }
01276
01277 ThePlayer.EyeYaw -= ThePlayer.GamepadRotate.x * dt;
01278 ThePlayer.HandleCollision(dt, &CollisionModels, &GroundCollisionModels, ShiftDown);
01279
01280 if(!pSensor)
01281 {
01282 ThePlayer.EyePitch -= ThePlayer.GamepadRotate.y * dt;
01283
01284 const float maxPitch = ((3.1415f / 2) * 0.98f);
01285 if(ThePlayer.EyePitch > maxPitch)
01286 {
01287 ThePlayer.EyePitch = maxPitch;
01288 }
01289 if(ThePlayer.EyePitch < -maxPitch)
01290 {
01291 ThePlayer.EyePitch = -maxPitch;
01292 }
01293 }
01294
01295
01296
01297 Matrix4f rollPitchYaw = Matrix4f::RotationY(ThePlayer.EyeYaw) * Matrix4f::RotationX(ThePlayer.EyePitch) *
01298 Matrix4f::RotationZ(ThePlayer.EyeRoll);
01299 Vector3f up = rollPitchYaw.Transform(UpVector);
01300 Vector3f forward = rollPitchYaw.Transform(ForwardVector);
01301
01302
01303
01304 float headBaseToEyeHeight = 0.15f;
01305 float headBaseToEyeProtrusion = 0.09f;
01306
01307 Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
01308 Vector3f shiftedEyePos = ThePlayer.EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
01309 shiftedEyePos.y -= eyeCenterInHeadFrame.y;
01310 View = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 switch(SConfig.GetStereoMode())
01323 {
01324 case Stereo_None:
01325 Render(SConfig.GetEyeRenderParams(StereoEye_Center));
01326 break;
01327
01328 case Stereo_LeftRight_Multipass:
01329
01330 Render(SConfig.GetEyeRenderParams(StereoEye_Left));
01331 Render(SConfig.GetEyeRenderParams(StereoEye_Right));
01332 break;
01333
01334 }
01335
01336 pRender->Present();
01337
01338 pRender->ForceFlushGPU();
01339 }
01340
01341
01342 void OculusWorldDemoApp::UpdateManualMagCalibration()
01343 {
01344 float tyaw, pitch, roll;
01345 Anglef yaw;
01346 Quatf hmdOrient = SFusion.GetOrientation();
01347 hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&tyaw, &pitch, &roll);
01348 Vector3f mag = SFusion.GetMagnetometer();
01349 float dtr = Math<float>::DegreeToRadFactor;
01350 yaw.Set(tyaw);
01351
01352 const int timeout = 100;
01353
01354 switch(ManualMagCalStage)
01355 {
01356 case 0:
01357 if (MagAwaitingForwardLook)
01358 SetAdjustMessage("Magnetometer Calibration\n** Step 1: Please Look Forward **\n** and Press Z When Ready **");
01359 else
01360 if (fabs(pitch) < 10.0f*dtr)
01361 {
01362 MagCal.InsertIfAcceptable(hmdOrient, mag);
01363 FirstMagYaw = yaw;
01364 MagAwaitingForwardLook = false;
01365 if (MagCal.NumberOfSamples() == 1)
01366 {
01367 ManualMagCalStage = 1;
01368 ManualMagFailures = 0;
01369 }
01370 }
01371 else
01372 MagAwaitingForwardLook = true;
01373 break;
01374 case 1:
01375 SetAdjustMessage("Magnetometer Calibration\n** Step 2: Please Look Up **");
01376 yaw -= FirstMagYaw;
01377 if ((pitch > 50.0f*dtr) && (yaw.Abs() < 20.0f*dtr))
01378 {
01379 MagCal.InsertIfAcceptable(hmdOrient, mag);
01380 ManualMagFailures++;
01381 if ((MagCal.NumberOfSamples() == 2)||(ManualMagFailures > timeout))
01382 {
01383 ManualMagCalStage = 2;
01384 ManualMagFailures = 0;
01385 }
01386 }
01387 break;
01388 case 2:
01389 SetAdjustMessage("Magnetometer Calibration\n** Step 3: Please Look Left **");
01390 yaw -= FirstMagYaw;
01391 if (yaw.Get() > 60.0f*dtr)
01392 {
01393 MagCal.InsertIfAcceptable(hmdOrient, mag);
01394 ManualMagFailures++;
01395 if ((MagCal.NumberOfSamples() == 3)||(ManualMagFailures > timeout))
01396 {
01397 ManualMagCalStage = 3;
01398 ManualMagFailures = 0;
01399 }
01400 }
01401 break;
01402 case 3:
01403 SetAdjustMessage("Magnetometer Calibration\n** Step 4: Please Look Right **");
01404 yaw -= FirstMagYaw;
01405 if (yaw.Get() < -60.0f*dtr)
01406 {
01407 MagCal.InsertIfAcceptable(hmdOrient, mag);
01408 ManualMagFailures++;
01409 if (MagCal.NumberOfSamples() == 4)
01410 ManualMagCalStage = 6;
01411 else
01412 {
01413 if (ManualMagFailures > timeout)
01414 {
01415 ManualMagCalStage = 4;
01416 ManualMagFailures = 0;
01417 }
01418 }
01419 }
01420 break;
01421 case 4:
01422 SetAdjustMessage("Magnetometer Calibration\n** Step 5: Please Look Upper Right **");
01423 yaw -= FirstMagYaw;
01424 if ((yaw.Get() < -50.0f*dtr) && (pitch > 40.0f*dtr))
01425 {
01426 MagCal.InsertIfAcceptable(hmdOrient, mag);
01427 if (MagCal.NumberOfSamples() == 4)
01428 ManualMagCalStage = 6;
01429 else
01430 {
01431 if (ManualMagFailures > timeout)
01432 {
01433 ManualMagCalStage = 5;
01434 ManualMagFailures = 0;
01435 }
01436 else
01437 ManualMagFailures++;
01438 }
01439 }
01440 break;
01441 case 5:
01442 SetAdjustMessage("Calibration Failed\n** Try Again From Another Location **");
01443 MagCal.AbortCalibration();
01444 break;
01445 case 6:
01446 if (!MagCal.IsCalibrated())
01447 {
01448 MagCal.SetCalibration(SFusion);
01449 SFusion.SetYawCorrectionEnabled(true);
01450 Vector3f mc = MagCal.GetMagCenter();
01451 SetAdjustMessage(" Magnetometer Calibration and Activation \nCenter: %f %f %f",
01452 mc.x,mc.y,mc.z);
01453 }
01454 }
01455 }
01456
01457
01458
01459 static const char* HelpText =
01460 "F1 \t100 NoStereo \t420 Z \t520 Manual Mag Calib\n"
01461 "F2 \t100 Stereo \t420 X \t520 Auto Mag Calib\n"
01462 "F3 \t100 StereoHMD \t420 ; \t520 Mag Set Ref Point\n"
01463 "F4 \t100 MSAA \t420 F6 \t520 Mag Info\n"
01464 "F9 \t100 FullScreen \t420 R \t520 Reset SensorFusion\n"
01465 "F11 \t100 Fast FullScreen \t500 - + \t660 Adj EyeHeight\n"
01466 "C \t100 Chromatic Ab \t500 [ ] \t660 Adj FOV\n"
01467 "P \t100 Motion Pred \t500 Shift \t660 Adj Faster\n"
01468 "N/M \t180 Adj Motion Pred\n"
01469 "( / ) \t180 Adj EyeDistance"
01470 ;
01471
01472
01473 enum DrawTextCenterType
01474 {
01475 DrawText_NoCenter= 0,
01476 DrawText_VCenter = 0x1,
01477 DrawText_HCenter = 0x2,
01478 DrawText_Center = DrawText_VCenter | DrawText_HCenter
01479 };
01480
01481 static void DrawTextBox(RenderDevice* prender, float x, float y,
01482 float textSize, const char* text,
01483 DrawTextCenterType centerType = DrawText_NoCenter)
01484 {
01485 float ssize[2] = {0.0f, 0.0f};
01486
01487 prender->MeasureText(&DejaVu, text, textSize, ssize);
01488
01489
01490 if (centerType & DrawText_HCenter)
01491 {
01492 x = -ssize[0]/2;
01493 }
01494 if (centerType & DrawText_VCenter)
01495 {
01496 y = -ssize[1]/2;
01497 }
01498
01499 prender->FillRect(x-0.02f, y-0.02f, x+ssize[0]+0.02f, y+ssize[1]+0.02f, Color(40,40,100,210));
01500 prender->RenderText(&DejaVu, text, x, y, textSize, Color(255,255,0,210));
01501 }
01502
01503 void OculusWorldDemoApp::Render(const StereoEyeParams& stereo)
01504 {
01505 pRender->BeginScene(PostProcess);
01506
01507
01508 pRender->ApplyStereoParams(stereo);
01509 pRender->Clear();
01510
01511 pRender->SetDepthMode(true, true);
01512 if (SceneMode != Scene_Grid)
01513 {
01514 MainScene.Render(pRender, stereo.ViewAdjust * View);
01515 }
01516
01517 if (SceneMode == Scene_YawView)
01518 {
01519 Matrix4f calView = Matrix4f();
01520 float viewYaw = -ThePlayer.LastSensorYaw + SFusion.GetMagRefYaw();
01521 calView.M[0][0] = calView.M[2][2] = cos(viewYaw);
01522 calView.M[0][2] = sin(viewYaw);
01523 calView.M[2][0] = -sin(viewYaw);
01524
01525
01526 if (SFusion.IsYawCorrectionInProgress())
01527 YawMarkGreenScene.Render(pRender, stereo.ViewAdjust);
01528 else
01529 YawMarkRedScene.Render(pRender, stereo.ViewAdjust);
01530
01531 if (fabs(ThePlayer.EyePitch) < Math<float>::Pi * 0.33)
01532 YawLinesScene.Render(pRender, stereo.ViewAdjust * calView);
01533 }
01534
01535
01536
01537
01538
01539 pRender->ApplyStereoParams2D(stereo);
01540 pRender->SetDepthMode(false, false);
01541
01542 float unitPixel = SConfig.Get2DUnitPixel();
01543 float textHeight= unitPixel * 22;
01544
01545 if ((SceneMode == Scene_Grid)||(SceneMode == Scene_Both))
01546 {
01547 GridScene.Render(pRender, Matrix4f());
01548 GridScene.Render(pRender, Matrix4f::Translation(unitPixel,unitPixel,0));
01549 }
01550
01551
01552 if (LoadingState != LoadingState_Finished)
01553 {
01554 LoadingScene.Render(pRender, Matrix4f());
01555 String loadMessage = String("Loading ") + MainFilePath;
01556 DrawTextBox(pRender, 0.0f, 0.25f, textHeight, loadMessage.ToCStr(), DrawText_HCenter);
01557 LoadingState = LoadingState_DoLoad;
01558 }
01559
01560 if(!AdjustMessage.IsEmpty() && AdjustMessageTimeout > pPlatform->GetAppTime())
01561 {
01562 DrawTextBox(pRender,0.0f,0.4f, textHeight, AdjustMessage.ToCStr(), DrawText_HCenter);
01563 }
01564
01565 switch(TextScreen)
01566 {
01567 case Text_Orientation:
01568 {
01569 char buf[256], gpustat[256];
01570 OVR_sprintf(buf, sizeof(buf),
01571 " Yaw:%4.0f Pitch:%4.0f Roll:%4.0f \n"
01572 " FPS: %d Frame: %d \n Pos: %3.2f, %3.2f, %3.2f \n"
01573 " EyeHeight: %3.2f",
01574 RadToDegree(ThePlayer.EyeYaw), RadToDegree(ThePlayer.EyePitch), RadToDegree(ThePlayer.EyeRoll),
01575 FPS, FrameCounter, ThePlayer.EyePos.x, ThePlayer.EyePos.y, ThePlayer.EyePos.z, ThePlayer.EyePos.y);
01576 size_t texMemInMB = pRender->GetTotalTextureMemoryUsage() / 1058576;
01577 if (texMemInMB)
01578 {
01579 OVR_sprintf(gpustat, sizeof(gpustat), "\n GPU Tex: %u MB", texMemInMB);
01580 OVR_strcat(buf, sizeof(buf), gpustat);
01581 }
01582
01583 DrawTextBox(pRender, 0.0f, -0.15f, textHeight, buf, DrawText_HCenter);
01584 }
01585 break;
01586
01587 case Text_Config:
01588 {
01589 char textBuff[2048];
01590
01591 OVR_sprintf(textBuff, sizeof(textBuff),
01592 "Fov\t300 %9.4f\n"
01593 "EyeDistance\t300 %9.4f\n"
01594 "DistortionK0\t300 %9.4f\n"
01595 "DistortionK1\t300 %9.4f\n"
01596 "DistortionK2\t300 %9.4f\n"
01597 "DistortionK3\t300 %9.4f\n"
01598 "TexScale\t300 %9.4f",
01599 SConfig.GetYFOVDegrees(),
01600 SConfig.GetIPD(),
01601 SConfig.GetDistortionK(0),
01602 SConfig.GetDistortionK(1),
01603 SConfig.GetDistortionK(2),
01604 SConfig.GetDistortionK(3),
01605 SConfig.GetDistortionScale());
01606
01607 DrawTextBox(pRender, 0.0f, 0.0f, textHeight, textBuff, DrawText_Center);
01608 }
01609 break;
01610
01611 case Text_Help:
01612 DrawTextBox(pRender, 0.0f, -0.1f, textHeight, HelpText, DrawText_Center);
01613
01614 default:
01615 break;
01616 }
01617
01618
01619
01620 Color colorToDisplay;
01621 if (LatencyUtil.DisplayScreenColor(colorToDisplay))
01622 {
01623 pRender->FillRect(-0.4f, -0.4f, 0.4f, 0.4f, colorToDisplay);
01624 }
01625
01626 pRender->FinishScene();
01627 }
01628
01629
01630
01631 void OculusWorldDemoApp::SetAdjustMessage(const char* format, ...)
01632 {
01633 Lock::Locker lock(pManager->GetHandlerLock());
01634 char textBuff[2048];
01635 va_list argList;
01636 va_start(argList, format);
01637 OVR_vsprintf(textBuff, sizeof(textBuff), format, argList);
01638 va_end(argList);
01639
01640
01641 AdjustMessage = textBuff;
01642 AdjustMessageTimeout = pPlatform->GetAppTime() + 4.0f;
01643 }
01644
01645 void OculusWorldDemoApp::SetAdjustMessageTimeout(float timeout)
01646 {
01647 AdjustMessageTimeout = pPlatform->GetAppTime() + timeout;
01648 }
01649
01650
01651
01652 void OculusWorldDemoApp::AdjustFov(float dt)
01653 {
01654 float esd = SConfig.GetEyeToScreenDistance() + 0.01f * dt;
01655 SConfig.SetEyeToScreenDistance(esd);
01656 SetAdjustMessage("ESD:%6.3f FOV: %6.3f", esd, SConfig.GetYFOVDegrees());
01657 }
01658
01659 void OculusWorldDemoApp::AdjustAspect(float dt)
01660 {
01661 float rawAspect = SConfig.GetAspect() / SConfig.GetAspectMultiplier();
01662 float newAspect = SConfig.GetAspect() + 0.01f * dt;
01663 SConfig.SetAspectMultiplier(newAspect / rawAspect);
01664 SetAdjustMessage("Aspect: %6.3f", newAspect);
01665 }
01666
01667 void OculusWorldDemoApp::AdjustDistortion(float dt, int kIndex, const char* label)
01668 {
01669 SConfig.SetDistortionK(kIndex, SConfig.GetDistortionK(kIndex) + 0.03f * dt);
01670 SetAdjustMessage("%s: %6.4f", label, SConfig.GetDistortionK(kIndex));
01671 }
01672
01673 void OculusWorldDemoApp::AdjustIPD(float dt)
01674 {
01675 SConfig.SetIPD(SConfig.GetIPD() + 0.025f * dt);
01676 SetAdjustMessage("EyeDistance: %6.4f", SConfig.GetIPD());
01677 }
01678
01679 void OculusWorldDemoApp::AdjustEyeHeight(float dt)
01680 {
01681 float dist = 0.5f * dt;
01682
01683 ThePlayer.EyeHeight += dist;
01684 ThePlayer.EyePos.y += dist;
01685
01686 SetAdjustMessage("EyeHeight: %4.2f", ThePlayer.EyeHeight);
01687 }
01688
01689 void OculusWorldDemoApp::AdjustMotionPrediction(float dt)
01690 {
01691 float motionPred = SFusion.GetPredictionDelta() + 0.01f * dt;
01692
01693 if (motionPred < 0.0f)
01694 {
01695 motionPred = 0.0f;
01696 }
01697
01698 SFusion.SetPrediction(motionPred);
01699
01700 SetAdjustMessage("MotionPrediction: %6.3fs", motionPred);
01701 }
01702
01703
01704
01705 void OculusWorldDemoApp::PopulateScene(const char *fileName)
01706 {
01707 XmlHandler xmlHandler;
01708 if(!xmlHandler.ReadFile(fileName, pRender, &MainScene, &CollisionModels, &GroundCollisionModels))
01709 {
01710 SetAdjustMessage("---------------------------------\nFILE LOAD FAILED\n---------------------------------");
01711 SetAdjustMessageTimeout(10.0f);
01712 }
01713
01714 MainScene.SetAmbient(Vector4f(1.0f, 1.0f, 1.0f, 1.0f));
01715
01716
01717 Ptr<Model> gridModel = *Model::CreateGrid(Vector3f(0,0,0), Vector3f(1.0f/10, 0,0), Vector3f(0,1.0f/10,0),
01718 10, 10, 5,
01719 Color(0, 255, 0, 255), Color(255, 50, 50, 255) );
01720 GridScene.World.Add(gridModel);
01721
01722
01723 float shifty = -0.5f;
01724 Ptr<Model> yawMarkGreenModel = *Model::CreateBox(Color(0, 255, 0, 255), Vector3f(0.0f, shifty, -2.0f), Vector3f(0.05f, 0.05f, 0.05f));
01725 YawMarkGreenScene.World.Add(yawMarkGreenModel);
01726 Ptr<Model> yawMarkRedModel = *Model::CreateBox(Color(255, 0, 0, 255), Vector3f(0.0f, shifty, -2.0f), Vector3f(0.05f, 0.05f, 0.05f));
01727 YawMarkRedScene.World.Add(yawMarkRedModel);
01728
01729 Ptr<Model> yawLinesModel = *new Model(Prim_Lines);
01730 float r = 2.0f;
01731 float theta0 = Math<float>::PiOver2;
01732 float theta1 = 0.0f;
01733 Color c = Color(255, 200, 200, 255);
01734 for (int i = 0; i < 35; i++)
01735 {
01736 theta1 = theta0 + Math<float>::Pi / 18.0f;
01737 yawLinesModel->AddLine(yawLinesModel->AddVertex(Vector3f(r*cos(theta0),shifty,-r*sin(theta0)),c),
01738 yawLinesModel->AddVertex(Vector3f(r*cos(theta1),shifty,-r*sin(theta1)),c));
01739 theta0 = theta1;
01740 yawLinesModel->AddLine(yawLinesModel->AddVertex(Vector3f(r*cos(theta0),shifty,-r*sin(theta0)),c),
01741 yawLinesModel->AddVertex(Vector3f(r*cos(theta0),shifty+0.1f,-r*sin(theta0)),c));
01742 theta0 = theta1;
01743 }
01744 theta1 = theta0 + Math<float>::Pi / 18.0f;
01745 yawLinesModel->AddLine(yawLinesModel->AddVertex(Vector3f(r*cos(theta0),shifty,-r*sin(theta0)),c),
01746 yawLinesModel->AddVertex(Vector3f(r*cos(theta1),shifty,-r*sin(theta1)),c));
01747 yawLinesModel->AddLine(yawLinesModel->AddVertex(Vector3f(0.0f,shifty+0.1f,-r),c),
01748 yawLinesModel->AddVertex(Vector3f(r*sin(0.02f),shifty,-r*cos(0.02f)),c));
01749 yawLinesModel->AddLine(yawLinesModel->AddVertex(Vector3f(0.0f,shifty+0.1f,-r),c),
01750 yawLinesModel->AddVertex(Vector3f(r*sin(-0.02f),shifty,-r*cos(-0.02f)),c));
01751 yawLinesModel->SetPosition(Vector3f(0.0f,0.0f,0.0f));
01752
01753 YawLinesScene.World.Add(yawLinesModel);
01754 }
01755
01756
01757 void OculusWorldDemoApp::PopulatePreloadScene()
01758 {
01759
01760 String fileName = MainFilePath;
01761 fileName.StripExtension();
01762
01763 Ptr<File> imageFile = *new SysFile(fileName + "_LoadScreen.tga");
01764 Ptr<Texture> imageTex;
01765 if (imageFile->IsValid())
01766 imageTex = *LoadTextureTga(pRender, imageFile);
01767
01768
01769 if (imageTex)
01770 {
01771 imageTex->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
01772 Ptr<Model> m = *new Model(Prim_Triangles);
01773 m->AddVertex(-0.5f, 0.5f, 0.0f, Color(255,255,255,255), 0.0f, 0.0f);
01774 m->AddVertex( 0.5f, 0.5f, 0.0f, Color(255,255,255,255), 1.0f, 0.0f);
01775 m->AddVertex( 0.5f, -0.5f, 0.0f, Color(255,255,255,255), 1.0f, 1.0f);
01776 m->AddVertex(-0.5f, -0.5f, 0.0f, Color(255,255,255,255), 0.0f, 1.0f);
01777 m->AddTriangle(2,1,0);
01778 m->AddTriangle(0,3,2);
01779
01780 Ptr<ShaderFill> fill = *new ShaderFill(*pRender->CreateShaderSet());
01781 fill->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
01782 fill->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Fragment, FShader_Texture));
01783 fill->SetTexture(0, imageTex);
01784 m->Fill = fill;
01785
01786 LoadingScene.World.Add(m);
01787 }
01788 }
01789
01790 void OculusWorldDemoApp::ClearScene()
01791 {
01792 MainScene.Clear();
01793 GridScene.Clear();
01794 YawMarkGreenScene.Clear();
01795 YawMarkRedScene.Clear();
01796 YawLinesScene.Clear();
01797 }
01798
01799 void OculusWorldDemoApp::PopulateLODFileNames()
01800 {
01801
01802 LODFilePaths.PushBack(MainFilePath);
01803 int LODIndex = 1;
01804 SPInt pos = strcspn(MainFilePath.ToCStr(), ".");
01805 SPInt len = strlen(MainFilePath.ToCStr());
01806 SPInt diff = len - pos;
01807
01808 if (diff == 0)
01809 return;
01810
01811 while(true)
01812 {
01813 char pathWithoutExt[250];
01814 char buffer[250];
01815 for(SPInt i = 0; i < pos; ++i)
01816 {
01817 pathWithoutExt[i] = MainFilePath[(int)i];
01818 }
01819 pathWithoutExt[pos] = '\0';
01820 OVR_sprintf(buffer, sizeof(buffer), "%s%i.xml", pathWithoutExt, LODIndex);
01821 FILE* fp = 0;
01822 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
01823 errno_t err = fopen_s(&fp, buffer, "rb");
01824 if(!fp || err)
01825 {
01826 #else
01827 fp = fopen(buffer, "rb");
01828 if(!fp)
01829 {
01830 #endif
01831 break;
01832 }
01833 fclose(fp);
01834 OVR::String result = buffer;
01835 LODFilePaths.PushBack(result);
01836 LODIndex++;
01837 }
01838 }
01839
01840 void OculusWorldDemoApp::DropLOD()
01841 {
01842 if(CurrentLODFileIndex < (int)(LODFilePaths.GetSize() - 1))
01843 {
01844 ClearScene();
01845 CurrentLODFileIndex++;
01846 PopulateScene(LODFilePaths[CurrentLODFileIndex].ToCStr());
01847 }
01848 }
01849
01850 void OculusWorldDemoApp::RaiseLOD()
01851 {
01852 if(CurrentLODFileIndex > 0)
01853 {
01854 ClearScene();
01855 CurrentLODFileIndex--;
01856 PopulateScene(LODFilePaths[CurrentLODFileIndex].ToCStr());
01857 }
01858 }
01859
01860
01861 void OculusWorldDemoApp::CycleDisplay()
01862 {
01863 int screenCount = pPlatform->GetDisplayCount();
01864
01865
01866
01867
01868 if (pRender->IsFullscreen())
01869 {
01870
01871 pPlatform->SetFullscreen(RenderParams, Display_Window);
01872
01873 Screen++;
01874 if (Screen == screenCount)
01875 Screen = 0;
01876
01877 RenderParams.Display = pPlatform->GetDisplay(Screen);
01878
01879 if (Screen != FirstScreenInCycle)
01880 {
01881 pRender->SetParams(RenderParams);
01882 pPlatform->SetFullscreen(RenderParams, Display_Fullscreen);
01883 }
01884 }
01885 else
01886 {
01887
01888 FirstScreenInCycle = 0;
01889
01890 if (pHMD)
01891 {
01892 DisplayId HMD (SConfig.GetHMDInfo().DisplayDeviceName, SConfig.GetHMDInfo().DisplayId);
01893 for (int i = 0; i< screenCount; i++)
01894 {
01895 if (pPlatform->GetDisplay(i) == HMD)
01896 {
01897 FirstScreenInCycle = i;
01898 break;
01899 }
01900 }
01901 }
01902
01903
01904 Screen = FirstScreenInCycle;
01905 RenderParams.Display = pPlatform->GetDisplay(Screen);
01906 pRender->SetParams(RenderParams);
01907 pPlatform->SetFullscreen(RenderParams, Display_Fullscreen);
01908 }
01909 }
01910
01911 void OculusWorldDemoApp::GamepadStateChanged(const GamepadState& pad)
01912 {
01913 ThePlayer.GamepadMove = Vector3f(pad.LX * pad.LX * (pad.LX > 0 ? 1 : -1),
01914 0,
01915 pad.LY * pad.LY * (pad.LY > 0 ? -1 : 1));
01916 ThePlayer.GamepadRotate = Vector3f(2 * pad.RX, -2 * pad.RY, 0);
01917 }
01918
01919
01920
01921
01922 OVR_PLATFORM_APP(OculusWorldDemoApp);