aboutsummaryrefslogtreecommitdiffstats
path: root/Samples/OculusWorldDemo
diff options
context:
space:
mode:
Diffstat (limited to 'Samples/OculusWorldDemo')
-rw-r--r--Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_OculusCube.tgabin0 -> 2699618 bytes
-rw-r--r--Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_blueCube.tgabin0 -> 270018 bytes
-rw-r--r--Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_redCube.tgabin0 -> 270018 bytes
-rw-r--r--Samples/OculusWorldDemo/Makefile135
-rw-r--r--Samples/OculusWorldDemo/Obj/Linux/Debug/i386/readme2
-rw-r--r--Samples/OculusWorldDemo/Obj/Linux/Debug/x86_64/readme2
-rw-r--r--Samples/OculusWorldDemo/Obj/Linux/Release/i386/readme2
-rw-r--r--Samples/OculusWorldDemo/Obj/Linux/Release/x86_64/readme2
-rw-r--r--Samples/OculusWorldDemo/OculusWorldDemo.cpp2390
-rw-r--r--Samples/OculusWorldDemo/OculusWorldDemo.h339
-rw-r--r--Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj.filters89
-rw-r--r--Samples/OculusWorldDemo/OculusWorldDemo_Scene.cpp399
-rw-r--r--Samples/OculusWorldDemo/OptionMenu.cpp896
-rw-r--r--Samples/OculusWorldDemo/OptionMenu.h442
-rw-r--r--Samples/OculusWorldDemo/Player.cpp226
-rw-r--r--Samples/OculusWorldDemo/Player.h48
-rw-r--r--Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj (renamed from Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj)114
-rw-r--r--Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj.filters107
-rw-r--r--Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj232
-rw-r--r--Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj.filters106
-rw-r--r--Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj232
-rw-r--r--Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj.filters106
-rw-r--r--Samples/OculusWorldDemo/Release/readme2
-rw-r--r--Samples/OculusWorldDemo/RenderProfiler.cpp99
-rw-r--r--Samples/OculusWorldDemo/RenderProfiler.h71
25 files changed, 4203 insertions, 1838 deletions
diff --git a/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_OculusCube.tga b/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_OculusCube.tga
new file mode 100644
index 0000000..be8b5de
--- /dev/null
+++ b/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_OculusCube.tga
Binary files differ
diff --git a/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_blueCube.tga b/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_blueCube.tga
new file mode 100644
index 0000000..fe4768e
--- /dev/null
+++ b/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_blueCube.tga
Binary files differ
diff --git a/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_redCube.tga b/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_redCube.tga
new file mode 100644
index 0000000..7b90b82
--- /dev/null
+++ b/Samples/OculusWorldDemo/Assets/Tuscany/Tuscany_redCube.tga
Binary files differ
diff --git a/Samples/OculusWorldDemo/Makefile b/Samples/OculusWorldDemo/Makefile
deleted file mode 100644
index 6015560..0000000
--- a/Samples/OculusWorldDemo/Makefile
+++ /dev/null
@@ -1,135 +0,0 @@
-#############################################################################
-#
-# Filename : Makefile
-# Content : Makefile for building linux OculusWorldDemo
-# Created : 2013
-# Authors : Simon Hallam and Peter Giokaris
-# Copyright : Copyright 2013 OculusVR, Inc. All Rights Reserved
-# Instruction : The g++ compiler and stdndard lib packages need to be
-# installed on the system. Navigate in a shell to the
-# directory where this Makefile is located and enter:
-#
-# make builds the release version for the
-# current architechture
-# make clean delete intermediate release object files
-# and the executabe file
-# make DEBUG=1 builds the debug version for the current
-# architechture
-# make clean DEBUG=1 deletes intermediate debug object files
-# and the executable file
-#
-# Output : Relative to the directory this Makefile lives in, executable
-# files get built at the following locations depending upon the
-# architechture of the system you are running:
-#
-# ./Release/OculusWorldDemo_i386_Release
-# ./Release/OculusWorldDemo_x86_64_Release
-# ./Release/OculusWorldDemo_i386_Debug
-# ./Release/OculusWorldDemo_x86_64_Debug
-#
-#############################################################################
-
-####### Detect system architecture
-
-SYSARCH = i386
-ifeq ($(shell uname -m),x86_64)
-SYSARCH = x86_64
-endif
-
-####### Compiler, tools and options
-
-CXX = g++
-LINK = g++
-MAKE = make
-DELETEFILE = rm -f
-DEFINES = -DQT_WEBKIT -DGL_GLEXT_PROTOTYPES
-
-####### Detect debug or release
-
-DEBUG = 0
-ifeq ($(DEBUG), 1)
- CXXFLAGS = -pipe -DDEBUG -g $(DEFINES)
- LFLAGS =
- RELEASETYPE = Debug
-else
- CXXFLAGS = -pipe -O2 $(DEFINES)
- LFLAGS = -O1
- RELEASETYPE = Release
-endif
-
-####### Paths
-
-LIBOVRPATH = ../../LibOVR
-COMMONSRCPATH = ../CommonSrc
-3RDPARTYPATH = ../../3rdParty
-INCPATH = -I. -I.. -I$(COMMONSRCPATH) -I$(LIBOVRPATH)/Include -I$(LIBOVRPATH)/Src
-OBJPATH = ./Obj/Linux/$(RELEASETYPE)/$(SYSARCH)
-CXX_BUILD = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $(OBJPATH)/
-
-####### Files
-
-LIBS = -L$(LIBOVRPATH)/Lib/Linux/$(RELEASETYPE)/$(SYSARCH) \
- -lovr \
- -ludev \
- -lpthread \
- -lGL \
- -lX11 \
- -lXinerama
-
-OBJECTS = $(OBJPATH)/OculusWorldDemo.o \
- $(OBJPATH)/Player.o \
- $(OBJPATH)/Platform.o \
- $(OBJPATH)/Linux_Platform.o \
- $(OBJPATH)/Linux_Gamepad.o \
- $(OBJPATH)/Render_Device.o \
- $(OBJPATH)/Render_GL_Device.o \
- $(OBJPATH)/Render_LoadTextureDDS.o \
- $(OBJPATH)/Render_LoadTextureTGA.o \
- $(OBJPATH)/Render_XmlSceneLoader.o
-
-TARGET = ./Release/OculusWorldDemo_$(SYSARCH)_$(RELEASETYPE)
-
-####### Rules
-
-all: $(TARGET)
-
-$(TARGET): $(LIBOVRPATH)/Lib/Linux/$(RELEASETYPE)/$(SYSARCH)/libovr.a
- $(MAKE) -C $(LIBOVRPATH) DEBUG=$(DEBUG)
-
-$(TARGET): $(OBJECTS)
- $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
-
-$(OBJPATH)/OculusWorldDemo.o: OculusWorldDemo.cpp
- $(CXX_BUILD)OculusWorldDemo.o OculusWorldDemo.cpp
-
-$(OBJPATH)/Player.o: Player.cpp
- $(CXX_BUILD)Player.o Player.cpp
-
-$(OBJPATH)/Platform.o: ../../Samples/CommonSrc/Platform/Platform.cpp
- $(CXX_BUILD)Platform.o ../../Samples/CommonSrc/Platform/Platform.cpp
-
-$(OBJPATH)/Linux_Platform.o: ../../Samples/CommonSrc/Platform/Linux_Platform.cpp
- $(CXX_BUILD)Linux_Platform.o ../../Samples/CommonSrc/Platform/Linux_Platform.cpp
-
-$(OBJPATH)/Linux_Gamepad.o: ../../Samples/CommonSrc/Platform/Linux_Gamepad.cpp
- $(CXX_BUILD)Linux_Gamepad.o ../../Samples/CommonSrc/Platform/Linux_Gamepad.cpp
-
-$(OBJPATH)/Render_Device.o: ../../Samples/CommonSrc/Render/Render_Device.cpp $
- $(CXX_BUILD)Render_Device.o ../../Samples/CommonSrc/Render/Render_Device.cpp
-
-$(OBJPATH)/Render_GL_Device.o: ../../Samples/CommonSrc/Render/Render_GL_Device.cpp
- $(CXX_BUILD)Render_GL_Device.o ../../Samples/CommonSrc/Render/Render_GL_Device.cpp
-
-$(OBJPATH)/Render_LoadTextureDDS.o: ../../Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp
- $(CXX_BUILD)Render_LoadTextureDDS.o ../../Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp
-
-$(OBJPATH)/Render_LoadTextureTGA.o: ../../Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp
- $(CXX_BUILD)Render_LoadTextureTGA.o ../../Samples/CommonSrc/Render/Render_LoadTextureTGA.cpp
-
-$(OBJPATH)/Render_XmlSceneLoader.o: ../../Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp
- $(CXX_BUILD)Render_XmlSceneLoader.o ../../Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp
-
-clean:
- -$(DELETEFILE) $(OBJECTS)
- -$(DELETEFILE) $(TARGET)
-
diff --git a/Samples/OculusWorldDemo/Obj/Linux/Debug/i386/readme b/Samples/OculusWorldDemo/Obj/Linux/Debug/i386/readme
deleted file mode 100644
index c9d0bc0..0000000
--- a/Samples/OculusWorldDemo/Obj/Linux/Debug/i386/readme
+++ /dev/null
@@ -1,2 +0,0 @@
-This document exits to ensure that the required directory structure gets created correctly.
-
diff --git a/Samples/OculusWorldDemo/Obj/Linux/Debug/x86_64/readme b/Samples/OculusWorldDemo/Obj/Linux/Debug/x86_64/readme
deleted file mode 100644
index c9d0bc0..0000000
--- a/Samples/OculusWorldDemo/Obj/Linux/Debug/x86_64/readme
+++ /dev/null
@@ -1,2 +0,0 @@
-This document exits to ensure that the required directory structure gets created correctly.
-
diff --git a/Samples/OculusWorldDemo/Obj/Linux/Release/i386/readme b/Samples/OculusWorldDemo/Obj/Linux/Release/i386/readme
deleted file mode 100644
index c9d0bc0..0000000
--- a/Samples/OculusWorldDemo/Obj/Linux/Release/i386/readme
+++ /dev/null
@@ -1,2 +0,0 @@
-This document exits to ensure that the required directory structure gets created correctly.
-
diff --git a/Samples/OculusWorldDemo/Obj/Linux/Release/x86_64/readme b/Samples/OculusWorldDemo/Obj/Linux/Release/x86_64/readme
deleted file mode 100644
index c9d0bc0..0000000
--- a/Samples/OculusWorldDemo/Obj/Linux/Release/x86_64/readme
+++ /dev/null
@@ -1,2 +0,0 @@
-This document exits to ensure that the required directory structure gets created correctly.
-
diff --git a/Samples/OculusWorldDemo/OculusWorldDemo.cpp b/Samples/OculusWorldDemo/OculusWorldDemo.cpp
index 1a81c8d..e89403f 100644
--- a/Samples/OculusWorldDemo/OculusWorldDemo.cpp
+++ b/Samples/OculusWorldDemo/OculusWorldDemo.cpp
@@ -1,10 +1,10 @@
/************************************************************************************
Filename : OculusWorldDemo.cpp
-Content : First-person view test application for Oculus Rift
+Content : First-person view test application for Oculus Rift - Implementation
Created : October 4, 2012
-Authors : Michael Antonov, Andrew Reisse, Steve LaValle
- Peter Hoff, Dan Goodman, Bryan Croteau
+Authors : Michael Antonov, Andrew Reisse, Steve LaValle, Dov Katz
+ Peter Hoff, Dan Goodman, Bryan Croteau
Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
@@ -22,286 +22,82 @@ limitations under the License.
*************************************************************************************/
-#include "OVR.h"
+#include "OculusWorldDemo.h"
-#include "../CommonSrc/Platform/Platform_Default.h"
-#include "../CommonSrc/Render/Render_Device.h"
-#include "../CommonSrc/Render/Render_XmlSceneLoader.h"
-#include "../CommonSrc/Render/Render_FontEmbed_DejaVu48.h"
-#include "../CommonSrc/Platform/Gamepad.h"
-
-#include <Kernel/OVR_SysFile.h>
-#include <Kernel/OVR_Log.h>
-#include <Kernel/OVR_Timer.h>
-
-#include "Player.h"
-
-// Filename to be loaded by default, searching specified paths.
-#define WORLDDEMO_ASSET_FILE "Tuscany.xml"
-#define WORLDDEMO_ASSET_PATH1 "Assets/Tuscany/"
-#define WORLDDEMO_ASSET_PATH2 "../Assets/Tuscany/"
-// This path allows the shortcut to work.
-#define WORLDDEMO_ASSET_PATH3 "Samples/OculusWorldDemo/Assets/Tuscany/"
-
-
-using namespace OVR;
-using namespace OVR::Platform;
-using namespace OVR::Render;
-
-//-------------------------------------------------------------------------------------
-// ***** OculusWorldDemo Description
-
-// This app renders a simple flat-shaded room allowing the user to move along the
-// floor and look around with an HMD, mouse and keyboard. The following keys work:
-//
-// 'W', 'S', 'A', 'D' and Arrow Keys - Move forward, back; strafe left/right.
-// F1 - No stereo, no distortion.
-// F2 - Stereo, no distortion.
-// F3 - Stereo and distortion.
-// F4 - Toggle MSAA.
-// F9 - Cycle through fullscreen and windowed modes. Necessary for previewing content with Rift.
-//
-// Important Oculus-specific logic can be found at following locations:
-//
-// OculusWorldDemoApp::OnStartup - This function will initialize OVR::DeviceManager and HMD,
-// creating SensorDevice and attaching it to SensorFusion.
-// This needs to be done before obtaining sensor data.
-//
-// OculusWorldDemoApp::OnIdle - Here we poll SensorFusion for orientation, apply it
-// to the scene and handle movement.
-// Stereo rendering is also done here, by delegating to
-// to Render function for each eye.
-//
-
-//-------------------------------------------------------------------------------------
-// ***** OculusWorldDemo Application class
-
-// An instance of this class is created on application startup (main/WinMain).
-// It then works as follows:
-// - Graphics and HMD setup is done OculusWorldDemoApp::OnStartup(). This function
-// also creates the room model from Slab declarations.
-// - Per-frame processing is done in OnIdle(). This function processes
-// sensor and movement input and then renders the frame.
-// - Additional input processing is done in OnMouse, OnKey.
-
-class OculusWorldDemoApp : public Application, public MessageHandler
-{
-public:
- OculusWorldDemoApp();
- ~OculusWorldDemoApp();
-
- virtual int OnStartup(int argc, const char** argv);
- virtual void OnIdle();
-
- virtual void OnMouseMove(int x, int y, int modifiers);
- virtual void OnKey(OVR::KeyCode key, int chr, bool down, int modifiers);
- virtual void OnResize(int width, int height);
-
- virtual void OnMessage(const Message& msg);
-
- void Render(const StereoEyeParams& stereo);
-
- // Sets temporarily displayed message for adjustments
- void SetAdjustMessage(const char* format, ...);
- // Overrides current timeout, in seconds (not the future default value);
- // intended to be called right after SetAdjustMessage.
- void SetAdjustMessageTimeout(float timeout);
-
- // Stereo setting adjustment functions.
- // Called with deltaTime when relevant key is held.
- void AdjustFov(float dt);
- void AdjustAspect(float dt);
- void AdjustIPD(float dt);
- void AdjustEyeHeight(float dt);
-
- void AdjustMotionPrediction(float dt);
-
- void AdjustDistortion(float dt, int kIndex, const char* label);
- void AdjustDistortionK0(float dt) { AdjustDistortion(dt, 0, "K0"); }
- void AdjustDistortionK1(float dt) { AdjustDistortion(dt, 1, "K1"); }
- void AdjustDistortionK2(float dt) { AdjustDistortion(dt, 2, "K2"); }
- void AdjustDistortionK3(float dt) { AdjustDistortion(dt, 3, "K3"); }
-
- void AdjustDistortion(float val, int kIndex);
- void AdjustEsd(float val);
-
- // Adds room model to scene.
- void PopulateScene(const char* fileName);
- void PopulatePreloadScene();
- void ClearScene();
-
- // Magnetometer calibration procedure
- void UpdateManualMagCalibration();
-
-protected:
- RenderDevice* pRender;
- RendererParams RenderParams;
- int Width, Height;
- int Screen;
- int FirstScreenInCycle;
-
- // *** Oculus HMD Variables
- Ptr<DeviceManager> pManager;
- Ptr<SensorDevice> pSensor;
- Ptr<HMDDevice> pHMD;
- Ptr<Profile> pUserProfile;
- SensorFusion SFusion;
- HMDInfo TheHMDInfo;
-
- Ptr<LatencyTestDevice> pLatencyTester;
- Util::LatencyTest LatencyUtil;
-
- double LastUpdate;
- int FPS;
- int FrameCounter;
- double NextFPSUpdate;
-
- Array<Ptr<CollisionModel> > CollisionModels;
- Array<Ptr<CollisionModel> > GroundCollisionModels;
-
- // Loading process displays screenshot in first frame
- // and then proceeds to load until finished.
- enum LoadingStateType
- {
- LoadingState_Frame0,
- LoadingState_DoLoad,
- LoadingState_Finished
- };
-
- // Player
- Player ThePlayer;
- Matrix4f View;
- Scene MainScene;
- Scene LoadingScene;
- Scene GridScene;
- Scene YawMarkGreenScene;
- Scene YawMarkRedScene;
- Scene YawLinesScene;
-
- LoadingStateType LoadingState;
-
- Ptr<ShaderFill> LitSolid, LitTextures[4];
-
- // Stereo view parameters.
- StereoConfig SConfig;
- PostProcessType PostProcess;
-
- // LOD
- String MainFilePath;
- Array<String> LODFilePaths;
- int ConsecutiveLowFPSFrames;
- int CurrentLODFileIndex;
-
- float DistortionK0;
- float DistortionK1;
- float DistortionK2;
- float DistortionK3;
-
- String AdjustMessage;
- double AdjustMessageTimeout;
-
- // Saved distortion state.
- float SavedK0, SavedK1, SavedK2, SavedK3;
- float SavedESD, SavedAspect, SavedEyeDistance;
-
- // Allows toggling color around distortion.
- Color DistortionClearColor;
-
- // Stereo settings adjustment state.
- typedef void (OculusWorldDemoApp::*AdjustFuncType)(float);
- bool ShiftDown;
- AdjustFuncType pAdjustFunc;
- float AdjustDirection;
-
- enum SceneRenderMode
- {
- Scene_World,
- Scene_Grid,
- Scene_Both,
- Scene_YawView
- };
- SceneRenderMode SceneMode;
-
-
- enum TextScreen
- {
- Text_None,
- Text_Orientation,
- Text_Config,
- Text_Help,
- Text_Count
- };
- TextScreen TextScreen;
-
- struct DeviceStatusNotificationDesc
- {
- DeviceHandle Handle;
- MessageType Action;
-
- DeviceStatusNotificationDesc():Action(Message_None) {}
- DeviceStatusNotificationDesc(MessageType mt, const DeviceHandle& dev)
- : Handle(dev), Action(mt) {}
- };
- Array<DeviceStatusNotificationDesc> DeviceStatusNotificationsQueue;
-
-
- Model* CreateModel(Vector3f pos, struct SlabModel* sm);
- Model* CreateBoundingModel(CollisionModel &cm);
- void PopulateLODFileNames();
- void DropLOD();
- void RaiseLOD();
- void CycleDisplay();
- void GamepadStateChanged(const GamepadState& pad);
-};
//-------------------------------------------------------------------------------------
+// ***** OculusWorldDemoApp
OculusWorldDemoApp::OculusWorldDemoApp()
: pRender(0),
- LastUpdate(0),
+ WindowSize(1280,800),
+ ScreenNumber(0),
+ FirstScreenInCycle(0),
+ Hmd(0),
+ StartSensorCaps(0),
+ UsingDebugHmd(false),
LoadingState(LoadingState_Frame0),
+ HaveVisionTracking(false),
+ HmdStatus(0),
+
// Initial location
- SConfig(),
- PostProcess(PostProcess_Distortion),
- DistortionClearColor(0, 0, 0),
-
+ DistortionClearBlue(0),
ShiftDown(false),
- pAdjustFunc(0),
- AdjustDirection(1.0f),
+ CtrlDown(false),
+ HmdSettingsChanged(false),
+
+ // Modifiable options.
+ RendertargetIsSharedByBothEyes(false),
+ DynamicRezScalingEnabled(false),
+ ForceZeroIpd(false),
+ DesiredPixelDensity(1.0f),
+ FovSideTanMax(1.0f), // Updated based on Hmd.
+ TimewarpEnabled(true),
+ TimewarpRenderIntervalInSeconds(0.0f),
+ FreezeEyeUpdate(false),
+ FreezeEyeOneFrameRendered(false),
+ CenterPupilDepthMeters(0.05f),
+ ForceZeroHeadMovement(false),
+ VsyncEnabled(true),
+ MultisampleEnabled(true),
+ IsLowPersistence(true),
+ DynamicPrediction(true),
+ PositionTrackingEnabled(true),
+
+ // Scene state
SceneMode(Scene_World),
- TextScreen(Text_None)
+ GridDisplayMode(GridDisplay_None),
+ GridMode(Grid_Lens),
+ TextScreen(Text_None),
+ BlocksShowType(0),
+ BlocksCenter(0.0f, 0.0f, 0.0f)
{
- Width = 1280;
- Height = 800;
- Screen = 0;
- FirstScreenInCycle = 0;
- FPS = 0;
- FrameCounter = 0;
- NextFPSUpdate = 0;
+ FPS = 0.0f;
+ SecondsPerFrame = 0.0f;
+ FrameCounter = 0;
+ LastFpsUpdate = 0;
- ConsecutiveLowFPSFrames = 0;
- CurrentLODFileIndex = 0;
-
- AdjustMessageTimeout = 0;
+ DistortionClearBlue = false;
}
OculusWorldDemoApp::~OculusWorldDemoApp()
{
- RemoveHandlerFromDevices();
+ CleanupDrawTextFont();
- if(DejaVu.fill)
+ if (Hmd)
{
- DejaVu.fill->Release();
+ ovrHmd_Destroy(Hmd);
+ Hmd = 0;
}
- pLatencyTester.Clear();
- pSensor.Clear();
- pHMD.Clear();
-
+
CollisionModels.ClearAndRelease();
GroundCollisionModels.ClearAndRelease();
+
+ ovr_Shutdown();
}
+
int OculusWorldDemoApp::OnStartup(int argc, const char** argv)
{
@@ -311,106 +107,84 @@ int OculusWorldDemoApp::OnStartup(int argc, const char** argv)
// Sensor object is created from the HMD, to ensure that it is on the
// correct device.
- pManager = *DeviceManager::Create();
+ ovr_Initialize();
- // We'll handle it's messages in this case.
- pManager->SetMessageHandler(this);
+ Hmd = ovrHmd_Create(0);
-
- pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
- if (pHMD)
+ if (!Hmd)
{
- pSensor = *pHMD->GetSensor();
-
- // This will initialize HMDInfo with information about configured IPD,
- // screen size and other variables needed for correct projection.
- // We pass HMD DisplayDeviceName into the renderer to select the
- // correct monitor in full-screen mode.
- if(pHMD->GetDeviceInfo(&TheHMDInfo))
- {
- //RenderParams.MonitorName = hmd.DisplayDeviceName;
- SConfig.SetHMDInfo(TheHMDInfo);
+ // If we didn't detect an Hmd, create a simulated one for debugging.
+ Hmd = ovrHmd_CreateDebug(ovrHmd_DK1);
+ UsingDebugHmd = true;
+ if (!Hmd)
+ { // Failed Hmd creation.
+ return 1;
}
-
- // Retrieve relevant profile settings.
- pUserProfile = pHMD->GetProfile();
- if (pUserProfile)
- {
- ThePlayer.UserEyeHeight = pUserProfile->GetEyeHeight();
- ThePlayer.EyePos.y = ThePlayer.UserEyeHeight;
- }
- }
- else
- {
- // If we didn't detect an HMD, try to create the sensor directly.
- // This is useful for debugging sensor interaction; it is not needed in
- // a shipping app.
- pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
- }
-
- // Create the Latency Tester device and assign it to the LatencyTesterUtil object.
- pLatencyTester = *pManager->EnumerateDevices<LatencyTestDevice>().CreateDevice();
- if (pLatencyTester)
- {
- LatencyUtil.SetDevice(pLatencyTester);
- }
- // Make the user aware which devices are present.
- if(pHMD == NULL && pSensor == NULL)
- {
- SetAdjustMessage("---------------------------------\nNO HMD DETECTED\nNO SENSOR DETECTED\n---------------------------------");
- }
- else if(pHMD == NULL)
- {
- SetAdjustMessage("----------------------------\nNO HMD DETECTED\n----------------------------");
- }
- else if(pSensor == NULL)
- {
- SetAdjustMessage("---------------------------------\nNO SENSOR DETECTED\n---------------------------------");
- }
- else
- {
- SetAdjustMessage("--------------------------------------------\n"
- "Press F9 for Full-Screen on Rift\n"
- "--------------------------------------------");
}
- // First message should be extra-long.
- SetAdjustMessageTimeout(10.0f);
+ // Get more details about the HMD.
+ ovrHmd_GetDesc(Hmd, &HmdDesc);
+ WindowSize = HmdDesc.Resolution;
- if(TheHMDInfo.HResolution > 0)
- {
- Width = TheHMDInfo.HResolution;
- Height = TheHMDInfo.VResolution;
- }
- if(!pPlatform->SetupWindow(Width, Height))
- {
+ // ***** Setup System Window & rendering.
+
+ if (!SetupWindowAndRendering(argc, argv))
return 1;
- }
- String Title = "Oculus World Demo";
- if(TheHMDInfo.ProductName[0])
- {
- Title += " : ";
- Title += TheHMDInfo.ProductName;
- }
- pPlatform->SetWindowTitle(Title);
+ // Initialize FovSideTanMax, which allows us to change all Fov sides at once - Fov
+ // starts at default and is clamped to this value.
+ FovSideTanLimit = FovPort::Max(HmdDesc.MaxEyeFov[0], HmdDesc.MaxEyeFov[1]).GetMaxSideTan();
+ FovSideTanMax = FovPort::Max(HmdDesc.DefaultEyeFov[0], HmdDesc.DefaultEyeFov[1]).GetMaxSideTan();
- // Report relative mouse motion in OnMouseMove
- pPlatform->SetMouseMode(Mouse_Relative);
+ PositionTrackingEnabled = (HmdDesc.Caps & ovrHmdCap_Position) ? true : false;
+
+
+ // *** Configure HMD Stereo settings.
- if(pSensor)
- {
- // We need to attach sensor to SensorFusion object for it to receive
- // body frame messages and update orientation. SFusion.GetOrientation()
- // is used in OnIdle() to orient the view.
- SFusion.AttachToSensor(pSensor);
+ CalculateHmdValues();
- SFusion.SetDelegateMessageHandler(this);
+ // Query eye height.
+ ThePlayer.UserEyeHeight = ovrHmd_GetFloat(Hmd, OVR_KEY_EYE_HEIGHT, ThePlayer.UserEyeHeight);
+ ThePlayer.BodyPos.y = ThePlayer.UserEyeHeight;
+ // Center pupil for customization; real game shouldn't need to adjust this.
+ CenterPupilDepthMeters = ovrHmd_GetFloat(Hmd, "CenterPupilDepth", 0.0f);
- SFusion.SetPredictionEnabled(true);
- }
+
+ ThePlayer.bMotionRelativeToBody = false; // Default to head-steering for DK1
+
+ if (UsingDebugHmd)
+ Menu.SetPopupMessage("NO HMD DETECTED");
+ else if (!(ovrHmd_GetSensorState(Hmd, 0.0f).StatusFlags & ovrStatus_OrientationTracked))
+ Menu.SetPopupMessage("NO SENSOR DETECTED");
+ else
+ Menu.SetPopupMessage("Press F9 for Full-Screen on Rift");
+ // Give first message 10 sec timeout, add border lines.
+ Menu.SetPopupTimeout(10.0f, true);
+
+ PopulateOptionMenu();
+
+ // *** Identify Scene File & Prepare for Loading
+
+ InitMainFilePath();
+ PopulatePreloadScene();
+
+ LastUpdate = ovr_GetTimeInSeconds();
+
+ return 0;
+}
+
+
+bool OculusWorldDemoApp::SetupWindowAndRendering(int argc, const char** argv)
+{
+ // *** Window creation
+
+ if (!pPlatform->SetupWindow(WindowSize.w, WindowSize.h))
+ return false;
+
+ // Report relative mouse motion in OnMouseMove
+ pPlatform->SetMouseMode(Mouse_Relative);
// *** Initialize Rendering
@@ -430,1332 +204,1065 @@ int OculusWorldDemoApp::OnStartup(int argc, const char** argv)
}
}
+ String title = "Oculus World Demo ";
+ title += graphics;
+
+ if (HmdDesc.ProductName[0])
+ {
+ title += " : ";
+ title += HmdDesc.ProductName;
+ }
+ pPlatform->SetWindowTitle(title);
+
// Enable multi-sampling by default.
- RenderParams.Multisample = 4;
+ RenderParams.Display = DisplayId(HmdDesc.DisplayDeviceName, HmdDesc.DisplayId);
+ RenderParams.Multisample = 1;
+ //RenderParams.Fullscreen = true;
pRender = pPlatform->SetupGraphics(OVR_DEFAULT_RENDER_DEVICE_SET,
graphics, RenderParams);
+ if (!pRender)
+ return false;
+ return true;
+}
+// Custom formatter for Timewarp interval message.
+static String FormatTimewarp(OptionVar* var)
+{
+ char buff[64];
+ float timewarpInterval = *var->AsFloat();
+ OVR_sprintf(buff, sizeof(buff), "%.1fms, %.1ffps",
+ timewarpInterval * 1000.0f,
+ ( timewarpInterval > 0.000001f ) ? 1.0f / timewarpInterval : 10000.0f);
+ return String(buff);
+}
- // *** Configure Stereo settings.
+static String FormatMaxFromSideTan(OptionVar* var)
+{
+ char buff[64];
+ float degrees = 2.0f * atan(*var->AsFloat()) * (180.0f / Math<float>::Pi);
+ OVR_sprintf(buff, sizeof(buff), "%.1f Degrees", degrees);
+ return String(buff);
+}
- SConfig.SetFullViewport(Viewport(0, 0, Width, Height));
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- // Configure proper Distortion Fit.
- // For 7" screen, fit to touch left side of the view, leaving a bit of
- // invisible screen on the top (saves on rendering cost).
- // For smaller screens (5.5"), fit to the top.
- if (TheHMDInfo.HScreenSize > 0.0f)
+void OculusWorldDemoApp::PopulateOptionMenu()
+{
+ // For shortened function member access.
+ typedef OculusWorldDemoApp OWD;
+
+ // *** Scene Content Sub-Menu
+
+ // Test
+ /*
+ Menu.AddEnum("Scene Content.EyePoseMode", &FT_EyePoseState).AddShortcutKey(Key_Y).
+ AddEnumValue("Separate Pose", 0).
+ AddEnumValue("Same Pose", 1).
+ AddEnumValue("Same Pose+TW", 2);
+ */
+
+ // Navigate between scenes.
+ Menu.AddEnum("Scene Content.Rendered Scene ';'", &SceneMode).AddShortcutKey(Key_Semicolon).
+ AddEnumValue("World", Scene_World).
+ AddEnumValue("Cubes", Scene_Cubes).
+ AddEnumValue("Oculus Cubes", Scene_OculusCubes);
+ // Animating blocks
+ Menu.AddEnum("Scene Content.Animated Blocks", &BlocksShowType).
+ AddShortcutKey(Key_B).SetNotify(this, &OWD::BlockShowChange).
+ AddEnumValue("None", 0).
+ AddEnumValue("Horizontal Circle", 1).
+ AddEnumValue("Vertical Circle", 2).
+ AddEnumValue("Bouncing Blocks", 3);
+ // Toggle grid
+ Menu.AddEnum("Scene Content.Grid Display 'G'", &GridDisplayMode).AddShortcutKey(Key_G).
+ AddEnumValue("No Grid", GridDisplay_None).
+ AddEnumValue("Grid Only", GridDisplay_GridOnly).
+ AddEnumValue("Grid And Scene", GridDisplay_GridAndScene);
+ Menu.AddEnum("Scene Content.Grid Mode 'H'", &GridMode).AddShortcutKey(Key_H).
+ AddEnumValue("4-pixel RT-centered", Grid_Rendertarget4).
+ AddEnumValue("16-pixel RT-centered",Grid_Rendertarget16).
+ AddEnumValue("Lens-centered grid", Grid_Lens);
+
+ // *** Scene Content Sub-Menu
+ Menu.AddBool( "Render Target.Share RenderTarget", &RendertargetIsSharedByBothEyes).
+ AddShortcutKey(Key_F8).SetNotify(this, &OWD::HmdSettingChange);
+ Menu.AddBool( "Render Target.Dynamic Res Scaling", &DynamicRezScalingEnabled).
+ AddShortcutKey(Key_F8, ShortcutKey::Shift_RequireOn);
+ Menu.AddBool( "Render Target.Zero IPD 'F7'", &ForceZeroIpd).
+ AddShortcutKey(Key_F7).
+ SetNotify(this, &OWD::HmdSettingChangeFreeRTs);
+ Menu.AddFloat("Render Target.Max Fov", &FovSideTanMax, 0.2f, FovSideTanLimit, 0.02f,
+ "%.1f Degrees", 1.0f, &FormatMaxFromSideTan).
+ SetNotify(this, &OWD::HmdSettingChange).
+ AddShortcutUpKey(Key_I).AddShortcutDownKey(Key_K);
+ Menu.AddFloat("Render Target.Pixel Density", &DesiredPixelDensity, 0.5f, 1.5, 0.025f, "%3.2f", 1.0f).
+ SetNotify(this, &OWD::HmdSettingChange);
+ Menu.AddEnum( "Render Target.Distortion Clear Color", &DistortionClearBlue).
+ SetNotify(this, &OWD::DistortionClearColorChange).
+ AddEnumValue("Black", 0).
+ AddEnumValue("Blue", 1);
+
+ // Timewarp
+ Menu.AddBool( "Timewarp.TimewarpEnabled 'O'", &TimewarpEnabled).AddShortcutKey(Key_O).
+ SetNotify(this, &OWD::HmdSettingChange);
+ Menu.AddBool( "Timewarp.FreezeEyeUpdate 'C'", &FreezeEyeUpdate).AddShortcutKey(Key_C);
+ Menu.AddFloat("Timewarp.RenderIntervalSeconds", &TimewarpRenderIntervalInSeconds,
+ 0.0001f, 1.00f, 0.0001f, "%.1f", 1.0f, &FormatTimewarp).
+ AddShortcutUpKey(Key_J).AddShortcutDownKey(Key_U);
+
+ // First page properties
+ Menu.AddFloat("User Eye Height", &ThePlayer.UserEyeHeight, 0.2f, 2.5f, 0.02f,
+ "%4.2f m").SetNotify(this, &OWD::EyeHeightChange).
+ AddShortcutUpKey(Key_Equal).AddShortcutDownKey(Key_Minus);
+ Menu.AddFloat("Center Pupil Depth", &CenterPupilDepthMeters, 0.0f, 0.2f, 0.001f,
+ "%4.3f m").SetNotify(this, &OWD::CenterPupilDepthChange);
+ Menu.AddBool("Body Relative Motion",&ThePlayer.bMotionRelativeToBody).AddShortcutKey(Key_E);
+ Menu.AddBool("Zero Head Movement", &ForceZeroHeadMovement) .AddShortcutKey(Key_F7, ShortcutKey::Shift_RequireOn);
+ Menu.AddBool("VSync 'V'", &VsyncEnabled) .AddShortcutKey(Key_V).SetNotify(this, &OWD::HmdSettingChange);
+ Menu.AddBool("MultiSample 'F4'", &MultisampleEnabled) .AddShortcutKey(Key_F4).SetNotify(this, &OWD::MultisampleChange);
+
+ // Add DK2 options to menu only for that headset.
+ if (HmdDesc.Caps & ovrHmdCap_Position)
{
- if (TheHMDInfo.HScreenSize > 0.140f) // 7"
- SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
- else
- SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
+ Menu.AddBool("Low Persistence 'P'", &IsLowPersistence).
+ AddShortcutKey(Key_P).SetNotify(this, &OWD::HmdSettingChange);
+ Menu.AddBool("Dynamic Prediction", &DynamicPrediction).
+ SetNotify(this, &OWD::HmdSettingChange);
+ Menu.AddBool("Positional Tracking 'X'", &PositionTrackingEnabled).
+ AddShortcutKey(Key_X).SetNotify(this, &OWD::HmdSettingChange);
}
+}
- pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
- //pRender->SetSceneRenderScale(1.0f);
- SConfig.Set2DAreaFov(DegreeToRad(85.0f));
+void OculusWorldDemoApp::CalculateHmdValues()
+{
+ // Initialize eye rendering information for ovrHmd_Configure.
+ // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations.
+ ovrEyeDesc eyes[2];
+ eyes[0].Eye = ovrEye_Left;
+ eyes[1].Eye = ovrEye_Right;
+ eyes[0].Fov = HmdDesc.DefaultEyeFov[0];
+ eyes[1].Fov = HmdDesc.DefaultEyeFov[1];
+ // Clamp Fov based on our dynamically adjustable FovSideTanMax.
+ // Most apps should use the default, but reducing Fov does reduce rendering cost.
+ eyes[0].Fov = FovPort::Min(eyes[0].Fov, FovPort(FovSideTanMax));
+ eyes[1].Fov = FovPort::Min(eyes[1].Fov, FovPort(FovSideTanMax));
- // *** Identify Scene File & Prepare for Loading
-
- // This creates lights and models.
- if (argc == 2)
- {
- MainFilePath = argv[1];
- PopulateLODFileNames();
+
+ if (ForceZeroIpd)
+ {
+ // ForceZeroIpd does three things:
+ // 1) Sets FOV to maximum symmetrical FOV based on both eyes
+ // 2) Sets eye ViewAdjust values to 0.0 (effective IPD == 0)
+ // 3) Uses only the Left texture for rendering.
+
+ eyes[0].Fov = FovPort::Max(eyes[0].Fov, eyes[1].Fov);
+ eyes[1].Fov = eyes[0].Fov;
+
+ Sizei recommenedTexSize = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left,
+ eyes[0].Fov, DesiredPixelDensity);
+
+ eyes[0].TextureSize = EnsureRendertargetAtLeastThisBig(Rendertarget_Left, recommenedTexSize);
+ eyes[1].TextureSize = eyes[0].TextureSize;
+ eyes[0].RenderViewport.Pos = Vector2i(0,0);
+ eyes[0].RenderViewport.Size = Sizei::Min(eyes[0].TextureSize, recommenedTexSize);
+ eyes[1].RenderViewport = eyes[0].RenderViewport;
+
+ // Store texture pointers that will be passed for rendering.
+ EyeTexture[0] = RenderTargets[Rendertarget_Left].Tex;
+ EyeTexture[1] = RenderTargets[Rendertarget_Left].Tex;
}
+
else
{
- fprintf(stderr, "Usage: OculusWorldDemo [input XML]\n");
- MainFilePath = WORLDDEMO_ASSET_FILE;
+ // Configure Stereo settings. Default pixel density is 1.0f.
+ Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left, eyes[0].Fov, DesiredPixelDensity);
+ Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Right, eyes[1].Fov, DesiredPixelDensity);
+
+ if (RendertargetIsSharedByBothEyes)
+ {
+ Sizei rtSize(recommenedTex0Size.w + recommenedTex1Size.w,
+ Alg::Max(recommenedTex0Size.h, recommenedTex1Size.h));
+
+ // Use returned size as the actual RT size may be different due to HW limits.
+ rtSize = EnsureRendertargetAtLeastThisBig(Rendertarget_BothEyes, rtSize);
+
+ // Don't draw more then recommended size; this also ensures that resolution reported
+ // in the overlay HUD size is updated correctly for FOV/pixel density change.
+ Sizei leftSize = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex0Size);
+ Sizei rightSize = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex1Size);
+
+ eyes[0].TextureSize = rtSize;
+ eyes[1].TextureSize = rtSize;
+ eyes[0].RenderViewport = Recti(Vector2i(0), leftSize);
+ eyes[1].RenderViewport = Recti(Vector2i((rtSize.w+1)/2, 0), rightSize);
+
+ // Store texture pointers that will be passed for rendering.
+ // Same texture is used, but with different viewports.
+ EyeTexture[0] = RenderTargets[Rendertarget_BothEyes].Tex;
+ EyeTexture[1] = RenderTargets[Rendertarget_BothEyes].Tex;
+ EyeTexture[0].Header.RenderViewport = eyes[0].RenderViewport;
+ EyeTexture[1].Header.RenderViewport = eyes[1].RenderViewport;
+ }
+
+ else
+ {
+ eyes[0].TextureSize = EnsureRendertargetAtLeastThisBig(Rendertarget_Left, recommenedTex0Size);
+ eyes[1].TextureSize = EnsureRendertargetAtLeastThisBig(Rendertarget_Right, recommenedTex1Size);
+ eyes[0].RenderViewport = Recti(Sizei::Min(eyes[0].TextureSize, recommenedTex0Size));
+ eyes[1].RenderViewport = Recti(Sizei::Min(eyes[1].TextureSize, recommenedTex1Size));
+
+ // Store texture pointers that will be passed for rendering.
+ EyeTexture[0] = RenderTargets[Rendertarget_Left].Tex;
+ EyeTexture[1] = RenderTargets[Rendertarget_Right].Tex;
+ }
}
- // Try to modify path for correctness in case specified file is not found.
- if (!SysFile(MainFilePath).IsValid())
+
+ unsigned hmdCaps = ovrHmdCap_Orientation | (VsyncEnabled ? 0 : ovrHmdCap_NoVSync);
+ unsigned distortionCaps = ovrDistortion_Chromatic;
+
+ ovrRenderAPIConfig config = pRender->Get_ovrRenderAPIConfig();
+
+ if (TimewarpEnabled)
+ distortionCaps |= ovrDistortion_TimeWarp;
+
+ if (!ovrHmd_ConfigureRendering( Hmd, &config, hmdCaps, distortionCaps,
+ eyes, EyeRenderDesc ))
{
- String prefixPath1(pPlatform->GetContentDirectory() + "/" + WORLDDEMO_ASSET_PATH1),
- prefixPath2(WORLDDEMO_ASSET_PATH2),
- prefixPath3(WORLDDEMO_ASSET_PATH3);
- if (SysFile(prefixPath1 + MainFilePath).IsValid())
- MainFilePath = prefixPath1 + MainFilePath;
- else if (SysFile(prefixPath2 + MainFilePath).IsValid())
- MainFilePath = prefixPath2 + MainFilePath;
- else if (SysFile(prefixPath3 + MainFilePath).IsValid())
- MainFilePath = prefixPath3 + MainFilePath;
+ // Fail exit? TBD
+ return;
}
- PopulatePreloadScene();
+ if (ForceZeroIpd)
+ {
+ // Remove IPD adjust
+ EyeRenderDesc[0].ViewAdjust = Vector3f(0);
+ EyeRenderDesc[1].ViewAdjust = Vector3f(0);
+ }
- LastUpdate = pPlatform->GetAppTime();
- //pPlatform->PlayMusicFile(L"Loop.wav");
+ // ovrHmdCap_LatencyTest - enables internal latency feedback
+ unsigned sensorCaps = ovrHmdCap_Orientation|ovrHmdCap_YawCorrection|ovrHmdCap_LatencyTest;
+ if (PositionTrackingEnabled)
+ sensorCaps |= ovrHmdCap_Position;
+ if (IsLowPersistence)
+ sensorCaps |= ovrHmdCap_LowPersistence;
+ if (DynamicPrediction)
+ sensorCaps |= ovrHmdCap_DynamicPrediction;
- return 0;
+ if (StartSensorCaps != sensorCaps)
+ {
+ ovrHmd_StartSensor(Hmd, sensorCaps, 0);
+ StartSensorCaps = sensorCaps;
+ }
+
+ // Calculate projections
+ Projection[0] = ovrMatrix4f_Projection(EyeRenderDesc[0].Desc.Fov, 0.01f, 10000.0f, true);
+ Projection[1] = ovrMatrix4f_Projection(EyeRenderDesc[1].Desc.Fov, 0.01f, 10000.0f, true);
+
+ float orthoDistance = 0.8f; // 2D is 0.8 meter from camera
+ Vector2f orthoScale0 = Vector2f(1.0f) / Vector2f(EyeRenderDesc[0].PixelsPerTanAngleAtCenter);
+ Vector2f orthoScale1 = Vector2f(1.0f) / Vector2f(EyeRenderDesc[1].PixelsPerTanAngleAtCenter);
+
+ OrthoProjection[0] = ovrMatrix4f_OrthoSubProjection(Projection[0], orthoScale0, orthoDistance,
+ EyeRenderDesc[0].ViewAdjust.x);
+ OrthoProjection[1] = ovrMatrix4f_OrthoSubProjection(Projection[1], orthoScale1, orthoDistance,
+ EyeRenderDesc[1].ViewAdjust.x);
}
-void OculusWorldDemoApp::OnMessage(const Message& msg)
+
+
+// Returns the actual size present.
+Sizei OculusWorldDemoApp::EnsureRendertargetAtLeastThisBig(int rtNum, Sizei requestedSize)
{
- if (msg.Type == Message_DeviceAdded || msg.Type == Message_DeviceRemoved)
+ OVR_ASSERT((rtNum >= 0) && (rtNum < Rendertarget_LAST));
+
+ // Texture size that we already have might be big enough.
+ Sizei newRTSize;
+
+ RenderTarget& rt = RenderTargets[rtNum];
+ if (!rt.pTex)
{
- if (msg.pDevice == pManager)
- {
- const MessageDeviceStatus& statusMsg =
- static_cast<const MessageDeviceStatus&>(msg);
+ // Hmmm... someone nuked my texture. Rez change or similar. Make sure we reallocate.
+ rt.Tex.Header.TextureSize = Sizei(0);
+ newRTSize = requestedSize;
+ }
+ else
+ {
+ newRTSize = rt.Tex.Header.TextureSize;
+ }
- { // limit the scope of the lock
- Lock::Locker lock(pManager->GetHandlerLock());
- DeviceStatusNotificationsQueue.PushBack(
- DeviceStatusNotificationDesc(statusMsg.Type, statusMsg.Handle));
- }
+ // %50 linear growth each time is a nice balance between being too greedy
+ // for a 2D surface and too slow to prevent fragmentation.
+ while ( newRTSize.w < requestedSize.w )
+ {
+ newRTSize.w += newRTSize.w/2;
+ }
+ while ( newRTSize.h < requestedSize.h )
+ {
+ newRTSize.h += newRTSize.h/2;
+ }
- switch (statusMsg.Type)
- {
- case OVR::Message_DeviceAdded:
- LogText("DeviceManager reported device added.\n");
- break;
-
- case OVR::Message_DeviceRemoved:
- LogText("DeviceManager reported device removed.\n");
- break;
-
- default: OVR_ASSERT(0); // unexpected type
- }
- }
+ // Put some sane limits on it. 4k x 4k is fine for most modern video cards.
+ // Nobody should be messing around with surfaces smaller than 4k pixels these days.
+ newRTSize = Sizei::Max(Sizei::Min(newRTSize, Sizei(4096)), Sizei(64));
+
+ // Does that require actual reallocation?
+ if (Sizei(rt.Tex.Header.TextureSize) != newRTSize)
+ {
+ rt.pTex = *pRender->CreateTexture(Texture_RGBA | Texture_RenderTarget | (MultisampleEnabled ? 4 : 1),
+ newRTSize.w, newRTSize.h, NULL);
+ rt.pTex->SetSampleMode(Sample_ClampBorder | Sample_Linear);
+
+
+ // Configure texture for SDK Rendering.
+ rt.Tex = rt.pTex->Get_ovrTexture();
}
+
+ return newRTSize;
}
+
+//-----------------------------------------------------------------------------
+// ***** Message Handlers
+
void OculusWorldDemoApp::OnResize(int width, int height)
{
- Width = width;
- Height = height;
- SConfig.SetFullViewport(Viewport(0, 0, Width, Height));
+ WindowSize = Sizei(width, height);
+ // Re-calculate?
}
void OculusWorldDemoApp::OnMouseMove(int x, int y, int modifiers)
{
+ OVR_UNUSED(y);
if(modifiers & Mod_MouseRelative)
{
// Get Delta
- int dx = x, dy = y;
-
- const float maxPitch = ((3.1415f / 2) * 0.98f);
+ int dx = x;
// Apply to rotation. Subtract for right body frame rotation,
// since yaw rotation is positive CCW when looking down on XZ plane.
- ThePlayer.EyeYaw -= (Sensitivity * dx) / 360.0f;
-
- if(!pSensor)
- {
- ThePlayer.EyePitch -= (Sensitivity * dy) / 360.0f;
-
- if(ThePlayer.EyePitch > maxPitch)
- {
- ThePlayer.EyePitch = maxPitch;
- }
- if(ThePlayer.EyePitch < -maxPitch)
- {
- ThePlayer.EyePitch = -maxPitch;
- }
- }
+ ThePlayer.BodyYaw -= (Sensitivity * dx) / 360.0f;
}
}
void OculusWorldDemoApp::OnKey(OVR::KeyCode key, int chr, bool down, int modifiers)
{
- OVR_UNUSED(chr);
+ if (Menu.OnKey(key, chr, down, modifiers))
+ return;
+
+ // Handle player movement keys.
+ if (ThePlayer.HandleMoveKey(key, down))
+ return;
switch(key)
{
case Key_Q:
if (down && (modifiers & Mod_Control))
- {
pPlatform->Exit(0);
- }
- break;
-
- // Handle player movement keys.
- // We just update movement state here, while the actual translation is done in OnIdle()
- // based on time.
- case Key_W:
- ThePlayer.MoveForward = down ? (ThePlayer.MoveForward | 1) : (ThePlayer.MoveForward & ~1);
- break;
- case Key_S:
- ThePlayer.MoveBack = down ? (ThePlayer.MoveBack | 1) : (ThePlayer.MoveBack & ~1);
- break;
- case Key_A:
- ThePlayer.MoveLeft = down ? (ThePlayer.MoveLeft | 1) : (ThePlayer.MoveLeft & ~1);
- break;
- case Key_D:
- ThePlayer.MoveRight = down ? (ThePlayer.MoveRight | 1) : (ThePlayer.MoveRight & ~1);
- break;
- case Key_Up:
- ThePlayer.MoveForward = down ? (ThePlayer.MoveForward | 2) : (ThePlayer.MoveForward & ~2);
- break;
- case Key_Down:
- ThePlayer.MoveBack = down ? (ThePlayer.MoveBack | 2) : (ThePlayer.MoveBack & ~2);
- break;
- case Key_Left:
- ThePlayer.MoveLeft = down ? (ThePlayer.MoveLeft | 2) : (ThePlayer.MoveLeft & ~2);
break;
- case Key_Right:
- ThePlayer.MoveRight = down ? (ThePlayer.MoveRight | 2) : (ThePlayer.MoveRight & ~2);
- break;
-
- case Key_Minus:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustEyeHeight : 0;
- AdjustDirection = -1;
- break;
- case Key_Equal:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustEyeHeight : 0;
- AdjustDirection = 1;
- break;
-
- case Key_B:
- if (down)
- {
- if(SConfig.GetDistortionScale() == 1.0f)
- {
- if(SConfig.GetHMDInfo().HScreenSize > 0.140f) // 7"
- {
- SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
- }
- else
- {
- SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
- }
- }
- else
- {
- // No fitting; scale == 1.0.
- SConfig.SetDistortionFitPointVP(0, 0);
- }
- }
- break;
-
- // Support toggling background color for distortion so that we can see
- // the effect on the periphery.
- case Key_V:
- if (down)
- {
- if(DistortionClearColor.B == 0)
- {
- DistortionClearColor = Color(0, 128, 255);
- }
- else
- {
- DistortionClearColor = Color(0, 0, 0);
- }
-
- pRender->SetDistortionClearColor(DistortionClearColor);
- }
- break;
-
-
- case Key_F1:
- SConfig.SetStereoMode(Stereo_None);
- PostProcess = PostProcess_None;
- SetAdjustMessage("StereoMode: None");
- break;
- case Key_F2:
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_None;
- SetAdjustMessage("StereoMode: Stereo + No Distortion");
- break;
- case Key_F3:
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_Distortion;
- SetAdjustMessage("StereoMode: Stereo + Distortion");
- break;
-
- case Key_R:
- SFusion.Reset();
- SetAdjustMessage("Sensor Fusion Reset");
- break;
-
- case Key_Space:
- if (!down)
- {
- TextScreen = (enum TextScreen)((TextScreen + 1) % Text_Count);
- }
+
+ case Key_Escape:
+ // Back to primary windowed
+ if (!down) ChangeDisplay ( true, false, false );
break;
- case Key_F4:
- if (!down)
- {
- RenderParams = pRender->GetParams();
- RenderParams.Multisample = RenderParams.Multisample > 1 ? 1 : 4;
- pRender->SetParams(RenderParams);
- if(RenderParams.Multisample > 1)
- {
- SetAdjustMessage("Multisampling On");
- }
- else
- {
- SetAdjustMessage("Multisampling Off");
- }
- }
- break;
case Key_F9:
-#ifndef OVR_OS_LINUX // On Linux F9 does the same as F11.
- if (!down)
- {
- CycleDisplay();
- }
+#ifndef OVR_OS_LINUX
+ // Cycle through displays, going fullscreen on each one.
+ if (!down) ChangeDisplay ( false, true, false );
break;
+#else
+ // On Linux, fallthrough to F10/F11
#endif
+
#ifdef OVR_OS_MAC
- case Key_F10: // F11 is reserved on Mac
+ // F11 is reserved on Mac, F10 doesn't work on Windows
+ case Key_F10:
#else
case Key_F11:
#endif
+ if (!down) ChangeDisplay ( false, false, true );
+ break;
+
+ case Key_R:
if (!down)
{
- RenderParams = pRender->GetParams();
- RenderParams.Display = DisplayId(SConfig.GetHMDInfo().DisplayDeviceName,SConfig.GetHMDInfo().DisplayId);
- pRender->SetParams(RenderParams);
-
- pPlatform->SetMouseMode(Mouse_Normal);
- pPlatform->SetFullscreen(RenderParams, pRender->IsFullscreen() ? Display_Window : Display_FakeFullscreen);
- pPlatform->SetMouseMode(Mouse_Relative); // Avoid mode world rotation jump.
- // If using an HMD, enable post-process (for distortion) and stereo.
- if(RenderParams.IsDisplaySet() && pRender->IsFullscreen())
- {
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_Distortion;
- }
+ ovrHmd_ResetSensor(Hmd);
+ Menu.SetPopupMessage("Sensor Fusion Reset");
}
break;
- case Key_Escape:
- if(!down)
+ case Key_Space:
+ if (!down)
{
- // switch to primary screen windowed mode
- pPlatform->SetFullscreen(RenderParams, Display_Window);
- RenderParams.Display = pPlatform->GetDisplay(0);
- pRender->SetParams(RenderParams);
- Screen = 0;
+ TextScreen = (enum TextScreen)((TextScreen + 1) % Text_Count);
}
break;
- // Stereo adjustments.
- case Key_BracketLeft:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustFov : 0;
- AdjustDirection = 1;
- break;
- case Key_BracketRight:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustFov : 0;
- AdjustDirection = -1;
- break;
-
- case Key_Insert:
- case Key_Num0:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustIPD : 0;
- AdjustDirection = 1;
+ // Distortion correction adjustments
+ case Key_Backslash:
break;
- case Key_Delete:
- case Key_Num9:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustIPD : 0;
- AdjustDirection = -1;
- break;
-
- case Key_PageUp:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustAspect : 0;
- AdjustDirection = 1;
- break;
- case Key_PageDown:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustAspect : 0;
- AdjustDirection = -1;
- break;
-
- // Distortion correction adjustments
- case Key_H:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK0 : NULL;
- AdjustDirection = -1;
- break;
- case Key_Y:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK0 : NULL;
- AdjustDirection = 1;
- break;
- case Key_J:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK1 : NULL;
- AdjustDirection = -1;
- break;
- case Key_U:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK1 : NULL;
- AdjustDirection = 1;
- break;
- case Key_K:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK2 : NULL;
- AdjustDirection = -1;
- break;
- case Key_I:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK2 : NULL;
- AdjustDirection = 1;
- break;
- case Key_L:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK3 : NULL;
- AdjustDirection = -1;
- break;
- case Key_O:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustDistortionK3 : NULL;
- AdjustDirection = 1;
- break;
-
- case Key_Tab:
- if (down)
- {
- float t0 = SConfig.GetDistortionK(0),
- t1 = SConfig.GetDistortionK(1),
- t2 = SConfig.GetDistortionK(2),
- t3 = SConfig.GetDistortionK(3);
- float tESD = SConfig.GetEyeToScreenDistance(),
- taspect = SConfig.GetAspectMultiplier(),
- tipd = SConfig.GetIPD();
-
- if(SavedK0 > 0.0f)
- {
- SConfig.SetDistortionK(0, SavedK0);
- SConfig.SetDistortionK(1, SavedK1);
- SConfig.SetDistortionK(2, SavedK2);
- SConfig.SetDistortionK(3, SavedK3);
- SConfig.SetEyeToScreenDistance(SavedESD);
- SConfig.SetAspectMultiplier(SavedAspect);
- SConfig.SetIPD(SavedEyeDistance);
-
- if ( ShiftDown )
- {
- // Swap saved and current values. Good for doing direct comparisons.
- SetAdjustMessage("Swapped current and saved. New settings:\n"
- "ESD:\t120 %.3f\t350 Eye:\t490 %.3f\n"
- "K0: \t120 %.4f\t350 K2: \t490 %.4f\n"
- "K1: \t120 %.4f\t350 K3: \t490 %.4f\n",
- SavedESD, SavedEyeDistance,
- SavedK0, SavedK2,
- SavedK1, SavedK3);
- SavedK0 = t0;
- SavedK1 = t1;
- SavedK2 = t2;
- SavedK3 = t3;
- SavedESD = tESD;
- SavedAspect = taspect;
- SavedEyeDistance = tipd;
- }
- else
- {
- SetAdjustMessage("Restored:\n"
- "ESD:\t120 %.3f\t350 Eye:\t490 %.3f\n"
- "K0: \t120 %.4f\t350 K2: \t490 %.4f\n"
- "K1: \t120 %.4f\t350 K3: \t490 %.4f\n",
- SavedESD, SavedEyeDistance,
- SavedK0, SavedK2,
- SavedK1, SavedK3);
- }
- }
- else
- {
- SetAdjustMessage("Setting Saved");
- SavedK0 = t0;
- SavedK1 = t1;
- SavedK2 = t2;
- SavedK3 = t3;
- SavedESD = tESD;
- SavedAspect = taspect;
- SavedEyeDistance = tipd;
- }
-
- }
- break;
-
- case Key_G:
- if (down)
- {
- if(SceneMode == Scene_World)
- {
- SceneMode = Scene_Grid;
- SetAdjustMessage("Grid Only");
- }
- else if(SceneMode == Scene_Grid)
- {
- SceneMode = Scene_Both;
- SetAdjustMessage("Grid Overlay");
- }
- else if(SceneMode == Scene_Both)
- {
- SceneMode = Scene_World;
- SetAdjustMessage("Grid Off");
- }
- }
- break;
-
// Holding down Shift key accelerates adjustment velocity.
case Key_Shift:
ShiftDown = down;
break;
-
- // Reset the camera position in case we get stuck
- case Key_T:
- ThePlayer.EyePos = Vector3f(10.0f, ThePlayer.UserEyeHeight, 10.0f);
+ case Key_Control:
+ CtrlDown = down;
break;
- case Key_F5:
- if (!down)
+ // Reset the camera position in case we get stuck
+ case Key_T:
+ if (down)
{
- UPInt numNodes = MainScene.Models.GetSize();
- for(UPInt i = 0; i < numNodes; i++)
+ struct {
+ float x, z;
+ float YawDegrees;
+ } Positions[] =
{
- Ptr<OVR::Render::Model> nodePtr = MainScene.Models[i];
- Render::Model* pNode = nodePtr.GetPtr();
- if(pNode->IsCollisionModel)
- {
- pNode->Visible = !pNode->Visible;
- }
- }
+ // x z Yaw
+ { 7.7f, -1.0f, 180.0f }, // The starting position.
+ { 10.0f, 10.0f, 90.0f }, // Outside, looking at some trees.
+ { 19.26f, 5.43f, 22.0f }, // Outside, looking at the fountain.
+ };
+
+ static int nextPosition = 0;
+ nextPosition = (nextPosition + 1) % (sizeof(Positions)/sizeof(Positions[0]));
+
+ ThePlayer.BodyPos = Vector3f(Positions[nextPosition].x,
+ ThePlayer.UserEyeHeight, Positions[nextPosition].z);
+ ThePlayer.BodyYaw = DegreeToRad( Positions[nextPosition].YawDegrees );
}
break;
- case Key_N:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustMotionPrediction : NULL;
- AdjustDirection = -1;
+ case Key_Num1:
+ ThePlayer.BodyPos = Vector3f(-1.85f, 6.0f, -0.52f);
+ ThePlayer.BodyPos.y += ThePlayer.UserEyeHeight;
+ ThePlayer.BodyYaw = 3.1415f / 2;
+ ThePlayer.HandleMovement(0, &CollisionModels, &GroundCollisionModels, ShiftDown);
break;
- case Key_M:
- pAdjustFunc = down ? &OculusWorldDemoApp::AdjustMotionPrediction : NULL;
- AdjustDirection = 1;
+ default:
break;
+ }
+}
-/*
- case Key_N:
- RaiseLOD();
- break;
- case Key_M:
- DropLOD();
- break;
-*/
+//-----------------------------------------------------------------------------
- // Cycle through drift correction options
- case Key_Z:
- if (down)
- {
- if (SFusion.IsYawCorrectionEnabled())
- {
- SFusion.SetGravityEnabled(false);
- SFusion.SetYawCorrectionEnabled(false);
- }
- else if (SFusion.IsGravityEnabled())
- {
- SFusion.SetYawCorrectionEnabled(true);
- }
- else
- {
- SFusion.SetGravityEnabled(true);
- }
- SetAdjustMessage("Tilt Correction %s\nYaw Correction %s",
- SFusion.IsGravityEnabled() ? "On" : "Off",
- SFusion.IsYawCorrectionEnabled() ? "On" : "Off");
- }
- break;
- // Show view of yaw angles (for mag calibration/analysis)
- case Key_F6:
- if (down)
- {
- if (SceneMode != Scene_YawView)
- {
- SceneMode = Scene_YawView;
- SetAdjustMessage("Magnetometer Yaw Angle Marks");
- }
- else
- {
- SceneMode = Scene_World;
- SetAdjustMessage("Magnetometer Marks Off");
- }
- }
- break;
+Matrix4f OculusWorldDemoApp::CalculateViewFromPose(const Posef& pose)
+{
+ Posef worldPose = ThePlayer.VirtualWorldPoseFromRealPose(pose);
- case Key_C:
- if (down)
- {
- // Toggle chromatic aberration correction on/off.
- RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
+ // Rotate and position View Camera
+ Vector3f up = worldPose.Orientation.Rotate(UpVector);
+ Vector3f forward = worldPose.Orientation.Rotate(ForwardVector);
- if (shader == RenderDevice::PostProcessShader_Distortion)
- {
- pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
- SetAdjustMessage("Chromatic Aberration Correction On");
- }
- else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
- {
- pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
- SetAdjustMessage("Chromatic Aberration Correction Off");
- }
- else
- OVR_ASSERT(false);
- }
- break;
+ // Transform the position of the center eye in the real world (i.e. sitting in your chair)
+ // into the frame of the player's virtual body.
- case Key_P:
- if (down)
- {
- // Toggle motion prediction.
- if (SFusion.IsPredictionEnabled())
- {
- SFusion.SetPredictionEnabled(false);
- SetAdjustMessage("Motion Prediction Off");
- }
- else
- {
- SFusion.SetPredictionEnabled(true);
- SetAdjustMessage("Motion Prediction On");
- }
- }
- break;
- default:
- break;
- }
+ // It is important to have head movement in scale with IPD.
+ // If you shrink one, you should also shrink the other.
+ // So with zero IPD (i.e. everything at infinity),
+ // head movement should also be zero.
+ Vector3f viewPos = ForceZeroHeadMovement ? ThePlayer.BodyPos : worldPose.Position;
+
+ Matrix4f view = Matrix4f::LookAtRH(viewPos, viewPos + forward, up);
+ return view;
}
+
+
void OculusWorldDemoApp::OnIdle()
{
+ double curtime = ovr_GetTimeInSeconds();
+ // If running slower than 10fps, clamp. Helps when debugging, because then dt can be minutes!
+ float dt = Alg::Min<float>(float(curtime - LastUpdate), 0.1f);
+ LastUpdate = curtime;
- double curtime = pPlatform->GetAppTime();
- float dt = float(curtime - LastUpdate);
- LastUpdate = curtime;
-
- // Update gamepad.
- GamepadState gamepadState;
- if (GetPlatformCore()->GetGamepadManager()->GetGamepadState(0, &gamepadState))
- {
- GamepadStateChanged(gamepadState);
- }
+ Profiler.RecordSample(RenderProfiler::Sample_FrameStart);
if (LoadingState == LoadingState_DoLoad)
{
PopulateScene(MainFilePath.ToCStr());
LoadingState = LoadingState_Finished;
return;
- }
-
- // Check if any new devices were connected.
- {
- bool queueIsEmpty = false;
- while (!queueIsEmpty)
- {
- DeviceStatusNotificationDesc desc;
-
- {
- Lock::Locker lock(pManager->GetHandlerLock());
- if (DeviceStatusNotificationsQueue.GetSize() == 0)
- break;
- desc = DeviceStatusNotificationsQueue.Front();
-
- // We can't call Clear under the lock since this may introduce a dead lock:
- // this thread is locked by HandlerLock and the Clear might cause
- // call of Device->Release, which will use Manager->DeviceLock. The bkg
- // thread is most likely locked by opposite way:
- // Manager->DeviceLock ==> HandlerLock, therefore - a dead lock.
- // So, just grab the first element, save a copy of it and remove
- // the element (Device->Release won't be called since we made a copy).
-
- DeviceStatusNotificationsQueue.RemoveAt(0);
- queueIsEmpty = (DeviceStatusNotificationsQueue.GetSize() == 0);
- }
-
- bool wasAlreadyCreated = desc.Handle.IsCreated();
-
- if (desc.Action == Message_DeviceAdded)
- {
- switch(desc.Handle.GetType())
- {
- case Device_Sensor:
- if (desc.Handle.IsAvailable() && !desc.Handle.IsCreated())
- {
- if (!pSensor)
- {
- pSensor = *desc.Handle.CreateDeviceTyped<SensorDevice>();
- if (pSensor)
- {
- SFusion.AttachToSensor(pSensor);
-
- SetAdjustMessage("---------------------------\n"
- "SENSOR connected\n"
- "---------------------------");
- }
- else
- {
- SetAdjustMessage("----------------------------\n"
- "SENSOR connect failed\n"
- "Unplug and reconnect it.\n"
- "----------------------------");
- }
- }
- else if (!wasAlreadyCreated)
- {
- LogText("A new SENSOR has been detected, but it is not currently used.");
- }
- }
- break;
- case Device_LatencyTester:
- if (desc.Handle.IsAvailable() && !desc.Handle.IsCreated())
- {
- if (!pLatencyTester)
- {
- pLatencyTester = *desc.Handle.CreateDeviceTyped<LatencyTestDevice>();
- LatencyUtil.SetDevice(pLatencyTester);
- if (!wasAlreadyCreated)
- SetAdjustMessage("----------------------------------------\n"
- "LATENCY TESTER connected\n"
- "----------------------------------------");
- }
- }
- break;
- case Device_HMD:
- {
- OVR::HMDInfo info;
- desc.Handle.GetDeviceInfo(&info);
- // if strlen(info.DisplayDeviceName) == 0 then
- // this HMD is 'fake' (created using sensor).
- if (strlen(info.DisplayDeviceName) > 0 && (!pHMD || !info.IsSameDisplay(TheHMDInfo)))
- {
- SetAdjustMessage("------------------------\n"
- "HMD connected\n"
- "------------------------");
- if (!pHMD || !desc.Handle.IsDevice(pHMD))
- pHMD = *desc.Handle.CreateDeviceTyped<HMDDevice>();
- // update stereo config with new HMDInfo
- if (pHMD && pHMD->GetDeviceInfo(&TheHMDInfo))
- {
- //RenderParams.MonitorName = hmd.DisplayDeviceName;
- SConfig.SetHMDInfo(TheHMDInfo);
- }
- LogText("HMD device added.\n");
- }
- break;
- }
- default:;
- }
- }
- else if (desc.Action == Message_DeviceRemoved)
- {
- if (desc.Handle.IsDevice(pSensor))
- {
- LogText("Sensor reported device removed.\n");
- SFusion.AttachToSensor(NULL);
- pSensor.Clear();
- SetAdjustMessage("-------------------------------\n"
- "SENSOR disconnected.\n"
- "-------------------------------");
- }
- else if (desc.Handle.IsDevice(pLatencyTester))
- {
- LogText("Latency Tester reported device removed.\n");
- LatencyUtil.SetDevice(NULL);
- pLatencyTester.Clear();
- SetAdjustMessage("---------------------------------------------\n"
- "LATENCY SENSOR disconnected.\n"
- "---------------------------------------------");
- }
- else if (desc.Handle.IsDevice(pHMD))
- {
- if (pHMD && !pHMD->IsDisconnected())
- {
- SetAdjustMessage("---------------------------\n"
- "HMD disconnected\n"
- "---------------------------");
- // Disconnect HMD. pSensor is used to restore 'fake' HMD device
- // (can be NULL).
- pHMD = pHMD->Disconnect(pSensor);
-
- // This will initialize TheHMDInfo with information about configured IPD,
- // screen size and other variables needed for correct projection.
- // We pass HMD DisplayDeviceName into the renderer to select the
- // correct monitor in full-screen mode.
- if (pHMD && pHMD->GetDeviceInfo(&TheHMDInfo))
- {
- //RenderParams.MonitorName = hmd.DisplayDeviceName;
- SConfig.SetHMDInfo(TheHMDInfo);
- }
- LogText("HMD device removed.\n");
- }
- }
- }
- else
- OVR_ASSERT(0); // unexpected action
- }
- }
+ }
- // If one of Stereo setting adjustment keys is pressed, adjust related state.
- if (pAdjustFunc)
+ if (HmdSettingsChanged)
{
- (this->*pAdjustFunc)(dt * AdjustDirection * (ShiftDown ? 5.0f : 1.0f));
+ CalculateHmdValues();
+ HmdSettingsChanged = false;
}
- // Process latency tester results.
- const char* results = LatencyUtil.GetResultsString();
- if (results != NULL)
- {
- LogText("LATENCY TESTER: %s\n", results);
- }
+ HmdFrameTiming = ovrHmd_BeginFrame(Hmd, 0);
- // >>> THIS MUST BE PLACED AS CLOSE AS POSSIBLE TO WHERE THE HMD ORIENTATION IS READ <<<
- LatencyUtil.ProcessInputs();
- // Handle Sensor motion.
- // We extract Yaw, Pitch, Roll instead of directly using the orientation
- // to allow "additional" yaw manipulation with mouse/controller.
- if(pSensor)
+ // Update gamepad.
+ GamepadState gamepadState;
+ if (GetPlatformCore()->GetGamepadManager()->GetGamepadState(0, &gamepadState))
{
- Quatf hmdOrient = SFusion.GetPredictedOrientation();
+ GamepadStateChanged(gamepadState);
+ }
- float yaw = 0.0f;
- hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &ThePlayer.EyePitch, &ThePlayer.EyeRoll);
+ SensorState ss = ovrHmd_GetSensorState(Hmd, HmdFrameTiming.ScanoutMidpointSeconds);
+ HmdStatus = ss.StatusFlags;
- ThePlayer.EyeYaw += (yaw - ThePlayer.LastSensorYaw);
- ThePlayer.LastSensorYaw = yaw;
+ // Change message status around positional tracking.
+ bool hadVisionTracking = HaveVisionTracking;
+ HaveVisionTracking = (ss.StatusFlags & Status_PositionTracked) != 0;
+ if (HaveVisionTracking && !hadVisionTracking)
+ Menu.SetPopupMessage("Vision Tracking Acquired");
+ if (!HaveVisionTracking && hadVisionTracking)
+ Menu.SetPopupMessage("Lost Vision Tracking");
+
+ // Check if any new devices were connected.
+ ProcessDeviceNotificationQueue();
+ // FPS count and timing.
+ UpdateFrameRateCounter(curtime);
- // NOTE: We can get a matrix from orientation as follows:
- // Matrix4f hmdMat(hmdOrient);
+
+ // Update pose based on frame!
+ ThePlayer.HeadPose = ss.Predicted.Transform;
+ // Movement/rotation with the gamepad.
+ ThePlayer.BodyYaw -= ThePlayer.GamepadRotate.x * dt;
+ ThePlayer.HandleMovement(dt, &CollisionModels, &GroundCollisionModels, ShiftDown);
- // Test logic - assign quaternion result directly to view:
- // Quatf hmdOrient = SFusion.GetOrientation();
- // View = Matrix4f(hmdOrient.Inverted()) * Matrix4f::Translation(-EyePos);
- }
+ // Record after processing time.
+ Profiler.RecordSample(RenderProfiler::Sample_AfterGameProcessing);
- if(curtime >= NextFPSUpdate)
- {
- NextFPSUpdate = curtime + 1.0;
- FPS = FrameCounter;
- FrameCounter = 0;
- }
- FrameCounter++;
- if(FPS < 40)
- {
- ConsecutiveLowFPSFrames++;
- }
- else
+ // Determine if we are rendering this frame. Frame rendering may be
+ // skipped based on FreezeEyeUpdate and Time-warp timing state.
+ bool bupdateRenderedView = FrameNeedsRendering(curtime);
+
+ if (bupdateRenderedView)
{
- ConsecutiveLowFPSFrames = 0;
- }
+ // If render texture size is changing, apply dynamic changes to viewport.
+ ApplyDynamicResolutionScaling();
- if(ConsecutiveLowFPSFrames > 200)
- {
- DropLOD();
- ConsecutiveLowFPSFrames = 0;
- }
+ pRender->BeginScene(PostProcess_None);
- ThePlayer.EyeYaw -= ThePlayer.GamepadRotate.x * dt;
- ThePlayer.HandleCollision(dt, &CollisionModels, &GroundCollisionModels, ShiftDown);
+ if (ForceZeroIpd)
+ {
+ // Zero IPD eye rendering: draw into left eye only,
+ // re-use texture for right eye.
+ pRender->SetRenderTarget(RenderTargets[Rendertarget_Left].pTex);
+ pRender->Clear();
+
+ ovrPosef eyeRenderPose = ovrHmd_BeginEyeRender(Hmd, ovrEye_Left);
+
+ View = CalculateViewFromPose(eyeRenderPose);
+ RenderEyeView(ovrEye_Left);
+ ovrHmd_EndEyeRender(Hmd, ovrEye_Left, eyeRenderPose, &EyeTexture[ovrEye_Left]);
- if(!pSensor)
- {
- ThePlayer.EyePitch -= ThePlayer.GamepadRotate.y * dt;
+ // Second eye gets the same texture (initialized to same value above).
+ ovrHmd_BeginEyeRender(Hmd, ovrEye_Right);
+ ovrHmd_EndEyeRender(Hmd, ovrEye_Right, eyeRenderPose, &EyeTexture[ovrEye_Right]);
+ }
- const float maxPitch = ((3.1415f / 2) * 0.98f);
- if(ThePlayer.EyePitch > maxPitch)
+ else if (RendertargetIsSharedByBothEyes)
{
- ThePlayer.EyePitch = maxPitch;
+ // Shared render target eye rendering; set up RT once for both eyes.
+ pRender->SetRenderTarget(RenderTargets[Rendertarget_BothEyes].pTex);
+ pRender->Clear();
+
+ for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++)
+ {
+ ovrEyeType eye = HmdDesc.EyeRenderOrder[eyeIndex];
+ ovrPosef eyeRenderPose = ovrHmd_BeginEyeRender(Hmd, eye);
+
+ View = CalculateViewFromPose(eyeRenderPose);
+ RenderEyeView(eye);
+ ovrHmd_EndEyeRender(Hmd, eye, eyeRenderPose, &EyeTexture[eye]);
+ }
}
- if(ThePlayer.EyePitch < -maxPitch)
+
+ else
{
- ThePlayer.EyePitch = -maxPitch;
- }
- }
+ // Separate eye rendering - each eye gets its own render target.
+ for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++)
+ {
+ ovrEyeType eye = HmdDesc.EyeRenderOrder[eyeIndex];
+ pRender->SetRenderTarget(
+ RenderTargets[(eye == 0) ? Rendertarget_Left : Rendertarget_Right].pTex);
+ pRender->Clear();
+
+ ovrPosef eyeRenderPose = ovrHmd_BeginEyeRender(Hmd, eye);
- // Rotate and position View Camera, using YawPitchRoll in BodyFrame coordinates.
- //
- Matrix4f rollPitchYaw = Matrix4f::RotationY(ThePlayer.EyeYaw) * Matrix4f::RotationX(ThePlayer.EyePitch) *
- Matrix4f::RotationZ(ThePlayer.EyeRoll);
- Vector3f up = rollPitchYaw.Transform(UpVector);
- Vector3f forward = rollPitchYaw.Transform(ForwardVector);
+ View = CalculateViewFromPose(eyeRenderPose);
+ RenderEyeView(eye);
+ ovrHmd_EndEyeRender(Hmd, eye, eyeRenderPose, &EyeTexture[eye]);
+ }
+ }
+ pRender->SetRenderTarget(0);
+ pRender->FinishScene();
+ }
- // Minimal head modeling; should be moved as an option to SensorFusion.
- float headBaseToEyeHeight = 0.15f; // Vertical height of eye from base of head
- float headBaseToEyeProtrusion = 0.09f; // Distance forward of eye from base of head
+ Profiler.RecordSample(RenderProfiler::Sample_AfterEyeRender);
- Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
- Vector3f shiftedEyePos = ThePlayer.EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
- shiftedEyePos.y -= eyeCenterInHeadFrame.y; // Bring the head back down to original height
- View = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
+ // TODO: These happen inside ovrHmd_EndFrame; need to hook into it.
+ //Profiler.RecordSample(RenderProfiler::Sample_BeforeDistortion);
+ ovrHmd_EndFrame(Hmd);
+ Profiler.RecordSample(RenderProfiler::Sample_AfterPresent);
+}
- // Transformation without head modeling.
- // View = Matrix4f::LookAtRH(EyePos, EyePos + forward, up);
- // This is an alternative to LookAtRH:
- // Here we transpose the rotation matrix to get its inverse.
- // View = (Matrix4f::RotationY(EyeYaw) * Matrix4f::RotationX(EyePitch) *
- // Matrix4f::RotationZ(EyeRoll)).Transposed() *
- // Matrix4f::Translation(-EyePos);
+// Determine whether this frame needs rendering based on time-warp timing and flags.
+bool OculusWorldDemoApp::FrameNeedsRendering(double curtime)
+{
+ static double lastUpdate = 0.0;
+ double renderInterval = TimewarpRenderIntervalInSeconds;
+ double timeSinceLast = curtime - lastUpdate;
+ bool updateRenderedView = true;
- switch(SConfig.GetStereoMode())
+ if (TimewarpEnabled)
{
- case Stereo_None:
- Render(SConfig.GetEyeRenderParams(StereoEye_Center));
- break;
+ if (FreezeEyeUpdate)
+ {
+ // Draw one frame after (FreezeEyeUpdate = true) to update message text.
+ if (FreezeEyeOneFrameRendered)
+ updateRenderedView = false;
+ else
+ FreezeEyeOneFrameRendered = true;
+ }
+ else
+ {
+ FreezeEyeOneFrameRendered = false;
- case Stereo_LeftRight_Multipass:
- //case Stereo_LeftDouble_Multipass:
- Render(SConfig.GetEyeRenderParams(StereoEye_Left));
- Render(SConfig.GetEyeRenderParams(StereoEye_Right));
- break;
+ if ( (timeSinceLast < 0.0) || ((float)timeSinceLast > renderInterval) )
+ {
+ // This allows us to do "fractional" speeds, e.g. 45fps rendering on a 60fps display.
+ lastUpdate += renderInterval;
+ if ( timeSinceLast > 5.0 )
+ {
+ // renderInterval is probably tiny (i.e. "as fast as possible")
+ lastUpdate = curtime;
+ }
+ updateRenderedView = true;
+ }
+ else
+ {
+ updateRenderedView = false;
+ }
+ }
}
-
- pRender->Present();
- // Force GPU to flush the scene, resulting in the lowest possible latency.
- pRender->ForceFlushGPU();
+
+ return updateRenderedView;
}
-static const char* HelpText =
- "F1 \t100 NoStereo\n"
- "F2 \t100 Stereo \t420 Z \t520 Drift Correction\n"
- "F3 \t100 StereoHMD \t420 F6 \t520 Yaw Drift Info\n"
- "F4 \t100 MSAA \t420 R \t520 Reset SensorFusion\n"
- "F9 \t100 FullScreen \t420\n"
- "F11 \t100 Fast FullScreen \t500 - + \t660 Adj EyeHeight\n"
- "C \t100 Chromatic Ab \t500 [ ] \t660 Adj FOV\n"
- "P \t100 Motion Pred \t500 Shift \t660 Adj Faster\n"
- "N/M \t180 Adj Motion Pred\n"
- "( / ) \t180 Adj EyeDistance"
- ;
-
-
-enum DrawTextCenterType
-{
- DrawText_NoCenter= 0,
- DrawText_VCenter = 0x1,
- DrawText_HCenter = 0x2,
- DrawText_Center = DrawText_VCenter | DrawText_HCenter
-};
-
-static void DrawTextBox(RenderDevice* prender, float x, float y,
- float textSize, const char* text,
- DrawTextCenterType centerType = DrawText_NoCenter)
+void OculusWorldDemoApp::ApplyDynamicResolutionScaling()
{
- float ssize[2] = {0.0f, 0.0f};
-
- prender->MeasureText(&DejaVu, text, textSize, ssize);
-
- // Treat 0 a VCenter.
- if (centerType & DrawText_HCenter)
+ if (!DynamicRezScalingEnabled)
{
- x = -ssize[0]/2;
+ // Restore viewport rectangle in case dynamic res scaling was enabled before.
+ EyeTexture[0].Header.RenderViewport = EyeRenderDesc[0].Desc.RenderViewport;
+ EyeTexture[1].Header.RenderViewport = EyeRenderDesc[1].Desc.RenderViewport;
+ return;
}
- if (centerType & DrawText_VCenter)
+
+ // Demonstrate dynamic-resolution rendering.
+ // This demo is too simple to actually have a framerate that varies that much, so we'll
+ // just pretend this is trying to cope with highly dynamic rendering load.
+ float dynamicRezScale = 1.0f;
+
{
- y = -ssize[1]/2;
+ // Hacky stuff to make up a scaling...
+ // This produces value oscillating as follows: 0 -> 1 -> 0.
+ static double dynamicRezStartTime = ovr_GetTimeInSeconds();
+ float dynamicRezPhase = float ( ovr_GetTimeInSeconds() - dynamicRezStartTime );
+ const float dynamicRezTimeScale = 4.0f;
+
+ dynamicRezPhase /= dynamicRezTimeScale;
+ if ( dynamicRezPhase < 1.0f )
+ {
+ dynamicRezScale = dynamicRezPhase;
+ }
+ else if ( dynamicRezPhase < 2.0f )
+ {
+ dynamicRezScale = 2.0f - dynamicRezPhase;
+ }
+ else
+ {
+ // Reset it to prevent creep.
+ dynamicRezStartTime = ovr_GetTimeInSeconds();
+ dynamicRezScale = 0.0f;
+ }
+
+ // Map oscillation: 0.5 -> 1.0 -> 0.5
+ dynamicRezScale = dynamicRezScale * 0.5f + 0.5f;
}
- prender->FillRect(x-0.02f, y-0.02f, x+ssize[0]+0.02f, y+ssize[1]+0.02f, Color(40,40,100,210));
- prender->RenderText(&DejaVu, text, x, y, textSize, Color(255,255,0,210));
+ Sizei sizeLeft = EyeRenderDesc[0].Desc.RenderViewport.Size;
+ Sizei sizeRight = EyeRenderDesc[1].Desc.RenderViewport.Size;
+
+ // This viewport is used for rendering and passed into ovrHmd_EndEyeRender.
+ EyeTexture[0].Header.RenderViewport.Size = Sizei(int(sizeLeft.w * dynamicRezScale),
+ int(sizeLeft.h * dynamicRezScale));
+ EyeTexture[1].Header.RenderViewport.Size = Sizei(int(sizeRight.w * dynamicRezScale),
+ int(sizeRight.h * dynamicRezScale));
}
-void OculusWorldDemoApp::Render(const StereoEyeParams& stereo)
+
+void OculusWorldDemoApp::UpdateFrameRateCounter(double curtime)
{
- pRender->BeginScene(PostProcess);
+ FrameCounter++;
+ float secondsSinceLastMeasurement = (float)( curtime - LastFpsUpdate );
+
+ if (secondsSinceLastMeasurement >= SecondsOfFpsMeasurement)
+ {
+ SecondsPerFrame = (float)( curtime - LastFpsUpdate ) / (float)FrameCounter;
+ FPS = 1.0f / SecondsPerFrame;
+ LastFpsUpdate = curtime;
+ FrameCounter = 0;
+ }
+}
- // *** 3D - Configures Viewport/Projection and Render
- pRender->ApplyStereoParams(stereo);
- pRender->Clear();
+void OculusWorldDemoApp::RenderEyeView(ovrEyeType eye)
+{
+ Recti renderViewport = EyeTexture[eye].Header.RenderViewport;
+ Matrix4f viewAdjust = Matrix4f::Translation(Vector3f(EyeRenderDesc[eye].ViewAdjust));
+
+
+ // *** 3D - Configures Viewport/Projection and Render
+
+ pRender->ApplyStereoParams(renderViewport, Projection[eye]);
pRender->SetDepthMode(true, true);
- if (SceneMode != Scene_Grid)
+
+ Matrix4f baseTranslate = Matrix4f::Translation(ThePlayer.BodyPos);
+ Matrix4f baseYaw = Matrix4f::RotationY(ThePlayer.BodyYaw.Get());
+
+
+ if (GridDisplayMode != GridDisplay_GridOnly)
{
- MainScene.Render(pRender, stereo.ViewAdjust * View);
- }
+ if (SceneMode != Scene_OculusCubes)
+ {
+ MainScene.Render(pRender, viewAdjust * View);
+ RenderAnimatedBlocks(eye, ovr_GetTimeInSeconds());
+ }
+
+ if (SceneMode == Scene_Cubes)
+ {
+ // Draw scene cubes overlay. Red if position tracked, blue otherwise.
+ Scene sceneCubes = (HmdStatus & ovrStatus_PositionTracked) ?
+ RedCubesScene : BlueCubesScene;
+ sceneCubes.Render(pRender, viewAdjust * View * baseTranslate * baseYaw);
+ }
- if (SceneMode == Scene_YawView)
+ else if (SceneMode == Scene_OculusCubes)
+ {
+ OculusCubesScene.Render(pRender, viewAdjust * View * baseTranslate * baseYaw);
+ }
+ }
+
+ if (GridDisplayMode != GridDisplay_None)
{
- Matrix4f trackerOnlyOrient = Matrix4f::RotationY(ThePlayer.LastSensorYaw)
- * Matrix4f::RotationX(ThePlayer.EyePitch)
- * Matrix4f::RotationZ(ThePlayer.EyeRoll);
- YawLinesScene.Render(pRender, stereo.ViewAdjust * trackerOnlyOrient.Inverted());
- //YawMarkRedScene.Render(pRender, stereo.ViewAdjust);
+ RenderGrid(eye);
}
- // *** 2D Text & Grid - Configure Orthographic rendering.
+
+ // *** 2D Text - Configure Orthographic rendering.
// Render UI in 2D orthographic coordinate system that maps [-1,1] range
// to a readable FOV area centered at your eye and properly adjusted.
- pRender->ApplyStereoParams2D(stereo);
+ pRender->ApplyStereoParams(renderViewport, OrthoProjection[eye]);
pRender->SetDepthMode(false, false);
- float unitPixel = SConfig.Get2DUnitPixel();
- float textHeight= unitPixel * 22;
-
- if ((SceneMode == Scene_Grid)||(SceneMode == Scene_Both))
- { // Draw grid two pixels thick.
- GridScene.Render(pRender, Matrix4f());
- GridScene.Render(pRender, Matrix4f::Translation(unitPixel,unitPixel,0));
- }
+ // We set this scale up in CreateOrthoSubProjection().
+ float textHeight = 22.0f;
// Display Loading screen-shot in frame 0.
if (LoadingState != LoadingState_Finished)
{
- LoadingScene.Render(pRender, Matrix4f());
+ const float scale = textHeight * 25.0f;
+ Matrix4f view ( scale, 0.0f, 0.0f, 0.0f, scale, 0.0f, 0.0f, 0.0f, scale );
+ LoadingScene.Render(pRender, view);
String loadMessage = String("Loading ") + MainFilePath;
- DrawTextBox(pRender, 0.0f, 0.0f, textHeight, loadMessage.ToCStr(), DrawText_HCenter);
+ DrawTextBox(pRender, 0.0f, -textHeight, textHeight, loadMessage.ToCStr(), DrawText_HCenter);
LoadingState = LoadingState_DoLoad;
}
- if(!AdjustMessage.IsEmpty() && AdjustMessageTimeout > pPlatform->GetAppTime())
- {
- DrawTextBox(pRender,0.0f,0.4f, textHeight, AdjustMessage.ToCStr(), DrawText_HCenter);
- }
+ // HUD overlay brought up by spacebar.
+ RenderTextInfoHud(textHeight);
+ // Menu brought up by
+ Menu.Render(pRender);
+}
+
+
+
+// NOTE - try to keep these in sync with the PDF docs!
+static const char* HelpText1 =
+ "Spacebar \t500 Toggle debug info overlay\n"
+ "W, S \t500 Move forward, back\n"
+ "A, D \t500 Strafe left, right\n"
+ "Mouse move \t500 Look left, right\n"
+ "Left gamepad stick \t500 Move\n"
+ "Right gamepad stick \t500 Turn\n"
+ "T \t500 Reset player position";
+
+static const char* HelpText2 =
+ "R \t250 Reset sensor orientation\n"
+ "G \t250 Cycle grid overlay mode\n"
+ "-, + \t250 Adjust eye height\n"
+ "Esc \t250 Cancel full-screen\n"
+ "F4 \t250 Multisampling toggle\n"
+ "F9 \t250 Hardware full-screen (low latency)\n"
+ "F11 \t250 Faked full-screen (easier debugging)\n"
+ "Ctrl+Q \t250 Quit";
+
+
+void FormatLatencyReading(char* buff, UPInt size, float val)
+{
+ if (val < 0.000001f)
+ OVR_strcpy(buff, size, "N/A ");
+ else
+ OVR_sprintf(buff, size, "%4.2fms", val * 1000.0f);
+}
+
+
+void OculusWorldDemoApp::RenderTextInfoHud(float textHeight)
+{
+ // View port & 2D ortho projection must be set before call.
+
+ float hmdYaw, hmdPitch, hmdRoll;
switch(TextScreen)
{
- case Text_Orientation:
+ case Text_Info:
{
- char buf[256], gpustat[256];
+ char buf[512], gpustat[256];
+
+ // Average FOVs.
+ FovPort leftFov = EyeRenderDesc[0].Desc.Fov;
+ FovPort rightFov = EyeRenderDesc[1].Desc.Fov;
+
+ // Rendered size changes based on selected options & dynamic rendering.
+ int pixelSizeWidth = EyeTexture[0].Header.RenderViewport.Size.w +
+ ((!ForceZeroIpd) ?
+ EyeTexture[1].Header.RenderViewport.Size.w : 0);
+ int pixelSizeHeight = ( EyeTexture[0].Header.RenderViewport.Size.h +
+ EyeTexture[1].Header.RenderViewport.Size.h ) / 2;
+
+ // No DK2, no message.
+ char latency2Text[128] = "";
+ {
+ //float latency2 = ovrHmd_GetMeasuredLatencyTest2(Hmd) * 1000.0f; // show it in ms
+ //if (latency2 > 0)
+ // OVR_sprintf(latency2Text, sizeof(latency2Text), "%.2fms", latency2);
+
+ float latencies[3] = { 0.0f, 0.0f, 0.0f };
+ if (ovrHmd_GetFloatArray(Hmd, "DK2Latency", latencies, 3) == 3)
+ {
+ char latencyText0[32], latencyText1[32], latencyText2[32];
+ FormatLatencyReading(latencyText0, sizeof(latencyText0), latencies[0]);
+ FormatLatencyReading(latencyText1, sizeof(latencyText1), latencies[1]);
+ FormatLatencyReading(latencyText2, sizeof(latencyText2), latencies[2]);
+
+ OVR_sprintf(latency2Text, sizeof(latency2Text),
+ " DK2 Latency Ren: %s TWrp: %s\n"
+ " PostPresent: %s ",
+ latencyText0, latencyText1, latencyText2);
+ }
+ }
+
+ ThePlayer.HeadPose.Orientation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&hmdYaw, &hmdPitch, &hmdRoll);
OVR_sprintf(buf, sizeof(buf),
- " Yaw:%4.0f Pitch:%4.0f Roll:%4.0f \n"
- " FPS: %d Frame: %d \n Pos: %3.2f, %3.2f, %3.2f \n"
- " EyeHeight: %3.2f",
- RadToDegree(ThePlayer.EyeYaw), RadToDegree(ThePlayer.EyePitch), RadToDegree(ThePlayer.EyeRoll),
- FPS, FrameCounter, ThePlayer.EyePos.x, ThePlayer.EyePos.y, ThePlayer.EyePos.z, ThePlayer.UserEyeHeight);
+ " HMD YPR:%4.0f %4.0f %4.0f Player Yaw: %4.0f\n"
+ " FPS: %.1f ms/frame: %.1f Frame: %d\n"
+ " Pos: %3.2f, %3.2f, %3.2f HMD: %s\n"
+ " EyeHeight: %3.2f, IPD: %3.1fmm\n" //", Lens: %s\n"
+ " FOV %3.1fx%3.1f, Resolution: %ix%i\n"
+ "%s",
+ RadToDegree(hmdYaw), RadToDegree(hmdPitch), RadToDegree(hmdRoll),
+ RadToDegree(ThePlayer.BodyYaw.Get()),
+ FPS, SecondsPerFrame * 1000.0f, FrameCounter,
+ ThePlayer.BodyPos.x, ThePlayer.BodyPos.y, ThePlayer.BodyPos.z,
+ //GetDebugNameHmdType ( TheHmdRenderInfo.HmdType ),
+ HmdDesc.ProductName,
+ ThePlayer.UserEyeHeight,
+ ovrHmd_GetFloat(Hmd, OVR_KEY_IPD, 0) * 1000.0f,
+ //( EyeOffsetFromNoseLeft + EyeOffsetFromNoseRight ) * 1000.0f,
+ //GetDebugNameEyeCupType ( TheHmdRenderInfo.EyeCups ), // Lens/EyeCup not exposed
+
+ (leftFov.GetHorizontalFovDegrees() + rightFov.GetHorizontalFovDegrees()) * 0.5f,
+ (leftFov.GetVerticalFovDegrees() + rightFov.GetVerticalFovDegrees()) * 0.5f,
+
+ pixelSizeWidth, pixelSizeHeight,
+
+ latency2Text
+ );
+
size_t texMemInMB = pRender->GetTotalTextureMemoryUsage() / 1058576;
if (texMemInMB)
{
- OVR_sprintf(gpustat, sizeof(gpustat), "\n GPU Tex: %u MB", texMemInMB);
+ OVR_sprintf(gpustat, sizeof(gpustat), " GPU Tex: %u MB", texMemInMB);
OVR_strcat(buf, sizeof(buf), gpustat);
}
- DrawTextBox(pRender, 0.0f, -0.15f, textHeight, buf, DrawText_HCenter);
+ DrawTextBox(pRender, 0.0f, 0.0f, textHeight, buf, DrawText_Center);
}
break;
-
- case Text_Config:
- {
- char textBuff[2048];
-
- OVR_sprintf(textBuff, sizeof(textBuff),
- "Fov\t300 %9.4f\n"
- "EyeDistance\t300 %9.4f\n"
- "DistortionK0\t300 %9.4f\n"
- "DistortionK1\t300 %9.4f\n"
- "DistortionK2\t300 %9.4f\n"
- "DistortionK3\t300 %9.4f\n"
- "TexScale\t300 %9.4f",
- SConfig.GetYFOVDegrees(),
- SConfig.GetIPD(),
- SConfig.GetDistortionK(0),
- SConfig.GetDistortionK(1),
- SConfig.GetDistortionK(2),
- SConfig.GetDistortionK(3),
- SConfig.GetDistortionScale());
-
- DrawTextBox(pRender, 0.0f, 0.0f, textHeight, textBuff, DrawText_Center);
- }
+
+ case Text_Timing:
+ Profiler.DrawOverlay(pRender);
break;
-
- case Text_Help:
- DrawTextBox(pRender, 0.0f, -0.1f, textHeight, HelpText, DrawText_Center);
-
- default:
+
+ case Text_Help1:
+ DrawTextBox(pRender, 0.0f, 0.0f, textHeight, HelpText1, DrawText_Center);
+ break;
+ case Text_Help2:
+ DrawTextBox(pRender, 0.0f, 0.0f, textHeight, HelpText2, DrawText_Center);
+ break;
+
+ case Text_None:
break;
- }
-
- // Display colored quad if we're doing a latency test.
- Color colorToDisplay;
- if (LatencyUtil.DisplayScreenColor(colorToDisplay))
- {
- pRender->FillRect(-0.4f, -0.4f, 0.4f, 0.4f, colorToDisplay);
+ default:
+ OVR_ASSERT ( !"Missing text screen" );
+ break;
}
-
- pRender->FinishScene();
}
-// Sets temporarily displayed message for adjustments
-void OculusWorldDemoApp::SetAdjustMessage(const char* format, ...)
-{
- Lock::Locker lock(pManager->GetHandlerLock());
- char textBuff[2048];
- va_list argList;
- va_start(argList, format);
- OVR_vsprintf(textBuff, sizeof(textBuff), format, argList);
- va_end(argList);
-
- // Message will time out in 4 seconds.
- AdjustMessage = textBuff;
- AdjustMessageTimeout = pPlatform->GetAppTime() + 4.0f;
-}
-
-void OculusWorldDemoApp::SetAdjustMessageTimeout(float timeout)
-{
- AdjustMessageTimeout = pPlatform->GetAppTime() + timeout;
-}
+//-----------------------------------------------------------------------------
+// ***** Callbacks For Menu changes
-// ***** View Control Adjustments
+// Non-trivial callback go here.
-void OculusWorldDemoApp::AdjustFov(float dt)
+void OculusWorldDemoApp::HmdSettingChangeFreeRTs(OptionVar*)
{
- float esd = SConfig.GetEyeToScreenDistance() + 0.01f * dt;
- SConfig.SetEyeToScreenDistance(esd);
- SetAdjustMessage("ESD:%6.3f FOV: %6.3f", esd, SConfig.GetYFOVDegrees());
+ HmdSettingsChanged = true;
+ // Cause the RTs to be recreated with the new mode.
+ for ( int rtNum = 0; rtNum < Rendertarget_LAST; rtNum++ )
+ RenderTargets[rtNum].pTex = NULL;
}
-void OculusWorldDemoApp::AdjustAspect(float dt)
+void OculusWorldDemoApp::MultisampleChange(OptionVar*)
{
- float rawAspect = SConfig.GetAspect() / SConfig.GetAspectMultiplier();
- float newAspect = SConfig.GetAspect() + 0.01f * dt;
- SConfig.SetAspectMultiplier(newAspect / rawAspect);
- SetAdjustMessage("Aspect: %6.3f", newAspect);
+ HmdSettingChangeFreeRTs();
}
-void OculusWorldDemoApp::AdjustDistortion(float dt, int kIndex, const char* label)
+void OculusWorldDemoApp::CenterPupilDepthChange(OptionVar*)
{
- SConfig.SetDistortionK(kIndex, SConfig.GetDistortionK(kIndex) + 0.03f * dt);
- SetAdjustMessage("%s: %6.4f", label, SConfig.GetDistortionK(kIndex));
+ ovrHmd_SetFloat(Hmd, "CenterPupilDepth", CenterPupilDepthMeters);
}
-void OculusWorldDemoApp::AdjustIPD(float dt)
+void OculusWorldDemoApp::DistortionClearColorChange(OptionVar*)
{
- SConfig.SetIPD(SConfig.GetIPD() + 0.025f * dt);
- SetAdjustMessage("EyeDistance: %6.4f", SConfig.GetIPD());
+ float clearColor[2][4] = { { 0.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.5f, 1.0f, 0.0f } };
+ ovrHmd_SetFloatArray(Hmd, "DistortionClearColor",
+ clearColor[(int)DistortionClearBlue], 4);
}
-void OculusWorldDemoApp::AdjustEyeHeight(float dt)
-{
- float dist = 0.5f * dt;
-
- ThePlayer.UserEyeHeight += dist;
- ThePlayer.EyePos.y += dist;
- SetAdjustMessage("UserEyeHeight: %4.2f", ThePlayer.UserEyeHeight);
-}
+//-----------------------------------------------------------------------------
-void OculusWorldDemoApp::AdjustMotionPrediction(float dt)
+void OculusWorldDemoApp::ProcessDeviceNotificationQueue()
{
- float motionPred = SFusion.GetPredictionDelta() + 0.01f * dt;
-
- if (motionPred < 0.0f)
- {
- motionPred = 0.0f;
- }
-
- SFusion.SetPrediction(motionPred);
-
- SetAdjustMessage("MotionPrediction: %6.3fs", motionPred);
+ // TBD: Process device plug & Unplug
}
-void OculusWorldDemoApp::AdjustDistortion(float val, int kIndex)
-{
- SConfig.SetDistortionK(kIndex, val);
- SetAdjustMessage("K%d: %6.4f", kIndex, SConfig.GetDistortionK(kIndex));
-}
-void OculusWorldDemoApp::AdjustEsd(float val)
+//-----------------------------------------------------------------------------
+void OculusWorldDemoApp::ChangeDisplay ( bool bBackToWindowed, bool bNextFullscreen,
+ bool bFullWindowDebugging )
{
- SConfig.SetEyeToScreenDistance(val);
- float esd = SConfig.GetEyeToScreenDistance();
- SetAdjustMessage("ESD:%6.3f FOV: %6.3f", esd, SConfig.GetYFOVDegrees());
-}
+ // Exactly one should be set...
+ OVR_ASSERT ( ( bBackToWindowed ? 1 : 0 ) + ( bNextFullscreen ? 1 : 0 ) +
+ ( bFullWindowDebugging ? 1 : 0 ) == 1 );
+ OVR_UNUSED ( bNextFullscreen );
-// Loads the scene data
-void OculusWorldDemoApp::PopulateScene(const char *fileName)
-{
- XmlHandler xmlHandler;
- if(!xmlHandler.ReadFile(fileName, pRender, &MainScene, &CollisionModels, &GroundCollisionModels))
+ if ( bFullWindowDebugging )
{
- SetAdjustMessage("---------------------------------\nFILE LOAD FAILED\n---------------------------------");
- SetAdjustMessageTimeout(10.0f);
- }
-
- MainScene.SetAmbient(Vector4f(1.0f, 1.0f, 1.0f, 1.0f));
-
- // Distortion debug grid (brought up by 'G' key).
- Ptr<Model> gridModel = *Model::CreateGrid(Vector3f(0,0,0), Vector3f(1.0f/10, 0,0), Vector3f(0,1.0f/10,0),
- 10, 10, 5,
- Color(0, 255, 0, 255), Color(255, 50, 50, 255) );
- GridScene.World.Add(gridModel);
-
- // Yaw angle marker and lines (brought up by ';' key).
- float shifty = -0.5f;
- Ptr<Model> yawMarkGreenModel = *Model::CreateBox(Color(0, 255, 0, 255), Vector3f(0.0f, shifty, -2.0f), Vector3f(0.05f, 0.05f, 0.05f));
- YawMarkGreenScene.World.Add(yawMarkGreenModel);
- Ptr<Model> yawMarkRedModel = *Model::CreateBox(Color(255, 0, 0, 255), Vector3f(0.0f, shifty, -2.0f), Vector3f(0.05f, 0.05f, 0.05f));
- YawMarkRedScene.World.Add(yawMarkRedModel);
-
- Ptr<Model> yawLinesModel = *new Model();
- Color c = Color(255, 200, 200, 255);
- float r = 1.5f;
- yawLinesModel->AddTriangle(yawLinesModel->AddVertex(Vector3f(-0.1f, 0, -r), c),
- yawLinesModel->AddVertex(Vector3f(0, 0, -r-0.2f), c),
- yawLinesModel->AddVertex(Vector3f(0.1f, 0, -r), c));
- yawLinesModel->AddTriangle(yawLinesModel->AddVertex(Vector3f(-r-0.1f, 0, -r), c),
- yawLinesModel->AddVertex(Vector3f(-r, 0, -r-0.2f), c),
- yawLinesModel->AddVertex(Vector3f(-r+0.1f, 0, -r), c));
- yawLinesModel->AddTriangle(yawLinesModel->AddVertex(Vector3f(r-0.1f, 0, -r), c),
- yawLinesModel->AddVertex(Vector3f(r, 0, -r-0.2f), c),
- yawLinesModel->AddVertex(Vector3f(r+0.1f, 0, -r), c));
- yawLinesModel->SetPosition(Vector3f(0.0f,-1.2f,0.0f));
- YawLinesScene.World.Add(yawLinesModel);
-}
-
-
-void OculusWorldDemoApp::PopulatePreloadScene()
-{
- // Load-screen screen shot image
- String fileName = MainFilePath;
- fileName.StripExtension();
-
- Ptr<File> imageFile = *new SysFile(fileName + "_LoadScreen.tga");
- Ptr<Texture> imageTex;
- if (imageFile->IsValid())
- imageTex = *LoadTextureTga(pRender, imageFile);
+ // Slightly hacky. Doesn't actually go fullscreen, just makes a screen-sized wndow.
+ // This has higher latency than fullscreen, and is not intended for actual use,
+ // but makes for much nicer debugging on some systems.
+ RenderParams = pRender->GetParams();
+ RenderParams.Display = DisplayId(HmdDesc.DisplayDeviceName, HmdDesc.DisplayId);
+ pRender->SetParams(RenderParams);
- // Image is rendered as a single quad.
- if (imageTex)
- {
- imageTex->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
- Ptr<Model> m = *new Model(Prim_Triangles);
- m->AddVertex(-0.5f, 0.5f, 0.0f, Color(255,255,255,255), 0.0f, 0.0f);
- m->AddVertex( 0.5f, 0.5f, 0.0f, Color(255,255,255,255), 1.0f, 0.0f);
- m->AddVertex( 0.5f, -0.5f, 0.0f, Color(255,255,255,255), 1.0f, 1.0f);
- m->AddVertex(-0.5f, -0.5f, 0.0f, Color(255,255,255,255), 0.0f, 1.0f);
- m->AddTriangle(2,1,0);
- m->AddTriangle(0,3,2);
-
- Ptr<ShaderFill> fill = *new ShaderFill(*pRender->CreateShaderSet());
- fill->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
- fill->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Fragment, FShader_Texture));
- fill->SetTexture(0, imageTex);
- m->Fill = fill;
-
- LoadingScene.World.Add(m);
+ pPlatform->SetMouseMode(Mouse_Normal);
+ pPlatform->SetFullscreen(RenderParams, pRender->IsFullscreen() ? Display_Window : Display_FakeFullscreen);
+ pPlatform->SetMouseMode(Mouse_Relative); // Avoid mode world rotation jump.
+
+ // If using an HMD, enable post-process (for distortion) and stereo.
+ if (RenderParams.IsDisplaySet() && pRender->IsFullscreen())
+ {
+ //SetPostProcessingMode ( PostProcess );
+ }
}
-}
-
-void OculusWorldDemoApp::ClearScene()
-{
- MainScene.Clear();
- GridScene.Clear();
- YawMarkGreenScene.Clear();
- YawMarkRedScene.Clear();
- YawLinesScene.Clear();
-}
-
-void OculusWorldDemoApp::PopulateLODFileNames()
-{
- //OVR::String mainFilePath = MainFilePath;
- LODFilePaths.PushBack(MainFilePath);
- int LODIndex = 1;
- SPInt pos = strcspn(MainFilePath.ToCStr(), ".");
- SPInt len = strlen(MainFilePath.ToCStr());
- SPInt diff = len - pos;
-
- if (diff == 0)
- return;
-
- while(true)
+ else
{
- char pathWithoutExt[250];
- char buffer[250];
- for(SPInt i = 0; i < pos; ++i)
+ int screenCount = pPlatform->GetDisplayCount();
+
+ int screenNumberToSwitchTo;
+ if ( bBackToWindowed )
{
- pathWithoutExt[i] = MainFilePath[(int)i];
+ screenNumberToSwitchTo = -1;
}
- pathWithoutExt[pos] = '\0';
- OVR_sprintf(buffer, sizeof(buffer), "%s%i.xml", pathWithoutExt, LODIndex);
- FILE* fp = 0;
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
- errno_t err = fopen_s(&fp, buffer, "rb");
- if(!fp || err)
+ else
{
-#else
- fp = fopen(buffer, "rb");
- if(!fp)
- {
-#endif
- break;
+ if (!pRender->IsFullscreen())
+ {
+ // Currently windowed.
+ // Try to find HMD Screen, making it the first screen in the full-screen cycle.
+ FirstScreenInCycle = 0;
+ if (!UsingDebugHmd)
+ {
+ DisplayId HMD (HmdDesc.DisplayDeviceName, HmdDesc.DisplayId);
+ for (int i = 0; i< screenCount; i++)
+ {
+ if (pPlatform->GetDisplay(i) == HMD)
+ {
+ FirstScreenInCycle = i;
+ break;
+ }
+ }
+ }
+ ScreenNumber = FirstScreenInCycle;
+ screenNumberToSwitchTo = ScreenNumber;
+ }
+ else
+ {
+ // Currently fullscreen, so cycle to the next screen.
+ ScreenNumber++;
+ if (ScreenNumber == screenCount)
+ {
+ ScreenNumber = 0;
+ }
+ screenNumberToSwitchTo = ScreenNumber;
+ if (ScreenNumber == FirstScreenInCycle)
+ {
+ // We have cycled through all the fullscreen displays, so go back to windowed mode.
+ screenNumberToSwitchTo = -1;
+ }
+ }
}
- fclose(fp);
- OVR::String result = buffer;
- LODFilePaths.PushBack(result);
- LODIndex++;
- }
-}
-
-void OculusWorldDemoApp::DropLOD()
-{
- if(CurrentLODFileIndex < (int)(LODFilePaths.GetSize() - 1))
- {
- ClearScene();
- CurrentLODFileIndex++;
- PopulateScene(LODFilePaths[CurrentLODFileIndex].ToCStr());
- }
-}
-void OculusWorldDemoApp::RaiseLOD()
-{
- if(CurrentLODFileIndex > 0)
- {
- ClearScene();
- CurrentLODFileIndex--;
- PopulateScene(LODFilePaths[CurrentLODFileIndex].ToCStr());
- }
-}
-
-//-----------------------------------------------------------------------------
-void OculusWorldDemoApp::CycleDisplay()
-{
- int screenCount = pPlatform->GetDisplayCount();
-
- // If Windowed, switch to the HMD screen first in Full-Screen Mode.
- // If already Full-Screen, cycle to next screen until we reach FirstScreenInCycle.
-
- if (pRender->IsFullscreen())
- {
- // Right now, we always need to restore window before going to next screen.
+ // Always restore windowed mode before going to next screen, even if we were already fullscreen.
pPlatform->SetFullscreen(RenderParams, Display_Window);
-
- Screen++;
- if (Screen == screenCount)
- Screen = 0;
-
- RenderParams.Display = pPlatform->GetDisplay(Screen);
-
- if (Screen != FirstScreenInCycle)
+ if ( screenNumberToSwitchTo >= 0 )
{
+ // Go fullscreen.
+ RenderParams.Display = pPlatform->GetDisplay(screenNumberToSwitchTo);
pRender->SetParams(RenderParams);
- pPlatform->SetFullscreen(RenderParams, Display_Fullscreen);
+ pPlatform->SetFullscreen(RenderParams, Display_Fullscreen);
}
}
- else
- {
- // Try to find HMD Screen, making it the first screen in full-screen Cycle.
- FirstScreenInCycle = 0;
-
- if (pHMD)
- {
- DisplayId HMD (SConfig.GetHMDInfo().DisplayDeviceName, SConfig.GetHMDInfo().DisplayId);
- for (int i = 0; i< screenCount; i++)
- {
- if (pPlatform->GetDisplay(i) == HMD)
- {
- FirstScreenInCycle = i;
- break;
- }
- }
- }
- // Switch full-screen on the HMD.
- Screen = FirstScreenInCycle;
- RenderParams.Display = pPlatform->GetDisplay(Screen);
- pRender->SetParams(RenderParams);
- pPlatform->SetFullscreen(RenderParams, Display_Fullscreen);
- }
+
+ // Updates render target pointers & sizes.
+ HmdSettingChangeFreeRTs();
}
void OculusWorldDemoApp::GamepadStateChanged(const GamepadState& pad)
@@ -1764,6 +1271,15 @@ void OculusWorldDemoApp::GamepadStateChanged(const GamepadState& pad)
0,
pad.LY * pad.LY * (pad.LY > 0 ? -1 : 1));
ThePlayer.GamepadRotate = Vector3f(2 * pad.RX, -2 * pad.RY, 0);
+
+ UInt32 gamepadDeltas = (pad.Buttons ^ LastGamepadState.Buttons) & pad.Buttons;
+
+ if (gamepadDeltas)
+ {
+ Menu.OnGamepad(gamepadDeltas);
+ }
+
+ LastGamepadState = pad;
}
diff --git a/Samples/OculusWorldDemo/OculusWorldDemo.h b/Samples/OculusWorldDemo/OculusWorldDemo.h
new file mode 100644
index 0000000..54f0e9d
--- /dev/null
+++ b/Samples/OculusWorldDemo/OculusWorldDemo.h
@@ -0,0 +1,339 @@
+/************************************************************************************
+
+Filename : OculusWorldDemo.h
+Content : First-person view test application for Oculus Rift - Header file
+Created : October 4, 2012
+Authors : Michael Antonov, Andrew Reisse, Steve LaValle, Dov Katz
+ Peter Hoff, Dan Goodman, Bryan Croteau
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef INC_OculusWorldDemo_h
+#define INC_OculusWorldDemo_h
+
+#include "OVR.h"
+
+#include "../CommonSrc/Platform/Platform_Default.h"
+#include "../CommonSrc/Render/Render_Device.h"
+#include "../CommonSrc/Render/Render_XmlSceneLoader.h"
+#include "../CommonSrc/Platform/Gamepad.h"
+
+#include "Util/Util_Render_Stereo.h"
+using namespace OVR::Util::Render;
+
+#include <Kernel/OVR_SysFile.h>
+#include <Kernel/OVR_Log.h>
+#include <Kernel/OVR_Timer.h>
+
+#include "Player.h"
+#include "OVR_DeviceConstants.h"
+
+#include "OptionMenu.h"
+#include "RenderProfiler.h"
+
+// Filename to be loaded by default, searching specified paths.
+#define WORLDDEMO_ASSET_FILE "Tuscany.xml"
+
+#define WORLDDEMO_ASSET_PATH1 "Assets/Tuscany/"
+#define WORLDDEMO_ASSET_PATH2 "../../../Assets/Tuscany/"
+// This path allows the shortcut to work.
+#define WORLDDEMO_ASSET_PATH3 "Samples/OculusWorldDemo/Assets/Tuscany/"
+
+using namespace OVR;
+using namespace OVR::Platform;
+using namespace OVR::Render;
+
+
+//-------------------------------------------------------------------------------------
+// ***** OculusWorldDemo Description
+
+// This app renders a loaded scene allowing the user to move along the
+// floor and look around with an HMD, mouse and keyboard. The following keys work:
+//
+// 'W', 'S', 'A', 'D' and Arrow Keys - Move forward, back; strafe left/right.
+//
+// Space - Bring up status and help display.
+// Tab - Bring up/hide menu with editable options.
+// F4 - Toggle MSAA.
+// F9 - Cycle through fullscreen and windowed modes.
+// Necessary for previewing content with Rift.
+//
+// Important Oculus-specific logic can be found at following locations:
+//
+// OculusWorldDemoApp::OnStartup - This function will initialize the SDK, creating the Hmd
+// and delegating to CalculateHmdValues to initialize it.
+//
+// OculusWorldDemoApp::OnIdle - Here we poll SensorFusion for orientation, apply it
+// to the scene and handle movement.
+// Stereo rendering is also done here, by delegating to
+// to the RenderEyeView() function for each eye.
+//
+
+//-------------------------------------------------------------------------------------
+// ***** OculusWorldDemo Application class
+
+// An instance of this class is created on application startup (main/WinMain).
+// It then works as follows:
+// - Graphics and HMD setup is done OculusWorldDemoApp::OnStartup(). Much of
+// HMD configuration here is moved to CalculateHmdValues.
+// OnStartup also creates the room model from Slab declarations.
+//
+// - Per-frame processing is done in OnIdle(). This function processes
+// sensor and movement input and then renders the frame.
+//
+// - Additional input processing is done in OnMouse, OnKey.
+
+class OculusWorldDemoApp : public Application
+{
+public:
+ OculusWorldDemoApp();
+ ~OculusWorldDemoApp();
+
+ virtual int OnStartup(int argc, const char** argv);
+ virtual void OnIdle();
+
+ virtual void OnMouseMove(int x, int y, int modifiers);
+ virtual void OnKey(OVR::KeyCode key, int chr, bool down, int modifiers);
+ virtual void OnResize(int width, int height);
+
+ bool SetupWindowAndRendering(int argc, const char** argv);
+
+ // Adds room model to scene.
+ void InitMainFilePath();
+ void PopulateScene(const char* fileName);
+ void PopulatePreloadScene();
+ void ClearScene();
+ void PopulateOptionMenu();
+
+
+ // Computes all of the Hmd values and configures render targets.
+ void CalculateHmdValues();
+ // Returns the actual size present.
+ Sizei EnsureRendertargetAtLeastThisBig (int rtNum, Sizei size);
+
+
+ // Renders full stereo scene for one eye.
+ void RenderEyeView(ovrEyeType eye);
+ // Renderes HUD overlay brough up by spacebar; 2D viewport must be set before call.
+ void RenderTextInfoHud(float textHeight);
+ void RenderAnimatedBlocks(ovrEyeType eye, double appTime);
+ void RenderGrid(ovrEyeType eye);
+
+ Matrix4f CalculateViewFromPose(const Posef& pose);
+
+ // Determine whether this frame needs rendering based on timewarp timing and flags.
+ bool FrameNeedsRendering(double curtime);
+ void ApplyDynamicResolutionScaling();
+ void UpdateFrameRateCounter(double curtime);
+
+
+ // Model creation and misc functions.
+ Model* CreateModel(Vector3f pos, struct SlabModel* sm);
+ Model* CreateBoundingModel(CollisionModel &cm);
+ void ChangeDisplay ( bool bBackToWindowed, bool bNextFullscreen, bool bFullWindowDebugging );
+ void GamepadStateChanged(const GamepadState& pad);
+
+ // Processes DeviceNotificationStatus queue to handles plug/unplug.
+ void ProcessDeviceNotificationQueue();
+
+
+ // ***** Callbacks for Menu option changes
+
+ // These contain extra actions to be taken in addition to switching the state.
+ void HmdSettingChange(OptionVar* = 0) { HmdSettingsChanged = true; }
+ void BlockShowChange(OptionVar* = 0) { BlocksCenter = ThePlayer.BodyPos; }
+ void EyeHeightChange(OptionVar* = 0) { ThePlayer.BodyPos.y = ThePlayer.UserEyeHeight; }
+
+ void HmdSettingChangeFreeRTs(OptionVar* = 0);
+ void MultisampleChange(OptionVar* = 0);
+ void CenterPupilDepthChange(OptionVar* = 0);
+ void DistortionClearColorChange(OptionVar* = 0);
+
+
+protected:
+ RenderDevice* pRender;
+ RendererParams RenderParams;
+ Sizei WindowSize;
+ int ScreenNumber;
+ int FirstScreenInCycle;
+
+ struct RenderTarget
+ {
+ Ptr<Texture> pTex;
+ ovrTexture Tex;
+ };
+ enum RendertargetsEnum
+ {
+ Rendertarget_Left,
+ Rendertarget_Right,
+ Rendertarget_BothEyes, // Used when both eyes are rendered to the same target.
+ Rendertarget_LAST
+ };
+ RenderTarget RenderTargets[Rendertarget_LAST];
+
+
+ // ***** Oculus HMD Variables
+
+ ovrHmd Hmd;
+ ovrHmdDesc HmdDesc;
+ ovrEyeRenderDesc EyeRenderDesc[2];
+ Matrix4f Projection[2]; // Projection matrix for eye.
+ Matrix4f OrthoProjection[2]; // Projection for 2D.
+ ovrTexture EyeTexture[2];
+ // Sensor caps applied.
+ unsigned StartSensorCaps;
+ bool UsingDebugHmd;
+
+ // Frame timing logic.
+ enum { SecondsOfFpsMeasurement = 1 };
+ int FrameCounter;
+ double NextFPSUpdate;
+ float SecondsPerFrame;
+ float FPS;
+ double LastFpsUpdate;
+
+ // Times a single frame.
+ double LastUpdate;
+
+ // Loaded data.
+ String MainFilePath;
+ Array<Ptr<CollisionModel> > CollisionModels;
+ Array<Ptr<CollisionModel> > GroundCollisionModels;
+
+ // Loading process displays screenshot in first frame
+ // and then proceeds to load until finished.
+ enum LoadingStateType
+ {
+ LoadingState_Frame0,
+ LoadingState_DoLoad,
+ LoadingState_Finished
+ } LoadingState;
+
+ // Set when vision tracking is detected.
+ bool HaveVisionTracking;
+
+ GamepadState LastGamepadState;
+
+ Player ThePlayer;
+ Matrix4f View;
+ Scene MainScene;
+ Scene LoadingScene;
+ Scene SmallGreenCube;
+
+ Scene OculusCubesScene;
+ Scene RedCubesScene;
+ Scene BlueCubesScene;
+
+ // Last frame asn sensor data reported by BeginFrame().
+ ovrFrameTiming HmdFrameTiming;
+ unsigned HmdStatus;
+
+
+ // ***** Modifiable Menu Options
+
+ // This flag is set when HMD settings change, causing HMD to be re-initialized.
+ bool HmdSettingsChanged;
+
+ // Render Target - affecting state.
+ bool RendertargetIsSharedByBothEyes;
+ bool DynamicRezScalingEnabled;
+ bool ForceZeroIpd;
+ float DesiredPixelDensity;
+ float FovSideTanMax;
+ float FovSideTanLimit; // Limit value for Fov.
+ // Time-warp.
+ bool TimewarpEnabled;
+ float TimewarpRenderIntervalInSeconds;
+ bool FreezeEyeUpdate;
+ bool FreezeEyeOneFrameRendered;
+
+ // Other global settings.
+ float CenterPupilDepthMeters;
+ // float IPD;
+ bool ForceZeroHeadMovement;
+ bool VsyncEnabled;
+ bool MultisampleEnabled;
+ // DK2 only
+ bool IsLowPersistence;
+ bool DynamicPrediction;
+ bool PositionTrackingEnabled;
+
+ // Support toggling background color for distortion so that we can see
+ // the effect on the periphery.
+ int DistortionClearBlue;
+
+ // Stereo settings adjustment state.
+ bool ShiftDown;
+ bool CtrlDown;
+
+
+ // ***** Scene Rendering Modes
+
+ enum SceneRenderMode
+ {
+ Scene_World,
+ Scene_Cubes,
+ Scene_OculusCubes
+ };
+ SceneRenderMode SceneMode;
+
+ enum GridDispayModeType
+ {
+ GridDisplay_None,
+ GridDisplay_GridOnly,
+ GridDisplay_GridAndScene
+ };
+ GridDispayModeType GridDisplayMode;
+
+ // What type of grid to display.
+ enum GridModeType
+ {
+ Grid_Rendertarget4,
+ Grid_Rendertarget16,
+ Grid_Lens,
+ Grid_Last
+ };
+ GridModeType GridMode;
+
+ // What help screen we display, brought up by 'Spacebar'.
+ enum TextScreen
+ {
+ Text_None,
+ Text_Info,
+ Text_Timing,
+ Text_Help1,
+ Text_Help2,
+ Text_Count
+ };
+ TextScreen TextScreen;
+
+ // Whether we are displaying animated blocks and what type.
+ int BlocksShowType;
+ Vector3f BlocksCenter;
+
+
+ // User configurable options, brought up by 'Tab' key.
+ // Also handles shortcuts and pop-up overlay messages.
+ OptionSelectionMenu Menu;
+
+ // Profiler for rendering - displays timing stats.
+ RenderProfiler Profiler;
+};
+
+
+
+#endif // INC_OculusWorldDemo_h
diff --git a/Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj.filters b/Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj.filters
deleted file mode 100644
index e96dc9e..0000000
--- a/Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj.filters
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="CommonSrc">
- <UniqueIdentifier>{ba6e9e50-0655-4f12-a136-6d2a06015925}</UniqueIdentifier>
- </Filter>
- <Filter Include="CommonSrc\Platform">
- <UniqueIdentifier>{16e20d8b-eff7-454c-be85-02037c399e97}</UniqueIdentifier>
- </Filter>
- <Filter Include="CommonSrc\Render">
- <UniqueIdentifier>{1b6d51ae-a405-4f3d-be93-41a50db4f328}</UniqueIdentifier>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\CommonSrc\Platform\Platform.cpp">
- <Filter>CommonSrc\Platform</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Platform\Win32_Platform.cpp">
- <Filter>CommonSrc\Platform</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Render\Render_Device.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Render\Render_D3D1X_Device.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Render\Render_D3D10_Device.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="OculusWorldDemo.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_D3D11_Device.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Render\Render_LoadTextureTGA.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="Player.cpp" />
- <ClCompile Include="..\..\3rdParty\TinyXml\tinyxml2.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_LoadTextureDDS.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Render\Render_XmlSceneLoader.cpp">
- <Filter>CommonSrc\Render</Filter>
- </ClCompile>
- <ClCompile Include="..\CommonSrc\Platform\Win32_Gamepad.cpp">
- <Filter>CommonSrc\Platform</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\CommonSrc\Platform\Win32_Platform.h">
- <Filter>CommonSrc\Platform</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Platform\Platform.h">
- <Filter>CommonSrc\Platform</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Platform\Platform_Default.h">
- <Filter>CommonSrc\Platform</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Render\Render_Font.h">
- <Filter>CommonSrc\Render</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Render\Render_Device.h">
- <Filter>CommonSrc\Render</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Render\Render_D3D1X_Device.h">
- <Filter>CommonSrc\Render</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Render\Render_D3D10_Device.h">
- <Filter>CommonSrc\Render</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Render\Render_D3D11_Device.h">
- <Filter>CommonSrc\Render</Filter>
- </ClInclude>
- <ClInclude Include="Player.h" />
- <ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_XmlSceneLoader.h">
- <Filter>CommonSrc\Render</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Platform\Gamepad.h">
- <Filter>CommonSrc\Platform</Filter>
- </ClInclude>
- <ClInclude Include="..\CommonSrc\Platform\Win32_Gamepad.h">
- <Filter>CommonSrc\Platform</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="OculusWorldDemo.rc" />
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/OculusWorldDemo_Scene.cpp b/Samples/OculusWorldDemo/OculusWorldDemo_Scene.cpp
new file mode 100644
index 0000000..5dfe2d2
--- /dev/null
+++ b/Samples/OculusWorldDemo/OculusWorldDemo_Scene.cpp
@@ -0,0 +1,399 @@
+/************************************************************************************
+
+Filename : OculusWorldDemo_Scene.cpp
+Content : Logic for loading, and creating rendered scene components,
+ cube and grid overlays, etc.
+Created : October 4, 2012
+Authors : Michael Antonov, Andrew Reisse, Steve LaValle, Dov Katz
+ Peter Hoff, Dan Goodman, Bryan Croteau
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OculusWorldDemo.h"
+
+
+//-------------------------------------------------------------------------------------
+// ***** Scene Creation / Loading
+
+void OculusWorldDemoApp::InitMainFilePath()
+{
+
+ MainFilePath = WORLDDEMO_ASSET_FILE;
+
+ // Try to modify path for correctness in case specified file is not found.
+ if (!SysFile(MainFilePath).IsValid())
+ {
+ String prefixPath1(pPlatform->GetContentDirectory() + "/" + WORLDDEMO_ASSET_PATH1),
+ prefixPath2(WORLDDEMO_ASSET_PATH2),
+ prefixPath3(WORLDDEMO_ASSET_PATH3);
+ if (SysFile(prefixPath1 + MainFilePath).IsValid())
+ MainFilePath = prefixPath1 + MainFilePath;
+ else if (SysFile(prefixPath2 + MainFilePath).IsValid())
+ MainFilePath = prefixPath2 + MainFilePath;
+ else if (SysFile(prefixPath3 + MainFilePath).IsValid())
+ MainFilePath = prefixPath3 + MainFilePath;
+ }
+}
+
+// Creates a grid of cubes.
+void PopulateCubeFieldScene(Scene* scene, Fill* fill,
+ int cubeCountX, int cubeCountY, int cubeCountZ, Vector3f offset,
+ float cubeSpacing = 0.5f, float cubeSize = 0.1f)
+{
+
+ Vector3f corner(-(((cubeCountX-1) * cubeSpacing) + cubeSize) * 0.5f,
+ -(((cubeCountY-1) * cubeSpacing) + cubeSize) * 0.5f,
+ -(((cubeCountZ-1) * cubeSpacing) + cubeSize) * 0.5f);
+ corner += offset;
+
+ Vector3f pos = corner;
+
+ for (int i = 0; i < cubeCountX; i++)
+ {
+ // Create a new model for each 'plane' of cubes so we don't exceed
+ // the vert size limit.
+ Ptr<Model> model = *new Model();
+ scene->World.Add(model);
+
+ if (fill)
+ model->Fill = fill;
+
+ for (int j = 0; j < cubeCountY; j++)
+ {
+ for (int k = 0; k < cubeCountZ; k++)
+ {
+ model->AddBox(0xFFFFFFFF, pos, Vector3f(cubeSize, cubeSize, cubeSize));
+ pos.z += cubeSpacing;
+ }
+
+ pos.z = corner.z;
+ pos.y += cubeSpacing;
+ }
+
+ pos.y = corner.y;
+ pos.x += cubeSpacing;
+ }
+}
+
+Fill* CreateTexureFill(RenderDevice* prender, const String& filename)
+{
+ Ptr<File> imageFile = *new SysFile(filename);
+ Ptr<Texture> imageTex;
+ if (imageFile->IsValid())
+ imageTex = *LoadTextureTga(prender, imageFile);
+
+ // Image is rendered as a single quad.
+ ShaderFill* fill = 0;
+ if (imageTex)
+ {
+ imageTex->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
+ fill = new ShaderFill(*prender->CreateShaderSet());
+ fill->GetShaders()->SetShader(prender->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
+ fill->GetShaders()->SetShader(prender->LoadBuiltinShader(Shader_Fragment, FShader_Texture));
+ fill->SetTexture(0, imageTex);
+ }
+
+ return fill;
+}
+
+
+// Loads the scene data
+void OculusWorldDemoApp::PopulateScene(const char *fileName)
+{
+ XmlHandler xmlHandler;
+ if(!xmlHandler.ReadFile(fileName, pRender, &MainScene, &CollisionModels, &GroundCollisionModels))
+ {
+ Menu.SetPopupMessage("FILE LOAD FAILED");
+ Menu.SetPopupTimeout(10.0f, true);
+ }
+
+ MainScene.SetAmbient(Color4f(1.0f, 1.0f, 1.0f, 1.0f));
+
+ // Handy cube.
+ Ptr<Model> smallGreenCubeModel = *Model::CreateBox(Color(0, 255, 0, 255), Vector3f(0.0f, 0.0f, 0.0f), Vector3f(0.004f, 0.004f, 0.004f));
+ SmallGreenCube.World.Add(smallGreenCubeModel);
+
+ String mainFilePathNoExtension = MainFilePath;
+ mainFilePathNoExtension.StripExtension();
+
+
+ // 10x10x10 cubes.
+ Ptr<Fill> fillR = *CreateTexureFill(pRender, mainFilePathNoExtension + "_redCube.tga");
+ PopulateCubeFieldScene(&RedCubesScene, fillR.GetPtr(), 10, 10, 10, Vector3f(0.0f, 0.0f, 0.0f), 0.4f);
+
+ // 10x10x10 cubes.
+ Ptr<Fill> fillB = *CreateTexureFill(pRender, mainFilePathNoExtension + "_blueCube.tga");
+ PopulateCubeFieldScene(&BlueCubesScene, fillB.GetPtr(), 10, 10, 10, Vector3f(0.0f, 0.0f, 0.0f), 0.4f);
+
+ // Anna: OculusWorldDemo/Assets/Tuscany/Tuscany_OculusCube.tga file needs to be added
+ Ptr<Fill> imageFill = *CreateTexureFill(pRender, mainFilePathNoExtension + "_OculusCube.tga");
+ PopulateCubeFieldScene(&OculusCubesScene, imageFill.GetPtr(), 11, 4, 35, Vector3f(0.0f, 0.0f, -6.0f), 0.5f);
+
+
+ float r = 0.01f;
+ Ptr<Model> purpleCubesModel = *new Model(Prim_Triangles);
+ for (int i = 0; i < 10; i++)
+ for (int j = 0; j < 10; j++)
+ for (int k = 0; k < 10; k++)
+ purpleCubesModel->AddSolidColorBox(i*0.25f-1.25f-r,j*0.25f-1.25f-r,k*0.25f-1.25f-r,
+ i*0.25f-1.25f+r,j*0.25f-1.25f+r,k*0.25f-1.25f+r,0xFF9F009F);
+}
+
+
+void OculusWorldDemoApp::PopulatePreloadScene()
+{
+ // Load-screen screen shot image
+ String fileName = MainFilePath;
+ fileName.StripExtension();
+
+ Ptr<File> imageFile = *new SysFile(fileName + "_LoadScreen.tga");
+ Ptr<Texture> imageTex;
+ if (imageFile->IsValid())
+ imageTex = *LoadTextureTga(pRender, imageFile);
+
+ // Image is rendered as a single quad.
+ if (imageTex)
+ {
+ imageTex->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
+ Ptr<Model> m = *new Model(Prim_Triangles);
+ m->AddVertex(-0.5f, 0.5f, 0.0f, Color(255,255,255,255), 0.0f, 0.0f);
+ m->AddVertex( 0.5f, 0.5f, 0.0f, Color(255,255,255,255), 1.0f, 0.0f);
+ m->AddVertex( 0.5f, -0.5f, 0.0f, Color(255,255,255,255), 1.0f, 1.0f);
+ m->AddVertex(-0.5f, -0.5f, 0.0f, Color(255,255,255,255), 0.0f, 1.0f);
+ m->AddTriangle(2,1,0);
+ m->AddTriangle(0,3,2);
+
+ Ptr<ShaderFill> fill = *new ShaderFill(*pRender->CreateShaderSet());
+ fill->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
+ fill->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Fragment, FShader_Texture));
+ fill->SetTexture(0, imageTex);
+ m->Fill = fill;
+
+ LoadingScene.World.Add(m);
+ }
+}
+
+void OculusWorldDemoApp::ClearScene()
+{
+ MainScene.Clear();
+ SmallGreenCube.Clear();
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Rendering Content
+
+
+void OculusWorldDemoApp::RenderAnimatedBlocks(ovrEyeType eye, double appTime)
+{
+ Matrix4f viewAdjust = Matrix4f::Translation(Vector3f(EyeRenderDesc[eye].ViewAdjust));
+
+ switch ( BlocksShowType )
+ {
+ case 0:
+ // No blocks;
+ break;
+ case 1: {
+ // Horizontal circle around your head.
+ int const numBlocks = 10;
+ float const radius = 1.0f;
+ Matrix4f scaleUp = Matrix4f::Scaling ( 20.0f );
+ double scaledTime = appTime * 0.1;
+ float fracTime = (float)( scaledTime - floor ( scaledTime ) );
+
+ for ( int j = 0; j < 2; j++ )
+ {
+ for ( int i = 0; i < numBlocks; i++ )
+ {
+ float angle = ( ( (float)i / numBlocks ) + fracTime ) * ( Math<float>::Pi * 2.0f );
+ Vector3f pos;
+ pos.x = BlocksCenter.x + radius * cosf ( angle );
+ pos.y = BlocksCenter.y;
+ pos.z = BlocksCenter.z + radius * sinf ( angle );
+ if ( j == 0 )
+ {
+ pos.x = BlocksCenter.x - radius * cosf ( angle );
+ pos.y = BlocksCenter.y - 0.5f;
+ }
+ Matrix4f mat = Matrix4f::Translation ( pos );
+ SmallGreenCube.Render(pRender, viewAdjust * View * mat * scaleUp);
+ }
+ }
+ }break;
+
+ case 2: {
+ // Vertical circle around your head.
+ int const numBlocks = 10;
+ float const radius = 1.0f;
+ Matrix4f scaleUp = Matrix4f::Scaling ( 20.0f );
+ double scaledTime = appTime * 0.1;
+ float fracTime = (float)( scaledTime - floor ( scaledTime ) );
+
+ for ( int j = 0; j < 2; j++ )
+ {
+ for ( int i = 0; i < numBlocks; i++ )
+ {
+ float angle = ( ( (float)i / numBlocks ) + fracTime ) * ( Math<float>::Pi * 2.0f );
+ Vector3f pos;
+ pos.x = BlocksCenter.x;
+ pos.y = BlocksCenter.y + radius * cosf ( angle );
+ pos.z = BlocksCenter.z + radius * sinf ( angle );
+ if ( j == 0 )
+ {
+ pos.x = BlocksCenter.x - 0.5f;
+ pos.y = BlocksCenter.y - radius * cosf ( angle );
+ }
+ Matrix4f mat = Matrix4f::Translation ( pos );
+ SmallGreenCube.Render(pRender, viewAdjust * View * mat * scaleUp);
+ }
+ }
+ }break;
+
+ case 3:{
+ // Bouncing.
+ int const numBlocks = 10;
+ Matrix4f scaleUp = Matrix4f::Scaling ( 20.0f );
+
+ for ( int i = 0; i < numBlocks; i++ )
+ {
+ double scaledTime = 4.0f * appTime / (double)i;
+ float fracTime = (float)( scaledTime - floor ( scaledTime ) );
+
+ Vector3f pos = BlocksCenter;
+ pos.z += (float)i;
+ pos.y += -1.5f + 4.0f * ( 2.0f * fracTime * ( 1.0f - fracTime ) );
+ Matrix4f mat = Matrix4f::Translation ( pos );
+ SmallGreenCube.Render(pRender, viewAdjust * View * mat * scaleUp);
+ }
+ }break;
+
+ default:
+ BlocksShowType = 0;
+ break;
+ }
+}
+
+void OculusWorldDemoApp::RenderGrid(ovrEyeType eye)
+{
+ Recti renderViewport = EyeTexture[eye].Header.RenderViewport;
+
+ // Draw actual pixel grid on the RT.
+ // 1:1 mapping to screen pixels, origin in top-left.
+ Matrix4f ortho;
+ ortho.SetIdentity();
+ ortho.M[0][0] = 2.0f / (renderViewport.w); // X scale
+ ortho.M[0][3] = -1.0f; // X offset
+ ortho.M[1][1] = -2.0f / (renderViewport.h); // Y scale (for Y=down)
+ ortho.M[1][3] = 1.0f; // Y offset (Y=down)
+ ortho.M[2][2] = 0;
+ pRender->SetProjection(ortho);
+
+ pRender->SetDepthMode(false, false);
+ Color cNormal ( 255, 0, 0 );
+ Color cSpacer ( 255, 255, 0 );
+ Color cMid ( 0, 128, 255 );
+
+ int lineStep = 1;
+ int midX = 0;
+ int midY = 0;
+ int limitX = 0;
+ int limitY = 0;
+
+ switch ( GridMode )
+ {
+ case Grid_Rendertarget4:
+ lineStep = 4;
+ midX = renderViewport.w / 2;
+ midY = renderViewport.h / 2;
+ limitX = renderViewport.w / 2;
+ limitY = renderViewport.h / 2;
+ break;
+ case Grid_Rendertarget16:
+ lineStep = 16;
+ midX = renderViewport.w / 2;
+ midY = renderViewport.h / 2;
+ limitX = renderViewport.w / 2;
+ limitY = renderViewport.h / 2;
+ break;
+ case Grid_Lens:
+ {
+ lineStep = 48;
+ Vector2f rendertargetNDC = FovPort(EyeRenderDesc[eye].Desc.Fov).TanAngleToRendertargetNDC(Vector2f(0.0f));
+ midX = (int)( ( rendertargetNDC.x * 0.5f + 0.5f ) * (float)renderViewport.w + 0.5f );
+ midY = (int)( ( rendertargetNDC.y * 0.5f + 0.5f ) * (float)renderViewport.h + 0.5f );
+ limitX = Alg::Max ( renderViewport.w - midX, midX );
+ limitY = Alg::Max ( renderViewport.h - midY, midY );
+ }
+ break;
+ default: OVR_ASSERT ( false ); break;
+ }
+
+ int spacerMask = (lineStep<<2)-1;
+
+
+ for ( int xp = 0; xp < limitX; xp += lineStep )
+ {
+ float x[4];
+ float y[4];
+ x[0] = (float)( midX + xp );
+ y[0] = (float)0;
+ x[1] = (float)( midX + xp );
+ y[1] = (float)renderViewport.h;
+ x[2] = (float)( midX - xp );
+ y[2] = (float)0;
+ x[3] = (float)( midX - xp );
+ y[3] = (float)renderViewport.h;
+ if ( xp == 0 )
+ {
+ pRender->RenderLines ( 1, cMid, x, y );
+ }
+ else if ( ( xp & spacerMask ) == 0 )
+ {
+ pRender->RenderLines ( 2, cSpacer, x, y );
+ }
+ else
+ {
+ pRender->RenderLines ( 2, cNormal, x, y );
+ }
+ }
+ for ( int yp = 0; yp < limitY; yp += lineStep )
+ {
+ float x[4];
+ float y[4];
+ x[0] = (float)0;
+ y[0] = (float)( midY + yp );
+ x[1] = (float)renderViewport.w;
+ y[1] = (float)( midY + yp );
+ x[2] = (float)0;
+ y[2] = (float)( midY - yp );
+ x[3] = (float)renderViewport.w;
+ y[3] = (float)( midY - yp );
+ if ( yp == 0 )
+ {
+ pRender->RenderLines ( 1, cMid, x, y );
+ }
+ else if ( ( yp & spacerMask ) == 0 )
+ {
+ pRender->RenderLines ( 2, cSpacer, x, y );
+ }
+ else
+ {
+ pRender->RenderLines ( 2, cNormal, x, y );
+ }
+ }
+}
+
diff --git a/Samples/OculusWorldDemo/OptionMenu.cpp b/Samples/OculusWorldDemo/OptionMenu.cpp
new file mode 100644
index 0000000..283136d
--- /dev/null
+++ b/Samples/OculusWorldDemo/OptionMenu.cpp
@@ -0,0 +1,896 @@
+/************************************************************************************
+
+Filename : OptionMenu.h
+Content : Option selection and editing for OculusWorldDemo
+Created : March 7, 2014
+Authors : Michael Antonov, Caleb Leak
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OptionMenu.h"
+
+// Embed the font.
+#include "../CommonSrc/Render/Render_FontEmbed_DejaVu48.h"
+
+
+//-------------------------------------------------------------------------------------
+bool OptionShortcut::MatchKey(KeyCode key, bool shift) const
+{
+ for (UInt32 i = 0; i < Keys.GetSize(); i++)
+ {
+ if (Keys[i].Key != key)
+ continue;
+
+ if (!shift && Keys[i].ShiftUsage == ShortcutKey::Shift_RequireOn)
+ continue;
+
+ if (shift && Keys[i].ShiftUsage == ShortcutKey::Shift_RequireOff)
+ continue;
+
+ if(Keys[i].ShiftUsage == ShortcutKey::Shift_Modify)
+ {
+ pNotify->CallNotify(&shift);
+ }
+ else
+ {
+ pNotify->CallNotify();
+ }
+ return true;
+ }
+ return false;
+}
+
+bool OptionShortcut::MatchGamepadButton(UInt32 gamepadButtonMask) const
+{
+ for (UInt32 i = 0; i < GamepadButtons.GetSize(); i++)
+ {
+ if (GamepadButtons[i] & gamepadButtonMask)
+ {
+ if (pNotify != NULL)
+ {
+ pNotify->CallNotify();
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+
+//-------------------------------------------------------------------------------------
+String OptionMenuItem::PopNamespaceFrom(OptionMenuItem* menuItem)
+{
+ String label = menuItem->Label;
+ for (UInt32 i = 0; i < label.GetLength(); i++)
+ {
+ if (label.GetCharAt(i) == '.')
+ {
+ String ns = label.Substring(0, i);
+ menuItem->Label = label.Substring(i + 1, label.GetLength());
+ return ns;
+ }
+ }
+ return "";
+}
+
+//-------------------------------------------------------------------------------------
+
+String OptionVar::FormatEnum(OptionVar* var)
+{
+ UInt32 index = var->GetEnumIndex();
+ if (index < var->EnumValues.GetSize())
+ return var->EnumValues[index].Name;
+ return String("<Bad enum index>");
+}
+
+String OptionVar::FormatInt(OptionVar* var)
+{
+ char buff[64];
+ OVR_sprintf(buff, sizeof(buff), var->FormatString, *var->AsInt());
+ return String(buff);
+}
+
+String OptionVar::FormatFloat(OptionVar* var)
+{
+ char buff[64];
+ OVR_sprintf(buff, sizeof(buff), var->FormatString, *var->AsFloat() * var->FormatScale);
+ return String(buff);
+}
+
+String OptionVar::FormatBool(OptionVar* var)
+{
+ return *var->AsBool() ? "On" : "Off";
+}
+
+
+OptionVar::OptionVar(const char* name, void* pvar, VarType type,
+ FormatFunction formatFunction,
+ UpdateFunction updateFunction)
+{
+ Label = name;
+ Type = type;
+ this->pVar = pvar;
+ fFormat = formatFunction;
+ fUpdate = updateFunction;
+ pNotify = 0;
+ FormatString= 0;
+
+ MaxFloat = Math<float>::MaxValue;
+ MinFloat = -Math<float>::MaxValue;
+ StepFloat = 1.0f;
+ FormatScale = 1.0f;
+
+ MaxInt = 0x7FFFFFFF;
+ MinInt = -(MaxInt) - 1;
+ StepInt = 1;
+
+ ShortcutUp.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::NextValue);
+ ShortcutDown.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::PrevValue);
+}
+
+OptionVar::OptionVar(const char* name, SInt32* pvar,
+ SInt32 min, SInt32 max, SInt32 stepSize,
+ const char* formatString,
+ FormatFunction formatFunction,
+ UpdateFunction updateFunction)
+{
+ Label = name;
+ Type = Type_Int;
+ this->pVar = pvar;
+ fFormat = formatFunction ? formatFunction : FormatInt;
+ fUpdate = updateFunction;
+ pNotify = 0;
+ FormatString= formatString;
+
+ MinInt = min;
+ MaxInt = max;
+ StepInt = stepSize;
+
+ ShortcutUp.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::NextValue);
+ ShortcutDown.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::PrevValue);
+}
+
+// Float with range and step size.
+OptionVar::OptionVar(const char* name, float* pvar,
+ float minf, float maxf, float stepSize,
+ const char* formatString, float formatScale,
+ FormatFunction formatFunction,
+ UpdateFunction updateFunction)
+{
+ Label = name;
+ Type = Type_Float;
+ this->pVar = pvar;
+ fFormat = formatFunction ? formatFunction : FormatFloat;
+ fUpdate = updateFunction;
+ pNotify = 0;
+ FormatString= formatString ? formatString : "%.3f";
+
+ MinFloat = minf;
+ MaxFloat = maxf;
+ StepFloat = stepSize;
+ FormatScale = formatScale;
+
+ ShortcutUp.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::NextValue);
+ ShortcutDown.pNotify = new FunctionNotifyContext<OptionVar, bool>(this, &OptionVar::PrevValue);
+}
+
+OptionVar::~OptionVar()
+{
+ if (pNotify)
+ delete pNotify;
+}
+
+void OptionVar::NextValue(bool* pFastStep)
+{
+ bool fastStep = (pFastStep != NULL && *pFastStep);
+ switch (Type)
+ {
+ case Type_Enum:
+ *AsInt() = ((GetEnumIndex() + 1) % EnumValues.GetSize());
+ break;
+
+ case Type_Int:
+ *AsInt() = Alg::Min<SInt32>(*AsInt() + StepInt * (fastStep ? 5 : 1), MaxInt);
+ break;
+
+ case Type_Float:
+ // TODO: Will behave strange with NaN values.
+ *AsFloat() = Alg::Min<float>(*AsFloat() + StepFloat * (fastStep ? 5.0f : 1.0f), MaxFloat);
+ break;
+
+ case Type_Bool:
+ *AsBool() = !*AsBool();
+ break;
+ }
+
+ SignalUpdate();
+}
+
+void OptionVar::PrevValue(bool* pFastStep)
+{
+ bool fastStep = (pFastStep != NULL && *pFastStep);
+ switch (Type)
+ {
+ case Type_Enum:
+ *AsInt() = ((GetEnumIndex() + (UInt32)EnumValues.GetSize() - 1) % EnumValues.GetSize());
+ break;
+
+ case Type_Int:
+ *AsInt() = Alg::Max<SInt32>(*AsInt() - StepInt * (fastStep ? 5 : 1), MinInt);
+ break;
+
+ case Type_Float:
+ // TODO: Will behave strange with NaN values.
+ *AsFloat() = Alg::Max<float>(*AsFloat() - StepFloat * (fastStep ? 5.0f : 1.0f), MinFloat);
+ break;
+
+ case Type_Bool:
+ *AsBool() = !*AsBool();
+ break;
+ }
+
+ SignalUpdate();
+}
+
+String OptionVar::HandleShortcutUpdate()
+{
+ SignalUpdate();
+ return Label + " - " + GetValue();
+}
+
+String OptionVar::ProcessShortcutKey(KeyCode key, bool shift)
+{
+ if (ShortcutUp.MatchKey(key, shift) || ShortcutDown.MatchKey(key, shift))
+ {
+ return HandleShortcutUpdate();
+ }
+
+ return String();
+}
+
+String OptionVar::ProcessShortcutButton(UInt32 buttonMask)
+{
+ if (ShortcutUp.MatchGamepadButton(buttonMask) || ShortcutDown.MatchGamepadButton(buttonMask))
+ {
+ return HandleShortcutUpdate();
+ }
+ return String();
+}
+
+
+OptionVar& OptionVar::AddEnumValue(const char* displayName, SInt32 value)
+{
+ EnumEntry entry;
+ entry.Name = displayName;
+ entry.Value = value;
+ EnumValues.PushBack(entry);
+ return *this;
+}
+
+String OptionVar::GetValue()
+{
+ return fFormat(this);
+}
+
+UInt32 OptionVar::GetEnumIndex()
+{
+ OVR_ASSERT(Type == Type_Enum);
+ OVR_ASSERT(EnumValues.GetSize() > 0);
+
+ // TODO: Change this from a linear search to binary or a hash.
+ for (UInt32 i = 0; i < EnumValues.GetSize(); i++)
+ {
+ if (EnumValues[i].Value == *AsInt())
+ return i;
+ }
+
+ // Enum values should always be found.
+ OVR_ASSERT(false);
+ return 0;
+}
+
+
+//-------------------------------------------------------------------------------------
+
+OptionSelectionMenu::OptionSelectionMenu(OptionSelectionMenu* parentMenu)
+{
+ DisplayState = Display_None;
+ SelectedIndex = 0;
+ SelectionActive = false;
+ ParentMenu = parentMenu;
+
+ PopupMessageTimeout = 0.0;
+ PopupMessageBorder = false;
+
+ // Setup handlers for menu navigation actions.
+ NavShortcuts[Nav_Up].pNotify = new FunctionNotifyContext<OptionSelectionMenu, bool>(this, &OptionSelectionMenu::HandleUp);
+ NavShortcuts[Nav_Down].pNotify = new FunctionNotifyContext<OptionSelectionMenu, bool>(this, &OptionSelectionMenu::HandleDown);
+ NavShortcuts[Nav_Left].pNotify = new FunctionNotifySimple<OptionSelectionMenu>(this, &OptionSelectionMenu::HandleLeft);
+ NavShortcuts[Nav_Right].pNotify = new FunctionNotifySimple<OptionSelectionMenu>(this, &OptionSelectionMenu::HandleRight);
+ NavShortcuts[Nav_Select].pNotify = new FunctionNotifySimple<OptionSelectionMenu>(this, &OptionSelectionMenu::HandleSelect);
+ NavShortcuts[Nav_Back].pNotify = new FunctionNotifySimple<OptionSelectionMenu>(this, &OptionSelectionMenu::HandleBack);
+ ToggleShortcut.pNotify = new FunctionNotifySimple<OptionSelectionMenu>(this, &OptionSelectionMenu::HandleMenuToggle);
+ ToggleSingleItemShortcut.pNotify = new FunctionNotifySimple<OptionSelectionMenu>(this, &OptionSelectionMenu::HandleSingleItemToggle);
+
+ // Bind keys and buttons to menu navigation actions.
+ NavShortcuts[Nav_Up].AddShortcut(ShortcutKey(Key_Up, ShortcutKey::Shift_Modify));
+ NavShortcuts[Nav_Up].AddShortcut(Gamepad_Up);
+
+ NavShortcuts[Nav_Down].AddShortcut(ShortcutKey(Key_Down, ShortcutKey::Shift_Modify));
+ NavShortcuts[Nav_Down].AddShortcut(Gamepad_Down);
+
+ NavShortcuts[Nav_Left].AddShortcut(ShortcutKey(Key_Left));
+ NavShortcuts[Nav_Left].AddShortcut(Gamepad_Left);
+
+ NavShortcuts[Nav_Right].AddShortcut(ShortcutKey(Key_Right));
+ NavShortcuts[Nav_Right].AddShortcut(Gamepad_Right);
+
+ NavShortcuts[Nav_Select].AddShortcut(ShortcutKey(Key_Return));
+ NavShortcuts[Nav_Select].AddShortcut(Gamepad_A);
+
+ NavShortcuts[Nav_Back].AddShortcut(ShortcutKey(Key_Escape));
+ NavShortcuts[Nav_Back].AddShortcut(Gamepad_B);
+
+ ToggleShortcut.AddShortcut(ShortcutKey(Key_Tab, ShortcutKey::Shift_Ignore));
+ ToggleShortcut.AddShortcut(Gamepad_Start);
+
+ ToggleSingleItemShortcut.AddShortcut(ShortcutKey(Key_Backspace, ShortcutKey::Shift_Ignore));
+}
+
+OptionSelectionMenu::~OptionSelectionMenu()
+{
+ for (UInt32 i = 0; i < Items.GetSize(); i++)
+ delete Items[i];
+}
+
+bool OptionSelectionMenu::OnKey(OVR::KeyCode key, int chr, bool down, int modifiers)
+{
+ bool shift = ((modifiers & Mod_Shift) != 0);
+
+ if (down)
+ {
+ String s = ProcessShortcutKey(key, shift);
+ if (!s.IsEmpty())
+ {
+ PopupMessage = s;
+ PopupMessageTimeout = ovr_GetTimeInSeconds() + 4.0f;
+ PopupMessageBorder = false;
+ return true;
+ }
+ }
+
+ if (GetSubmenu() != NULL)
+ {
+ return GetSubmenu()->OnKey(key, chr, down, modifiers);
+ }
+
+ if (down)
+ {
+ if (ToggleShortcut.MatchKey(key, shift))
+ return true;
+
+ if (ToggleSingleItemShortcut.MatchKey(key, shift))
+ return true;
+
+ if (DisplayState == Display_None)
+ return false;
+
+ for (int i = 0; i < Nav_LAST; i++)
+ {
+ if (NavShortcuts[i].MatchKey(key, shift))
+ return true;
+ }
+ }
+
+ // Let the caller process keystroke
+ return false;
+}
+
+bool OptionSelectionMenu::OnGamepad(UInt32 buttonMask)
+{
+ // Check global shortcuts first.
+ String s = ProcessShortcutButton(buttonMask);
+ if (!s.IsEmpty())
+ {
+ PopupMessage = s;
+ PopupMessageTimeout = ovr_GetTimeInSeconds() + 4.0f;
+ return true;
+ }
+
+ if (GetSubmenu() != NULL)
+ {
+ return GetSubmenu()->OnGamepad(buttonMask);
+ }
+
+ if (ToggleShortcut.MatchGamepadButton(buttonMask))
+ return true;
+
+ if (DisplayState == Display_None)
+ return false;
+
+ for (int i = 0; i < Nav_LAST; i++)
+ {
+ if (NavShortcuts[i].MatchGamepadButton(buttonMask))
+ return true;
+ }
+
+ // Let the caller process keystroke
+ return false;
+}
+
+String OptionSelectionMenu::ProcessShortcutKey(KeyCode key, bool shift)
+{
+ String s;
+
+ for (UPInt i = 0; (i < Items.GetSize()) && s.IsEmpty(); i++)
+ {
+ s = Items[i]->ProcessShortcutKey(key, shift);
+ }
+
+ return s;
+}
+
+String OptionSelectionMenu::ProcessShortcutButton(UInt32 buttonMask)
+{
+ String s;
+
+ for (UPInt i = 0; (i < Items.GetSize()) && s.IsEmpty(); i++)
+ {
+ s = Items[i]->ProcessShortcutButton(buttonMask);
+ }
+
+ return s;
+}
+
+// Fills in inclusive character range; returns false if line not found.
+bool FindLineCharRange(const char* text, int searchLine, UPInt charRange[2])
+{
+ UPInt i = 0;
+
+ for (int line = 0; line <= searchLine; line ++)
+ {
+ if (line == searchLine)
+ {
+ charRange[0] = i;
+ }
+
+ // Find end of line.
+ while (text[i] != '\n' && text[i] != 0)
+ {
+ i++;
+ }
+
+ if (line == searchLine)
+ {
+ charRange[1] = (charRange[0] == i) ? charRange[0] : i-1;
+ return true;
+ }
+
+ if (text[i] == 0)
+ break;
+ // Skip newline
+ i++;
+ }
+
+ return false;
+}
+
+
+void OptionSelectionMenu::Render(RenderDevice* prender, String title)
+{
+ // If we are invisible, render shortcut notifications.
+ // Both child and parent have visible == true even if only child is shown.
+ if (DisplayState == Display_None)
+ {
+ renderShortcutChangeMessage(prender);
+ return;
+ }
+
+ title += Label;
+
+ // Delegate to sub-menu if active.
+ if (GetSubmenu() != NULL)
+ {
+ if (title.GetSize() > 0)
+ title += " > ";
+
+ GetSubmenu()->Render(prender, title);
+ return;
+ }
+
+ Color focusColor(180, 80, 20, 210);
+ Color pickedColor(120, 55, 10, 140);
+ Color titleColor(0x18, 0x1A, 0x4D, 210);
+ Color titleOutlineColor(0x18, 0x18, 0x18, 240);
+
+ float labelsSize[2] = {0.0f, 0.0f};
+ float bufferSize[2] = {0.0f, 0.0f};
+ float valuesSize[2] = {0.0f, 0.0f};
+ float maxValueWidth = 0.0f;
+
+ UPInt selection[2] = { 0, 0 };
+ Vector2f labelSelectionRect[2];
+ Vector2f valueSelectionRect[2];
+ bool havelLabelSelection = false;
+ bool haveValueSelection = false;
+
+ float textSize = 22.0f;
+ prender->MeasureText(&DejaVu, " ", textSize, bufferSize);
+
+ String values;
+ String menuItems;
+
+ int highlightIndex = 0;
+ if (DisplayState == Display_Menu)
+ {
+ highlightIndex = SelectedIndex;
+ for (UInt32 i = 0; i < Items.GetSize(); i++)
+ {
+ if (i > 0)
+ values += "\n";
+ values += Items[i]->GetValue();
+ }
+
+ for (UInt32 i = 0; i < Items.GetSize(); i++)
+ {
+ if (i > 0)
+ menuItems += "\n";
+ menuItems += Items[i]->GetLabel();
+ }
+ }
+ else
+ {
+ values = Items[SelectedIndex]->GetValue();
+ menuItems = Items[SelectedIndex]->GetLabel();
+ }
+
+ // Measure labels
+ const char* menuItemsCStr = menuItems.ToCStr();
+ havelLabelSelection = FindLineCharRange(menuItemsCStr, highlightIndex, selection);
+ prender->MeasureText(&DejaVu, menuItemsCStr, textSize, labelsSize,
+ selection, labelSelectionRect);
+
+ // Measure label-to-value gap
+ const char* valuesCStr = values.ToCStr();
+ haveValueSelection = FindLineCharRange(valuesCStr, highlightIndex, selection);
+ prender->MeasureText(&DejaVu, valuesCStr, textSize, valuesSize, selection, valueSelectionRect);
+
+ // Measure max value size (absolute size varies, so just use a reasonable max)
+ maxValueWidth = prender->MeasureText(&DejaVu, "Max value width", textSize);
+ maxValueWidth = Alg::Max(maxValueWidth, valuesSize[0]);
+
+ Vector2f borderSize(4.0f, 4.0f);
+ Vector2f totalDimensions = borderSize * 2 + Vector2f(bufferSize[0], 0) + Vector2f(maxValueWidth, 0)
+ + Vector2f(labelsSize[0], labelsSize[1]);
+
+ Vector2f fudgeOffset= Vector2f(10.0f, 25.0f); // This offset looks better
+ Vector2f topLeft = (-totalDimensions / 2.0f) + fudgeOffset;
+ Vector2f bottomRight = topLeft + totalDimensions;
+
+ // If displaying a single item, shift it down.
+ if (DisplayState == Display_SingleItem)
+ {
+ topLeft.y += textSize * 7;
+ bottomRight.y += textSize * 7;
+ }
+
+ prender->FillRect(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y, Color(40,40,100,210));
+
+ Vector2f labelsPos = topLeft + borderSize;
+ Vector2f valuesPos = labelsPos + Vector2f(labelsSize[0], 0) + Vector2f(bufferSize[0], 0);
+
+ // Highlight selected label
+ Vector2f selectionInset = Vector2f(0.3f, 2.0f);
+ if (DisplayState == Display_Menu)
+ {
+ Vector2f labelSelectionTopLeft = labelsPos + labelSelectionRect[0] - selectionInset;
+ Vector2f labelSelectionBottomRight = labelsPos + labelSelectionRect[1] + selectionInset;
+
+ prender->FillRect(labelSelectionTopLeft.x, labelSelectionTopLeft.y,
+ labelSelectionBottomRight.x, labelSelectionBottomRight.y,
+ SelectionActive ? pickedColor : focusColor);
+ }
+
+ // Highlight selected value if active
+ if (SelectionActive)
+ {
+ Vector2f valueSelectionTopLeft = valuesPos + valueSelectionRect[0] - selectionInset;
+ Vector2f valueSelectionBottomRight = valuesPos + valueSelectionRect[1] + selectionInset;
+ prender->FillRect(valueSelectionTopLeft.x, valueSelectionTopLeft.y,
+ valueSelectionBottomRight.x, valueSelectionBottomRight.y,
+ focusColor);
+ }
+
+ // Measure and draw title
+ if (DisplayState == Display_Menu && title.GetLength() > 0)
+ {
+ Vector2f titleDimensions;
+ prender->MeasureText(&DejaVu, title.ToCStr(), textSize, &titleDimensions.x);
+ Vector2f titleTopLeft = topLeft - Vector2f(0, borderSize.y) * 2 - Vector2f(0, titleDimensions.y);
+ titleDimensions.x = totalDimensions.x;
+
+ prender->FillRect(titleTopLeft.x, titleTopLeft.y,
+ titleTopLeft.x + totalDimensions.x,
+ titleTopLeft.y + titleDimensions.y + borderSize.y * 2,
+ titleOutlineColor);
+
+ prender->FillRect(titleTopLeft.x + borderSize.x / 2, titleTopLeft.y + borderSize.y / 2,
+ titleTopLeft.x + totalDimensions.x - borderSize.x / 2,
+ titleTopLeft.y + borderSize.y / 2 + titleDimensions.y,
+ titleColor);
+
+ prender->RenderText(&DejaVu, title.ToCStr(), titleTopLeft.x + borderSize.x,
+ titleTopLeft.y + borderSize.y, textSize, Color(255,255,0,210));
+ }
+
+ prender->RenderText(&DejaVu, menuItemsCStr, labelsPos.x, labelsPos.y, textSize, Color(255,255,0,210));
+
+ prender->RenderText(&DejaVu, valuesCStr, valuesPos.x, valuesPos.y, textSize, Color(255,255,0,210));
+}
+
+
+void OptionSelectionMenu::renderShortcutChangeMessage(RenderDevice* prender)
+{
+ if (ovr_GetTimeInSeconds() < PopupMessageTimeout)
+ {
+ DrawTextBox(prender, 0, 120, 22.0f, PopupMessage.ToCStr(),
+ DrawText_Center | (PopupMessageBorder ? DrawText_Border : 0));
+ }
+}
+
+
+void OptionSelectionMenu::SetPopupMessage(const char* format, ...)
+{
+ //Lock::Locker lock(pManager->GetHandlerLock());
+ char textBuff[2048];
+ va_list argList;
+ va_start(argList, format);
+ OVR_vsprintf(textBuff, sizeof(textBuff), format, argList);
+ va_end(argList);
+
+ // Message will time out in 4 seconds.
+ PopupMessage = textBuff;
+ PopupMessageTimeout = ovr_GetTimeInSeconds() + 4.0f;
+ PopupMessageBorder = false;
+}
+
+void OptionSelectionMenu::SetPopupTimeout(double timeoutSeconds, bool border)
+{
+ PopupMessageTimeout = ovr_GetTimeInSeconds() + timeoutSeconds;
+ PopupMessageBorder = border;
+}
+
+
+
+void OptionSelectionMenu::AddItem(OptionMenuItem* menuItem)
+{
+ String ns = PopNamespaceFrom(menuItem);
+
+ if (ns.GetLength() == 0)
+ {
+ Items.PushBack(menuItem);
+ }
+ else
+ {
+ // Item is part of a submenu, add it to that instead.
+ GetOrCreateSubmenu(ns)->AddItem(menuItem);
+ }
+}
+
+//virtual
+void OptionSelectionMenu::Select()
+{
+ SelectedIndex = 0;
+ SelectionActive = false;
+ DisplayState = Display_Menu;
+}
+
+
+OptionSelectionMenu* OptionSelectionMenu::GetSubmenu()
+{
+ if (!SelectionActive)
+ return NULL;
+
+ OptionSelectionMenu* submenu = dynamic_cast<OptionSelectionMenu*>(Items[SelectedIndex]);
+ return submenu;
+}
+
+
+OptionSelectionMenu* OptionSelectionMenu::GetOrCreateSubmenu(String submenuName)
+{
+ for (UInt32 i = 0; i < Items.GetSize(); i++)
+ {
+ OptionSelectionMenu* submenu = dynamic_cast<OptionSelectionMenu*>(Items[i]);
+
+ if (submenu != NULL && submenu->Label == submenuName)
+ {
+ return submenu;
+ }
+ }
+
+ // Submenu doesn't exist, create it.
+ OptionSelectionMenu* newSubmenu = new OptionSelectionMenu(this);
+ newSubmenu->Label = submenuName;
+ Items.PushBack(newSubmenu);
+ return newSubmenu;
+}
+
+void OptionSelectionMenu::HandleUp(bool* pFast)
+{
+ int numItems = (int)Items.GetSize();
+ if (SelectionActive)
+ Items[SelectedIndex]->NextValue(pFast);
+ else
+ SelectedIndex = ((SelectedIndex - 1 + numItems) % numItems);
+}
+
+void OptionSelectionMenu::HandleDown(bool* pFast)
+{
+ if (SelectionActive)
+ Items[SelectedIndex]->PrevValue(pFast);
+ else
+ SelectedIndex = ((SelectedIndex + 1) % Items.GetSize());
+}
+
+void OptionSelectionMenu::HandleLeft()
+{
+ if (DisplayState != Display_Menu)
+ return;
+
+ if (SelectionActive)
+ SelectionActive = false;
+ else if (ParentMenu)
+ {
+ // Escape to parent menu
+ ParentMenu->SelectionActive = false;
+ DisplayState = Display_Menu;
+ }
+}
+
+void OptionSelectionMenu::HandleRight()
+{
+ if (DisplayState != Display_Menu)
+ return;
+
+ if (!SelectionActive)
+ {
+ SelectionActive = true;
+ Items[SelectedIndex]->Select();
+ }
+}
+
+void OptionSelectionMenu::HandleSelect()
+{
+ if (!SelectionActive)
+ {
+ SelectionActive = true;
+ Items[SelectedIndex]->Select();
+ }
+ else
+ {
+ Items[SelectedIndex]->NextValue();
+ }
+}
+
+void OptionSelectionMenu::HandleBack()
+{
+ if (DisplayState != Display_Menu)
+ return;
+
+ if (!SelectionActive)
+ DisplayState = Display_None;
+ else
+ SelectionActive = false;
+}
+
+void OptionSelectionMenu::HandleMenuToggle()
+{
+ // Mark this & parent With correct visibility.
+ OptionSelectionMenu* menu = this;
+
+ if (DisplayState == Display_Menu)
+ DisplayState = Display_None;
+ else
+ DisplayState = Display_Menu;
+
+ while (menu)
+ {
+ menu->DisplayState = DisplayState;
+ menu = menu->ParentMenu;
+ }
+ // Hide message
+ PopupMessageTimeout = 0;
+}
+
+void OptionSelectionMenu::HandleSingleItemToggle()
+{
+ // Mark this & parent With correct visibility.
+ OptionSelectionMenu* menu = this;
+
+ if (DisplayState == Display_SingleItem)
+ DisplayState = Display_None;
+ else
+ {
+ DisplayState = Display_SingleItem;
+ SelectionActive = true;
+ }
+
+ while (menu)
+ {
+ menu->DisplayState = DisplayState;
+ menu = menu->ParentMenu;
+ }
+ // Hide message
+ PopupMessageTimeout = 0;
+}
+
+
+//-------------------------------------------------------------------------------------
+// **** Text Rendering / Management
+
+void DrawTextBox(RenderDevice* prender, float x, float y,
+ float textSize, const char* text, unsigned centerType)
+{
+ float ssize[2] = {0.0f, 0.0f};
+
+ prender->MeasureText(&DejaVu, text, textSize, ssize);
+
+ // Treat 0 a VCenter.
+ if (centerType & DrawText_HCenter)
+ {
+ x -= ssize[0]/2;
+ }
+ if (centerType & DrawText_VCenter)
+ {
+ y -= ssize[1]/2;
+ }
+
+ const float borderSize = 4.0f;
+ float linesHeight = 0.0f;
+
+ if (centerType & DrawText_Border)
+ linesHeight = 10.0f;
+
+ prender->FillRect(x-borderSize, y-borderSize - linesHeight,
+ x+ssize[0]+borderSize, y+ssize[1]+borderSize + linesHeight,
+ Color(40,40,100,210));
+
+ if (centerType & DrawText_Border)
+ {
+ // Add top & bottom lines
+ float topLineY = y-borderSize - linesHeight * 0.5f,
+ bottomLineY = y+ssize[1]+borderSize + linesHeight * 0.5f;
+
+ prender->FillRect(x-borderSize * 0.5f, topLineY,
+ x+ssize[0]+borderSize * 0.5f, topLineY + 2.0f,
+ Color(255,255,0,210));
+ prender->FillRect(x-borderSize * 0.5f, bottomLineY,
+ x+ssize[0]+borderSize * 0.5f, bottomLineY + 2.0f,
+ Color(255,255,0,210));
+ }
+
+ prender->RenderText(&DejaVu, text, x, y, textSize, Color(255,255,0,210));
+}
+
+void CleanupDrawTextFont()
+{
+ if (DejaVu.fill)
+ {
+ DejaVu.fill->Release();
+ DejaVu.fill = 0;
+ }
+}
diff --git a/Samples/OculusWorldDemo/OptionMenu.h b/Samples/OculusWorldDemo/OptionMenu.h
new file mode 100644
index 0000000..ba90b08
--- /dev/null
+++ b/Samples/OculusWorldDemo/OptionMenu.h
@@ -0,0 +1,442 @@
+/************************************************************************************
+
+Filename : OptionMenu.h
+Content : Option selection and editing for OculusWorldDemo
+Created : March 7, 2014
+Authors : Michael Antonov, Caleb Leak
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef INC_OptionMenu_h
+#define INC_OptionMenu_h
+
+#include "OVR.h"
+
+#include "../CommonSrc/Platform/Platform_Default.h"
+#include "../CommonSrc/Render/Render_Device.h"
+#include "../CommonSrc/Platform/Gamepad.h"
+
+#include "Util/Util_Render_Stereo.h"
+using namespace OVR::Util::Render;
+
+#include <Kernel/OVR_SysFile.h>
+#include <Kernel/OVR_Log.h>
+#include <Kernel/OVR_Timer.h>
+
+#include "Player.h"
+#include "OVR_DeviceConstants.h"
+
+
+using namespace OVR;
+using namespace OVR::Platform;
+using namespace OVR::Render;
+
+
+//-------------------------------------------------------------------------------------
+struct FunctionNotifyBase : public NewOverrideBase
+{
+ virtual void CallNotify(void*) { }
+ virtual void CallNotify() { }
+};
+
+// Simple member pointer wrapper to support calling class members
+template<class C, class X>
+struct FunctionNotifyContext : public FunctionNotifyBase
+{
+ typedef void (C::*FnPtr)(X*);
+
+ FunctionNotifyContext(C* p, FnPtr fn) : pClass(p), pFn(fn), pContext(NULL) { }
+ FunctionNotifyContext(C* p, FnPtr fn, X* pContext) : pClass(p), pFn(fn), pContext(pContext) { }
+ virtual void CallNotify(void* var) { (void)(pClass->*pFn)(static_cast<X*>(var)); }
+ virtual void CallNotify() { (void)(pClass->*pFn)(pContext); }
+private:
+
+ X* pContext;
+ C* pClass;
+ FnPtr pFn;
+};
+
+template<class C>
+struct FunctionNotifySimple : public FunctionNotifyBase
+{
+ typedef void (C::*FnPtr)(void);
+
+ FunctionNotifySimple(C* p, FnPtr fn) : pClass(p), pFn(fn) { }
+ virtual void CallNotify(void*) { CallNotify(); }
+ virtual void CallNotify() { (void)(pClass->*pFn)(); }
+private:
+
+ C* pClass;
+ FnPtr pFn;
+};
+
+
+//-------------------------------------------------------------------------------------
+// Describes a shortcut key
+struct ShortcutKey
+{
+ enum ShiftUsageType
+ {
+ Shift_Ignore,
+ Shift_Modify,
+ Shift_RequireOn,
+ Shift_RequireOff
+ };
+
+ ShortcutKey(KeyCode key = Key_None, ShiftUsageType shiftUsage = Shift_RequireOff)
+ : Key(key), ShiftUsage(shiftUsage) { }
+
+ KeyCode Key;
+ ShiftUsageType ShiftUsage;
+};
+
+
+//-------------------------------------------------------------------------------------
+struct OptionShortcut
+{
+ Array<ShortcutKey> Keys;
+ Array<UInt32> GamepadButtons;
+ FunctionNotifyBase* pNotify;
+
+ OptionShortcut() : pNotify(NULL) {}
+ OptionShortcut(FunctionNotifyBase* pNotify) : pNotify(pNotify) {}
+ ~OptionShortcut() { if (pNotify) delete pNotify; }
+
+ void AddShortcut(ShortcutKey key) { Keys.PushBack(key); }
+ void AddShortcut(UInt32 gamepadButton) { GamepadButtons.PushBack(gamepadButton); }
+
+ bool MatchKey(KeyCode key, bool shift) const;
+ bool MatchGamepadButton(UInt32 gamepadButtonMask) const;
+};
+
+
+//-------------------------------------------------------------------------------------
+
+// Base class for a menu item. Internally, this can also be OptionSelectionMenu itself
+// to support nested menus. Users shouldn't need to use this class.
+class OptionMenuItem : public NewOverrideBase
+{
+public:
+ virtual ~OptionMenuItem() { }
+
+ virtual void Select() { }
+
+ virtual void NextValue(bool* pFastStep = NULL) { OVR_UNUSED1(pFastStep); }
+ virtual void PrevValue(bool* pFastStep = NULL) { OVR_UNUSED1(pFastStep); }
+
+ virtual String GetLabel() { return Label; }
+ virtual String GetValue() { return ""; }
+
+ // Returns empty string if shortcut not handled
+ virtual String ProcessShortcutKey(KeyCode key, bool shift) = 0;
+ virtual String ProcessShortcutButton(UInt32 buttonMask) = 0;
+
+protected:
+ String Label;
+ String PopNamespaceFrom(OptionMenuItem* menuItem);
+};
+
+
+//-------------------------------------------------------------------------------------
+
+// OptionVar implements a basic menu item, which binds to an external variable,
+// displaying and editing its state.
+class OptionVar : public OptionMenuItem
+{
+public:
+
+ enum VarType
+ {
+ Type_Enum,
+ Type_Int,
+ Type_Float,
+ Type_Bool
+ };
+
+ typedef String (*FormatFunction)(OptionVar*);
+ typedef void (*UpdateFunction)(OptionVar*);
+
+ static String FormatEnum(OptionVar* var);
+ static String FormatInt(OptionVar* var);
+ static String FormatFloat(OptionVar* var);
+ static String FormatTan(OptionVar* var);
+ static String FormatBool(OptionVar* var);
+
+ OptionVar(const char* name, void* pVar, VarType type,
+ FormatFunction formatFunction,
+ UpdateFunction updateFunction = NULL);
+
+ // Integer with range and step size.
+ OptionVar(const char* name, SInt32* pVar,
+ SInt32 min, SInt32 max, SInt32 stepSize=1,
+ const char* formatString = "%d",
+ FormatFunction formatFunction = 0, // Default int formatting.
+ UpdateFunction updateFunction = NULL);
+
+ // Float with range and step size.
+ OptionVar(const char* name, float* pvar,
+ float minf, float maxf, float stepSize = 1.0f,
+ const char* formatString = "%.3f", float formatScale = 1.0f,
+ FormatFunction formatFunction = 0, // Default float formatting.
+ UpdateFunction updateFunction = 0 );
+
+ virtual ~OptionVar();
+
+ SInt32* AsInt() { return reinterpret_cast<SInt32*>(pVar); }
+ bool* AsBool() { return reinterpret_cast<bool*>(pVar); }
+ float* AsFloat() { return reinterpret_cast<float*>(pVar); }
+ VarType GetType() { return Type; }
+
+ // Step through values (wrap for enums).
+ virtual void NextValue(bool* pFastStep);
+ virtual void PrevValue(bool* pFastStep);
+
+ // Executes shortcut message and returns notification string.
+ // Returns empty string for no action.
+ String HandleShortcutUpdate();
+ virtual String ProcessShortcutKey(KeyCode key, bool shift);
+ virtual String ProcessShortcutButton(UInt32 buttonMask);
+
+ OptionVar& AddEnumValue(const char* displayName, SInt32 value);
+
+ template<class C>
+ OptionVar& SetNotify(C* p, void (C::*fn)(OptionVar*))
+ {
+ OVR_ASSERT(pNotify == 0); // Can't set notifier twice.
+ pNotify = new FunctionNotifyContext<C, OptionVar>(p, fn, this);
+ return *this;
+ }
+
+
+ //String Format();
+ virtual String GetValue();
+
+ OptionVar& AddShortcutUpKey(const ShortcutKey& shortcut)
+ { ShortcutUp.AddShortcut(shortcut); return *this; }
+ OptionVar& AddShortcutUpKey(KeyCode key,
+ ShortcutKey::ShiftUsageType shiftUsage = ShortcutKey::Shift_Modify)
+ { ShortcutUp.AddShortcut(ShortcutKey(key, shiftUsage)); return *this; }
+ OptionVar& AddShortcutUpButton(UInt32 gamepadButton)
+ { ShortcutUp.AddShortcut(gamepadButton); return *this; }
+
+ OptionVar& AddShortcutDownKey(const ShortcutKey& shortcut)
+ { ShortcutDown.AddShortcut(shortcut); return *this; }
+ OptionVar& AddShortcutDownKey(KeyCode key,
+ ShortcutKey::ShiftUsageType shiftUsage = ShortcutKey::Shift_Modify)
+ { ShortcutDown.AddShortcut(ShortcutKey(key, shiftUsage)); return *this; }
+ OptionVar& AddShortcutDownButton(UInt32 gamepadButton)
+ { ShortcutDown.AddShortcut(gamepadButton); return *this; }
+
+ OptionVar& AddShortcutKey(const ShortcutKey& shortcut)
+ { return AddShortcutUpKey(shortcut); }
+ OptionVar& AddShortcutKey(KeyCode key,
+ ShortcutKey::ShiftUsageType shiftUsage = ShortcutKey::Shift_RequireOff)
+ { return AddShortcutUpKey(key, shiftUsage); }
+ OptionVar& AddShortcutButton(UInt32 gamepadButton)
+ { return AddShortcutUpButton(gamepadButton); }
+
+private:
+
+ void SignalUpdate()
+ {
+ if (fUpdate) fUpdate(this);
+ if (pNotify) pNotify->CallNotify(this);
+ }
+
+ struct EnumEntry
+ {
+ // Human readable name for enum.
+ String Name;
+ SInt32 Value;
+ };
+
+ // Array of possible enum values.
+ Array<EnumEntry> EnumValues;
+ // Gets the index of the current enum value.
+ UInt32 GetEnumIndex();
+
+ FormatFunction fFormat;
+ UpdateFunction fUpdate;
+ FunctionNotifyBase* pNotify;
+
+ VarType Type;
+ void* pVar;
+ const char* FormatString;
+
+ OptionShortcut ShortcutUp;
+ OptionShortcut ShortcutDown;
+
+ float MinFloat;
+ float MaxFloat;
+ float StepFloat;
+ float FormatScale; // Multiply float by this before rendering
+
+ SInt32 MinInt;
+ SInt32 MaxInt;
+ SInt32 StepInt;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** OptionSelectionMenu
+
+// Implements an overlay option menu, brought up by the 'Tab' key.
+// Items are added to the menu with AddBool, AddEnum, AddFloat on startup,
+// and are editable by using arrow keys (underlying variable is modified).
+//
+// Call Render() to render the menu every frame.
+//
+// Menu also support displaying popup messages with a timeout, displayed
+// when menu body isn't up.
+
+class OptionSelectionMenu : public OptionMenuItem
+{
+public:
+ OptionSelectionMenu(OptionSelectionMenu* parentMenu = NULL);
+ ~OptionSelectionMenu();
+
+
+ bool OnKey(OVR::KeyCode key, int chr, bool down, int modifiers);
+ bool OnGamepad(UInt32 buttonMask);
+
+ void Render(RenderDevice* prender, String title = "");
+
+ void AddItem(OptionMenuItem* menuItem);
+
+ // Adds a boolean toggle. Returns added item to allow customization.
+ OptionVar& AddBool(const char* name, bool* pvar,
+ OptionVar::UpdateFunction updateFunction = 0,
+ OptionVar::FormatFunction formatFunction = OptionVar::FormatBool)
+ {
+ OptionVar* p = new OptionVar(name, pvar, OptionVar::Type_Bool,
+ formatFunction, updateFunction);
+ AddItem(p);
+ return *p;
+ }
+
+ // Adds a boolean toggle. Returns added item to allow customization.
+ OptionVar& AddEnum(const char* name, void* pvar,
+ OptionVar::UpdateFunction updateFunction = 0)
+ {
+ OptionVar* p = new OptionVar(name, pvar, OptionVar::Type_Enum,
+ OptionVar::FormatEnum, updateFunction);
+ AddItem(p);
+ return *p;
+ }
+
+
+ // Adds a Float variable. Returns added item to allow customization.
+ OptionVar& AddFloat( const char* name, float* pvar,
+ float minf, float maxf, float stepSize = 1.0f,
+ const char* formatString = "%.3f", float formatScale = 1.0f,
+ OptionVar::FormatFunction formatFunction = 0, // Default float formatting.
+ OptionVar::UpdateFunction updateFunction = 0 )
+ {
+ OptionVar* p = new OptionVar(name, pvar, minf, maxf, stepSize,
+ formatString, formatScale,
+ formatFunction, updateFunction);
+ AddItem(p);
+ return *p;
+ }
+
+ virtual void Select();
+ virtual String GetLabel() { return Label + " >"; }
+
+ virtual String ProcessShortcutKey(KeyCode key, bool shift);
+ virtual String ProcessShortcutButton(UInt32 buttonMask);
+
+ // Sets a message to display with a time-out. Default time-out is 4 seconds.
+ // This uses the same overlay approach as used for shortcut notifications.
+ void SetPopupMessage(const char* format, ...);
+ // Overrides current timeout, in seconds (not the future default value);
+ // intended to be called right after SetPopupMessage.
+ void SetPopupTimeout(double timeoutSeconds, bool border = false);
+
+protected:
+
+ void renderShortcutChangeMessage(RenderDevice* prender);
+
+public:
+ OptionSelectionMenu* GetSubmenu();
+ OptionSelectionMenu* GetOrCreateSubmenu(String submenuName);
+
+ enum DisplayStateType
+ {
+ Display_None,
+ Display_Menu,
+ Display_SingleItem
+ };
+
+ DisplayStateType DisplayState;
+ OptionSelectionMenu* ParentMenu;
+
+ ArrayPOD<OptionMenuItem*> Items;
+ int SelectedIndex;
+ bool SelectionActive;
+
+ String PopupMessage;
+ double PopupMessageTimeout;
+ bool PopupMessageBorder;
+
+ // Possible menu navigation actions.
+ enum NavigationActions
+ {
+ Nav_Up,
+ Nav_Down,
+ Nav_Left,
+ Nav_Right,
+ Nav_Select,
+ Nav_Back,
+ Nav_LAST
+ };
+
+ // Handlers for navigation actions.
+ void HandleUp(bool* pFast);
+ void HandleDown(bool* pFast);
+ void HandleLeft();
+ void HandleRight();
+ void HandleSelect();
+ void HandleBack();
+
+ void HandleMenuToggle();
+ void HandleSingleItemToggle();
+
+ OptionShortcut NavShortcuts[Nav_LAST];
+ OptionShortcut ToggleShortcut;
+ OptionShortcut ToggleSingleItemShortcut;
+};
+
+
+//-------------------------------------------------------------------------------------
+// Text Rendering Utility
+enum DrawTextCenterType
+{
+ DrawText_NoCenter= 0,
+ DrawText_VCenter = 0x01,
+ DrawText_HCenter = 0x02,
+ DrawText_Center = DrawText_VCenter | DrawText_HCenter,
+ DrawText_Border = 0x10,
+};
+
+void DrawTextBox(RenderDevice* prender, float x, float y,
+ float textSize, const char* text,
+ unsigned centerType = DrawText_NoCenter);
+
+void CleanupDrawTextFont();
+
+
+#endif // INC_OptionMenu_h
diff --git a/Samples/OculusWorldDemo/Player.cpp b/Samples/OculusWorldDemo/Player.cpp
index b910307..b2bf00e 100644
--- a/Samples/OculusWorldDemo/Player.cpp
+++ b/Samples/OculusWorldDemo/Player.cpp
@@ -23,135 +23,138 @@ limitations under the License.
#include "Player.h"
#include <Kernel/OVR_Alg.h>
-Player::Player(void)
- : UserEyeHeight(1.8f),
- EyePos(7.7f, 1.8f, -1.0f),
- EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
- LastSensorYaw(0)
+Player::Player()
+ : UserEyeHeight(1.76f - 0.15f), // 1.76 meters height (ave US male, Wikipedia), less 15 centimeters (TomF's top-of-head-to-eye distance).
+ BodyPos(7.7f, 1.76f - 0.15f, -1.0f),
+ BodyYaw(YawInitial)
{
MoveForward = MoveBack = MoveLeft = MoveRight = 0;
GamepadMove = Vector3f(0);
GamepadRotate = Vector3f(0);
}
+Player::~Player()
+{
+}
+
+Vector3f Player::GetPosition()
+{
+ return BodyPos + Quatf(Vector3f(0,1,0), BodyYaw.Get()).Rotate(HeadPose.Position);
+}
+
+Quatf Player::GetOrientation(bool baseOnly)
+{
+ Quatf baseQ = Quatf(Vector3f(0,1,0), BodyYaw.Get());
+ return baseOnly ? baseQ : baseQ * HeadPose.Orientation;
+}
-Player::~Player(void)
+Posef Player::VirtualWorldPoseFromRealPose(const Posef &sensorHeadPose)
{
+ Quatf baseQ = Quatf(Vector3f(0,1,0), BodyYaw.Get());
+
+ return Posef(baseQ * sensorHeadPose.Orientation,
+ BodyPos + baseQ.Rotate(sensorHeadPose.Position));
}
-void Player::HandleCollision(double dt, Array<Ptr<CollisionModel> >* collisionModels,
- Array<Ptr<CollisionModel> >* groundCollisionModels, bool shiftDown)
+
+void Player::HandleMovement(double dt, Array<Ptr<CollisionModel> >* collisionModels,
+ Array<Ptr<CollisionModel> >* groundCollisionModels, bool shiftDown)
{
- if(MoveForward || MoveBack || MoveLeft || MoveRight || GamepadMove.LengthSq() > 0)
+ // Handle keyboard movement.
+ // This translates BasePos based on the orientation and keys pressed.
+ // Note that Pitch and Roll do not affect movement (they only affect view).
+ Vector3f controllerMove;
+ if(MoveForward || MoveBack || MoveLeft || MoveRight)
{
- Vector3f orientationVector;
- // Handle keyboard movement.
- // This translates EyePos based on Yaw vector direction and keys pressed.
- // Note that Pitch and Roll do not affect movement (they only affect view).
- if(MoveForward || MoveBack || MoveLeft || MoveRight)
+ if (MoveForward)
{
- Vector3f localMoveVector(0, 0, 0);
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
-
- if (MoveForward)
- {
- localMoveVector = ForwardVector;
- }
- else if (MoveBack)
- {
- localMoveVector = -ForwardVector;
- }
-
- if (MoveRight)
- {
- localMoveVector += RightVector;
- }
- else if (MoveLeft)
- {
- localMoveVector -= RightVector;
- }
+ controllerMove += ForwardVector;
+ }
+ else if (MoveBack)
+ {
+ controllerMove -= ForwardVector;
+ }
- // Normalize vector so we don't move faster diagonally.
- localMoveVector.Normalize();
- orientationVector = yawRotate.Transform(localMoveVector);
+ if (MoveRight)
+ {
+ controllerMove += RightVector;
}
- else if (GamepadMove.LengthSq() > 0)
+ else if (MoveLeft)
{
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
- GamepadMove.Normalize();
- orientationVector = yawRotate.Transform(GamepadMove);
+ controllerMove -= RightVector;
}
+ }
+ else if (GamepadMove.LengthSq() > 0)
+ {
+ controllerMove = GamepadMove;
+ }
+ controllerMove = GetOrientation(bMotionRelativeToBody).Rotate(controllerMove);
+ controllerMove.y = 0; // Project to the horizontal plane
+ if (controllerMove.LengthSq() > 0)
+ {
+ // Normalize vector so we don't move faster diagonally.
+ controllerMove.Normalize();
+ controllerMove *= OVR::Alg::Min<float>(MoveSpeed * (float)dt * (shiftDown ? 3.0f : 1.0f), 1.0f);
+ }
- float moveLength = OVR::Alg::Min<float>(MoveSpeed * (float)dt * (shiftDown ? 3.0f : 1.0f), 1.0f);
+ // Compute total move direction vector and move length
+ Vector3f orientationVector = controllerMove;
+ float moveLength = orientationVector.Length();
+ if (moveLength > 0)
+ orientationVector.Normalize();
+
+ float checkLengthForward = moveLength;
+ Planef collisionPlaneForward;
+ bool gotCollision = false;
+
+ for(unsigned int i = 0; i < collisionModels->GetSize(); ++i)
+ {
+ // Checks for collisions at model base level, which should prevent us from
+ // slipping under walls
+ if (collisionModels->At(i)->TestRay(BodyPos, orientationVector, checkLengthForward,
+ &collisionPlaneForward))
+ {
+ gotCollision = true;
+ break;
+ }
+ }
- float checkLengthForward = moveLength;
- Planef collisionPlaneForward;
- float checkLengthLeft = moveLength;
- Planef collisionPlaneLeft;
- float checkLengthRight = moveLength;
- Planef collisionPlaneRight;
- bool gotCollision = false;
- bool gotCollisionLeft = false;
- bool gotCollisionRight = false;
+ if (gotCollision)
+ {
+ // Project orientationVector onto the plane
+ Vector3f slideVector = orientationVector - collisionPlaneForward.N
+ * (orientationVector.Dot(collisionPlaneForward.N));
- for(unsigned int i = 0; i < collisionModels->GetSize(); ++i)
+ // Make sure we aren't in a corner
+ for(unsigned int j = 0; j < collisionModels->GetSize(); ++j)
{
- // Checks for collisions at eye level, which should prevent us from
- // slipping under walls
- if (collisionModels->At(i)->TestRay(EyePos, orientationVector, checkLengthForward,
- &collisionPlaneForward))
- {
- gotCollision = true;
- }
-
- Matrix4f leftRotation = Matrix4f::RotationY(45 * (Math<float>::Pi / 180.0f));
- Vector3f leftVector = leftRotation.Transform(orientationVector);
- if (collisionModels->At(i)->TestRay(EyePos, leftVector, checkLengthLeft,
- &collisionPlaneLeft))
- {
- gotCollisionLeft = true;
- }
- Matrix4f rightRotation = Matrix4f::RotationY(-45 * (Math<float>::Pi / 180.0f));
- Vector3f rightVector = rightRotation.Transform(orientationVector);
- if (collisionModels->At(i)->TestRay(EyePos, rightVector, checkLengthRight,
- &collisionPlaneRight))
+ if (collisionModels->At(j)->TestPoint(BodyPos - Vector3f(0.0f, RailHeight, 0.0f) +
+ (slideVector * (moveLength))) )
{
- gotCollisionRight = true;
+ moveLength = 0;
+ break;
}
}
-
- if (gotCollision)
+ if (moveLength != 0)
{
- // Project orientationVector onto the plane
- Vector3f slideVector = orientationVector - collisionPlaneForward.N
- * (orientationVector.Dot(collisionPlaneForward.N));
-
- // Make sure we aren't in a corner
- for(unsigned int j = 0; j < collisionModels->GetSize(); ++j)
- {
- if (collisionModels->At(j)->TestPoint(EyePos - Vector3f(0.0f, RailHeight, 0.0f) +
- (slideVector * (moveLength))) )
- {
- moveLength = 0;
- }
- }
- if (moveLength != 0)
- {
- orientationVector = slideVector;
- }
+ orientationVector = slideVector;
}
- // Checks for collisions at foot level, which allows us to follow terrain
- orientationVector *= moveLength;
- EyePos += orientationVector;
+ }
+ // Checks for collisions at foot level, which allows us to follow terrain
+ orientationVector *= moveLength;
+ BodyPos += orientationVector;
- Planef collisionPlaneDown;
- float finalDistanceDown = 10;
+ Planef collisionPlaneDown;
+ float finalDistanceDown = 10;
+ // Only apply down if there is collision model (otherwise we get jitter).
+ if (groundCollisionModels->GetSize())
+ {
for(unsigned int i = 0; i < groundCollisionModels->GetSize(); ++i)
{
float checkLengthDown = 10;
- if (groundCollisionModels->At(i)->TestRay(EyePos, Vector3f(0.0f, -1.0f, 0.0f),
- checkLengthDown, &collisionPlaneDown))
+ if (groundCollisionModels->At(i)->TestRay(BodyPos, Vector3f(0.0f, -1.0f, 0.0f),
+ checkLengthDown, &collisionPlaneDown))
{
finalDistanceDown = Alg::Min(finalDistanceDown, checkLengthDown);
}
@@ -160,7 +163,32 @@ void Player::HandleCollision(double dt, Array<Ptr<CollisionModel> >* collisionMo
// Maintain the minimum camera height
if (UserEyeHeight - finalDistanceDown < 1.0f)
{
- EyePos.y += UserEyeHeight - finalDistanceDown;
+ BodyPos.y += UserEyeHeight - finalDistanceDown;
}
}
+
+}
+
+
+
+// Handle directional movement. Returns 'true' if movement was processed.
+bool Player::HandleMoveKey(OVR::KeyCode key, bool down)
+{
+ switch(key)
+ {
+ // Handle player movement keys.
+ // We just update movement state here, while the actual translation is done in OnIdle()
+ // based on time.
+ case OVR::Key_W: MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); return true;
+ case OVR::Key_S: MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); return true;
+ case OVR::Key_A: MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); return true;
+ case OVR::Key_D: MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); return true;
+ case OVR::Key_Up: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); return true;
+ case OVR::Key_Down: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); return true;
+ case OVR::Key_Left: MoveLeft = down ? (MoveLeft | 2) : (MoveLeft & ~2); return true;
+ case OVR::Key_Right: MoveRight = down ? (MoveRight | 2) : (MoveRight & ~2); return true;
+ }
+ return false;
}
+
+
diff --git a/Samples/OculusWorldDemo/Player.h b/Samples/OculusWorldDemo/Player.h
index e57e67c..f8d29d5 100644
--- a/Samples/OculusWorldDemo/Player.h
+++ b/Samples/OculusWorldDemo/Player.h
@@ -1,7 +1,7 @@
/************************************************************************************
Filename : Player.h
-Content : Player location and hit-testing logic
+Content : Avatar movement and collision detection
Created : October 4, 2012
Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
@@ -25,23 +25,20 @@ limitations under the License.
#define OVR_WorldDemo_Player_h
#include "OVR.h"
+#include "Kernel/OVR_KeyCodes.h"
#include "../CommonSrc/Render/Render_Device.h"
using namespace OVR;
using namespace OVR::Render;
//-------------------------------------------------------------------------------------
-// The RHS coordinate system is defines as follows (as seen in perspective view):
-// Y - Up
-// Z - Back
-// X - Right
-const Vector3f UpVector(0.0f, 1.0f, 0.0f);
-const Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
+// The RHS coordinate system is assumed.
const Vector3f RightVector(1.0f, 0.0f, 0.0f);
+const Vector3f UpVector(0.0f, 1.0f, 0.0f);
+const Vector3f ForwardVector(0.0f, 0.0f, -1.0f); // -1 because HMD looks along -Z at identity orientation
-// We start out looking in the positive Z (180 degree rotation).
-const float YawInitial = 3.141592f;
-const float Sensitivity = 1.0f;
+const float YawInitial = 0.0f;
+const float Sensitivity = 0.3f; // low sensitivity to ease people into it gently.
const float MoveSpeed = 3.0f; // m/s
// These are used for collision detection
@@ -58,24 +55,37 @@ public:
float UserEyeHeight;
- // Position and look. The following apply:
- Vector3f EyePos;
- float EyeYaw; // Rotation around Y, CCW positive when looking at RHS (X,Z) plane.
- float EyePitch; // Pitch. If sensor is plugged in, only read from sensor.
- float EyeRoll; // Roll, only accessible from Sensor.
- float LastSensorYaw; // Stores previous Yaw value from to support computing delta.
+ // Where the avatar coordinate system (and body) is positioned and oriented in the virtual world
+ // Modified by gamepad/mouse input
+ Vector3f BodyPos;
+ Anglef BodyYaw;
+
+ // Where the player head is positioned and oriented in the real world
+ Posef HeadPose;
+
+ // Where the avatar head is positioned and oriented in the virtual world
+ Vector3f GetPosition();
+ Quatf GetOrientation(bool baseOnly = false);
+
+ // Returns virtual world position based on a real world head pose.
+ // Allows predicting eyes separately based on scanout time.
+ Posef VirtualWorldPoseFromRealPose(const Posef &sensorHeadPose);
+
+ // Handle directional movement. Returns 'true' if movement was processed.
+ bool HandleMoveKey(OVR::KeyCode key, bool down);
- // Movement state; different bits may be set based on the state of keys.
+ // Movement state; different bits may be set based on the state of keys.
UByte MoveForward;
UByte MoveBack;
UByte MoveLeft;
UByte MoveRight;
Vector3f GamepadMove, GamepadRotate;
+ bool bMotionRelativeToBody;
Player();
~Player();
- void HandleCollision(double dt, Array<Ptr<CollisionModel> >* collisionModels,
- Array<Ptr<CollisionModel> >* groundCollisionModels, bool shiftDown);
+ void HandleMovement(double dt, Array<Ptr<CollisionModel> >* collisionModels,
+ Array<Ptr<CollisionModel> >* groundCollisionModels, bool shiftDown);
};
#endif
diff --git a/Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj b/Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj
index a881ab8..2167237 100644
--- a/Samples/OculusWorldDemo/OculusWorldDemo_Msvc2010.vcxproj
+++ b/Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj
@@ -19,7 +19,7 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
- <ProjectGuid>{8051B877-2992-4F64-8C3B-FAF88B6D83AA}</ProjectGuid>
+ <ProjectGuid>{456DA1F5-7D65-4B77-8336-277F3921639B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>OculusWorldDemo</RootNamespace>
<ProjectName>OculusWorldDemo</ProjectName>
@@ -65,23 +65,27 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -90,16 +94,17 @@
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../3rdParty/TinyXml;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>libovrd.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovrd.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -108,17 +113,18 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;_WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>libovr64d.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr64d.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -130,7 +136,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../3rdParty/TinyXml;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
@@ -140,8 +146,8 @@
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libovr.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -152,8 +158,8 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
@@ -163,47 +169,57 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libovr64.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr64.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="..\CommonSrc\Platform\Platform.cpp" />
- <ClCompile Include="..\CommonSrc\Platform\Win32_Gamepad.cpp" />
- <ClCompile Include="..\CommonSrc\Platform\Win32_Platform.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_LoadTextureDDS.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_LoadTextureTGA.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_Device.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_D3D10_Device.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_D3D11_Device.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_D3D1X_Device.cpp">
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Platform.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureDDS.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureTGA.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
- <ClCompile Include="..\..\3rdParty\TinyXml\tinyxml2.cpp" />
- <ClCompile Include="..\CommonSrc\Render\Render_XmlSceneLoader.cpp" />
- <ClCompile Include="OculusWorldDemo.cpp" />
- <ClCompile Include="Player.cpp" />
+ <ClCompile Include="..\..\..\..\..\3rdParty\TinyXml\tinyxml2.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.cpp" />
+ <ClCompile Include="..\..\..\OculusWorldDemo.cpp" />
+ <ClCompile Include="..\..\..\OculusWorldDemo_Scene.cpp" />
+ <ClCompile Include="..\..\..\OptionMenu.cpp" />
+ <ClCompile Include="..\..\..\Player.cpp" />
+ <ClCompile Include="..\..\..\RenderProfiler.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="..\CommonSrc\Platform\Gamepad.h" />
- <ClInclude Include="..\CommonSrc\Platform\Platform.h" />
- <ClInclude Include="..\CommonSrc\Platform\Platform_Default.h" />
- <ClInclude Include="..\CommonSrc\Platform\Win32_Gamepad.h" />
- <ClInclude Include="..\CommonSrc\Platform\Win32_Platform.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_Font.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_Device.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_D3D10_Device.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_D3D11_Device.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_D3D1X_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Gamepad.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform_Default.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Font.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.h" />
+ <ClInclude Include="..\..\..\OptionMenu.h" />
<ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
- <ClInclude Include="..\CommonSrc\Render\Render_XmlSceneLoader.h" />
- <ClInclude Include="Player.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.h" />
+ <ClInclude Include="..\..\..\OculusWorldDemo.h" />
+ <ClInclude Include="..\..\..\Player.h" />
+ <ClInclude Include="..\..\..\RenderProfiler.h" />
</ItemGroup>
<ItemGroup>
- <ResourceCompile Include="OculusWorldDemo.rc" />
+ <ResourceCompile Include="..\..\..\OculusWorldDemo.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj.filters b/Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj.filters
new file mode 100644
index 0000000..67678ea
--- /dev/null
+++ b/Samples/OculusWorldDemo/Projects/Win/VS2010/OculusWorldDemo.vcxproj.filters
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="CommonSrc">
+ <UniqueIdentifier>{ba6e9e50-0655-4f12-a136-6d2a06015925}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="CommonSrc\Platform">
+ <UniqueIdentifier>{16e20d8b-eff7-454c-be85-02037c399e97}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="CommonSrc\Render">
+ <UniqueIdentifier>{1b6d51ae-a405-4f3d-be93-41a50db4f328}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Platform.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\OculusWorldDemo.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureTGA.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\Player.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureDDS.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\OculusWorldDemo_Scene.cpp" />
+ <ClCompile Include="..\..\..\OptionMenu.cpp" />
+ <ClCompile Include="..\..\..\RenderProfiler.cpp" />
+ <ClCompile Include="..\..\..\..\..\3rdParty\TinyXml\tinyxml2.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform_Default.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Font.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Gamepad.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\OculusWorldDemo.h" />
+ <ClInclude Include="..\..\..\RenderProfiler.h" />
+ <ClInclude Include="..\..\..\Player.h" />
+ <ClInclude Include="..\..\..\OptionMenu.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\OculusWorldDemo.rc" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj b/Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj
new file mode 100644
index 0000000..1dae2b3
--- /dev/null
+++ b/Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4F8C2B89-7CF1-4763-8EEF-E969FB760E32}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>OculusWorldDemo</RootNamespace>
+ <ProjectName>OculusWorldDemo</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2012/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovrd.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;_WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2012/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr64d.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2012/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2012/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr64.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Platform.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureDDS.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureTGA.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\3rdParty\TinyXml\tinyxml2.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.cpp" />
+ <ClCompile Include="..\..\..\OculusWorldDemo.cpp" />
+ <ClCompile Include="..\..\..\OculusWorldDemo_Scene.cpp" />
+ <ClCompile Include="..\..\..\OptionMenu.cpp" />
+ <ClCompile Include="..\..\..\Player.cpp" />
+ <ClCompile Include="..\..\..\RenderProfiler.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Gamepad.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform_Default.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Font.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.h" />
+ <ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.h" />
+ <ClInclude Include="..\..\..\OculusWorldDemo.h" />
+ <ClInclude Include="..\..\..\Player.h" />
+ <ClInclude Include="..\..\..\RenderProfiler.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\OculusWorldDemo.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj.filters b/Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj.filters
new file mode 100644
index 0000000..7246205
--- /dev/null
+++ b/Samples/OculusWorldDemo/Projects/Win/VS2012/OculusWorldDemo.vcxproj.filters
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="CommonSrc">
+ <UniqueIdentifier>{ba6e9e50-0655-4f12-a136-6d2a06015925}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="CommonSrc\Platform">
+ <UniqueIdentifier>{16e20d8b-eff7-454c-be85-02037c399e97}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="CommonSrc\Render">
+ <UniqueIdentifier>{1b6d51ae-a405-4f3d-be93-41a50db4f328}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Platform.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\OculusWorldDemo.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureTGA.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\Player.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureDDS.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\OculusWorldDemo_Scene.cpp" />
+ <ClCompile Include="..\..\..\OptionMenu.cpp" />
+ <ClCompile Include="..\..\..\RenderProfiler.cpp" />
+ <ClCompile Include="..\..\..\..\..\3rdParty\TinyXml\tinyxml2.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform_Default.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Font.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Gamepad.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\OculusWorldDemo.h" />
+ <ClInclude Include="..\..\..\RenderProfiler.h" />
+ <ClInclude Include="..\..\..\Player.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\OculusWorldDemo.rc" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj b/Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj
new file mode 100644
index 0000000..b894075
--- /dev/null
+++ b/Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CA4E4127-1BAD-447C-BFF9-5AF940EEC376}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>OculusWorldDemo</RootNamespace>
+ <ProjectName>OculusWorldDemo</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/</IntDir>
+ <OutDir>$(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/</OutDir>
+ <TargetName>OculusWorldDemo</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2013/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovrd.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;_WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2013/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr64d.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2013/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../../../../LibOVR/Include;../../../../../LibOVR/Src;../../../../../3rdParty/glext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>../../../../../LibOVR/Lib/$(Platform)/VS2013/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;libovr64.lib;dxgi.lib;d3d10_1.lib;d3d11.lib;d3dcompiler.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Platform.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureDDS.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureTGA.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\3rdParty\TinyXml\tinyxml2.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.cpp" />
+ <ClCompile Include="..\..\..\OculusWorldDemo.cpp" />
+ <ClCompile Include="..\..\..\OculusWorldDemo_Scene.cpp" />
+ <ClCompile Include="..\..\..\OptionMenu.cpp" />
+ <ClCompile Include="..\..\..\Player.cpp" />
+ <ClCompile Include="..\..\..\RenderProfiler.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Gamepad.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform_Default.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Font.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.h" />
+ <ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.h" />
+ <ClInclude Include="..\..\..\OculusWorldDemo.h" />
+ <ClInclude Include="..\..\..\Player.h" />
+ <ClInclude Include="..\..\..\RenderProfiler.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\OculusWorldDemo.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj.filters b/Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj.filters
new file mode 100644
index 0000000..93fff72
--- /dev/null
+++ b/Samples/OculusWorldDemo/Projects/Win/VS2013/OculusWorldDemo.vcxproj.filters
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="CommonSrc">
+ <UniqueIdentifier>{ba6e9e50-0655-4f12-a136-6d2a06015925}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="CommonSrc\Platform">
+ <UniqueIdentifier>{16e20d8b-eff7-454c-be85-02037c399e97}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="CommonSrc\Render">
+ <UniqueIdentifier>{1b6d51ae-a405-4f3d-be93-41a50db4f328}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Platform.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\OculusWorldDemo.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureTGA.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\Player.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_LoadTextureDDS.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.cpp">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\OculusWorldDemo_Scene.cpp" />
+ <ClCompile Include="..\..\..\OptionMenu.cpp" />
+ <ClCompile Include="..\..\..\RenderProfiler.cpp" />
+ <ClCompile Include="..\..\..\..\..\3rdParty\TinyXml\tinyxml2.cpp" />
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.cpp">
+ <Filter>CommonSrc\Render</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Platform.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Platform_Default.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Font.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D1X_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D10_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_D3D11_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\3rdParty\TinyXml\tinyxml2.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_XmlSceneLoader.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Gamepad.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Platform\Win32_Gamepad.h">
+ <Filter>CommonSrc\Platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\OculusWorldDemo.h" />
+ <ClInclude Include="..\..\..\RenderProfiler.h" />
+ <ClInclude Include="..\..\..\Player.h" />
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Win32_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\CommonSrc\Render\Render_GL_Device.h">
+ <Filter>CommonSrc\Render</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\OculusWorldDemo.rc" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/Release/readme b/Samples/OculusWorldDemo/Release/readme
deleted file mode 100644
index c9d0bc0..0000000
--- a/Samples/OculusWorldDemo/Release/readme
+++ /dev/null
@@ -1,2 +0,0 @@
-This document exits to ensure that the required directory structure gets created correctly.
-
diff --git a/Samples/OculusWorldDemo/RenderProfiler.cpp b/Samples/OculusWorldDemo/RenderProfiler.cpp
new file mode 100644
index 0000000..00bbdd9
--- /dev/null
+++ b/Samples/OculusWorldDemo/RenderProfiler.cpp
@@ -0,0 +1,99 @@
+/************************************************************************************
+
+Filename : RenderProfiler.cpp
+Content : Profiling for render.
+Created : March 10, 2014
+Authors : Caleb Leak
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "RenderProfiler.h"
+
+using namespace OVR;
+
+RenderProfiler::RenderProfiler()
+{
+ memset(SampleHistory, 0, sizeof(SampleHistory));
+ memset(SampleAverage, 0, sizeof(SampleAverage));
+ SampleCurrentFrame = 0;
+}
+
+void RenderProfiler::RecordSample(SampleType sampleType)
+{
+ if (sampleType == Sample_FrameStart)
+ {
+ // Recompute averages and subtract off frame start time.
+ for (int sample = 1; sample < Sample_LAST; sample++)
+ {
+ SampleHistory[SampleCurrentFrame][sample] -= SampleHistory[SampleCurrentFrame][0];
+
+ // Recompute the average for the current sample type.
+ SampleAverage[sample] = 0.0;
+ for (int frame = 0; frame < NumFramesOfTimerHistory; frame++)
+ {
+ SampleAverage[sample] += SampleHistory[frame][sample];
+ }
+ SampleAverage[sample] /= NumFramesOfTimerHistory;
+ }
+
+ SampleCurrentFrame = ((SampleCurrentFrame + 1) % NumFramesOfTimerHistory);
+ }
+
+ SampleHistory[SampleCurrentFrame][sampleType] = ovr_GetTimeInSeconds();
+}
+
+const double* RenderProfiler::GetLastSampleSet() const
+{
+ return SampleHistory[(SampleCurrentFrame - 1 + NumFramesOfTimerHistory) % NumFramesOfTimerHistory];
+}
+
+void RenderProfiler::DrawOverlay(RenderDevice* prender)
+{
+ char buf[256 * Sample_LAST];
+ OVR_strcpy ( buf, sizeof(buf), "Timing stats" ); // No trailing \n is deliberate.
+
+ /*int timerLastFrame = TimerCurrentFrame - 1;
+ if ( timerLastFrame < 0 )
+ {
+ timerLastFrame = NumFramesOfTimerHistory - 1;
+ }*/
+ // Timer 0 is always the time at the start of the frame.
+
+ const double* averages = GetAverages();
+ const double* lastSampleSet = GetLastSampleSet();
+
+ for ( int timerNum = 1; timerNum < Sample_LAST; timerNum++ )
+ {
+ char const *pName = "";
+ switch ( timerNum )
+ {
+ case Sample_AfterGameProcessing: pName = "AfterGameProcessing"; break;
+ case Sample_AfterEyeRender : pName = "AfterEyeRender "; break;
+// case Sample_BeforeDistortion : pName = "BeforeDistortion "; break;
+// case Sample_AfterDistortion : pName = "AfterDistortion "; break;
+ case Sample_AfterPresent : pName = "AfterPresent "; break;
+// case Sample_AfterFlush : pName = "AfterFlush "; break;
+ default: OVR_ASSERT ( false );
+ }
+ char bufTemp[256];
+ OVR_sprintf ( bufTemp, sizeof(bufTemp), "\nRaw: %.2lfms\t400Ave: %.2lfms\t800%s",
+ lastSampleSet[timerNum] * 1000.0, averages[timerNum] * 1000.0, pName );
+ OVR_strcat ( buf, sizeof(buf), bufTemp );
+ }
+
+ DrawTextBox(prender, 0.0f, 0.0f, 22.0f, buf, DrawText_Center);
+} \ No newline at end of file
diff --git a/Samples/OculusWorldDemo/RenderProfiler.h b/Samples/OculusWorldDemo/RenderProfiler.h
new file mode 100644
index 0000000..96ec50a
--- /dev/null
+++ b/Samples/OculusWorldDemo/RenderProfiler.h
@@ -0,0 +1,71 @@
+/************************************************************************************
+
+Filename : RenderProfiler.h
+Content : Profiling for render.
+Created : March 10, 2014
+Authors : Caleb Leak
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef INC_RenderProfiler_h
+#define INC_RenderProfiler_h
+
+#include "OVR.h"
+
+// TODO: Refactor option menu so dependencies are in a separate file.
+#include "OptionMenu.h"
+
+//-------------------------------------------------------------------------------------
+// ***** RenderProfiler
+
+// Tracks reported timing sample in a frame and dislays them an overlay from DrawOverlay().
+class RenderProfiler
+{
+public:
+ enum { NumFramesOfTimerHistory = 10 };
+
+ enum SampleType
+ {
+ Sample_FrameStart ,
+ Sample_AfterGameProcessing ,
+ Sample_AfterEyeRender ,
+ // Sample_BeforeDistortion ,
+ // Sample_AfterDistortion ,
+ Sample_AfterPresent ,
+ // Sample_AfterFlush ,
+
+ Sample_LAST
+ };
+
+ RenderProfiler();
+
+ // Records the current time for the given sample type.
+ void RecordSample(SampleType sampleType);
+
+ const double* GetAverages() const { return SampleAverage; }
+ const double* GetLastSampleSet() const;
+
+ void DrawOverlay(RenderDevice* prender);
+
+private:
+
+ double SampleHistory[NumFramesOfTimerHistory][Sample_LAST];
+ double SampleAverage[Sample_LAST];
+ int SampleCurrentFrame;
+};
+
+#endif // INC_RenderProfiler_h