openvr_test1
changeset 0:806d30b46748
OpenVR test initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 13 Apr 2016 09:39:37 +0300 |
parents | |
children | 4310ced01da8 |
files | .hgignore openvr_test1.sln openvr_test1.vcxproj openvr_test1.vcxproj.filters src/app.cc src/app.h src/main.cc |
diffstat | 7 files changed, 693 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Wed Apr 13 09:39:37 2016 +0300 1.3 @@ -0,0 +1,10 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +^test$ 1.8 +Debug/ 1.9 +Release/ 1.10 +\.sdf$ 1.11 +\.suo$ 1.12 +\.opensdf$ 1.13 +\.exe$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/openvr_test1.sln Wed Apr 13 09:39:37 2016 +0300 2.3 @@ -0,0 +1,22 @@ 2.4 + 2.5 +Microsoft Visual Studio Solution File, Format Version 12.00 2.6 +# Visual Studio 2013 2.7 +VisualStudioVersion = 12.0.31101.0 2.8 +MinimumVisualStudioVersion = 10.0.40219.1 2.9 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openvr_test1", "openvr_test1.vcxproj", "{9A02CFA8-E1B4-4F9B-B63D-65D9B60E1E50}" 2.10 +EndProject 2.11 +Global 2.12 + GlobalSection(SolutionConfigurationPlatforms) = preSolution 2.13 + Debug|Win32 = Debug|Win32 2.14 + Release|Win32 = Release|Win32 2.15 + EndGlobalSection 2.16 + GlobalSection(ProjectConfigurationPlatforms) = postSolution 2.17 + {9A02CFA8-E1B4-4F9B-B63D-65D9B60E1E50}.Debug|Win32.ActiveCfg = Debug|Win32 2.18 + {9A02CFA8-E1B4-4F9B-B63D-65D9B60E1E50}.Debug|Win32.Build.0 = Debug|Win32 2.19 + {9A02CFA8-E1B4-4F9B-B63D-65D9B60E1E50}.Release|Win32.ActiveCfg = Release|Win32 2.20 + {9A02CFA8-E1B4-4F9B-B63D-65D9B60E1E50}.Release|Win32.Build.0 = Release|Win32 2.21 + EndGlobalSection 2.22 + GlobalSection(SolutionProperties) = preSolution 2.23 + HideSolutionNode = FALSE 2.24 + EndGlobalSection 2.25 +EndGlobal
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/openvr_test1.vcxproj Wed Apr 13 09:39:37 2016 +0300 3.3 @@ -0,0 +1,92 @@ 3.4 +<?xml version="1.0" encoding="utf-8"?> 3.5 +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3.6 + <ItemGroup Label="ProjectConfigurations"> 3.7 + <ProjectConfiguration Include="Debug|Win32"> 3.8 + <Configuration>Debug</Configuration> 3.9 + <Platform>Win32</Platform> 3.10 + </ProjectConfiguration> 3.11 + <ProjectConfiguration Include="Release|Win32"> 3.12 + <Configuration>Release</Configuration> 3.13 + <Platform>Win32</Platform> 3.14 + </ProjectConfiguration> 3.15 + </ItemGroup> 3.16 + <PropertyGroup Label="Globals"> 3.17 + <ProjectGuid>{9A02CFA8-E1B4-4F9B-B63D-65D9B60E1E50}</ProjectGuid> 3.18 + <Keyword>Win32Proj</Keyword> 3.19 + <RootNamespace>openvr_test1</RootNamespace> 3.20 + </PropertyGroup> 3.21 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 3.22 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 3.23 + <ConfigurationType>Application</ConfigurationType> 3.24 + <UseDebugLibraries>true</UseDebugLibraries> 3.25 + <PlatformToolset>v120</PlatformToolset> 3.26 + <CharacterSet>Unicode</CharacterSet> 3.27 + </PropertyGroup> 3.28 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 3.29 + <ConfigurationType>Application</ConfigurationType> 3.30 + <UseDebugLibraries>false</UseDebugLibraries> 3.31 + <PlatformToolset>v120</PlatformToolset> 3.32 + <WholeProgramOptimization>true</WholeProgramOptimization> 3.33 + <CharacterSet>Unicode</CharacterSet> 3.34 + </PropertyGroup> 3.35 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 3.36 + <ImportGroup Label="ExtensionSettings"> 3.37 + </ImportGroup> 3.38 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 3.39 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 3.40 + </ImportGroup> 3.41 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 3.42 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 3.43 + </ImportGroup> 3.44 + <PropertyGroup Label="UserMacros" /> 3.45 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 3.46 + <LinkIncremental>true</LinkIncremental> 3.47 + </PropertyGroup> 3.48 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 3.49 + <LinkIncremental>false</LinkIncremental> 3.50 + </PropertyGroup> 3.51 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 3.52 + <ClCompile> 3.53 + <PrecompiledHeader> 3.54 + </PrecompiledHeader> 3.55 + <WarningLevel>Level3</WarningLevel> 3.56 + <Optimization>Disabled</Optimization> 3.57 + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> 3.58 + <DisableSpecificWarnings>4305;4244</DisableSpecificWarnings> 3.59 + </ClCompile> 3.60 + <Link> 3.61 + <SubSystem>Console</SubSystem> 3.62 + <GenerateDebugInformation>true</GenerateDebugInformation> 3.63 + <AdditionalDependencies>opengl32.lib;glu32.lib;glew32.lib;SDL2.lib;SDL2main.lib;openvr_api.lib;libgmath.lib;%(AdditionalDependencies)</AdditionalDependencies> 3.64 + </Link> 3.65 + </ItemDefinitionGroup> 3.66 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 3.67 + <ClCompile> 3.68 + <WarningLevel>Level3</WarningLevel> 3.69 + <PrecompiledHeader> 3.70 + </PrecompiledHeader> 3.71 + <Optimization>MaxSpeed</Optimization> 3.72 + <FunctionLevelLinking>true</FunctionLevelLinking> 3.73 + <IntrinsicFunctions>true</IntrinsicFunctions> 3.74 + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> 3.75 + <DisableSpecificWarnings>4305;4244</DisableSpecificWarnings> 3.76 + </ClCompile> 3.77 + <Link> 3.78 + <SubSystem>Console</SubSystem> 3.79 + <GenerateDebugInformation>true</GenerateDebugInformation> 3.80 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 3.81 + <OptimizeReferences>true</OptimizeReferences> 3.82 + <AdditionalDependencies>opengl32.lib;glu32.lib;glew32.lib;SDL2.lib;SDL2main.lib;openvr_api.lib;libgmath.lib;%(AdditionalDependencies)</AdditionalDependencies> 3.83 + </Link> 3.84 + </ItemDefinitionGroup> 3.85 + <ItemGroup> 3.86 + <ClCompile Include="src\app.cc" /> 3.87 + <ClCompile Include="src\main.cc" /> 3.88 + </ItemGroup> 3.89 + <ItemGroup> 3.90 + <ClInclude Include="src\app.h" /> 3.91 + </ItemGroup> 3.92 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 3.93 + <ImportGroup Label="ExtensionTargets"> 3.94 + </ImportGroup> 3.95 +</Project> 3.96 \ No newline at end of file
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/openvr_test1.vcxproj.filters Wed Apr 13 09:39:37 2016 +0300 4.3 @@ -0,0 +1,30 @@ 4.4 +<?xml version="1.0" encoding="utf-8"?> 4.5 +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 4.6 + <ItemGroup> 4.7 + <Filter Include="Source Files"> 4.8 + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> 4.9 + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> 4.10 + </Filter> 4.11 + <Filter Include="Header Files"> 4.12 + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> 4.13 + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> 4.14 + </Filter> 4.15 + <Filter Include="Resource Files"> 4.16 + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> 4.17 + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> 4.18 + </Filter> 4.19 + </ItemGroup> 4.20 + <ItemGroup> 4.21 + <ClCompile Include="src\main.cc"> 4.22 + <Filter>Source Files</Filter> 4.23 + </ClCompile> 4.24 + <ClCompile Include="src\app.cc"> 4.25 + <Filter>Source Files</Filter> 4.26 + </ClCompile> 4.27 + </ItemGroup> 4.28 + <ItemGroup> 4.29 + <ClInclude Include="src\app.h"> 4.30 + <Filter>Header Files</Filter> 4.31 + </ClInclude> 4.32 + </ItemGroup> 4.33 +</Project> 4.34 \ No newline at end of file
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/app.cc Wed Apr 13 09:39:37 2016 +0300 5.3 @@ -0,0 +1,439 @@ 5.4 +#include <stdio.h> 5.5 +#include <assert.h> 5.6 +#include <GL/glew.h> 5.7 +#include <openvr.h> 5.8 +#include <gmath/gmath.h> 5.9 +#include "app.h" 5.10 + 5.11 +using namespace vr; // OpenVR namespace 5.12 + 5.13 +static void draw_scene(); 5.14 +static void draw_box(float xsz, float ysz, float zsz, float norm_sign); 5.15 +static Mat4 openvr_matrix4(const HmdMatrix44_t &mat); 5.16 +static Mat4 openvr_matrix(const HmdMatrix34_t &mat); 5.17 +static VRTextureBounds_t openvr_tex_bounds(float umin, float vmin, float umax, float vmax); 5.18 +static void update_rtarg(int width, int height); 5.19 +static unsigned int next_pow2(unsigned int x); 5.20 +static unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1); 5.21 + 5.22 +static int win_width, win_height; 5.23 + 5.24 +static unsigned int fbo, fb_tex, fb_depth; 5.25 +static int fb_width, fb_height; 5.26 +static int fb_tex_width, fb_tex_height; 5.27 + 5.28 +static unsigned int chess_tex; 5.29 + 5.30 +// openvr stuff 5.31 +static IVRSystem *vrsys; 5.32 +static IVRCompositor *vrcomp; 5.33 +static bool vrdev_state[k_unMaxTrackedDeviceCount]; 5.34 +static TrackedDevicePose_t vrdev_pose[k_unMaxTrackedDeviceCount]; 5.35 +static Mat4 eye_matrix[2]; 5.36 +static Mat4 proj_matrix[2]; 5.37 +static Texture_t vrtex = {0, API_OpenGL, ColorSpace_Linear}; 5.38 +static VRTextureBounds_t vrtex_bounds[2]; 5.39 + 5.40 +bool app_init() 5.41 +{ 5.42 + glewInit(); 5.43 + 5.44 + glEnable(GL_DEPTH_TEST); 5.45 + glEnable(GL_CULL_FACE); 5.46 + glEnable(GL_LIGHTING); 5.47 + glEnable(GL_LIGHT0); 5.48 + glEnable(GL_LIGHT1); 5.49 + glEnable(GL_NORMALIZE); 5.50 + 5.51 + glClearColor(0.1, 0.1, 0.1, 1); 5.52 + 5.53 + chess_tex = gen_chess_tex(1.0, 0.7, 0.4, 0.4, 0.7, 1.0); 5.54 + 5.55 + // Initialize OpenVR 5.56 + EVRInitError vrerr; 5.57 + if(!(vrsys = VR_Init(&vrerr, VRApplication_Scene))) { 5.58 + fprintf(stderr, "failed to initialize OpenVR: %s\n", 5.59 + VR_GetVRInitErrorAsEnglishDescription(vrerr)); 5.60 + return false; 5.61 + } 5.62 + if(!(vrcomp = VRCompositor())) { 5.63 + fprintf(stderr, "failed to initialize OpenVR compositor\n"); 5.64 + return false; 5.65 + } 5.66 + 5.67 + uint32_t xsz, ysz; 5.68 + vrsys->GetRecommendedRenderTargetSize(&xsz, &ysz); 5.69 + fb_width = xsz * 2; 5.70 + fb_height = ysz; 5.71 + update_rtarg(fb_width, fb_height); // create render target 5.72 + 5.73 + for(int i=0; i<2; i++) { 5.74 + EVREye eye = i == 0 ? Eye_Left : Eye_Right; 5.75 + 5.76 + // projection matrix for each eye 5.77 + proj_matrix[i] = openvr_matrix4(vrsys->GetProjectionMatrix(eye, 0.5, 500.0, API_OpenGL)); 5.78 + // eye (relative to head) matrix 5.79 + eye_matrix[i] = openvr_matrix(vrsys->GetEyeToHeadTransform(eye)); 5.80 + } 5.81 + 5.82 + // XXX this doesn't seem to work correctly for some reason 5.83 + //vrcomp->ShowMirrorWindow(); 5.84 + 5.85 + assert(glGetError() == GL_NO_ERROR); 5.86 + return true; 5.87 +} 5.88 + 5.89 +void app_shutdown() 5.90 +{ 5.91 + // if we call VR_Shutdown while a frame is pending, we'll crash 5.92 + vrcomp->ClearLastSubmittedFrame(); 5.93 + VR_Shutdown(); 5.94 +} 5.95 + 5.96 +static void update() 5.97 +{ 5.98 + // process OpenVR events (TODO: I think there are more events to handle) 5.99 + VREvent_t ev; 5.100 + while(vrsys->PollNextEvent(&ev, sizeof ev)) { 5.101 + switch(ev.eventType) { 5.102 + case VREvent_TrackedDeviceActivated: 5.103 + printf("Device %u activated\n", ev.trackedDeviceIndex); 5.104 + break; 5.105 + 5.106 + case VREvent_TrackedDeviceDeactivated: 5.107 + printf("Device %u lost\n", ev.trackedDeviceIndex); 5.108 + break; 5.109 + 5.110 + case VREvent_TrackedDeviceUpdated: 5.111 + printf("Device %u updated(?)\n", ev.trackedDeviceIndex); 5.112 + break; 5.113 + } 5.114 + } 5.115 + 5.116 + // TODO implement controllers 5.117 + for(int i=0; i<k_unMaxTrackedDeviceCount; i++) { 5.118 + VRControllerState_t st; 5.119 + if(vrsys->GetControllerState(i, &st)) { 5.120 + // XXX ? 5.121 + vrdev_state[i] = st.ulButtonPressed == 0; 5.122 + } 5.123 + } 5.124 + 5.125 + // this will probably block at some point... investigate further 5.126 + vrcomp->WaitGetPoses(vrdev_pose, k_unMaxTrackedDeviceCount, 0, 0); 5.127 +} 5.128 + 5.129 +void app_draw() 5.130 +{ 5.131 + update(); 5.132 + 5.133 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 5.134 + glClearColor(0, 0, 0, 1); 5.135 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 5.136 + 5.137 + for(int i=0; i<2; i++) { 5.138 + EVREye eye = i == 0 ? Eye_Left : Eye_Right; 5.139 + 5.140 + glViewport(i == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height); 5.141 + 5.142 + glMatrixMode(GL_PROJECTION); 5.143 + glLoadMatrixf(proj_matrix[i][0]); 5.144 + 5.145 + Mat4 hmd_mat = openvr_matrix(vrdev_pose[k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); 5.146 + Mat4 view_mat = inverse(eye_matrix[i] * hmd_mat); 5.147 + 5.148 + glMatrixMode(GL_MODELVIEW); 5.149 + glLoadMatrixf(view_mat[0]); 5.150 + 5.151 + draw_scene(); 5.152 + vrcomp->Submit(eye, &vrtex, vrtex_bounds + i); 5.153 + } 5.154 + /* this is supposed to tell the compositor to get on with showing the frame without waiting for 5.155 + * the next WaitGetPoses call. 5.156 + */ 5.157 + vrcomp->PostPresentHandoff(); 5.158 + 5.159 + glUseProgram(0); 5.160 + 5.161 + // render window output 5.162 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 5.163 + glViewport(0, 0, win_width, win_height); 5.164 + 5.165 + glMatrixMode(GL_PROJECTION); 5.166 + glLoadIdentity(); 5.167 + glMatrixMode(GL_MODELVIEW); 5.168 + glLoadIdentity(); 5.169 + 5.170 + glPushAttrib(GL_ENABLE_BIT); 5.171 + glBindTexture(GL_TEXTURE_2D, fb_tex); 5.172 + glEnable(GL_TEXTURE_2D); 5.173 + glDisable(GL_LIGHTING); 5.174 + glDisable(GL_DEPTH_TEST); 5.175 + 5.176 + glBegin(GL_QUADS); 5.177 + float umax = (float)fb_width / fb_tex_width; 5.178 + float vmax = (float)fb_height / fb_tex_height; 5.179 + glTexCoord2f(0, 0); glVertex2f(-1, -1); 5.180 + glTexCoord2f(umax, 0); glVertex2f(1, -1); 5.181 + glTexCoord2f(umax, vmax); glVertex2f(1, 1); 5.182 + glTexCoord2f(0, vmax); glVertex2f(-1, 1); 5.183 + glEnd(); 5.184 + 5.185 + glPopAttrib(); 5.186 + 5.187 + app_swap_buffers(); 5.188 +} 5.189 + 5.190 +void app_reshape(int x, int y) 5.191 +{ 5.192 + win_width = x; 5.193 + win_height = y; 5.194 + glViewport(0, 0, x, y); 5.195 + 5.196 + glMatrixMode(GL_PROJECTION); 5.197 + glLoadIdentity(); 5.198 + gluPerspective(50, (float)x / (float)y, 0.5, 500.0); 5.199 +} 5.200 + 5.201 +static void draw_scene(void) 5.202 +{ 5.203 + float grey[] = {0.8, 0.8, 0.8, 1}; 5.204 + float col[] = {0, 0, 0, 1}; 5.205 + float lpos[][4] = { 5.206 + {-8, 2, 10, 1}, 5.207 + {0, 15, 0, 1} 5.208 + }; 5.209 + float lcol[][4] = { 5.210 + {0.8, 0.8, 0.8, 1}, 5.211 + {0.4, 0.3, 0.3, 1} 5.212 + }; 5.213 + 5.214 + for(int i=0; i<2; i++) { 5.215 + glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]); 5.216 + glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]); 5.217 + } 5.218 + 5.219 + glMatrixMode(GL_MODELVIEW); 5.220 + 5.221 + glPushMatrix(); 5.222 + glTranslatef(0, 10, 0); 5.223 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey); 5.224 + glBindTexture(GL_TEXTURE_2D, chess_tex); 5.225 + glEnable(GL_TEXTURE_2D); 5.226 + draw_box(30, 20, 30, -1.0); 5.227 + glDisable(GL_TEXTURE_2D); 5.228 + glPopMatrix(); 5.229 + 5.230 + for(int i=0; i<4; i++) { 5.231 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey); 5.232 + glPushMatrix(); 5.233 + glTranslatef(i & 1 ? 5 : -5, 1, i & 2 ? -5 : 5); 5.234 + draw_box(0.5, 2, 0.5, 1.0); 5.235 + glPopMatrix(); 5.236 + 5.237 + col[0] = i & 1 ? 1.0 : 0.3; 5.238 + col[1] = i == 0 ? 1.0 : 0.3; 5.239 + col[2] = i & 2 ? 1.0 : 0.3; 5.240 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); 5.241 + 5.242 + glPushMatrix(); 5.243 + if(i & 1) { 5.244 + glTranslatef(0, 0.25, i & 2 ? 2 : -2); 5.245 + } else { 5.246 + glTranslatef(i & 2 ? 2 : -2, 0.25, 0); 5.247 + } 5.248 + draw_box(0.5, 0.5, 0.5, 1.0); 5.249 + glPopMatrix(); 5.250 + } 5.251 + 5.252 + col[0] = 1; 5.253 + col[1] = 1; 5.254 + col[2] = 0.4; 5.255 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); 5.256 + draw_box(0.05, 1.2, 6, 1.0); 5.257 + draw_box(6, 1.2, 0.05, 1.0); 5.258 +} 5.259 + 5.260 +static void draw_box(float xsz, float ysz, float zsz, float norm_sign) 5.261 +{ 5.262 + glMatrixMode(GL_MODELVIEW); 5.263 + glPushMatrix(); 5.264 + glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5); 5.265 + 5.266 + if(norm_sign < 0.0) { 5.267 + glFrontFace(GL_CW); 5.268 + } 5.269 + 5.270 + glBegin(GL_QUADS); 5.271 + glNormal3f(0, 0, 1 * norm_sign); 5.272 + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); 5.273 + glTexCoord2f(1, 0); glVertex3f(1, -1, 1); 5.274 + glTexCoord2f(1, 1); glVertex3f(1, 1, 1); 5.275 + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 5.276 + glNormal3f(1 * norm_sign, 0, 0); 5.277 + glTexCoord2f(0, 0); glVertex3f(1, -1, 1); 5.278 + glTexCoord2f(1, 0); glVertex3f(1, -1, -1); 5.279 + glTexCoord2f(1, 1); glVertex3f(1, 1, -1); 5.280 + glTexCoord2f(0, 1); glVertex3f(1, 1, 1); 5.281 + glNormal3f(0, 0, -1 * norm_sign); 5.282 + glTexCoord2f(0, 0); glVertex3f(1, -1, -1); 5.283 + glTexCoord2f(1, 0); glVertex3f(-1, -1, -1); 5.284 + glTexCoord2f(1, 1); glVertex3f(-1, 1, -1); 5.285 + glTexCoord2f(0, 1); glVertex3f(1, 1, -1); 5.286 + glNormal3f(-1 * norm_sign, 0, 0); 5.287 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 5.288 + glTexCoord2f(1, 0); glVertex3f(-1, -1, 1); 5.289 + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); 5.290 + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 5.291 + glEnd(); 5.292 + glBegin(GL_TRIANGLE_FAN); 5.293 + glNormal3f(0, 1 * norm_sign, 0); 5.294 + glTexCoord2f(0.5, 0.5); glVertex3f(0, 1, 0); 5.295 + glTexCoord2f(0, 0); glVertex3f(-1, 1, 1); 5.296 + glTexCoord2f(1, 0); glVertex3f(1, 1, 1); 5.297 + glTexCoord2f(1, 1); glVertex3f(1, 1, -1); 5.298 + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 5.299 + glTexCoord2f(0, 0); glVertex3f(-1, 1, 1); 5.300 + glEnd(); 5.301 + glBegin(GL_TRIANGLE_FAN); 5.302 + glNormal3f(0, -1 * norm_sign, 0); 5.303 + glTexCoord2f(0.5, 0.5); glVertex3f(0, -1, 0); 5.304 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 5.305 + glTexCoord2f(1, 0); glVertex3f(1, -1, -1); 5.306 + glTexCoord2f(1, 1); glVertex3f(1, -1, 1); 5.307 + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 5.308 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 5.309 + glEnd(); 5.310 + 5.311 + glFrontFace(GL_CCW); 5.312 + glPopMatrix(); 5.313 +} 5.314 + 5.315 +static Mat4 openvr_matrix4(const HmdMatrix44_t &mat) 5.316 +{ 5.317 + return Mat4(mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0], 5.318 + mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1], 5.319 + mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2], 5.320 + mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3]); 5.321 +} 5.322 + 5.323 +static Mat4 openvr_matrix(const HmdMatrix34_t &mat) 5.324 +{ 5.325 + return Mat4(mat.m[0][0], mat.m[1][0], mat.m[2][0], 0, 5.326 + mat.m[0][1], mat.m[1][1], mat.m[2][1], 0, 5.327 + mat.m[0][2], mat.m[1][2], mat.m[2][2], 0, 5.328 + mat.m[0][3], mat.m[1][3], mat.m[2][3], 1); 5.329 +} 5.330 + 5.331 +static VRTextureBounds_t openvr_tex_bounds(float umin, float vmin, float umax, float vmax) 5.332 +{ 5.333 + VRTextureBounds_t res; 5.334 + res.uMin = umin; 5.335 + res.uMax = umax; 5.336 + res.vMin = vmin; 5.337 + res.vMax = vmax; 5.338 + return res; 5.339 +} 5.340 + 5.341 +/* update_rtarg creates (and/or resizes) the render target used to draw the two stero views */ 5.342 +static void update_rtarg(int width, int height) 5.343 +{ 5.344 + if(!fbo) { 5.345 + /* if fbo does not exist, then nothing does... create every opengl object */ 5.346 + glGenFramebuffers(1, &fbo); 5.347 + glGenTextures(1, &fb_tex); 5.348 + glGenRenderbuffers(1, &fb_depth); 5.349 + 5.350 + glBindTexture(GL_TEXTURE_2D, fb_tex); 5.351 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5.352 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 5.353 + } 5.354 + 5.355 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 5.356 + 5.357 + /* calculate the next power of two in both dimensions and use that as a texture size */ 5.358 + fb_tex_width = next_pow2(width); 5.359 + fb_tex_height = next_pow2(height); 5.360 + 5.361 + /* create and attach the texture that will be used as a color buffer */ 5.362 + glBindTexture(GL_TEXTURE_2D, fb_tex); 5.363 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0, 5.364 + GL_RGBA, GL_UNSIGNED_BYTE, 0); 5.365 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0); 5.366 + 5.367 + /* create and attach the renderbuffer that will serve as our z-buffer */ 5.368 + glBindRenderbuffer(GL_RENDERBUFFER, fb_depth); 5.369 + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height); 5.370 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth); 5.371 + 5.372 + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 5.373 + fprintf(stderr, "incomplete framebuffer!\n"); 5.374 + } 5.375 + 5.376 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 5.377 + printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height); 5.378 + 5.379 + /* update the OpenVR texture descriptors */ 5.380 + vrtex.handle = (void*)fb_tex; 5.381 + float umax = (float)fb_width / fb_tex_width; 5.382 + float vmax = (float)fb_height / fb_tex_height; 5.383 + vrtex_bounds[0] = openvr_tex_bounds(0, 1.0 - vmax, 0.5 * umax, 1.0); 5.384 + vrtex_bounds[1] = openvr_tex_bounds(0.5 * umax, 1.0 - vmax, umax, 1.0); 5.385 +} 5.386 + 5.387 + 5.388 +void app_keyboard(int key, bool pressed) 5.389 +{ 5.390 + if(pressed) { 5.391 + switch(key) { 5.392 + case 27: 5.393 + app_quit(); 5.394 + break; 5.395 + 5.396 + case ' ': 5.397 + case 'r': 5.398 + vrsys->ResetSeatedZeroPose(); 5.399 + break; 5.400 + 5.401 + default: 5.402 + break; 5.403 + } 5.404 + } 5.405 +} 5.406 + 5.407 +static unsigned int next_pow2(unsigned int x) 5.408 +{ 5.409 + x -= 1; 5.410 + x |= x >> 1; 5.411 + x |= x >> 2; 5.412 + x |= x >> 4; 5.413 + x |= x >> 8; 5.414 + x |= x >> 16; 5.415 + return x + 1; 5.416 +} 5.417 + 5.418 +/* generate a chessboard texture with tiles colored (r0, g0, b0) and (r1, g1, b1) */ 5.419 +unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1) 5.420 +{ 5.421 + unsigned int tex; 5.422 + unsigned char img[8 * 8 * 3]; 5.423 + unsigned char *pix = img; 5.424 + 5.425 + for(int i=0; i<8; i++) { 5.426 + for(int j=0; j<8; j++) { 5.427 + int black = (i & 1) == (j & 1); 5.428 + pix[0] = (black ? r0 : r1) * 255; 5.429 + pix[1] = (black ? g0 : g1) * 255; 5.430 + pix[2] = (black ? b0 : b1) * 255; 5.431 + pix += 3; 5.432 + } 5.433 + } 5.434 + 5.435 + glGenTextures(1, &tex); 5.436 + glBindTexture(GL_TEXTURE_2D, tex); 5.437 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5.438 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 5.439 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, img); 5.440 + 5.441 + return tex; 5.442 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/app.h Wed Apr 13 09:39:37 2016 +0300 6.3 @@ -0,0 +1,15 @@ 6.4 +#ifndef APP_H_ 6.5 +#define APP_H_ 6.6 + 6.7 +bool app_init(); 6.8 +void app_shutdown(); 6.9 +void app_draw(); 6.10 +void app_reshape(int x, int y); 6.11 +void app_keyboard(int bn, bool pressed); 6.12 +void app_mouse(int bn, bool pressed, int x, int y); 6.13 +void app_motion(int x, int y); 6.14 + 6.15 +void app_swap_buffers(); 6.16 +void app_quit(); 6.17 + 6.18 +#endif // APP_H_ 6.19 \ No newline at end of file
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/main.cc Wed Apr 13 09:39:37 2016 +0300 7.3 @@ -0,0 +1,85 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <assert.h> 7.7 +#include <SDL2/SDL.h> 7.8 +#include <GL/glew.h> 7.9 +#include "app.h" 7.10 + 7.11 +static bool handle_event(SDL_Event *ev); 7.12 + 7.13 +static SDL_Window *win; 7.14 +static SDL_GLContext ctx; 7.15 +static bool quit; 7.16 + 7.17 +int main(int argc, char **argv) 7.18 +{ 7.19 + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); 7.20 + int winx = SDL_WINDOWPOS_UNDEFINED; 7.21 + int winy = SDL_WINDOWPOS_UNDEFINED; 7.22 + 7.23 + if(!(win = SDL_CreateWindow("OpenVR test", winx, winy, 1024, 640, SDL_WINDOW_OPENGL))) { 7.24 + fprintf(stderr, "failed to open window\n"); 7.25 + return 1; 7.26 + } 7.27 + if(!(ctx = SDL_GL_CreateContext(win))) { 7.28 + fprintf(stderr, "failed to create OpenGL context\n"); 7.29 + return 1; 7.30 + } 7.31 + int xsz, ysz; 7.32 + SDL_GetWindowSize(win, &xsz, &ysz); 7.33 + app_reshape(xsz, ysz); 7.34 + 7.35 + if(!app_init()) { 7.36 + return 1; 7.37 + } 7.38 + 7.39 + for(;;) { 7.40 + SDL_Event ev; 7.41 + while(SDL_PollEvent(&ev)) { 7.42 + if(!handle_event(&ev) || quit) { 7.43 + goto done; 7.44 + } 7.45 + } 7.46 + 7.47 + app_draw(); 7.48 + assert(glGetError() == GL_NO_ERROR); 7.49 + } 7.50 + 7.51 +done: 7.52 + app_shutdown(); 7.53 + SDL_Quit(); 7.54 + return 0; 7.55 +} 7.56 + 7.57 +void app_swap_buffers() 7.58 +{ 7.59 + SDL_GL_SwapWindow(win); 7.60 +} 7.61 + 7.62 +void app_quit() 7.63 +{ 7.64 + quit = true; 7.65 +} 7.66 + 7.67 +static bool handle_event(SDL_Event *ev) 7.68 +{ 7.69 + switch(ev->type) { 7.70 + case SDL_QUIT: 7.71 + return false; 7.72 + 7.73 + case SDL_KEYDOWN: 7.74 + case SDL_KEYUP: 7.75 + app_keyboard(ev->key.keysym.sym, ev->key.state == SDL_PRESSED); 7.76 + break; 7.77 + 7.78 + case SDL_WINDOWEVENT: 7.79 + if(ev->window.event == SDL_WINDOWEVENT_RESIZED) { 7.80 + app_reshape(ev->window.data1, ev->window.data2); 7.81 + } 7.82 + break; 7.83 + 7.84 + default: 7.85 + break; 7.86 + } 7.87 + return true; 7.88 +} 7.89 \ No newline at end of file