├── .gitignore ├── CMakeLists.txt ├── OpenXRExample.kdev4 ├── README.md ├── Readme_ori.md ├── glimpl.cpp ├── glimpl.h ├── main.cpp ├── math_3d.h ├── openxr-simple-example.sln ├── openxr-simple-example.vcxproj ├── openxr-simple-example.vcxproj.filters ├── openxr_headers ├── loader_interfaces.h ├── openxr.h ├── openxr_platform.h ├── openxr_platform_defines.h └── openxr_reflection.h └── xrmath.h /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs/ 2 | /x64/ 3 | *.user 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(openxr-example) 3 | 4 | if (POLICY CMP0072) 5 | cmake_policy (SET CMP0072 NEW) 6 | endif(POLICY CMP0072) 7 | 8 | find_package(X11 REQUIRED) 9 | find_package(OpenGL REQUIRED) 10 | 11 | INCLUDE(FindPkgConfig) 12 | PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2) 13 | 14 | # uncomment to use an openxr/build directory that is next to the openxr-example directory 15 | include_directories("${CMAKE_SOURCE_DIR}/../OpenXR-SDK-Source/build/include/" ${SDL2_INCLUDE_DIR}) 16 | link_directories("${CMAKE_SOURCE_DIR}/../OpenXR-SDK-Source/build/src/loader/") 17 | 18 | add_executable(openxr-example main.c glimpl.c) 19 | 20 | target_link_libraries(openxr-example openxr_loader Xrandr ${X11_LIBRARIES} ${OPENGL_LIBRARIES} ${SDL2_LIBRARIES} m) 21 | 22 | if(MSVC) 23 | target_compile_options(openxr-example PRIVATE /W4 /WX) 24 | else(MSVC) 25 | target_compile_options(openxr-example PRIVATE -pedantic -Wall -Wextra -Wno-unused-parameter) 26 | endif(MSVC) 27 | 28 | 29 | install(TARGETS openxr-example RUNTIME DESTINATION bin) 30 | -------------------------------------------------------------------------------- /OpenXRExample.kdev4: -------------------------------------------------------------------------------- 1 | [Project] 2 | Name=OpenXRExample 3 | Manager=KDevCMakeManager 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple OpenXR C++ Example 2 | 3 | An OpenXR sample with OpenGL + SDL2. 4 | 5 | Fork from https://gitlab.freedesktop.org/monado/demos/openxr-simple-example 6 | 7 | Modify for Windows and Visual Studio 2019. 8 | 9 | [Original readme](Readme_ori.md) 10 | -------------------------------------------------------------------------------- /Readme_ori.md: -------------------------------------------------------------------------------- 1 | # Simple OpenXR C Example 2 | 3 | Note: Currently this example only supports Linux/X11. 4 | 5 | This application is neither complex nor optimized for performance. 6 | It is intended to showcase OpenXR and how it is to be used for a simple VR application. 7 | 8 | It is split into two parts. `main.c` contains almost only the interaction with OpenXR. 9 | The OpenGL rendering is contained as much as possible in `glimpl.c` so it does not clutter the main application. 10 | 11 | Unless the OpenXR runtime is installed in the file system, the `XR_RUNTIME_JSON` variable has to be set for the loader to know where to look for the runtime and how the runtime is named 12 | 13 | XR_RUNTIME_JSON=~/monado/build/openxr_monado-dev.json 14 | 15 | then, you should be ready to run `./openxr-example`. 16 | 17 | If you want to use API layers that are not installed in the default path, set the variable `XR_API_LAYER_PATH` 18 | 19 | XR_API_LAYER_PATH=/path/to/api_layers/ 20 | 21 | This will enable to loader to find api layers at this path and enumerate them with `xrEnumerateApiLayerProperties()` 22 | 23 | API Layers can be enabled either with code or the loader can be told to enable an API layer with `XR_ENABLE_API_LAYERS` 24 | 25 | XR_ENABLE_API_LAYERS=XR_APILAYER_LUNARG_core_validation 26 | -------------------------------------------------------------------------------- /glimpl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019, Collabora, Ltd. 2 | // SPDX-License-Identifier: BSL-1.0 3 | /*! 4 | * @file 5 | * @brief A simple OpenXR example 6 | * @author Christoph Haag 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #define degreesToRadians(angleDegrees) ((angleDegrees)*M_PI / 180.0) 15 | #define radiansToDegrees(angleRadians) ((angleRadians)*180.0 / M_PI) 16 | 17 | #define MATH_3D_IMPLEMENTATION 18 | #include "math_3d.h" 19 | #include "glimpl.h" 20 | 21 | GLuint shaderProgramID = 0; 22 | GLuint VAOs[1] = {0}; 23 | 24 | static const char* vertexshader = 25 | "#version 330 core\n" 26 | "#extension GL_ARB_explicit_uniform_location : require\n" 27 | "layout(location = 0) in vec3 aPos;\n" 28 | "layout(location = 2) uniform mat4 model;\n" 29 | "layout(location = 3) uniform mat4 view;\n" 30 | "layout(location = 4) uniform mat4 proj;\n" 31 | "layout(location = 5) in vec2 aColor;\n" 32 | "out vec2 vertexColor;\n" 33 | "void main() {\n" 34 | " gl_Position = proj * view * model * vec4(aPos.x, aPos.y, aPos.z, " 35 | "1.0);\n" 36 | " vertexColor = aColor;\n" 37 | "}\n"; 38 | 39 | static const char* fragmentshader = 40 | "#version 330 core\n" 41 | "#extension GL_ARB_explicit_uniform_location : require\n" 42 | "layout(location = 0) out vec4 FragColor;\n" 43 | "layout(location = 1) uniform vec3 uniformColor;\n" 44 | "in vec2 vertexColor;\n" 45 | "void main() {\n" 46 | " FragColor = (uniformColor.x < 0.01 && uniformColor.y < 0.01 && " 47 | "uniformColor.z < 0.01) ? vec4(vertexColor, 1.0, 1.0) : vec4(uniformColor, " 48 | "1.0);\n" 49 | "}\n"; 50 | 51 | static SDL_Window* desktop_window; 52 | static SDL_GLContext gl_context; 53 | 54 | void GLAPIENTRY 55 | MessageCallback(GLenum source, 56 | GLenum type, 57 | GLuint id, 58 | GLenum severity, 59 | GLsizei length, 60 | const GLchar* message, 61 | const void* userParam) 62 | { 63 | fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", 64 | (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message); 65 | } 66 | 67 | bool 68 | init_sdl_window(HDC& xDisplay, HGLRC& glxContext, 69 | int w, 70 | int h) 71 | { 72 | 73 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { 74 | printf("Unable to initialize SDL"); 75 | return false; 76 | } 77 | 78 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 79 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); 80 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); 81 | 82 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0); 83 | 84 | /* Create our window centered at half the VR resolution */ 85 | desktop_window = SDL_CreateWindow("OpenXR Example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 86 | w / 2, h / 2, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); 87 | if (!desktop_window) { 88 | printf("Unable to create window"); 89 | return false; 90 | } 91 | 92 | gl_context = SDL_GL_CreateContext(desktop_window); 93 | auto err = glewInit(); 94 | 95 | glEnable(GL_DEBUG_OUTPUT); 96 | glDebugMessageCallback(MessageCallback, 0); 97 | 98 | SDL_GL_SetSwapInterval(0); 99 | 100 | 101 | // HACK? OpenXR wants us to report these values, so "work around" SDL a 102 | // bit and get the underlying glx stuff. Does this still work when e.g. 103 | // SDL switches to xcb? 104 | xDisplay = wglGetCurrentDC(); 105 | glxContext = wglGetCurrentContext(); 106 | 107 | return true; 108 | } 109 | 110 | int 111 | init_gl() 112 | { 113 | GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER); 114 | const GLchar* vertex_shader_source[1]; 115 | vertex_shader_source[0] = vertexshader; 116 | // printf("Vertex Shader:\n%s\n", vertexShaderSource); 117 | glShaderSource(vertex_shader_id, 1, vertex_shader_source, NULL); 118 | glCompileShader(vertex_shader_id); 119 | int vertex_compile_res; 120 | glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &vertex_compile_res); 121 | if (!vertex_compile_res) { 122 | char info_log[512]; 123 | glGetShaderInfoLog(vertex_shader_id, 512, NULL, info_log); 124 | printf("Vertex Shader failed to compile: %s\n", info_log); 125 | return 1; 126 | } else { 127 | printf("Successfully compiled vertex shader!\n"); 128 | } 129 | 130 | GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER); 131 | const GLchar* fragment_shader_source[1]; 132 | fragment_shader_source[0] = fragmentshader; 133 | glShaderSource(fragment_shader_id, 1, fragment_shader_source, NULL); 134 | glCompileShader(fragment_shader_id); 135 | int fragment_compile_res; 136 | glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &fragment_compile_res); 137 | if (!fragment_compile_res) { 138 | char info_log[512]; 139 | glGetShaderInfoLog(fragment_shader_id, 512, NULL, info_log); 140 | printf("Fragment Shader failed to compile: %s\n", info_log); 141 | return 1; 142 | } else { 143 | printf("Successfully compiled fragment shader!\n"); 144 | } 145 | 146 | shaderProgramID = glCreateProgram(); 147 | glAttachShader(shaderProgramID, vertex_shader_id); 148 | glAttachShader(shaderProgramID, fragment_shader_id); 149 | glLinkProgram(shaderProgramID); 150 | GLint shader_program_res; 151 | glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &shader_program_res); 152 | if (!shader_program_res) { 153 | char info_log[512]; 154 | glGetProgramInfoLog(shaderProgramID, 512, NULL, info_log); 155 | printf("Shader Program failed to link: %s\n", info_log); 156 | return 1; 157 | } else { 158 | printf("Successfully linked shader program!\n"); 159 | } 160 | 161 | glDeleteShader(vertex_shader_id); 162 | glDeleteShader(fragment_shader_id); 163 | 164 | float vertices[] = {-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 165 | 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 166 | -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 167 | 168 | -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 169 | 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 170 | -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 171 | 172 | -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 173 | -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 174 | -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 175 | 176 | 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 177 | 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 178 | 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 179 | 180 | -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 181 | 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 182 | -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 183 | 184 | -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 185 | 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 186 | -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f}; 187 | 188 | GLuint VBOs[1]; 189 | glGenBuffers(1, VBOs); 190 | 191 | glGenVertexArrays(1, &VAOs[0]); 192 | glBindVertexArray(VAOs[0]); 193 | glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]); 194 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 195 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 196 | glEnableVertexAttribArray(0); 197 | 198 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 199 | glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); 200 | glEnableVertexAttribArray(5); 201 | 202 | glEnable(GL_DEPTH_TEST); 203 | 204 | return 0; 205 | } 206 | 207 | void 208 | render_cube( 209 | vec3_t position, float scale, float rotation, float* view_matrix, float* projection_matrix) 210 | { 211 | 212 | mat4_t modelmatrix = m4_mul(m4_translation(position), m4_scaling(vec3(scale, scale, scale))); 213 | 214 | mat4_t rotationmatrix = m4_rotation_y(degreesToRadians(rotation)); 215 | modelmatrix = m4_mul(modelmatrix, rotationmatrix); 216 | 217 | glUseProgram(shaderProgramID); 218 | glBindVertexArray(VAOs[0]); 219 | 220 | 221 | int color = glGetUniformLocation(shaderProgramID, "uniformColor"); 222 | // the color (0, 0, 0) will get replaced by some UV color in the shader 223 | glUniform3f(color, 0.0, 0.0, 0.0); 224 | 225 | int viewLoc = glGetUniformLocation(shaderProgramID, "view"); 226 | glUniformMatrix4fv(viewLoc, 1, GL_FALSE, view_matrix); 227 | int projLoc = glGetUniformLocation(shaderProgramID, "proj"); 228 | glUniformMatrix4fv(projLoc, 1, GL_FALSE, projection_matrix); 229 | 230 | int modelLoc = glGetUniformLocation(shaderProgramID, "model"); 231 | glUniformMatrix4fv(modelLoc, 1, GL_FALSE, (float*)modelmatrix.m); 232 | glDrawArrays(GL_TRIANGLES, 0, 36); 233 | } 234 | 235 | void 236 | render_quad(int w, 237 | int h, 238 | int64_t swapchain_format, 239 | XrSwapchainImageOpenGLKHR image, 240 | XrTime predictedDisplayTime) 241 | { 242 | glActiveTexture(GL_TEXTURE0); 243 | glBindTexture(GL_TEXTURE_2D, image.image); 244 | 245 | glViewport(0, 0, w, h); 246 | glScissor(0, 0, w, h); 247 | 248 | uint8_t* rgb = new uint8_t[w * h * 4]; 249 | for (int row = 0; row < h; row++) { 250 | for (int col = 0; col < w; col++) { 251 | uint8_t* base = &rgb[(row * w * 4 + col * 4)]; 252 | *(base + 0) = (((float)row / (float)h)) * 255.; 253 | *(base + 1) = 0; 254 | *(base + 2) = 0; 255 | *(base + 3) = 255; 256 | 257 | if (abs(row - col) < 3) { 258 | *(base + 0) = 255.; 259 | *(base + 1) = 255; 260 | *(base + 2) = 255; 261 | *(base + 3) = 255; 262 | } 263 | 264 | if (abs((w - col) - (row)) < 3) { 265 | *(base + 0) = 0.; 266 | *(base + 1) = 0; 267 | *(base + 2) = 0; 268 | *(base + 3) = 255; 269 | } 270 | } 271 | } 272 | 273 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)w, (GLsizei)h, GL_RGBA, GL_UNSIGNED_BYTE, 274 | (GLvoid*)rgb); 275 | delete [] rgb; 276 | } 277 | 278 | void 279 | render_frame(int w, 280 | int h, 281 | XrMatrix4x4f projectionmatrix, 282 | XrMatrix4x4f viewmatrix, 283 | XrSpaceLocation* hand_locations, 284 | bool* hand_locations_valid, 285 | XrHandJointLocationsEXT* joint_locations, 286 | GLuint framebuffer, 287 | GLuint depthbuffer, 288 | XrSwapchainImageOpenGLKHR image, 289 | int view_index, 290 | XrTime predictedDisplayTime) 291 | { 292 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 293 | 294 | glViewport(0, 0, w, h); 295 | glScissor(0, 0, w, h); 296 | 297 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image.image, 0); 298 | if (depthbuffer != UINT32_MAX) { 299 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthbuffer, 0); 300 | } else { 301 | // TODO: need a depth attachment for depth test when rendering to fbo 302 | } 303 | 304 | glClearColor(.0f, 0.0f, 0.2f, 1.0f); 305 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 306 | 307 | double display_time_seconds = ((double)predictedDisplayTime) / (1000. * 1000. * 1000.); 308 | const float rotations_per_sec = .25; 309 | float rotation = ((long)(display_time_seconds * 360. * rotations_per_sec)) % 360; 310 | 311 | float dist = 1.5f; 312 | float height = 0.5f; 313 | render_cube(vec3(0, height, -dist), .33f, rotation, viewmatrix.m, projectionmatrix.m); 314 | render_cube(vec3(0, height, dist), .33f, rotation, viewmatrix.m, projectionmatrix.m); 315 | render_cube(vec3(dist, height, 0), .33f, rotation, viewmatrix.m, projectionmatrix.m); 316 | render_cube(vec3(-dist, height, 0), .33f, rotation, viewmatrix.m, projectionmatrix.m); 317 | 318 | glUseProgram(shaderProgramID); 319 | glBindVertexArray(VAOs[0]); 320 | 321 | int color = glGetUniformLocation(shaderProgramID, "uniformColor"); 322 | // the color (0, 0, 0) will get replaced by some UV color in the shader 323 | glUniform3f(color, 0.0, 0.0, 0.0); 324 | 325 | int viewLoc = glGetUniformLocation(shaderProgramID, "view"); 326 | glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (float*)viewmatrix.m); 327 | int projLoc = glGetUniformLocation(shaderProgramID, "proj"); 328 | glUniformMatrix4fv(projLoc, 1, GL_FALSE, (float*)projectionmatrix.m); 329 | 330 | int modelLoc = glGetUniformLocation(shaderProgramID, "model"); 331 | for (int hand = 0; hand < 2; hand++) { 332 | if (hand == 0) { 333 | glUniform3f(color, 1.0, 0.5, 0.5); 334 | } else { 335 | glUniform3f(color, 0.5, 1.0, 0.5); 336 | } 337 | 338 | // draw blocks for controller locations if hand tracking is not available 339 | if (!joint_locations[hand].isActive) { 340 | 341 | if (!hand_locations_valid[hand]) 342 | continue; 343 | 344 | XrMatrix4x4f matrix; 345 | XrVector3f scale = {.x = .05f, .y = .05f, .z = .2f}; 346 | XrMatrix4x4f_CreateModelMatrix(&matrix, &hand_locations[hand].pose.position, 347 | &hand_locations[hand].pose.orientation, &scale); 348 | glUniformMatrix4fv(modelLoc, 1, GL_FALSE, (float*)matrix.m); 349 | 350 | glDrawArrays(GL_TRIANGLES, 0, 36); 351 | continue; 352 | } 353 | 354 | for (uint32_t i = 0; i < joint_locations[hand].jointCount; i++) { 355 | struct XrHandJointLocationEXT* joint_location = &joint_locations[hand].jointLocations[i]; 356 | 357 | if (!(joint_location->locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT)) { 358 | continue; 359 | } 360 | 361 | float size = joint_location->radius; 362 | 363 | XrVector3f scale = {.x = size, .y = size, .z = size}; 364 | XrMatrix4x4f joint_matrix; 365 | XrMatrix4x4f_CreateModelMatrix(&joint_matrix, &joint_location->pose.position, 366 | &joint_location->pose.orientation, &scale); 367 | glUniformMatrix4fv(modelLoc, 1, GL_FALSE, (float*)joint_matrix.m); 368 | glDrawArrays(GL_TRIANGLES, 0, 36); 369 | } 370 | } 371 | 372 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 373 | 374 | if (view_index == 0) { 375 | //glBlitNamedFramebuffer((GLuint)framebuffer, // readFramebuffer 376 | // (GLuint)0, // backbuffer // drawFramebuffer 377 | // (GLint)0, // srcX0 378 | // (GLint)0, // srcY0 379 | // (GLint)w, // srcX1 380 | // (GLint)h, // srcY1 381 | // (GLint)0, // dstX0 382 | // (GLint)0, // dstY0 383 | // (GLint)w / 2, // dstX1 384 | // (GLint)h / 2, // dstY1 385 | // (GLbitfield)GL_COLOR_BUFFER_BIT, // mask 386 | // (GLenum)GL_LINEAR); // filter 387 | 388 | SDL_GL_SwapWindow(desktop_window); 389 | } 390 | } 391 | 392 | void 393 | cleanup_gl() 394 | { 395 | // TODO clean up gl stuff 396 | } 397 | -------------------------------------------------------------------------------- /glimpl.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019, Collabora, Ltd. 2 | // SPDX-License-Identifier: BSL-1.0 3 | /*! 4 | * @file 5 | * @brief A simple OpenXR example 6 | * @author Christoph Haag 7 | */ 8 | 9 | #ifndef GLIMPL 10 | #define GLIMPL 11 | 12 | #include 13 | 14 | #define NO_SDL_GLEXT 15 | #include 16 | #include 17 | #include 18 | 19 | #include "xrmath.h" 20 | 21 | #define XR_USE_PLATFORM_WIN32 22 | #define XR_USE_GRAPHICS_API_OPENGL 23 | #include "openxr/openxr.h" 24 | #include "openxr/openxr_platform.h" 25 | 26 | bool 27 | init_sdl_window(HDC& xDisplay, HGLRC& glxContext, 28 | int w, 29 | int h); 30 | 31 | int 32 | init_gl(); 33 | 34 | void 35 | render_quad(int w, 36 | int h, 37 | int64_t swapchain_format, 38 | XrSwapchainImageOpenGLKHR image, 39 | XrTime predictedDisplayTime); 40 | 41 | void 42 | render_frame(int w, 43 | int h, 44 | XrMatrix4x4f projectionmatrix, 45 | XrMatrix4x4f viewmatrix, 46 | XrSpaceLocation* hand_locations, 47 | bool* hand_locations_valid, 48 | XrHandJointLocationsEXT* joint_locations, 49 | GLuint framebuffer, 50 | GLuint depthbuffer, 51 | XrSwapchainImageOpenGLKHR image, 52 | int view_index, 53 | XrTime predictedDisplayTime); 54 | 55 | void 56 | cleanup_gl(); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019, Collabora, Ltd. 2 | // SPDX-License-Identifier: BSL-1.0 3 | /*! 4 | * @file 5 | * @brief A simple OpenXR example 6 | * @author Christoph Haag 7 | */ 8 | 9 | // STD Header 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "glimpl.h" // factored out rendering of a simple scene 16 | 17 | // OpenXR Header and defination 18 | #define XR_USE_GRAPHICS_API_OPENGL 19 | #define XR_USE_PLATFORM_WIN32 20 | #include "openxr/openxr.h" 21 | 22 | #include "xrmath.h" // math glue between OpenXR and OpenGL 23 | #include "math_3d.h" 24 | 25 | #include 26 | 27 | // we need an identity pose for creating spaces without offsets 28 | static XrPosef identity_pose = {.orientation = {.x = 0, .y = 0, .z = 0, .w = 1.0}, 29 | .position = {.x = 0, .y = 0, .z = 0}}; 30 | 31 | // small helper so we don't forget whether we treat 0 as left or right hand 32 | enum OPENXR_HANDS 33 | { 34 | HAND_LEFT = 0, 35 | HAND_RIGHT = 1, 36 | HAND_COUNT 37 | }; 38 | 39 | std::string h_str(int hand) 40 | { 41 | if (hand == HAND_LEFT) 42 | return "left"; 43 | else if (hand == HAND_RIGHT) 44 | return "right"; 45 | else 46 | return "invalid"; 47 | } 48 | 49 | std::string h_p_str(int hand) 50 | { 51 | if (hand == HAND_LEFT) 52 | return "/user/hand/left"; 53 | else if (hand == HAND_RIGHT) 54 | return "/user/hand/right"; 55 | else 56 | return "invalid"; 57 | } 58 | 59 | class XrExample 60 | { 61 | public: 62 | // every OpenXR app that displays something needs at least an instance and a session 63 | XrInstance instance = XR_NULL_HANDLE; 64 | XrSession session; 65 | XrSystemId system_id; 66 | XrSessionState state; 67 | 68 | // Play space is usually local (head is origin, seated) or stage (room scale) 69 | XrSpace play_space; 70 | 71 | // Each physical Display/Eye is described by a view 72 | std::vector viewconfig_views; 73 | std::vector projection_views; 74 | std::vector views; 75 | 76 | // The runtime interacts with the OpenGL images (textures) via a Swapchain. 77 | XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl; 78 | 79 | int64_t swapchain_format; 80 | // one array of images per view. 81 | std::vector> images; 82 | // one swapchain per view. Using only one and rendering l/r to the same image is also possible. 83 | std::vector swapchains; 84 | 85 | int64_t depth_swapchain_format; 86 | std::vector> depth_images; 87 | std::vector depth_swapchains; 88 | 89 | // quad layers are placed into world space, no need to render them per eye 90 | int64_t quad_swapchain_format; 91 | uint32_t quad_pixel_width, quad_pixel_height; 92 | uint32_t quad_swapchain_length; 93 | std::vector quad_images; 94 | XrSwapchain quad_swapchain; 95 | 96 | float near_z; 97 | float far_z; 98 | 99 | // depth layer data 100 | struct 101 | { 102 | bool supported; 103 | std::vector infos; 104 | } depth; 105 | 106 | // cylinder layer extension data 107 | struct 108 | { 109 | bool supported; 110 | int64_t format; 111 | uint32_t swapchain_width, swapchain_height; 112 | uint32_t swapchain_length; 113 | std::vector images; 114 | XrSwapchain swapchain; 115 | } cylinder; 116 | 117 | // To render into a texture we need a framebuffer (one per texture to make it easy) 118 | std::vector> framebuffers; 119 | 120 | std::array hand_paths; 121 | 122 | // hand tracking extension data 123 | struct 124 | { 125 | bool supported; 126 | // whether the current VR system in use has hand tracking 127 | bool system_supported; 128 | PFN_xrLocateHandJointsEXT pfnLocateHandJointsEXT; 129 | std::array trackers; 130 | } hand_tracking; 131 | } xr_example; 132 | 133 | bool xr_result(XrInstance instance, XrResult result, const char* format, ...) 134 | { 135 | if (XR_SUCCEEDED(result)) 136 | return true; 137 | 138 | char resultString[XR_MAX_RESULT_STRING_SIZE]; 139 | xrResultToString(instance, result, resultString); 140 | 141 | size_t len1 = strlen(format); 142 | size_t len2 = strlen(resultString) + 1; 143 | char *formatRes = new char[len1 + len2 + 4]; // + " []\n" 144 | sprintf(formatRes, "%s [%s]\n", format, resultString); 145 | 146 | va_list args; 147 | va_start(args, format); 148 | vprintf(formatRes, args); 149 | va_end(args); 150 | 151 | delete [] formatRes; 152 | return false; 153 | } 154 | 155 | void sdl_handle_events(SDL_Event event, bool* running); 156 | 157 | // some optional OpenXR calls demonstrated in functions to clutter the main app less 158 | void get_instance_properties(XrInstance instance) 159 | { 160 | XrResult result; 161 | XrInstanceProperties instance_props = { 162 | .type = XR_TYPE_INSTANCE_PROPERTIES, 163 | .next = NULL, 164 | }; 165 | 166 | result = xrGetInstanceProperties(instance, &instance_props); 167 | if (!xr_result(NULL, result, "Failed to get instance info")) 168 | return; 169 | 170 | std::cout 171 | << "Runtime Name: " << instance_props.runtimeName << "\n" 172 | << "Runtime Version: " << XR_VERSION_MAJOR(instance_props.runtimeVersion) << "." << XR_VERSION_MINOR(instance_props.runtimeVersion) << "." << XR_VERSION_PATCH(instance_props.runtimeVersion) << std::endl; 173 | } 174 | 175 | void print_system_properties(XrSystemProperties* system_properties, bool hand_tracking_ext) 176 | { 177 | std::cout 178 | << "System properties for system " << system_properties->systemId << " \"" 179 | << system_properties->systemName << "\", vendor ID " << system_properties->vendorId << "\n" 180 | << "\tMax layers : " << system_properties->graphicsProperties.maxLayerCount << "\n" 181 | << "\tMax swapchain height: " << system_properties->graphicsProperties.maxSwapchainImageHeight << "\n" 182 | << "\tMax swapchain width : " << system_properties->graphicsProperties.maxSwapchainImageWidth << "\n" 183 | << "\tOrientation Tracking: " << system_properties->trackingProperties.orientationTracking << "\n" 184 | << "\tPosition Tracking : " << system_properties->trackingProperties.positionTracking << std::endl; 185 | 186 | if (hand_tracking_ext) { 187 | XrSystemHandTrackingPropertiesEXT* ht = (XrSystemHandTrackingPropertiesEXT*)system_properties->next; 188 | std::cout << "\tHand Tracking : " << ht->supportsHandTracking << std::endl; 189 | } 190 | } 191 | 192 | void print_supported_view_configs(XrExample* self) 193 | { 194 | XrResult result; 195 | 196 | uint32_t view_config_count; 197 | result = xrEnumerateViewConfigurations(self->instance, self->system_id, 0, &view_config_count, NULL); 198 | if (!xr_result(self->instance, result, "Failed to get view configuration count")) 199 | return; 200 | 201 | std::cout << "Runtime supports " << view_config_count << " view configurations\n"; 202 | 203 | std::vector view_configs(view_config_count); 204 | result = xrEnumerateViewConfigurations(self->instance, self->system_id, view_config_count, &view_config_count, view_configs.data()); 205 | if (!xr_result(self->instance, result, "Failed to enumerate view configurations!")) 206 | return; 207 | 208 | std::cout << "Runtime supports view configurations:\n"; 209 | for (uint32_t i = 0; i < view_config_count; ++i) { 210 | XrViewConfigurationProperties props = {.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES, 211 | .next = NULL}; 212 | 213 | result = xrGetViewConfigurationProperties(self->instance, self->system_id, view_configs[i], &props); 214 | if (!xr_result(self->instance, result, "Failed to get view configuration info %d!", i)) 215 | return; 216 | 217 | std::cout << props.viewConfigurationType << ": FOV mutable: "<< props.fovMutable << "\n"; 218 | } 219 | } 220 | 221 | void print_viewconfig_view_info(XrExample* self) 222 | { 223 | for (uint32_t i = 0; i < self->viewconfig_views.size(); i++) { 224 | printf("View Configuration View %d:\n", i); 225 | printf("\tResolution : Recommended %dx%d, Max: %dx%d\n", 226 | self->viewconfig_views[0].recommendedImageRectWidth, 227 | self->viewconfig_views[0].recommendedImageRectHeight, 228 | self->viewconfig_views[0].maxImageRectWidth, 229 | self->viewconfig_views[0].maxImageRectHeight); 230 | printf("\tSwapchain Samples: Recommended: %d, Max: %d)\n", 231 | self->viewconfig_views[0].recommendedSwapchainSampleCount, 232 | self->viewconfig_views[0].maxSwapchainSampleCount); 233 | } 234 | } 235 | 236 | bool check_opengl_version(XrGraphicsRequirementsOpenGLKHR* opengl_reqs) 237 | { 238 | XrVersion desired_opengl_version = XR_MAKE_VERSION(3, 3, 0); 239 | if (desired_opengl_version > opengl_reqs->maxApiVersionSupported || 240 | desired_opengl_version < opengl_reqs->minApiVersionSupported) { 241 | printf( 242 | "We want OpenGL %d.%d.%d, but runtime only supports OpenGL %d.%d.%d - %d.%d.%d!\n", 243 | XR_VERSION_MAJOR(desired_opengl_version), XR_VERSION_MINOR(desired_opengl_version), 244 | XR_VERSION_PATCH(desired_opengl_version), 245 | XR_VERSION_MAJOR(opengl_reqs->minApiVersionSupported), 246 | XR_VERSION_MINOR(opengl_reqs->minApiVersionSupported), 247 | XR_VERSION_PATCH(opengl_reqs->minApiVersionSupported), 248 | XR_VERSION_MAJOR(opengl_reqs->maxApiVersionSupported), 249 | XR_VERSION_MINOR(opengl_reqs->maxApiVersionSupported), 250 | XR_VERSION_PATCH(opengl_reqs->maxApiVersionSupported)); 251 | return false; 252 | } 253 | return true; 254 | } 255 | 256 | void print_reference_spaces(XrExample* self) 257 | { 258 | XrResult result; 259 | 260 | uint32_t ref_space_count; 261 | result = xrEnumerateReferenceSpaces(self->session, 0, &ref_space_count, NULL); 262 | if (!xr_result(self->instance, result, "Getting number of reference spaces failed!")) 263 | return; 264 | 265 | std::vector ref_spaces(ref_space_count); 266 | result = xrEnumerateReferenceSpaces(self->session, ref_space_count, &ref_space_count, ref_spaces.data()); 267 | if (!xr_result(self->instance, result, "Enumerating reference spaces failed!")) 268 | return; 269 | 270 | printf("Runtime supports %d reference spaces:\n", ref_space_count); 271 | for (uint32_t i = 0; i < ref_space_count; i++) { 272 | if (ref_spaces[i] == XR_REFERENCE_SPACE_TYPE_LOCAL) { 273 | printf("\tXR_REFERENCE_SPACE_TYPE_LOCAL\n"); 274 | } else if (ref_spaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) { 275 | printf("\tXR_REFERENCE_SPACE_TYPE_STAGE\n"); 276 | } else if (ref_spaces[i] == XR_REFERENCE_SPACE_TYPE_VIEW) { 277 | printf("\tXR_REFERENCE_SPACE_TYPE_VIEW\n"); 278 | } else { 279 | printf("\tOther (extension?) refspace %u\\n", ref_spaces[i]); 280 | } 281 | } 282 | } 283 | 284 | int init_openxr(XrExample* self) 285 | { 286 | XrResult result; 287 | 288 | // --- Make sure runtime supports the OpenGL extension 289 | 290 | // xrEnumerate*() functions are usually called once with CapacityInput = 0. 291 | // The function will write the required amount into CountOutput. We then have 292 | // to allocate an array to hold CountOutput elements and call the function 293 | // with CountOutput as CapacityInput. 294 | uint32_t ext_count = 0; 295 | result = xrEnumerateInstanceExtensionProperties(NULL, 0, &ext_count, NULL); 296 | 297 | /* TODO: instance null will not be able to convert XrResult to string */ 298 | if (!xr_result(NULL, result, "Failed to enumerate number of extension properties")) 299 | return 1; 300 | 301 | printf("Runtime supports %d extensions\n", ext_count); 302 | 303 | std::vector extensionProperties(ext_count, { XR_TYPE_EXTENSION_PROPERTIES, nullptr }); 304 | result = xrEnumerateInstanceExtensionProperties(NULL, ext_count, &ext_count, extensionProperties.data()); 305 | if (!xr_result(NULL, result, "Failed to enumerate extension properties")) 306 | return 1; 307 | 308 | bool opengl_ext = false; 309 | for (uint32_t i = 0; i < ext_count; i++) { 310 | printf("\t%s v%d\n", extensionProperties[i].extensionName, extensionProperties[i].extensionVersion); 311 | if (strcmp(XR_KHR_OPENGL_ENABLE_EXTENSION_NAME, extensionProperties[i].extensionName) == 0) { 312 | opengl_ext = true; 313 | } 314 | 315 | if (strcmp(XR_EXT_HAND_TRACKING_EXTENSION_NAME, extensionProperties[i].extensionName) == 0) { 316 | self->hand_tracking.supported = true; 317 | } 318 | 319 | if (strcmp(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME, extensionProperties[i].extensionName) == 0) { 320 | self->cylinder.supported = true; 321 | } 322 | 323 | if (strcmp(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME, extensionProperties[i].extensionName) == 0) { 324 | self->depth.supported = true; 325 | } 326 | } 327 | 328 | // A graphics extension like OpenGL is required to draw anything in VR 329 | if (!opengl_ext) { 330 | printf("Runtime does not support OpenGL extension!\n"); 331 | return 1; 332 | } 333 | 334 | printf("Runtime supports extensions:\n"); 335 | printf("\t%s: %d\n", XR_KHR_OPENGL_ENABLE_EXTENSION_NAME, opengl_ext); 336 | printf("\t%s: %d\n", XR_EXT_HAND_TRACKING_EXTENSION_NAME, self->hand_tracking.supported); 337 | printf("\t%s: %d\n", XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME, self->cylinder.supported); 338 | printf("\t%s: %d\n", XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME, self->depth.supported); 339 | 340 | // --- Create XrInstance 341 | int enabled_ext_count = 1; 342 | const char* enabled_exts[3] = {XR_KHR_OPENGL_ENABLE_EXTENSION_NAME}; 343 | 344 | if (self->hand_tracking.supported) { 345 | enabled_exts[enabled_ext_count++] = XR_EXT_HAND_TRACKING_EXTENSION_NAME; 346 | } 347 | if (self->cylinder.supported) { 348 | enabled_exts[enabled_ext_count++] = XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME; 349 | } 350 | 351 | // same can be done for API layers, but API layers can also be enabled by env var 352 | 353 | XrInstanceCreateInfo instance_create_info = { 354 | XR_TYPE_INSTANCE_CREATE_INFO, 355 | nullptr, 356 | 0, 357 | { 358 | "OpenXR OpenGL Example", 1, 359 | "Custom", 0, 360 | XR_CURRENT_API_VERSION, 361 | }, 362 | 0, 363 | NULL, 364 | enabled_ext_count, 365 | enabled_exts 366 | }; 367 | 368 | result = xrCreateInstance(&instance_create_info, &self->instance); 369 | if (!xr_result(NULL, result, "Failed to create XR instance.")) 370 | return 1; 371 | 372 | // Optionally get runtime name and version 373 | get_instance_properties(self->instance); 374 | 375 | // --- Create XrSystem 376 | XrSystemGetInfo system_get_info = { .type = XR_TYPE_SYSTEM_GET_INFO, 377 | .next = NULL, 378 | .formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY }; 379 | 380 | result = xrGetSystem(self->instance, &system_get_info, &self->system_id); 381 | if (!xr_result(self->instance, result, "Failed to get system for HMD form factor.")) 382 | return 1; 383 | 384 | printf("Successfully got XrSystem with id %lu for HMD form factor\n", self->system_id); 385 | 386 | 387 | // checking system properties is generally optional, but we are interested in hand tracking 388 | // support 389 | { 390 | XrSystemProperties system_props = { 391 | .type = XR_TYPE_SYSTEM_PROPERTIES, 392 | .next = NULL, 393 | .graphicsProperties = {0}, 394 | .trackingProperties = {0}, 395 | }; 396 | 397 | XrSystemHandTrackingPropertiesEXT ht = {.type = XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT, 398 | .next = NULL}; 399 | if (self->hand_tracking.supported) { 400 | system_props.next = &ht; 401 | } 402 | 403 | result = xrGetSystemProperties(self->instance, self->system_id, &system_props); 404 | if (!xr_result(self->instance, result, "Failed to get System properties")) 405 | return 1; 406 | 407 | self->hand_tracking.system_supported = self->hand_tracking.supported && ht.supportsHandTracking; 408 | 409 | print_system_properties(&system_props, self->hand_tracking.supported); 410 | } 411 | 412 | print_supported_view_configs(self); 413 | // Stereo is most common for VR. We could check if stereo is supported and maybe choose another 414 | // one, but as this app is only tested with stereo, we assume it is (next call will error anyway 415 | // if not). 416 | XrViewConfigurationType view_type = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; 417 | 418 | uint32_t view_count = 0; 419 | result = xrEnumerateViewConfigurationViews(self->instance, self->system_id, view_type, 0, &view_count, NULL); 420 | if (!xr_result(self->instance, result, "Failed to get view configuration view count!")) 421 | return 1; 422 | 423 | self->viewconfig_views.resize(view_count, { XR_TYPE_VIEW_CONFIGURATION_VIEW, nullptr }); 424 | 425 | result = xrEnumerateViewConfigurationViews(self->instance, self->system_id, view_type, view_count, &view_count, self->viewconfig_views.data()); 426 | if (!xr_result(self->instance, result, "Failed to enumerate view configuration views!")) 427 | return 1; 428 | print_viewconfig_view_info(self); 429 | 430 | 431 | // OpenXR requires checking graphics requirements before creating a session. 432 | XrGraphicsRequirementsOpenGLKHR opengl_reqs = {.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR, .next = NULL}; 433 | 434 | PFN_xrGetOpenGLGraphicsRequirementsKHR pfnGetOpenGLGraphicsRequirementsKHR = NULL; 435 | { 436 | result = xrGetInstanceProcAddr(self->instance, "xrGetOpenGLGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&pfnGetOpenGLGraphicsRequirementsKHR); 437 | if (!xr_result(self->instance, result, "Failed to get OpenGL graphics requirements function!")) 438 | return 1; 439 | } 440 | 441 | result = pfnGetOpenGLGraphicsRequirementsKHR(self->instance, self->system_id, &opengl_reqs); 442 | if (!xr_result(self->instance, result, "Failed to get OpenGL graphics requirements!")) 443 | return 1; 444 | 445 | // On OpenGL we never fail this check because the version requirement is not useful. 446 | // Other APIs may have more useful requirements. 447 | check_opengl_version(&opengl_reqs); 448 | 449 | 450 | // --- Create session 451 | self->graphics_binding_gl = XrGraphicsBindingOpenGLWin32KHR{ .type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, }; 452 | 453 | // create SDL window the size of the left eye & fill GL graphics binding info 454 | if (!init_sdl_window(self->graphics_binding_gl.hDC, self->graphics_binding_gl.hGLRC, 455 | self->viewconfig_views[0].recommendedImageRectWidth, 456 | self->viewconfig_views[0].recommendedImageRectHeight)) { 457 | printf("GLX init failed!\n"); 458 | return 1; 459 | } 460 | 461 | printf("Using OpenGL version: %s\n", glGetString(GL_VERSION)); 462 | printf("Using OpenGL Renderer: %s\n", glGetString(GL_RENDERER)); 463 | 464 | // Set up rendering (compile shaders, ...) 465 | if (init_gl() != 0) { 466 | printf("OpenGl setup failed!\n"); 467 | return 1; 468 | } 469 | 470 | self->state = XR_SESSION_STATE_UNKNOWN; 471 | 472 | XrSessionCreateInfo session_create_info = {.type = XR_TYPE_SESSION_CREATE_INFO, 473 | .next = &self->graphics_binding_gl, 474 | .systemId = self->system_id}; 475 | 476 | result = xrCreateSession(self->instance, &session_create_info, &self->session); 477 | if (!xr_result(self->instance, result, "Failed to create session")) 478 | return 1; 479 | 480 | printf("Successfully created a session with OpenGL!\n"); 481 | 482 | if (self->hand_tracking.system_supported) { 483 | result = xrGetInstanceProcAddr(self->instance, "xrLocateHandJointsEXT", (PFN_xrVoidFunction*)&self->hand_tracking.pfnLocateHandJointsEXT); 484 | xr_result(self->instance, result, "Failed to get xrLocateHandJointsEXT function!"); 485 | 486 | PFN_xrCreateHandTrackerEXT pfnCreateHandTrackerEXT = NULL; 487 | result = xrGetInstanceProcAddr(self->instance, "xrCreateHandTrackerEXT", (PFN_xrVoidFunction*)&pfnCreateHandTrackerEXT); 488 | 489 | if (!xr_result(self->instance, result, "Failed to get xrCreateHandTrackerEXT function!")) 490 | return 1; 491 | 492 | { 493 | XrHandTrackerCreateInfoEXT hand_tracker_create_info = { 494 | .type = XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, 495 | .next = NULL, 496 | .hand = XR_HAND_LEFT_EXT, 497 | .handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT}; 498 | result = pfnCreateHandTrackerEXT(self->session, &hand_tracker_create_info, 499 | &self->hand_tracking.trackers[HAND_LEFT]); 500 | if (!xr_result(self->instance, result, "Failed to create left hand tracker")) { 501 | return 1; 502 | } 503 | printf("Created hand tracker for left hand\n"); 504 | } 505 | { 506 | XrHandTrackerCreateInfoEXT hand_tracker_create_info = { 507 | .type = XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, 508 | .next = NULL, 509 | .hand = XR_HAND_RIGHT_EXT, 510 | .handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT}; 511 | result = pfnCreateHandTrackerEXT(self->session, &hand_tracker_create_info, 512 | &self->hand_tracking.trackers[HAND_RIGHT]); 513 | if (!xr_result(self->instance, result, "Failed to create right hand tracker")) { 514 | return 1; 515 | } 516 | printf("Created hand tracker for right hand\n"); 517 | } 518 | } 519 | 520 | XrReferenceSpaceType play_space_type = XR_REFERENCE_SPACE_TYPE_LOCAL; 521 | // We could check if our ref space type is supported, but next call will error anyway if not 522 | print_reference_spaces(self); 523 | 524 | XrReferenceSpaceCreateInfo play_space_create_info = {.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO, 525 | .next = NULL, 526 | .referenceSpaceType = play_space_type, 527 | .poseInReferenceSpace = identity_pose}; 528 | 529 | result = xrCreateReferenceSpace(self->session, &play_space_create_info, &self->play_space); 530 | if (!xr_result(self->instance, result, "Failed to create play space!")) 531 | return 1; 532 | 533 | // --- Begin session 534 | XrSessionBeginInfo session_begin_info = { .type = XR_TYPE_SESSION_BEGIN_INFO, .next = NULL, .primaryViewConfigurationType = view_type}; 535 | result = xrBeginSession(self->session, &session_begin_info); 536 | if (!xr_result(self->instance, result, "Failed to begin session!")) 537 | return 1; 538 | printf("Session started!\n"); 539 | 540 | // --- Create Swapchains 541 | uint32_t swapchain_format_count; 542 | result = xrEnumerateSwapchainFormats(self->session, 0, &swapchain_format_count, NULL); 543 | if (!xr_result(self->instance, result, "Failed to get number of supported swapchain formats")) 544 | return 1; 545 | 546 | printf("Runtime supports %d swapchain formats\n", swapchain_format_count); 547 | std::vector swapchain_formats(swapchain_format_count); 548 | result = xrEnumerateSwapchainFormats(self->session, swapchain_format_count, &swapchain_format_count, swapchain_formats.data()); 549 | if (!xr_result(self->instance, result, "Failed to enumerate swapchain formats")) 550 | return 1; 551 | 552 | // SRGB is usually the best choice. Selection logic should be expanded though. 553 | int64_t preferred_swapchain_format = GL_SRGB8_ALPHA8; 554 | // Using a depth format that directly maps to vulkan is a good idea: 555 | // GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32F 556 | int64_t preferred_depth_swapchain_format = GL_DEPTH_COMPONENT32F; 557 | int64_t preferred_quad_swapchain_format = GL_RGBA8_EXT; 558 | 559 | self->swapchain_format = swapchain_formats[0]; 560 | self->quad_swapchain_format = swapchain_formats[0]; 561 | self->cylinder.format = swapchain_formats[0]; 562 | self->depth_swapchain_format = -1; 563 | for (auto& swapchain_format : swapchain_formats) 564 | { 565 | printf("Supported GL format: %#lx\n", swapchain_format); 566 | if (swapchain_format == preferred_swapchain_format) { 567 | self->swapchain_format = swapchain_format; 568 | printf("Using preferred swapchain format %#lx\n", self->swapchain_format); 569 | } 570 | if (swapchain_format == preferred_depth_swapchain_format) { 571 | self->depth_swapchain_format = swapchain_format; 572 | printf("Using preferred depth swapchain format %#lx\n", self->depth_swapchain_format); 573 | } 574 | if (swapchain_format == preferred_quad_swapchain_format) { 575 | self->quad_swapchain_format = swapchain_format; 576 | self->cylinder.format = swapchain_format; 577 | printf("Using preferred quad swapchain format %#lx\n", self->quad_swapchain_format); 578 | } 579 | } 580 | 581 | if (self->swapchain_format != preferred_swapchain_format) { 582 | printf("Using non preferred swapchain format %#lx\n", self->swapchain_format); 583 | } 584 | /* All OpenGL textures that will be submitted in xrEndFrame are created by the runtime here. 585 | * The runtime will give us a number (not controlled by us) of OpenGL textures per swapchain 586 | * and tell us with xrAcquireSwapchainImage, which of those we can render to per frame. 587 | * Here we use one swapchain per view (eye), and for example 3 ("triple buffering") images per 588 | * swapchain. 589 | */ 590 | self->swapchains.resize(view_count); 591 | self->images.resize(view_count); 592 | for (uint32_t i = 0; i < view_count; i++) { 593 | XrSwapchainCreateInfo swapchain_create_info; 594 | swapchain_create_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; 595 | swapchain_create_info.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; 596 | swapchain_create_info.createFlags = 0; 597 | swapchain_create_info.format = self->swapchain_format; 598 | swapchain_create_info.sampleCount = self->viewconfig_views[i].recommendedSwapchainSampleCount; 599 | swapchain_create_info.width = self->viewconfig_views[i].recommendedImageRectWidth; 600 | swapchain_create_info.height = self->viewconfig_views[i].recommendedImageRectHeight; 601 | swapchain_create_info.faceCount = 1; 602 | swapchain_create_info.arraySize = 1; 603 | swapchain_create_info.mipCount = 1; 604 | swapchain_create_info.next = NULL; 605 | 606 | result = xrCreateSwapchain(self->session, &swapchain_create_info, &self->swapchains[i]); 607 | if (!xr_result(self->instance, result, "Failed to create swapchain %d!", i)) 608 | return 1; 609 | 610 | uint32_t swapchain_length; 611 | result = xrEnumerateSwapchainImages(self->swapchains[i], 0, &swapchain_length, nullptr); 612 | if (!xr_result(self->instance, result, "Failed to enumerate swapchains")) 613 | return 1; 614 | 615 | // these are wrappers for the actual OpenGL texture id 616 | self->images[i].resize(swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR , nullptr}); 617 | result = xrEnumerateSwapchainImages(self->swapchains[i], swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader*)self->images[i].data()); 618 | if (!xr_result(self->instance, result, "Failed to enumerate swapchain images")) 619 | return 1; 620 | } 621 | 622 | /* Allocate resources that we use for our own rendering. 623 | * We will bind framebuffers to the runtime provided textures for rendering. 624 | * For this, we create one framebuffer per OpenGL texture. 625 | * This is not mandated by OpenXR, other ways to render to textures will work too. 626 | */ 627 | self->framebuffers.resize(view_count); 628 | for (uint32_t i = 0; i < view_count; i++) { 629 | self->framebuffers[i].resize(self->images[i].size()); 630 | glGenFramebuffers(self->framebuffers[i].size(), self->framebuffers[i].data()); 631 | } 632 | 633 | if (self->depth_swapchain_format == -1) { 634 | printf("Preferred depth swapchain format %#lx not supported!\n", 635 | preferred_depth_swapchain_format); 636 | } 637 | 638 | if (self->depth_swapchain_format != -1) { 639 | self->depth_swapchains.resize(view_count); 640 | self->depth_images.resize( view_count); 641 | for (uint32_t i = 0; i < view_count; i++) { 642 | XrSwapchainCreateInfo swapchain_create_info; 643 | swapchain_create_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; 644 | swapchain_create_info.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 645 | swapchain_create_info.createFlags = 0; 646 | swapchain_create_info.format = self->depth_swapchain_format; 647 | swapchain_create_info.sampleCount = self->viewconfig_views[i].recommendedSwapchainSampleCount; 648 | swapchain_create_info.width = self->viewconfig_views[i].recommendedImageRectWidth; 649 | swapchain_create_info.height = self->viewconfig_views[i].recommendedImageRectHeight; 650 | swapchain_create_info.faceCount = 1; 651 | swapchain_create_info.arraySize = 1; 652 | swapchain_create_info.mipCount = 1; 653 | swapchain_create_info.next = NULL; 654 | 655 | result = xrCreateSwapchain(self->session, &swapchain_create_info, &self->depth_swapchains[i]); 656 | if (!xr_result(self->instance, result, "Failed to create swapchain %d!", i)) 657 | return 1; 658 | 659 | uint32_t depth_swapchain_length; 660 | result = xrEnumerateSwapchainImages(self->depth_swapchains[i], 0, &depth_swapchain_length, nullptr); 661 | if (!xr_result(self->instance, result, "Failed to enumerate swapchains")) 662 | return 1; 663 | 664 | // these are wrappers for the actual OpenGL texture id 665 | self->depth_images[i].resize(depth_swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR , nullptr}); 666 | result = xrEnumerateSwapchainImages( self->depth_swapchains[i], depth_swapchain_length, &depth_swapchain_length, (XrSwapchainImageBaseHeader*)self->depth_images[i].data()); 667 | if (!xr_result(self->instance, result, "Failed to enumerate swapchain images")) 668 | return 1; 669 | } 670 | } 671 | 672 | { 673 | self->quad_pixel_width = 800; 674 | self->quad_pixel_height = 600; 675 | XrSwapchainCreateInfo swapchain_create_info; 676 | swapchain_create_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; 677 | swapchain_create_info.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; 678 | swapchain_create_info.createFlags = 0; 679 | swapchain_create_info.format = self->quad_swapchain_format; 680 | swapchain_create_info.sampleCount = 1; 681 | swapchain_create_info.width = self->quad_pixel_width; 682 | swapchain_create_info.height = self->quad_pixel_height; 683 | swapchain_create_info.faceCount = 1; 684 | swapchain_create_info.arraySize = 1; 685 | swapchain_create_info.mipCount = 1; 686 | swapchain_create_info.next = NULL; 687 | 688 | result = xrCreateSwapchain(self->session, &swapchain_create_info, &self->quad_swapchain); 689 | if (!xr_result(self->instance, result, "Failed to create swapchain!")) 690 | return 1; 691 | 692 | result = xrEnumerateSwapchainImages(self->quad_swapchain, 0, &self->quad_swapchain_length, NULL); 693 | if (!xr_result(self->instance, result, "Failed to enumerate swapchains")) 694 | return 1; 695 | 696 | // these are wrappers for the actual OpenGL texture id 697 | self->quad_images.resize(self->quad_swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR , nullptr}); 698 | result = xrEnumerateSwapchainImages(self->quad_swapchain, self->quad_swapchain_length, 699 | &self->quad_swapchain_length, 700 | (XrSwapchainImageBaseHeader*)self->quad_images.data()); 701 | if (!xr_result(self->instance, result, "Failed to enumerate swapchain images")) 702 | return 1; 703 | } 704 | 705 | if (self->cylinder.supported) { 706 | self->cylinder.swapchain_width = 800; 707 | self->cylinder.swapchain_height = 600; 708 | XrSwapchainCreateInfo swapchain_create_info; 709 | swapchain_create_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO; 710 | swapchain_create_info.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; 711 | swapchain_create_info.createFlags = 0; 712 | swapchain_create_info.format = self->cylinder.format; 713 | swapchain_create_info.sampleCount = 1; 714 | swapchain_create_info.width = self->cylinder.swapchain_width; 715 | swapchain_create_info.height = self->cylinder.swapchain_height; 716 | swapchain_create_info.faceCount = 1; 717 | swapchain_create_info.arraySize = 1; 718 | swapchain_create_info.mipCount = 1; 719 | swapchain_create_info.next = NULL; 720 | 721 | result = xrCreateSwapchain(self->session, &swapchain_create_info, &self->cylinder.swapchain); 722 | if (!xr_result(self->instance, result, "Failed to create swapchain!")) 723 | return 1; 724 | 725 | result = xrEnumerateSwapchainImages(self->cylinder.swapchain, 0, 726 | &self->cylinder.swapchain_length, NULL); 727 | if (!xr_result(self->instance, result, "Failed to enumerate swapchains")) 728 | return 1; 729 | 730 | // these are wrappers for the actual OpenGL texture id 731 | self->cylinder.images.resize(self->cylinder.swapchain_length, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR , nullptr}); 732 | result = xrEnumerateSwapchainImages(self->cylinder.swapchain, self->cylinder.swapchain_length, 733 | &self->cylinder.swapchain_length, 734 | (XrSwapchainImageBaseHeader*)self->cylinder.images.data()); 735 | if (!xr_result(self->instance, result, "Failed to enumerate swapchain images")) 736 | return 1; 737 | } 738 | 739 | 740 | self->near_z = 0.01f; 741 | self->far_z = 100.f; 742 | 743 | // A stereo view config implies two views, but our code is set up for a dynamic amount of views. 744 | // So we need to allocate a bunch of memory for data structures dynamically. 745 | self->views.resize(view_count, { XR_TYPE_VIEW , nullptr}); 746 | self->projection_views.resize(view_count); 747 | for (uint32_t i = 0; i < view_count; i++) { 748 | self->projection_views[i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW; 749 | self->projection_views[i].next = NULL; 750 | 751 | self->projection_views[i].subImage.swapchain = self->swapchains[i]; 752 | self->projection_views[i].subImage.imageArrayIndex = 0; 753 | self->projection_views[i].subImage.imageRect.offset.x = 0; 754 | self->projection_views[i].subImage.imageRect.offset.y = 0; 755 | self->projection_views[i].subImage.imageRect.extent.width = self->viewconfig_views[i].recommendedImageRectWidth; 756 | self->projection_views[i].subImage.imageRect.extent.height = self->viewconfig_views[i].recommendedImageRectHeight; 757 | 758 | // projection_views[i].pose (and fov) have to be filled every frame in frame loop 759 | }; 760 | 761 | // analog to projection layer allocation, though we can actually fill everything in here 762 | if (self->depth.supported) { 763 | self->depth.infos.resize(view_count); 764 | for (uint32_t i = 0; i < view_count; i++) { 765 | self->depth.infos[i].type = XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR; 766 | self->depth.infos[i].next = NULL; 767 | self->depth.infos[i].minDepth = 0.f; 768 | self->depth.infos[i].maxDepth = 1.f; 769 | self->depth.infos[i].nearZ = self->near_z; 770 | self->depth.infos[i].farZ = self->far_z; 771 | 772 | self->depth.infos[i].subImage.swapchain = self->depth_swapchains[i]; 773 | 774 | self->depth.infos[i].subImage.imageArrayIndex = 0; 775 | self->depth.infos[i].subImage.imageRect.offset.x = 0; 776 | self->depth.infos[i].subImage.imageRect.offset.y = 0; 777 | self->depth.infos[i].subImage.imageRect.extent.width = self->viewconfig_views[i].recommendedImageRectWidth; 778 | self->depth.infos[i].subImage.imageRect.extent.height = self->viewconfig_views[i].recommendedImageRectHeight; 779 | 780 | self->projection_views[i].next = &self->depth.infos[i]; 781 | }; 782 | } 783 | 784 | return 0; 785 | } 786 | 787 | void main_loop(XrExample* self) 788 | { 789 | XrResult result; 790 | 791 | XrActionSetCreateInfo main_actionset_info = { .type = XR_TYPE_ACTION_SET_CREATE_INFO, .next = NULL, .priority = 0}; 792 | strcpy(main_actionset_info.actionSetName, "mainactions"); 793 | strcpy(main_actionset_info.localizedActionSetName, "Main Actions"); 794 | 795 | XrActionSet main_actionset; 796 | result = xrCreateActionSet(self->instance, &main_actionset_info, &main_actionset); 797 | if (!xr_result(self->instance, result, "failed to create actionset")) 798 | return; 799 | 800 | xrStringToPath(self->instance, "/user/hand/left", &self->hand_paths[HAND_LEFT]); 801 | xrStringToPath(self->instance, "/user/hand/right", &self->hand_paths[HAND_RIGHT]); 802 | 803 | XrAction grab_action_float; 804 | { 805 | XrActionCreateInfo action_info = {.type = XR_TYPE_ACTION_CREATE_INFO, 806 | .next = NULL, 807 | .actionType = XR_ACTION_TYPE_FLOAT_INPUT, 808 | .countSubactionPaths = HAND_COUNT, 809 | .subactionPaths = self->hand_paths.data()}; 810 | strcpy(action_info.actionName, "grabobjectfloat"); 811 | strcpy(action_info.localizedActionName, "Grab Object"); 812 | 813 | result = xrCreateAction(main_actionset, &action_info, &grab_action_float); 814 | if (!xr_result(self->instance, result, "failed to create grab action")) 815 | return; 816 | } 817 | 818 | // just an example that could sensibly use one axis of e.g. a thumbstick 819 | XrAction throttle_action_float; 820 | { 821 | XrActionCreateInfo action_info = {.type = XR_TYPE_ACTION_CREATE_INFO, 822 | .next = NULL, 823 | .actionType = XR_ACTION_TYPE_FLOAT_INPUT, 824 | .countSubactionPaths = HAND_COUNT, 825 | .subactionPaths = self->hand_paths.data() }; 826 | strcpy(action_info.actionName, "throttle"); 827 | strcpy(action_info.localizedActionName, "Use Throttle forward/backward"); 828 | 829 | result = xrCreateAction(main_actionset, &action_info, &throttle_action_float); 830 | if (!xr_result(self->instance, result, "failed to create throttle action")) 831 | return; 832 | } 833 | 834 | XrAction pose_action; 835 | { 836 | XrActionCreateInfo action_info = {.type = XR_TYPE_ACTION_CREATE_INFO, 837 | .next = NULL, 838 | .actionType = XR_ACTION_TYPE_POSE_INPUT, 839 | .countSubactionPaths = HAND_COUNT, 840 | .subactionPaths = self->hand_paths.data() }; 841 | strcpy(action_info.actionName, "handpose"); 842 | strcpy(action_info.localizedActionName, "Hand Pose"); 843 | 844 | result = xrCreateAction(main_actionset, &action_info, &pose_action); 845 | if (!xr_result(self->instance, result, "failed to create pose action")) 846 | return; 847 | } 848 | 849 | XrAction haptic_action; 850 | { 851 | XrActionCreateInfo action_info = {.type = XR_TYPE_ACTION_CREATE_INFO, 852 | .next = NULL, 853 | .actionType = XR_ACTION_TYPE_VIBRATION_OUTPUT, 854 | .countSubactionPaths = HAND_COUNT, 855 | .subactionPaths = self->hand_paths.data() }; 856 | strcpy(action_info.actionName, "haptic"); 857 | strcpy(action_info.localizedActionName, "Haptic Vibration"); 858 | result = xrCreateAction(main_actionset, &action_info, &haptic_action); 859 | if (!xr_result(self->instance, result, "failed to create haptic action")) 860 | return; 861 | } 862 | 863 | XrPath select_click_path[HAND_COUNT]; 864 | xrStringToPath(self->instance, "/user/hand/left/input/select/click", 865 | &select_click_path[HAND_LEFT]); 866 | xrStringToPath(self->instance, "/user/hand/right/input/select/click", 867 | &select_click_path[HAND_RIGHT]); 868 | 869 | XrPath trigger_value_path[HAND_COUNT]; 870 | xrStringToPath(self->instance, "/user/hand/left/input/trigger/value", 871 | &trigger_value_path[HAND_LEFT]); 872 | xrStringToPath(self->instance, "/user/hand/right/input/trigger/value", 873 | &trigger_value_path[HAND_RIGHT]); 874 | 875 | XrPath thumbstick_y_path[HAND_COUNT]; 876 | xrStringToPath(self->instance, "/user/hand/left/input/thumbstick/y", 877 | &thumbstick_y_path[HAND_LEFT]); 878 | xrStringToPath(self->instance, "/user/hand/right/input/thumbstick/y", 879 | &thumbstick_y_path[HAND_RIGHT]); 880 | 881 | XrPath grip_pose_path[HAND_COUNT]; 882 | xrStringToPath(self->instance, "/user/hand/left/input/grip/pose", &grip_pose_path[HAND_LEFT]); 883 | xrStringToPath(self->instance, "/user/hand/right/input/grip/pose", &grip_pose_path[HAND_RIGHT]); 884 | 885 | XrPath haptic_path[HAND_COUNT]; 886 | xrStringToPath(self->instance, "/user/hand/left/output/haptic", &haptic_path[HAND_LEFT]); 887 | xrStringToPath(self->instance, "/user/hand/right/output/haptic", &haptic_path[HAND_RIGHT]); 888 | 889 | { 890 | XrPath interaction_profile_path; 891 | result = xrStringToPath(self->instance, "/interaction_profiles/khr/simple_controller", 892 | &interaction_profile_path); 893 | if (!xr_result(self->instance, result, "failed to get interaction profile")) 894 | return; 895 | 896 | const XrActionSuggestedBinding bindings[] = { 897 | {.action = pose_action, .binding = grip_pose_path[HAND_LEFT]}, 898 | {.action = pose_action, .binding = grip_pose_path[HAND_RIGHT]}, 899 | {.action = grab_action_float, .binding = select_click_path[HAND_LEFT]}, 900 | {.action = grab_action_float, .binding = select_click_path[HAND_RIGHT]}, 901 | {.action = haptic_action, .binding = haptic_path[HAND_LEFT]}, 902 | {.action = haptic_action, .binding = haptic_path[HAND_RIGHT]}, 903 | }; 904 | 905 | const XrInteractionProfileSuggestedBinding suggested_bindings = { 906 | .type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, 907 | .next = NULL, 908 | .interactionProfile = interaction_profile_path, 909 | .countSuggestedBindings = sizeof(bindings) / sizeof(bindings[0]), 910 | .suggestedBindings = bindings}; 911 | 912 | xrSuggestInteractionProfileBindings(self->instance, &suggested_bindings); 913 | if (!xr_result(self->instance, result, "failed to suggest bindings")) 914 | return; 915 | } 916 | 917 | { 918 | XrPath interaction_profile_path; 919 | result = xrStringToPath(self->instance, "/interaction_profiles/valve/index_controller", 920 | &interaction_profile_path); 921 | if (!xr_result(self->instance, result, "failed to get interaction profile")) 922 | return; 923 | 924 | const XrActionSuggestedBinding bindings[] = { 925 | {.action = pose_action, .binding = grip_pose_path[HAND_LEFT]}, 926 | {.action = pose_action, .binding = grip_pose_path[HAND_RIGHT]}, 927 | {.action = grab_action_float, .binding = trigger_value_path[HAND_LEFT]}, 928 | {.action = grab_action_float, .binding = trigger_value_path[HAND_RIGHT]}, 929 | {.action = throttle_action_float, .binding = thumbstick_y_path[HAND_LEFT]}, 930 | {.action = throttle_action_float, .binding = thumbstick_y_path[HAND_RIGHT]}, 931 | {.action = haptic_action, .binding = haptic_path[HAND_LEFT]}, 932 | {.action = haptic_action, .binding = haptic_path[HAND_RIGHT]}, 933 | }; 934 | 935 | const XrInteractionProfileSuggestedBinding suggested_bindings = { 936 | .type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, 937 | .next = NULL, 938 | .interactionProfile = interaction_profile_path, 939 | .countSuggestedBindings = sizeof(bindings) / sizeof(bindings[0]), 940 | .suggestedBindings = bindings}; 941 | 942 | xrSuggestInteractionProfileBindings(self->instance, &suggested_bindings); 943 | if (!xr_result(self->instance, result, "failed to suggest bindings")) 944 | return; 945 | } 946 | 947 | // poses can't be queried directly, we need to create a space for each 948 | XrSpace pose_action_spaces[HAND_COUNT]; 949 | { 950 | XrActionSpaceCreateInfo action_space_info; 951 | action_space_info.type = XR_TYPE_ACTION_SPACE_CREATE_INFO; 952 | action_space_info.next = NULL; 953 | action_space_info.action = pose_action; 954 | action_space_info.poseInActionSpace = identity_pose; 955 | action_space_info.subactionPath = self->hand_paths[HAND_LEFT]; 956 | 957 | result = xrCreateActionSpace(self->session, &action_space_info, &pose_action_spaces[HAND_LEFT]); 958 | if (!xr_result(self->instance, result, "failed to create left hand pose space")) 959 | return; 960 | } 961 | { 962 | XrActionSpaceCreateInfo action_space_info; 963 | action_space_info.type = XR_TYPE_ACTION_SPACE_CREATE_INFO; 964 | action_space_info.next = NULL; 965 | action_space_info.action = pose_action; 966 | action_space_info.poseInActionSpace = identity_pose; 967 | action_space_info.subactionPath = self->hand_paths[HAND_RIGHT]; 968 | 969 | result = 970 | xrCreateActionSpace(self->session, &action_space_info, &pose_action_spaces[HAND_RIGHT]); 971 | if (!xr_result(self->instance, result, "failed to create left hand pose space")) 972 | return; 973 | } 974 | 975 | XrSessionActionSetsAttachInfo actionset_attach_info = { 976 | .type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO, 977 | .next = NULL, 978 | .countActionSets = 1, 979 | .actionSets = &main_actionset}; 980 | result = xrAttachSessionActionSets(self->session, &actionset_attach_info); 981 | if (!xr_result(self->instance, result, "failed to attach action set")) 982 | return; 983 | 984 | int loop_count = 0; 985 | while (true) { 986 | loop_count++; 987 | 988 | // --- Poll SDL for events so we can exit with esc 989 | SDL_Event sdl_event; 990 | bool sdl_should_exit = false; 991 | while (SDL_PollEvent(&sdl_event)) { 992 | sdl_handle_events(sdl_event, &sdl_should_exit); 993 | } 994 | if (sdl_should_exit) { 995 | printf("Requesting exit...\n"); 996 | xrRequestExitSession(self->session); 997 | } 998 | 999 | 1000 | bool session_stopping = false; 1001 | 1002 | // --- Handle runtime Events 1003 | // we do this before xrWaitFrame() so we can go idle or 1004 | // break out of the main render loop as early as possible and don't have to 1005 | // uselessly render or submit one. Calling xrWaitFrame commits you to 1006 | // calling xrBeginFrame eventually. 1007 | XrEventDataBuffer runtime_event = {.type = XR_TYPE_EVENT_DATA_BUFFER, .next = NULL}; 1008 | XrResult poll_result = xrPollEvent(self->instance, &runtime_event); 1009 | while (poll_result == XR_SUCCESS) { 1010 | switch (runtime_event.type) { 1011 | case XR_TYPE_EVENT_DATA_EVENTS_LOST: { 1012 | XrEventDataEventsLost* event = (XrEventDataEventsLost*)&runtime_event; 1013 | printf("EVENT: %d events data lost!\n", event->lostEventCount); 1014 | // do we care if the runtime loses events? 1015 | break; 1016 | } 1017 | case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: { 1018 | XrEventDataInstanceLossPending* event = (XrEventDataInstanceLossPending*)&runtime_event; 1019 | printf("EVENT: instance loss pending at %lu! Destroying instance.\n", event->lossTime); 1020 | session_stopping = true; 1021 | break; 1022 | } 1023 | case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: { 1024 | XrEventDataSessionStateChanged* event = (XrEventDataSessionStateChanged*)&runtime_event; 1025 | printf("EVENT: session state changed from %d to %d\n", self->state, event->state); 1026 | 1027 | self->state = event->state; 1028 | 1029 | if (event->state >= XR_SESSION_STATE_STOPPING) { 1030 | printf("Session is stopping...\n"); 1031 | // still handle rest of the events instead of immediately quitting 1032 | session_stopping = true; 1033 | } 1034 | break; 1035 | } 1036 | case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: { 1037 | printf("EVENT: reference space change pending!\n"); 1038 | XrEventDataReferenceSpaceChangePending* event = 1039 | (XrEventDataReferenceSpaceChangePending*)&runtime_event; 1040 | (void)event; 1041 | // TODO: do something 1042 | break; 1043 | } 1044 | case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: { 1045 | printf("EVENT: interaction profile changed!\n"); 1046 | XrEventDataInteractionProfileChanged* event = 1047 | (XrEventDataInteractionProfileChanged*)&runtime_event; 1048 | (void)event; 1049 | 1050 | XrInteractionProfileState state = {.type = XR_TYPE_INTERACTION_PROFILE_STATE}; 1051 | 1052 | for (int i = 0; i < 2; i++) { 1053 | XrResult res = xrGetCurrentInteractionProfile(self->session, self->hand_paths[i], &state); 1054 | if (!xr_result(self->instance, res, "Failed to get interaction profile for %d", i)) 1055 | continue; 1056 | 1057 | XrPath prof = state.interactionProfile; 1058 | 1059 | uint32_t strl; 1060 | char profile_str[XR_MAX_PATH_LENGTH]; 1061 | res = xrPathToString(self->instance, prof, XR_MAX_PATH_LENGTH, &strl, profile_str); 1062 | if (!xr_result(self->instance, res, "Failed to get interaction profile path str for %s", 1063 | h_p_str(i))) 1064 | continue; 1065 | 1066 | printf("Event: Interaction profile changed for %s: %s\n", h_p_str(i), profile_str); 1067 | } 1068 | // TODO: do something 1069 | break; 1070 | } 1071 | 1072 | case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR: { 1073 | printf("EVENT: visibility mask changed!!\n"); 1074 | XrEventDataVisibilityMaskChangedKHR* event = 1075 | (XrEventDataVisibilityMaskChangedKHR*)&runtime_event; 1076 | (void)event; 1077 | // this event is from an extension 1078 | break; 1079 | } 1080 | case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT: { 1081 | printf("EVENT: perf settings!\n"); 1082 | XrEventDataPerfSettingsEXT* event = (XrEventDataPerfSettingsEXT*)&runtime_event; 1083 | (void)event; 1084 | // this event is from an extension 1085 | break; 1086 | } 1087 | default: printf("Unhandled event type %d\n", runtime_event.type); 1088 | } 1089 | 1090 | runtime_event.type = XR_TYPE_EVENT_DATA_BUFFER; 1091 | poll_result = xrPollEvent(self->instance, &runtime_event); 1092 | } 1093 | if (poll_result == XR_EVENT_UNAVAILABLE) { 1094 | // processed all events in the queue 1095 | } else { 1096 | printf("Failed to poll events!\n"); 1097 | break; 1098 | } 1099 | 1100 | if (session_stopping) { 1101 | printf("Quitting main render loop\n"); 1102 | return; 1103 | } 1104 | 1105 | // --- Wait for our turn to do head-pose dependent computation and render a frame 1106 | XrFrameState frameState = {.type = XR_TYPE_FRAME_STATE, .next = NULL}; 1107 | XrFrameWaitInfo frameWaitInfo = {.type = XR_TYPE_FRAME_WAIT_INFO, .next = NULL}; 1108 | result = xrWaitFrame(self->session, &frameWaitInfo, &frameState); 1109 | if (!xr_result(self->instance, result, "xrWaitFrame() was not successful, exiting...")) 1110 | break; 1111 | 1112 | 1113 | XrHandJointLocationEXT joints[HAND_COUNT][XR_HAND_JOINT_COUNT_EXT]; 1114 | XrHandJointLocationsEXT joint_locations[HAND_COUNT] = {{0}}; 1115 | if (self->hand_tracking.system_supported) { 1116 | 1117 | for (int i = 0; i < HAND_COUNT; i++) { 1118 | 1119 | joint_locations[i] = XrHandJointLocationsEXT{ 1120 | .type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT, 1121 | .jointCount = XR_HAND_JOINT_COUNT_EXT, 1122 | .jointLocations = joints[i], 1123 | }; 1124 | 1125 | if (self->hand_tracking.trackers[i] == NULL) 1126 | continue; 1127 | 1128 | XrHandJointsLocateInfoEXT locateInfo = {.type = XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT, 1129 | .next = NULL, 1130 | .baseSpace = self->play_space, 1131 | .time = frameState.predictedDisplayTime}; 1132 | 1133 | result = self->hand_tracking.pfnLocateHandJointsEXT(self->hand_tracking.trackers[i], 1134 | &locateInfo, &joint_locations[i]); 1135 | if (!xr_result(self->instance, result, "failed to locate hand %d joints!", i)) 1136 | break; 1137 | 1138 | /* 1139 | if (joint_locations[i].isActive) { 1140 | printf("located hand %d joints", i); 1141 | for (uint32_t j = 0; j < joint_locations[i].jointCount; j++) { 1142 | printf("%f ", joint_locations[i].jointLocations[j].radius); 1143 | } 1144 | printf("\n"); 1145 | } else { 1146 | printf("hand %d joints inactive\n", i); 1147 | } 1148 | */ 1149 | } 1150 | } 1151 | 1152 | // --- Create projection matrices and view matrices for each eye 1153 | XrViewLocateInfo view_locate_info = {.type = XR_TYPE_VIEW_LOCATE_INFO, 1154 | .next = NULL, 1155 | .viewConfigurationType = 1156 | XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 1157 | .displayTime = frameState.predictedDisplayTime, 1158 | .space = self->play_space}; 1159 | 1160 | uint32_t view_count = self->viewconfig_views.size(); 1161 | std::vector views(view_count); 1162 | for (uint32_t i = 0; i < view_count; i++) { 1163 | views[i].type = XR_TYPE_VIEW; 1164 | views[i].next = NULL; 1165 | }; 1166 | 1167 | XrViewState view_state = {.type = XR_TYPE_VIEW_STATE, .next = NULL}; 1168 | result = xrLocateViews(self->session, &view_locate_info, &view_state, view_count, 1169 | &view_count, views.data()); 1170 | if (!xr_result(self->instance, result, "Could not locate views")) 1171 | break; 1172 | 1173 | //! @todo Move this action processing to before xrWaitFrame, probably. 1174 | const XrActiveActionSet active_actionsets[] = { 1175 | {.actionSet = main_actionset, .subactionPath = XR_NULL_PATH}}; 1176 | 1177 | XrActionsSyncInfo actions_sync_info = { 1178 | .type = XR_TYPE_ACTIONS_SYNC_INFO, 1179 | .countActiveActionSets = sizeof(active_actionsets) / sizeof(active_actionsets[0]), 1180 | .activeActionSets = active_actionsets, 1181 | }; 1182 | result = xrSyncActions(self->session, &actions_sync_info); 1183 | xr_result(self->instance, result, "failed to sync actions!"); 1184 | 1185 | // query each value / location with a subaction path != XR_NULL_PATH 1186 | // resulting in individual values per hand/. 1187 | XrActionStateFloat grab_value[HAND_COUNT]; 1188 | XrActionStateFloat throttle_value[HAND_COUNT]; 1189 | XrSpaceLocation hand_locations[HAND_COUNT]; 1190 | bool hand_locations_valid[HAND_COUNT]; 1191 | 1192 | for (int i = 0; i < HAND_COUNT; i++) { 1193 | XrActionStatePose pose_state = {.type = XR_TYPE_ACTION_STATE_POSE, .next = NULL}; 1194 | { 1195 | XrActionStateGetInfo get_info = {.type = XR_TYPE_ACTION_STATE_GET_INFO, 1196 | .next = NULL, 1197 | .action = pose_action, 1198 | .subactionPath = self->hand_paths[i]}; 1199 | result = xrGetActionStatePose(self->session, &get_info, &pose_state); 1200 | xr_result(self->instance, result, "failed to get pose value!"); 1201 | } 1202 | // printf("Hand pose %d active: %d\n", i, poseState.isActive); 1203 | 1204 | hand_locations[i].type = XR_TYPE_SPACE_LOCATION; 1205 | hand_locations[i].next = NULL; 1206 | 1207 | result = xrLocateSpace(pose_action_spaces[i], self->play_space, 1208 | frameState.predictedDisplayTime, &hand_locations[i]); 1209 | xr_result(self->instance, result, "failed to locate space %d!", i); 1210 | hand_locations_valid[i] = 1211 | //(spaceLocation[i].locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 && 1212 | (hand_locations[i].locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0; 1213 | 1214 | /* 1215 | printf("Pose %d valid %d: %f %f %f %f, %f %f %f\n", i, 1216 | spaceLocationValid[i], spaceLocation[0].pose.orientation.x, 1217 | spaceLocation[0].pose.orientation.y, spaceLocation[0].pose.orientation.z, 1218 | spaceLocation[0].pose.orientation.w, spaceLocation[0].pose.position.x, 1219 | spaceLocation[0].pose.position.y, spaceLocation[0].pose.position.z 1220 | ); 1221 | */ 1222 | 1223 | grab_value[i].type = XR_TYPE_ACTION_STATE_FLOAT; 1224 | grab_value[i].next = NULL; 1225 | { 1226 | XrActionStateGetInfo get_info = {.type = XR_TYPE_ACTION_STATE_GET_INFO, 1227 | .next = NULL, 1228 | .action = grab_action_float, 1229 | .subactionPath = self->hand_paths[i]}; 1230 | 1231 | result = xrGetActionStateFloat(self->session, &get_info, &grab_value[i]); 1232 | xr_result(self->instance, result, "failed to get grab value!"); 1233 | } 1234 | 1235 | // printf("Grab %d active %d, current %f, changed %d\n", i, 1236 | // grabValue[i].isActive, grabValue[i].currentState, 1237 | // grabValue[i].changedSinceLastSync); 1238 | 1239 | if (grab_value[i].isActive && grab_value[i].currentState > 0.75) { 1240 | XrHapticVibration vibration; 1241 | vibration.type = XR_TYPE_HAPTIC_VIBRATION; 1242 | vibration.next = NULL; 1243 | vibration.amplitude = 0.5; 1244 | vibration.duration = XR_MIN_HAPTIC_DURATION; 1245 | vibration.frequency = XR_FREQUENCY_UNSPECIFIED; 1246 | 1247 | XrHapticActionInfo haptic_action_info = {.type = XR_TYPE_HAPTIC_ACTION_INFO, 1248 | .next = NULL, 1249 | .action = haptic_action, 1250 | .subactionPath = self->hand_paths[i]}; 1251 | result = xrApplyHapticFeedback(self->session, &haptic_action_info, 1252 | (const XrHapticBaseHeader*)&vibration); 1253 | xr_result(self->instance, result, "failed to apply haptic feedback!"); 1254 | // printf("Sent haptic output to hand %d\n", i); 1255 | } 1256 | 1257 | 1258 | throttle_value[i].type = XR_TYPE_ACTION_STATE_FLOAT; 1259 | throttle_value[i].next = NULL; 1260 | { 1261 | XrActionStateGetInfo get_info = {.type = XR_TYPE_ACTION_STATE_GET_INFO, 1262 | .next = NULL, 1263 | .action = throttle_action_float, 1264 | .subactionPath = self->hand_paths[i]}; 1265 | 1266 | result = xrGetActionStateFloat(self->session, &get_info, &throttle_value[i]); 1267 | xr_result(self->instance, result, "failed to get throttle value!"); 1268 | } 1269 | if (throttle_value[i].isActive && throttle_value[i].currentState != 0) { 1270 | printf("Throttle value %d: changed %d: %f\n", i, throttle_value[i].changedSinceLastSync, 1271 | throttle_value[i].currentState); 1272 | } 1273 | }; 1274 | 1275 | // --- Begin frame 1276 | XrFrameBeginInfo frame_begin_info = {.type = XR_TYPE_FRAME_BEGIN_INFO, .next = NULL}; 1277 | 1278 | result = xrBeginFrame(self->session, &frame_begin_info); 1279 | if (!xr_result(self->instance, result, "failed to begin frame!")) 1280 | break; 1281 | 1282 | 1283 | // render each eye and fill projection_views with the result 1284 | for (uint32_t i = 0; i < view_count; i++) { 1285 | XrMatrix4x4f projection_matrix; 1286 | XrMatrix4x4f_CreateProjectionFov(&projection_matrix, GRAPHICS_OPENGL, views[i].fov, 1287 | self->near_z, self->far_z); 1288 | 1289 | XrMatrix4x4f view_matrix; 1290 | XrMatrix4x4f_CreateViewMatrix(&view_matrix, &views[i].pose.position, 1291 | &views[i].pose.orientation); 1292 | 1293 | XrSwapchainImageAcquireInfo acquire_info = {.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, 1294 | .next = NULL}; 1295 | uint32_t acquired_index; 1296 | result = xrAcquireSwapchainImage(self->swapchains[i], &acquire_info, &acquired_index); 1297 | if (!xr_result(self->instance, result, "failed to acquire swapchain image!")) 1298 | break; 1299 | 1300 | XrSwapchainImageWaitInfo wait_info = { 1301 | .type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, .next = NULL, .timeout = 1000}; 1302 | result = xrWaitSwapchainImage(self->swapchains[i], &wait_info); 1303 | if (!xr_result(self->instance, result, "failed to wait for swapchain image!")) 1304 | break; 1305 | 1306 | uint32_t depth_acquired_index = UINT32_MAX; 1307 | if (self->depth_swapchain_format != -1) { 1308 | XrSwapchainImageAcquireInfo depth_acquire_info = { 1309 | .type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, .next = NULL}; 1310 | result = xrAcquireSwapchainImage(self->depth_swapchains[i], &depth_acquire_info, 1311 | &depth_acquired_index); 1312 | if (!xr_result(self->instance, result, "failed to acquire swapchain image!")) 1313 | break; 1314 | 1315 | XrSwapchainImageWaitInfo depth_wait_info = { 1316 | .type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, .next = NULL, .timeout = 1000}; 1317 | result = xrWaitSwapchainImage(self->depth_swapchains[i], &depth_wait_info); 1318 | if (!xr_result(self->instance, result, "failed to wait for swapchain image!")) 1319 | break; 1320 | } 1321 | 1322 | self->projection_views[i].pose = views[i].pose; 1323 | self->projection_views[i].fov = views[i].fov; 1324 | 1325 | GLuint depth_image = self->depth_swapchain_format != -1 1326 | ? self->depth_images[i][depth_acquired_index].image 1327 | : UINT32_MAX; 1328 | 1329 | render_frame(self->viewconfig_views[i].recommendedImageRectWidth, 1330 | self->viewconfig_views[i].recommendedImageRectHeight, projection_matrix, 1331 | view_matrix, hand_locations, hand_locations_valid, joint_locations, 1332 | self->framebuffers[i][acquired_index], depth_image, 1333 | self->images[i][acquired_index], i, frameState.predictedDisplayTime); 1334 | glFinish(); 1335 | XrSwapchainImageReleaseInfo release_info = {.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, 1336 | .next = NULL}; 1337 | result = xrReleaseSwapchainImage(self->swapchains[i], &release_info); 1338 | if (!xr_result(self->instance, result, "failed to release swapchain image!")) 1339 | break; 1340 | 1341 | if (self->depth_swapchain_format != -1) { 1342 | XrSwapchainImageReleaseInfo depth_release_info = { 1343 | .type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, .next = NULL}; 1344 | result = xrReleaseSwapchainImage(self->depth_swapchains[i], &depth_release_info); 1345 | if (!xr_result(self->instance, result, "failed to release swapchain image!")) 1346 | break; 1347 | } 1348 | } 1349 | 1350 | 1351 | XrSwapchainImageAcquireInfo acquire_info = {.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, 1352 | .next = NULL}; 1353 | uint32_t acquired_index; 1354 | result = xrAcquireSwapchainImage(self->quad_swapchain, &acquire_info, &acquired_index); 1355 | if (!xr_result(self->instance, result, "failed to acquire swapchain image!")) 1356 | break; 1357 | 1358 | XrSwapchainImageWaitInfo wait_info = { 1359 | .type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, .next = NULL, .timeout = 1000}; 1360 | result = xrWaitSwapchainImage(self->quad_swapchain, &wait_info); 1361 | if (!xr_result(self->instance, result, "failed to wait for swapchain image!")) 1362 | break; 1363 | 1364 | render_quad(self->quad_pixel_width, self->quad_pixel_height, self->swapchain_format, 1365 | self->quad_images[acquired_index], frameState.predictedDisplayTime); 1366 | 1367 | XrSwapchainImageReleaseInfo release_info = {.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, 1368 | .next = NULL}; 1369 | result = xrReleaseSwapchainImage(self->quad_swapchain, &release_info); 1370 | if (!xr_result(self->instance, result, "failed to release swapchain image!")) 1371 | break; 1372 | 1373 | 1374 | if (self->cylinder.supported) { 1375 | XrSwapchainImageAcquireInfo acquire_info = {.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, 1376 | .next = NULL}; 1377 | uint32_t acquired_index; 1378 | result = xrAcquireSwapchainImage(self->cylinder.swapchain, &acquire_info, &acquired_index); 1379 | if (!xr_result(self->instance, result, "failed to acquire swapchain image!")) 1380 | break; 1381 | 1382 | XrSwapchainImageWaitInfo wait_info = { 1383 | .type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, .next = NULL, .timeout = 1000}; 1384 | result = xrWaitSwapchainImage(self->cylinder.swapchain, &wait_info); 1385 | if (!xr_result(self->instance, result, "failed to wait for swapchain image!")) 1386 | break; 1387 | 1388 | render_quad(self->cylinder.swapchain_width, self->cylinder.swapchain_height, 1389 | self->cylinder.format, self->cylinder.images[acquired_index], 1390 | frameState.predictedDisplayTime); 1391 | 1392 | XrSwapchainImageReleaseInfo release_info = {.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, 1393 | .next = NULL}; 1394 | result = xrReleaseSwapchainImage(self->cylinder.swapchain, &release_info); 1395 | if (!xr_result(self->instance, result, "failed to release swapchain image!")) 1396 | break; 1397 | } 1398 | 1399 | 1400 | 1401 | // projectionLayers struct reused for every frame 1402 | XrCompositionLayerProjection projection_layer = { 1403 | .type = XR_TYPE_COMPOSITION_LAYER_PROJECTION, 1404 | .next = NULL, 1405 | .layerFlags = 0, 1406 | .space = self->play_space, 1407 | .viewCount = view_count, 1408 | .views = self->projection_views.data(), 1409 | }; 1410 | 1411 | float aspect = (float)self->quad_pixel_width / (float)self->quad_pixel_height; 1412 | float quad_width = 1.f; 1413 | XrCompositionLayerQuad quad_layer; 1414 | 1415 | quad_layer.type = XR_TYPE_COMPOSITION_LAYER_QUAD, 1416 | quad_layer.next = NULL, 1417 | quad_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT, 1418 | quad_layer.space = self->play_space, 1419 | quad_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH, 1420 | quad_layer.pose = {.orientation = {.x = 0.f, .y = 0.f, .z = 0.f, .w = 1.f}, 1421 | .position = {.x = 1.5f, .y = .7f, .z = -1.5f}}, 1422 | quad_layer.size = {.width = quad_width, .height = quad_width / aspect}, 1423 | quad_layer.subImage = { 1424 | .swapchain = self->quad_swapchain, 1425 | .imageRect = { 1426 | .offset = {.x = 0, .y = 0}, 1427 | .extent = {.width = (int32_t)self->quad_pixel_width, 1428 | .height = (int32_t)self->quad_pixel_height}, 1429 | }}; 1430 | 1431 | 1432 | float cylinder_aspect = 1433 | (float)self->cylinder.swapchain_width / (float)self->cylinder.swapchain_height; 1434 | 1435 | float threesixty = M_PI * 2 - 0.0001; /* TODO: spec issue range [0, 2π)*/ 1436 | 1437 | float angleratio = 1 + (loop_count % 1000) / 50.; 1438 | XrCompositionLayerCylinderKHR cylinder_layer = { 1439 | .type = XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR, 1440 | .next = NULL, 1441 | .layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT, 1442 | .space = self->play_space, 1443 | .eyeVisibility = XR_EYE_VISIBILITY_BOTH, 1444 | .subImage = {.swapchain = self->cylinder.swapchain, 1445 | .imageRect = {.offset = {.x = 0, .y = 0}, 1446 | .extent = {.width = (int32_t)self->cylinder.swapchain_width, 1447 | .height = (int32_t)self->cylinder.swapchain_height}}}, 1448 | .pose = {.orientation = {.x = 0.f, .y = 0.f, .z = 0.f, .w = 1.f}, 1449 | .position = {.x = 1.5f, .y = 0.f, .z = -1.5f}}, 1450 | .radius = 0.5, 1451 | .centralAngle = threesixty / 3, 1452 | .aspectRatio = cylinder_aspect}; 1453 | 1454 | int submitted_layer_count = 1; 1455 | const XrCompositionLayerBaseHeader* submittedLayers[3] = { 1456 | (const XrCompositionLayerBaseHeader* const) & projection_layer}; 1457 | 1458 | if (true) { 1459 | submittedLayers[submitted_layer_count++] = 1460 | (const XrCompositionLayerBaseHeader* const) & quad_layer; 1461 | } 1462 | if (self->cylinder.supported) { 1463 | submittedLayers[submitted_layer_count++] = 1464 | (const XrCompositionLayerBaseHeader* const) & cylinder_layer; 1465 | }; 1466 | 1467 | XrFrameEndInfo frameEndInfo; 1468 | frameEndInfo.type = XR_TYPE_FRAME_END_INFO; 1469 | frameEndInfo.displayTime = frameState.predictedDisplayTime; 1470 | frameEndInfo.layerCount = submitted_layer_count; 1471 | frameEndInfo.layers = submittedLayers; 1472 | frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE; 1473 | frameEndInfo.next = NULL; 1474 | result = xrEndFrame(self->session, &frameEndInfo); 1475 | if (!xr_result(self->instance, result, "failed to end frame!")) 1476 | break; 1477 | } 1478 | } 1479 | 1480 | void sdl_handle_events(SDL_Event event, bool* request_exit) 1481 | { 1482 | if (event.type == SDL_QUIT || 1483 | (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) { 1484 | *request_exit = true; 1485 | } 1486 | } 1487 | 1488 | void cleanup(XrExample* self) 1489 | { 1490 | XrResult result; 1491 | 1492 | xrEndSession(self->session); 1493 | 1494 | if (self->hand_tracking.system_supported) { 1495 | PFN_xrDestroyHandTrackerEXT pfnDestroyHandTrackerEXT = NULL; 1496 | result = xrGetInstanceProcAddr(self->instance, "xrDestroyHandTrackerEXT", 1497 | (PFN_xrVoidFunction*)&pfnDestroyHandTrackerEXT); 1498 | 1499 | xr_result(self->instance, result, "Failed to get xrDestroyHandTrackerEXT function!"); 1500 | 1501 | if (self->hand_tracking.trackers[HAND_LEFT]) { 1502 | result = pfnDestroyHandTrackerEXT(self->hand_tracking.trackers[HAND_LEFT]); 1503 | if (xr_result(self->instance, result, "Failed to destroy left hand tracker")) { 1504 | printf("Destroyed hand tracker for left hand\n"); 1505 | } 1506 | } 1507 | if (self->hand_tracking.trackers[HAND_RIGHT]) { 1508 | result = pfnDestroyHandTrackerEXT(self->hand_tracking.trackers[HAND_RIGHT]); 1509 | if (xr_result(self->instance, result, "Failed to destroy left hand tracker")) { 1510 | printf("Destroyed hand tracker for left hand\n"); 1511 | } 1512 | } 1513 | } 1514 | 1515 | xrDestroySession(self->session); 1516 | 1517 | for(auto& frame_buffer: self->framebuffers) { 1518 | glDeleteFramebuffers(frame_buffer.size(), frame_buffer.data()); 1519 | } 1520 | xrDestroyInstance(self->instance); 1521 | 1522 | cleanup_gl(); 1523 | } 1524 | 1525 | int main() 1526 | { 1527 | XrExample self; 1528 | int ret = init_openxr(&self); 1529 | if (ret != 0) 1530 | return ret; 1531 | main_loop(&self); 1532 | cleanup(&self); 1533 | return 0; 1534 | } 1535 | -------------------------------------------------------------------------------- /math_3d.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Math 3D v1.0 4 | By Stephan Soller and Tobias Malmsheimer 5 | Licensed under the MIT license 6 | 7 | Math 3D is a compact C99 library meant to be used with OpenGL. It provides basic 8 | 3D vector and 4x4 matrix operations as well as functions to create 9 | transformation and projection matrices. The OpenGL binary layout is used so you 10 | can just upload vectors and matrices into shaders and work with them without any 11 | conversions. 12 | 13 | It's an stb style single header file library. Define MATH_3D_IMPLEMENTATION 14 | before you include this file in *one* C file to create the implementation. 15 | 16 | 17 | QUICK NOTES 18 | 19 | - If not explicitly stated by a parameter name all angles are in radians. 20 | - The matrices use column-major indices. This is the same as in OpenGL and GLSL. 21 | The matrix documentation below for details. 22 | - Matrices are passed by value. This is probably a bit inefficient but 23 | simplifies code quite a bit. Most operations will be inlined by the compiler 24 | anyway so the difference shouldn't matter that much. A matrix fits into 4 of 25 | the 16 SSE2 registers anyway. If profiling shows significant slowdowns the 26 | matrix type might change but ease of use is more important than every last 27 | percent of performance. 28 | - When combining matrices with multiplication the effects apply right to left. 29 | This is the convention used in mathematics and OpenGL. Source: 30 | https://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations 31 | Direct3D does it differently. 32 | - The `m4_mul_pos()` and `m4_mul_dir()` functions do a correct perspective 33 | divide (division by w) when necessary. This is a bit slower but ensures that 34 | the functions will properly work with projection matrices. If profiling shows 35 | this is a bottleneck special functions without perspective division can be 36 | added. But the normal multiplications should avoid any surprises. 37 | - The library consistently uses a right-handed coordinate system. The old 38 | `glOrtho()` broke that rule and `m4_ortho()` has be slightly modified so you 39 | can always think of right-handed cubes that are projected into OpenGLs 40 | normalized device coordinates. 41 | - Special care has been taken to document all complex operations and important 42 | sources. Most code is covered by test cases that have been manually calculated 43 | and checked on the whiteboard. Since indices and math code is prone to be 44 | confusing we used pair programming to avoid mistakes. 45 | 46 | 47 | FURTHER IDEARS 48 | 49 | These are ideas for future work on the library. They're implemented as soon as 50 | there is a proper use case and we can find good names for them. 51 | 52 | - bool v3_is_null(vec3_t v, float epsilon) 53 | To check if the length of a vector is smaller than `epsilon`. 54 | - vec3_t v3_length_default(vec3_t v, float default_length, float epsilon) 55 | Returns `default_length` if the length of `v` is smaller than `epsilon`. 56 | Otherwise same as `v3_length()`. 57 | - vec3_t v3_norm_default(vec3_t v, vec3_t default_vector, float epsilon) 58 | Returns `default_vector` if the length of `v` is smaller than `epsilon`. 59 | Otherwise the same as `v3_norm()`. 60 | - mat4_t m4_invert(mat4_t matrix) 61 | Matrix inversion that works with arbitrary matrices. `m4_invert_affine()` can 62 | already invert translation, rotation, scaling, mirroring, reflection and 63 | shearing matrices. So a general inversion might only be useful to invert 64 | projection matrices for picking. But with orthographic and perspective 65 | projection it's probably simpler to calculate the ray into the scene directly 66 | based on the screen coordinates. 67 | 68 | 69 | VERSION HISTORY 70 | 71 | v1.0 2016-02-15 Initial release 72 | 73 | **/ 74 | 75 | #ifndef MATH_3D_HEADER 76 | #define MATH_3D_HEADER 77 | 78 | #include 79 | #include 80 | 81 | 82 | // Define PI directly because we would need to define the _BSD_SOURCE or 83 | // _XOPEN_SOURCE feature test macros to get it from math.h. That would be a 84 | // rather harsh dependency. So we define it directly if necessary. 85 | #ifndef M_PI 86 | #define M_PI 3.14159265358979323846 87 | #endif 88 | 89 | 90 | // 91 | // 3D vectors 92 | // 93 | // Use the `vec3()` function to create vectors. All other vector functions start 94 | // with the `v3_` prefix. 95 | // 96 | // The binary layout is the same as in GLSL and everything else (just 3 floats). 97 | // So you can just upload the vectors into shaders as they are. 98 | // 99 | 100 | typedef struct 101 | { 102 | float x, y, z; 103 | } vec3_t; 104 | static inline vec3_t 105 | vec3(float x, float y, float z) 106 | { 107 | return vec3_t{x, y, z}; 108 | } 109 | 110 | static inline vec3_t 111 | v3_add(vec3_t a, vec3_t b) 112 | { 113 | return vec3_t{a.x + b.x, a.y + b.y, a.z + b.z}; 114 | } 115 | static inline vec3_t 116 | v3_adds(vec3_t a, float s) 117 | { 118 | return vec3_t{a.x + s, a.y + s, a.z + s}; 119 | } 120 | static inline vec3_t 121 | v3_sub(vec3_t a, vec3_t b) 122 | { 123 | return vec3_t{a.x - b.x, a.y - b.y, a.z - b.z}; 124 | } 125 | static inline vec3_t 126 | v3_subs(vec3_t a, float s) 127 | { 128 | return vec3_t{a.x - s, a.y - s, a.z - s}; 129 | } 130 | static inline vec3_t 131 | v3_mul(vec3_t a, vec3_t b) 132 | { 133 | return vec3_t{a.x * b.x, a.y * b.y, a.z * b.z}; 134 | } 135 | static inline vec3_t 136 | v3_muls(vec3_t a, float s) 137 | { 138 | return vec3_t{a.x * s, a.y * s, a.z * s}; 139 | } 140 | static inline vec3_t 141 | v3_div(vec3_t a, vec3_t b) 142 | { 143 | return vec3_t{a.x / b.x, a.y / b.y, a.z / b.z}; 144 | } 145 | static inline vec3_t 146 | v3_divs(vec3_t a, float s) 147 | { 148 | return vec3_t{a.x / s, a.y / s, a.z / s}; 149 | } 150 | static inline float 151 | v3_length(vec3_t v) 152 | { 153 | return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 154 | } 155 | static inline vec3_t 156 | v3_norm(vec3_t v); 157 | static inline float 158 | v3_dot(vec3_t a, vec3_t b) 159 | { 160 | return a.x * b.x + a.y * b.y + a.z * b.z; 161 | } 162 | static inline vec3_t 163 | v3_proj(vec3_t v, vec3_t onto); 164 | static inline vec3_t 165 | v3_cross(vec3_t a, vec3_t b); 166 | static inline float 167 | v3_angle_between(vec3_t a, vec3_t b); 168 | 169 | 170 | // 171 | // 4x4 matrices 172 | // 173 | // Use the `mat4()` function to create a matrix. You can write the matrix 174 | // members in the same way as you would write them on paper or on a whiteboard: 175 | // 176 | // mat4_t m = mat4( 177 | // 1, 0, 0, 7, 178 | // 0, 1, 0, 5, 179 | // 0, 0, 1, 3, 180 | // 0, 0, 0, 1 181 | // ) 182 | // 183 | // This creates a matrix that translates points by vec3(7, 5, 3). All other 184 | // matrix functions start with the `m4_` prefix. Among them functions to create 185 | // identity, translation, rotation, scaling and projection matrices. 186 | // 187 | // The matrix is stored in column-major order, just as OpenGL expects. Members 188 | // can be accessed by indices or member names. When you write a matrix on paper 189 | // or on the whiteboard the indices and named members correspond to these 190 | // positions: 191 | // 192 | // | m[0][0] m[1][0] m[2][0] m[3][0] | 193 | // | m[0][1] m[1][1] m[2][1] m[3][1] | 194 | // | m[0][2] m[1][2] m[2][2] m[3][2] | 195 | // | m[0][3] m[1][3] m[2][3] m[3][3] | 196 | // 197 | // | m00 m10 m20 m30 | 198 | // | m01 m11 m21 m31 | 199 | // | m02 m12 m22 m32 | 200 | // | m03 m13 m23 m33 | 201 | // 202 | // The first index or number in a name denotes the column, the second the row. 203 | // So m[i][j] denotes the member in the ith column and the jth row. This is the 204 | // same as in GLSL (source: GLSL v1.3 specification, 5.6 Matrix Components). 205 | // 206 | 207 | typedef union { 208 | // The first index is the column index, the second the row index. The 209 | // memory layout of nested arrays in C matches the memory layout 210 | // expected by OpenGL. 211 | float m[4][4]; 212 | // OpenGL expects the first 4 floats to be the first column of the 213 | // matrix. So we need to define the named members column by column for 214 | // the names to match the memory locations of the array elements. 215 | struct 216 | { 217 | float m00, m01, m02, m03; 218 | float m10, m11, m12, m13; 219 | float m20, m21, m22, m23; 220 | float m30, m31, m32, m33; 221 | }; 222 | } mat4_t; 223 | 224 | static inline mat4_t 225 | mat4(float m00, 226 | float m10, 227 | float m20, 228 | float m30, 229 | float m01, 230 | float m11, 231 | float m21, 232 | float m31, 233 | float m02, 234 | float m12, 235 | float m22, 236 | float m32, 237 | float m03, 238 | float m13, 239 | float m23, 240 | float m33); 241 | 242 | static inline mat4_t 243 | mat4_f(float* mat); 244 | 245 | static inline mat4_t 246 | m4_identity(); 247 | static inline mat4_t 248 | m4_translation(vec3_t offset); 249 | static inline mat4_t 250 | m4_scaling(vec3_t scale); 251 | static inline mat4_t 252 | m4_rotation_x(float angle_in_rad); 253 | static inline mat4_t 254 | m4_rotation_y(float angle_in_rad); 255 | static inline mat4_t 256 | m4_rotation_z(float angle_in_rad); 257 | mat4_t 258 | m4_rotation(float angle_in_rad, vec3_t axis); 259 | 260 | mat4_t 261 | m4_ortho(float left, float right, float bottom, float top, float back, float front); 262 | mat4_t 263 | m4_perspective(float vertical_field_of_view_in_deg, 264 | float aspect_ratio, 265 | float near_view_distance, 266 | float far_view_distance); 267 | mat4_t 268 | m4_look_at(vec3_t from, vec3_t to, vec3_t up); 269 | 270 | static inline mat4_t 271 | m4_transpose(mat4_t matrix); 272 | static inline mat4_t 273 | m4_mul(mat4_t a, mat4_t b); 274 | mat4_t 275 | m4_invert_affine(mat4_t matrix); 276 | vec3_t 277 | m4_mul_pos(mat4_t matrix, vec3_t position); 278 | vec3_t 279 | m4_mul_dir(mat4_t matrix, vec3_t direction); 280 | 281 | void 282 | m4_print(mat4_t matrix); 283 | void 284 | m4_printp(mat4_t matrix, int width, int precision); 285 | void 286 | m4_fprint(FILE* stream, mat4_t matrix); 287 | void 288 | m4_fprintp(FILE* stream, mat4_t matrix, int width, int precision); 289 | 290 | 291 | 292 | // 293 | // 3D vector functions header implementation 294 | // 295 | 296 | static inline vec3_t 297 | v3_norm(vec3_t v) 298 | { 299 | float len = v3_length(v); 300 | if (len > 0) 301 | return vec3_t{v.x / len, v.y / len, v.z / len}; 302 | else 303 | return vec3_t{0, 0, 0}; 304 | } 305 | 306 | static inline vec3_t 307 | v3_proj(vec3_t v, vec3_t onto) 308 | { 309 | return v3_muls(onto, v3_dot(v, onto) / v3_dot(onto, onto)); 310 | } 311 | 312 | static inline vec3_t 313 | v3_cross(vec3_t a, vec3_t b) 314 | { 315 | return vec3_t{a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; 316 | } 317 | 318 | static inline float 319 | v3_angle_between(vec3_t a, vec3_t b) 320 | { 321 | return acosf(v3_dot(a, b) / (v3_length(a) * v3_length(b))); 322 | } 323 | 324 | 325 | // 326 | // Matrix functions header implementation 327 | // 328 | 329 | static inline mat4_t 330 | mat4(float m00, 331 | float m10, 332 | float m20, 333 | float m30, 334 | float m01, 335 | float m11, 336 | float m21, 337 | float m31, 338 | float m02, 339 | float m12, 340 | float m22, 341 | float m32, 342 | float m03, 343 | float m13, 344 | float m23, 345 | float m33) 346 | { 347 | mat4_t m; 348 | m.m[0][0] = m00; 349 | m.m[1][0] = m10; 350 | m.m[2][0] = m20; 351 | m.m[3][0] = m30; 352 | m.m[0][1] = m01; 353 | m.m[1][1] = m11; 354 | m.m[2][1] = m21; 355 | m.m[3][1] = m31; 356 | m.m[0][2] = m02; 357 | m.m[1][2] = m12; 358 | m.m[2][2] = m22; 359 | m.m[3][2] = m32; 360 | m.m[0][3] = m03; 361 | m.m[1][3] = m13; 362 | m.m[2][3] = m23; 363 | m.m[3][3] = m33; 364 | return m; 365 | } 366 | 367 | static inline mat4_t 368 | mat4_f(float* mat) 369 | { 370 | mat4_t m; 371 | m.m[0][0] = mat[0]; 372 | m.m[1][0] = mat[4]; 373 | m.m[2][0] = mat[8]; 374 | m.m[3][0] = mat[12]; 375 | m.m[0][1] = mat[1]; 376 | m.m[1][1] = mat[5]; 377 | m.m[2][1] = mat[9]; 378 | m.m[3][1] = mat[13]; 379 | m.m[0][2] = mat[2]; 380 | m.m[1][2] = mat[6]; 381 | m.m[2][2] = mat[10]; 382 | m.m[3][2] = mat[14]; 383 | m.m[0][3] = mat[3]; 384 | m.m[1][3] = mat[7]; 385 | m.m[2][3] = mat[11]; 386 | m.m[3][3] = mat[15]; 387 | return m; 388 | } 389 | 390 | static inline mat4_t 391 | m4_identity() 392 | { 393 | return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 394 | } 395 | 396 | static inline mat4_t 397 | m4_translation(vec3_t offset) 398 | { 399 | return mat4(1, 0, 0, offset.x, 0, 1, 0, offset.y, 0, 0, 1, offset.z, 0, 0, 0, 1); 400 | } 401 | 402 | static inline mat4_t 403 | m4_scaling(vec3_t scale) 404 | { 405 | float x = scale.x, y = scale.y, z = scale.z; 406 | return mat4(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); 407 | } 408 | 409 | static inline mat4_t 410 | m4_rotation_x(float angle_in_rad) 411 | { 412 | float s = sinf(angle_in_rad), c = cosf(angle_in_rad); 413 | return mat4(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1); 414 | } 415 | 416 | static inline mat4_t 417 | m4_rotation_y(float angle_in_rad) 418 | { 419 | float s = sinf(angle_in_rad), c = cosf(angle_in_rad); 420 | return mat4(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1); 421 | } 422 | 423 | static inline mat4_t 424 | m4_rotation_z(float angle_in_rad) 425 | { 426 | float s = sinf(angle_in_rad), c = cosf(angle_in_rad); 427 | return mat4(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 428 | } 429 | 430 | static inline mat4_t 431 | m4_transpose(mat4_t matrix) 432 | { 433 | return mat4(matrix.m00, matrix.m01, matrix.m02, matrix.m03, matrix.m10, matrix.m11, matrix.m12, 434 | matrix.m13, matrix.m20, matrix.m21, matrix.m22, matrix.m23, matrix.m30, matrix.m31, 435 | matrix.m32, matrix.m33); 436 | } 437 | 438 | /** 439 | * Multiplication of two 4x4 matrices. 440 | * 441 | * Implemented by following the row times column rule and illustrating it on a 442 | * whiteboard with the proper indices in mind. 443 | * 444 | * Further reading: https://en.wikipedia.org/wiki/Matrix_multiplication 445 | * But note that the article use the first index for rows and the second for 446 | * columns. 447 | */ 448 | static inline mat4_t 449 | m4_mul(mat4_t a, mat4_t b) 450 | { 451 | mat4_t result; 452 | 453 | for (int i = 0; i < 4; i++) { 454 | for (int j = 0; j < 4; j++) { 455 | float sum = 0; 456 | for (int k = 0; k < 4; k++) { 457 | sum += a.m[k][j] * b.m[i][k]; 458 | } 459 | result.m[i][j] = sum; 460 | } 461 | } 462 | 463 | return result; 464 | } 465 | 466 | #endif // MATH_3D_HEADER 467 | 468 | 469 | #ifdef MATH_3D_IMPLEMENTATION 470 | 471 | /** 472 | * Creates a matrix to rotate around an axis by a given angle. The axis doesn't 473 | * need to be normalized. 474 | * 475 | * Sources: 476 | * 477 | * https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle 478 | */ 479 | mat4_t 480 | m4_rotation(float angle_in_rad, vec3_t axis) 481 | { 482 | vec3_t normalized_axis = v3_norm(axis); 483 | float x = normalized_axis.x, y = normalized_axis.y, z = normalized_axis.z; 484 | float c = cosf(angle_in_rad), s = sinf(angle_in_rad); 485 | 486 | return mat4(c + x * x * (1 - c), x * y * (1 - c) - z * s, x * z * (1 - c) + y * s, 0, 487 | y * x * (1 - c) + z * s, c + y * y * (1 - c), y * z * (1 - c) - x * s, 0, 488 | z * x * (1 - c) - y * s, z * y * (1 - c) + x * s, c + z * z * (1 - c), 0, 0, 0, 0, 1); 489 | } 490 | 491 | 492 | /** 493 | * Creates an orthographic projection matrix. It maps the right handed cube 494 | * defined by left, right, bottom, top, back and front onto the screen and 495 | * z-buffer. You can think of it as a cube you move through world or camera 496 | * space and everything inside is visible. 497 | * 498 | * This is slightly different from the traditional glOrtho() and from the linked 499 | * sources. These functions require the user to negate the last two arguments 500 | * (creating a left-handed coordinate system). We avoid that here so you can 501 | * think of this function as moving a right-handed cube through world space. 502 | * 503 | * The arguments are ordered in a way that for each axis you specify the minimum 504 | * followed by the maximum. Thats why it's bottom to top and back to front. 505 | * 506 | * Implementation details: 507 | * 508 | * To be more exact the right-handed cube is mapped into normalized device 509 | * coordinates, a left-handed cube where (-1 -1) is the lower left corner, 510 | * (1, 1) the upper right corner and a z-value of -1 is the nearest point and 511 | * 1 the furthest point. OpenGL takes it from there and puts it on the screen 512 | * and into the z-buffer. 513 | * 514 | * Sources: 515 | * 516 | * https://msdn.microsoft.com/en-us/library/windows/desktop/dd373965(v=vs.85).aspx 517 | * https://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/ 518 | */ 519 | mat4_t 520 | m4_ortho(float left, float right, float bottom, float top, float back, float front) 521 | { 522 | float l = left, r = right, b = bottom, t = top, n = front, f = back; 523 | float tx = -(r + l) / (r - l); 524 | float ty = -(t + b) / (t - b); 525 | float tz = -(f + n) / (f - n); 526 | return mat4(2 / (r - l), 0, 0, tx, 0, 2 / (t - b), 0, ty, 0, 0, 2 / (f - n), tz, 0, 0, 0, 1); 527 | } 528 | 529 | /** 530 | * Creates a perspective projection matrix for a camera. 531 | * 532 | * The camera is at the origin and looks in the direction of the negative Z 533 | * axis. `near_view_distance` and `far_view_distance` have to be positive and > 534 | * 0. They are distances from the camera eye, not values on an axis. 535 | * 536 | * `near_view_distance` can be small but not 0. 0 breaks the projection and 537 | * everything ends up at the max value (far end) of the z-buffer. Making the 538 | * z-buffer useless. 539 | * 540 | * The matrix is the same as `gluPerspective()` builds. The view distance is 541 | * mapped to the z-buffer with a reciprocal function (1/x). Therefore the 542 | * z-buffer resolution for near objects is very good while resolution for far 543 | * objects is limited. 544 | * 545 | * Sources: 546 | * 547 | * https://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/ 548 | */ 549 | mat4_t 550 | m4_perspective(float vertical_field_of_view_in_deg, 551 | float aspect_ratio, 552 | float near_view_distance, 553 | float far_view_distance) 554 | { 555 | float fovy_in_rad = vertical_field_of_view_in_deg / 180 * M_PI; 556 | float f = 1.0f / tanf(fovy_in_rad / 2.0f); 557 | float ar = aspect_ratio; 558 | float nd = near_view_distance, fd = far_view_distance; 559 | 560 | return mat4(f / ar, 0, 0, 0, 0, f, 0, 0, 0, 0, (fd + nd) / (nd - fd), (2 * fd * nd) / (nd - fd), 561 | 0, 0, -1, 0); 562 | } 563 | 564 | /** 565 | * Builds a transformation matrix for a camera that looks from `from` towards 566 | * `to`. `up` defines the direction that's upwards for the camera. All three 567 | * vectors are given in world space and `up` doesn't need to be normalized. 568 | * 569 | * Sources: Derived on whiteboard. 570 | * 571 | * Implementation details: 572 | * 573 | * x, y and z are the right-handed base vectors of the cameras subspace. 574 | * x has to be normalized because the cross product only produces a normalized 575 | * output vector if both input vectors are orthogonal to each other. And up 576 | * probably isn't orthogonal to z. 577 | * 578 | * These vectors are then used to build a 3x3 rotation matrix. This matrix 579 | * rotates a vector by the same amount the camera is rotated. But instead we 580 | * need to rotate all incoming vertices backwards by that amount. That's what a 581 | * camera matrix is for: To move the world so that the camera is in the origin. 582 | * So we take the inverse of that rotation matrix and in case of an rotation 583 | * matrix this is just the transposed matrix. That's why the 3x3 part of the 584 | * matrix are the x, y and z vectors but written horizontally instead of 585 | * vertically. 586 | * 587 | * The translation is derived by creating a translation matrix to move the world 588 | * into the origin (thats translate by minus `from`). The complete lookat matrix 589 | * is then this translation followed by the rotation. Written as matrix 590 | * multiplication: 591 | * 592 | * lookat = rotation * translation 593 | * 594 | * Since we're right-handed this equals to first doing the translation and after 595 | * that doing the rotation. During that multiplication the rotation 3x3 part 596 | * doesn't change but the translation vector is multiplied with each rotation 597 | * axis. The dot product is just a more compact way to write the actual 598 | * multiplications. 599 | */ 600 | mat4_t 601 | m4_look_at(vec3_t from, vec3_t to, vec3_t up) 602 | { 603 | vec3_t z = v3_muls(v3_norm(v3_sub(to, from)), -1); 604 | vec3_t x = v3_norm(v3_cross(up, z)); 605 | vec3_t y = v3_cross(z, x); 606 | 607 | return mat4(x.x, x.y, x.z, -v3_dot(from, x), y.x, y.y, y.z, -v3_dot(from, y), z.x, z.y, z.z, 608 | -v3_dot(from, z), 0, 0, 0, 1); 609 | } 610 | 611 | 612 | /** 613 | * Inverts an affine transformation matrix. That are translation, scaling, 614 | * mirroring, reflection, rotation and shearing matrices or any combination of 615 | * them. 616 | * 617 | * Implementation details: 618 | * 619 | * - Invert the 3x3 part of the 4x4 matrix to handle rotation, scaling, etc. 620 | * correctly (see source). 621 | * - Invert the translation part of the 4x4 matrix by multiplying it with the 622 | * inverted rotation matrix and negating it. 623 | * 624 | * When a 3D point is multiplied with a transformation matrix it is first 625 | * rotated and then translated. The inverted transformation matrix is the 626 | * inverse translation followed by the inverse rotation. Written as a matrix 627 | * multiplication (remember, the effect applies right to left): 628 | * 629 | * inv(matrix) = inv(rotation) * inv(translation) 630 | * 631 | * The inverse translation is a translation into the opposite direction, just 632 | * the negative translation. The rotation part isn't changed by that 633 | * multiplication but the translation part is multiplied by the inverse rotation 634 | * matrix. It's the same situation as with `m4_look_at()`. But since we don't 635 | * store the rotation matrix as 3D vectors we can't use the dot product and have 636 | * to write the matrix multiplication operations by hand. 637 | * 638 | * Sources for 3x3 matrix inversion: 639 | * 640 | * https://www.khanacademy.org/math/precalculus/precalc-matrices/determinants-and-inverses-of-large-matrices/v/inverting-3x3-part-2-determinant-and-adjugate-of-a-matrix 641 | */ 642 | mat4_t 643 | m4_invert_affine(mat4_t matrix) 644 | { 645 | // Create shorthands to access matrix members 646 | float m00 = matrix.m00, m10 = matrix.m10, m20 = matrix.m20, m30 = matrix.m30; 647 | float m01 = matrix.m01, m11 = matrix.m11, m21 = matrix.m21, m31 = matrix.m31; 648 | float m02 = matrix.m02, m12 = matrix.m12, m22 = matrix.m22, m32 = matrix.m32; 649 | 650 | // Invert 3x3 part of the 4x4 matrix that contains the rotation, etc. 651 | // That part is called R from here on. 652 | 653 | // Calculate cofactor matrix of R 654 | float c00 = m11 * m22 - m12 * m21, c10 = -(m01 * m22 - m02 * m21), c20 = m01 * m12 - m02 * m11; 655 | float c01 = -(m10 * m22 - m12 * m20), c11 = m00 * m22 - m02 * m20, c21 = -(m00 * m12 - m02 * m10); 656 | float c02 = m10 * m21 - m11 * m20, c12 = -(m00 * m21 - m01 * m20), c22 = m00 * m11 - m01 * m10; 657 | 658 | // Caclculate the determinant by using the already calculated 659 | // determinants in the cofactor matrix. Second sign is already minus 660 | // from the cofactor matrix. 661 | float det = m00 * c00 + m10 * c10 + m20 * c20; 662 | if (fabsf(det) < 0.00001) 663 | return m4_identity(); 664 | 665 | // Calcuate inverse of R by dividing the transposed cofactor matrix by 666 | // the determinant. 667 | float i00 = c00 / det, i10 = c01 / det, i20 = c02 / det; 668 | float i01 = c10 / det, i11 = c11 / det, i21 = c12 / det; 669 | float i02 = c20 / det, i12 = c21 / det, i22 = c22 / det; 670 | 671 | // Combine the inverted R with the inverted translation 672 | return mat4(i00, i10, i20, -(i00 * m30 + i10 * m31 + i20 * m32), i01, i11, i21, 673 | -(i01 * m30 + i11 * m31 + i21 * m32), i02, i12, i22, 674 | -(i02 * m30 + i12 * m31 + i22 * m32), 0, 0, 0, 1); 675 | } 676 | 677 | /** 678 | * Multiplies a 4x4 matrix with a 3D vector representing a point in 3D space. 679 | * 680 | * Before the matrix multiplication the vector is first expanded to a 4D vector 681 | * (x, y, z, 1). After the multiplication the vector is reduced to 3D again by 682 | * dividing through the 4th component (if it's not 0 or 1). 683 | */ 684 | vec3_t 685 | m4_mul_pos(mat4_t matrix, vec3_t position) 686 | { 687 | vec3_t result = vec3( 688 | matrix.m00 * position.x + matrix.m10 * position.y + matrix.m20 * position.z + matrix.m30, 689 | matrix.m01 * position.x + matrix.m11 * position.y + matrix.m21 * position.z + matrix.m31, 690 | matrix.m02 * position.x + matrix.m12 * position.y + matrix.m22 * position.z + matrix.m32); 691 | 692 | float w = 693 | matrix.m03 * position.x + matrix.m13 * position.y + matrix.m23 * position.z + matrix.m33; 694 | if (w != 0 && w != 1) 695 | return vec3(result.x / w, result.y / w, result.z / w); 696 | 697 | return result; 698 | } 699 | 700 | /** 701 | * Multiplies a 4x4 matrix with a 3D vector representing a direction in 3D 702 | * space. 703 | * 704 | * Before the matrix multiplication the vector is first expanded to a 4D vector 705 | * (x, y, z, 0). For directions the 4th component is set to 0 because directions 706 | * are only rotated, not translated. After the multiplication the vector is 707 | * reduced to 3D again by dividing through the 4th component (if it's not 0 or 708 | * 1). This is necessary because the matrix might contains something other than 709 | * (0, 0, 0, 1) in the bottom row which might set w to something other than 0 710 | * or 1. 711 | */ 712 | vec3_t 713 | m4_mul_dir(mat4_t matrix, vec3_t direction) 714 | { 715 | vec3_t result = 716 | vec3(matrix.m00 * direction.x + matrix.m10 * direction.y + matrix.m20 * direction.z, 717 | matrix.m01 * direction.x + matrix.m11 * direction.y + matrix.m21 * direction.z, 718 | matrix.m02 * direction.x + matrix.m12 * direction.y + matrix.m22 * direction.z); 719 | 720 | float w = matrix.m03 * direction.x + matrix.m13 * direction.y + matrix.m23 * direction.z; 721 | if (w != 0 && w != 1) 722 | return vec3(result.x / w, result.y / w, result.z / w); 723 | 724 | return result; 725 | } 726 | 727 | void 728 | m4_print(mat4_t matrix) 729 | { 730 | m4_fprintp(stdout, matrix, 6, 2); 731 | } 732 | 733 | void 734 | m4_printp(mat4_t matrix, int width, int precision) 735 | { 736 | m4_fprintp(stdout, matrix, width, precision); 737 | } 738 | 739 | void 740 | m4_fprint(FILE* stream, mat4_t matrix) 741 | { 742 | m4_fprintp(stream, matrix, 6, 2); 743 | } 744 | 745 | void 746 | m4_fprintp(FILE* stream, mat4_t matrix, int width, int precision) 747 | { 748 | mat4_t m = matrix; 749 | int w = width, p = precision; 750 | for (int r = 0; r < 4; r++) { 751 | fprintf(stream, "| %*.*f %*.*f %*.*f %*.*f |\n", w, p, m.m[0][r], w, p, m.m[1][r], w, p, 752 | m.m[2][r], w, p, m.m[3][r]); 753 | } 754 | } 755 | 756 | #endif // MATH_3D_IMPLEMENTATION 757 | -------------------------------------------------------------------------------- /openxr-simple-example.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openxr-simple-example", "openxr-simple-example.vcxproj", "{5EF3DBA1-352B-4811-B541-151B36E409DD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5EF3DBA1-352B-4811-B541-151B36E409DD}.Debug|x64.ActiveCfg = Debug|x64 15 | {5EF3DBA1-352B-4811-B541-151B36E409DD}.Debug|x64.Build.0 = Debug|x64 16 | {5EF3DBA1-352B-4811-B541-151B36E409DD}.Release|x64.ActiveCfg = Release|x64 17 | {5EF3DBA1-352B-4811-B541-151B36E409DD}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {D065160C-0215-4F7A-A2F4-25B85F236D7B} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /openxr-simple-example.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {5EF3DBA1-352B-4811-B541-151B36E409DD} 27 | Win32Proj 28 | My3DSimple 29 | 10.0.16299.0 30 | 31 | 32 | 33 | Application 34 | true 35 | v142 36 | Unicode 37 | 38 | 39 | Application 40 | false 41 | v142 42 | true 43 | Unicode 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | true 59 | 60 | 61 | false 62 | 63 | 64 | 65 | 66 | 67 | Level3 68 | Disabled 69 | NO_SDL_GLEXT;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 70 | true 71 | S:\OpenXR-Samples\ExtLib\include 72 | stdcpplatest 73 | 74 | 75 | Console 76 | true 77 | D:\CodeBase\openvr\lib\win64;D:\CodeBase\OpenGL\x64;D:\CodeBase\OpenCV\opencv3\build\x64\vc14\lib;S:\OpenXR-Samples\ExtLib\lib 78 | SDL2.lib;SDL2main.lib;SDL2test.lib;openxr_loader.lib;glew32.lib;OpenGL32.lib;glu32.lib;Shell32.lib 79 | 80 | 81 | 82 | 83 | Level3 84 | 85 | 86 | MaxSpeed 87 | true 88 | true 89 | NO_SDL_GLEXT;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | S:\OpenXR-Samples\ExtLib\include 92 | stdcpplatest 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | D:\CodeBase\openvr\lib\win64;D:\CodeBase\OpenGL\x64;D:\CodeBase\OpenCV\opencv3\build\x64\vc14\lib;S:\OpenXR-Samples\ExtLib\lib 100 | SDL2.lib;SDL2main.lib;SDL2test.lib;openxr_loader.lib;glew32.lib;OpenGL32.lib;glu32.lib;Shell32.lib 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /openxr-simple-example.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 原始程式檔 20 | 21 | 22 | 原始程式檔 23 | 24 | 25 | 26 | 27 | 標頭檔 28 | 29 | 30 | 標頭檔 31 | 32 | 33 | 標頭檔 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /openxr_headers/loader_interfaces.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 The Khronos Group Inc. 2 | // Copyright (c) 2017 Valve Corporation 3 | // Copyright (c) 2017 LunarG, Inc. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | // Author: Mark Young 18 | // 19 | 20 | #pragma once 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | // Forward declare. 27 | typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo; 28 | 29 | // Function pointer prototype for the xrCreateApiLayerInstance function used in place of xrCreateInstance. 30 | // This function allows us to pass special API layer information to each layer during the process of creating an Instance. 31 | typedef XrResult(XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info, 32 | const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance); 33 | 34 | // Loader/API Layer Interface versions 35 | // 1 - First version, introduces negotiation structure and functions 36 | #define XR_CURRENT_LOADER_API_LAYER_VERSION 1 37 | 38 | // Loader/Runtime Interface versions 39 | // 1 - First version, introduces negotiation structure and functions 40 | #define XR_CURRENT_LOADER_RUNTIME_VERSION 1 41 | 42 | // Version negotiation values 43 | typedef enum XrLoaderInterfaceStructs { 44 | XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0, 45 | XR_LOADER_INTERFACE_STRUCT_LOADER_INFO, 46 | XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST, 47 | XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST, 48 | XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO, 49 | XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO, 50 | } XrLoaderInterfaceStructs; 51 | 52 | #define XR_LOADER_INFO_STRUCT_VERSION 1 53 | typedef struct XrNegotiateLoaderInfo { 54 | XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_LOADER_INFO 55 | uint32_t structVersion; // XR_LOADER_INFO_STRUCT_VERSION 56 | size_t structSize; // sizeof(XrNegotiateLoaderInfo) 57 | uint32_t minInterfaceVersion; 58 | uint32_t maxInterfaceVersion; 59 | uint32_t minXrVersion; 60 | uint32_t maxXrVersion; 61 | } XrNegotiateLoaderInfo; 62 | 63 | #define XR_API_LAYER_INFO_STRUCT_VERSION 1 64 | typedef struct XrNegotiateApiLayerRequest { 65 | XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST 66 | uint32_t structVersion; // XR_API_LAYER_INFO_STRUCT_VERSION 67 | size_t structSize; // sizeof(XrNegotiateApiLayerRequest) 68 | uint32_t layerInterfaceVersion; // CURRENT_LOADER_API_LAYER_VERSION 69 | uint32_t layerXrVersion; 70 | PFN_xrGetInstanceProcAddr getInstanceProcAddr; 71 | PFN_xrCreateApiLayerInstance createApiLayerInstance; 72 | } XrNegotiateApiLayerRequest; 73 | 74 | #define XR_RUNTIME_INFO_STRUCT_VERSION 1 75 | typedef struct XrNegotiateRuntimeRequest { 76 | XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST 77 | uint32_t structVersion; // XR_RUNTIME_INFO_STRUCT_VERSION 78 | size_t structSize; // sizeof(XrNegotiateRuntimeRequest) 79 | uint32_t runtimeInterfaceVersion; // CURRENT_LOADER_RUNTIME_VERSION 80 | uint32_t runtimeXrVersion; 81 | PFN_xrGetInstanceProcAddr getInstanceProcAddr; 82 | } XrNegotiateRuntimeRequest; 83 | 84 | // Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or 85 | // more API layers needs to expose at least this function. 86 | typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo *loaderInfo, 87 | const char *apiLayerName, 88 | XrNegotiateApiLayerRequest *apiLayerRequest); 89 | 90 | // Function used to negotiate an interface betewen the loader and a runtime. Each runtime should expose 91 | // at least this function. 92 | typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo *loaderInfo, 93 | XrNegotiateRuntimeRequest *runtimeRequest); 94 | 95 | // Forward declare. 96 | typedef struct XrApiLayerNextInfo XrApiLayerNextInfo; 97 | 98 | #define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1 99 | struct XrApiLayerNextInfo { 100 | XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO 101 | uint32_t structVersion; // XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 102 | size_t structSize; // sizeof(XrApiLayerNextInfo) 103 | char layerName[XR_MAX_API_LAYER_NAME_SIZE]; // Name of API layer which should receive this info 104 | PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; // Pointer to next API layer's xrGetInstanceProcAddr 105 | PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; // Pointer to next API layer's xrCreateApiLayerInstance 106 | XrApiLayerNextInfo *next; // Pointer to the next API layer info in the sequence 107 | }; 108 | 109 | #define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512 110 | #define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1 111 | typedef struct XrApiLayerCreateInfo { 112 | XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO 113 | uint32_t structVersion; // XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 114 | size_t structSize; // sizeof(XrApiLayerCreateInfo) 115 | void *loaderInstance; // Pointer to the LoaderInstance class 116 | char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; // Location to the found settings file (or empty '\0') 117 | XrApiLayerNextInfo *nextInfo; // Pointer to the next API layer's Info 118 | } XrApiLayerCreateInfo; 119 | 120 | #ifdef __cplusplus 121 | } // extern "C" 122 | #endif 123 | -------------------------------------------------------------------------------- /openxr_headers/openxr_platform.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENXR_PLATFORM_H_ 2 | #define OPENXR_PLATFORM_H_ 1 3 | 4 | /* 5 | ** Copyright (c) 2017-2020 The Khronos Group Inc. 6 | ** 7 | ** SPDX-License-Identifier: Apache-2.0 OR MIT 8 | */ 9 | 10 | /* 11 | ** This header is generated from the Khronos OpenXR XML API Registry. 12 | ** 13 | */ 14 | 15 | #include "openxr.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | #ifdef XR_USE_PLATFORM_ANDROID 23 | 24 | #define XR_KHR_android_thread_settings 1 25 | #define XR_KHR_android_thread_settings_SPEC_VERSION 5 26 | #define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings" 27 | 28 | typedef enum XrAndroidThreadTypeKHR { 29 | XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1, 30 | XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2, 31 | XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3, 32 | XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4, 33 | XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF 34 | } XrAndroidThreadTypeKHR; 35 | typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId); 36 | 37 | #ifndef XR_NO_PROTOTYPES 38 | XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR( 39 | XrSession session, 40 | XrAndroidThreadTypeKHR threadType, 41 | uint32_t threadId); 42 | #endif 43 | #endif /* XR_USE_PLATFORM_ANDROID */ 44 | 45 | #ifdef XR_USE_PLATFORM_ANDROID 46 | 47 | #define XR_KHR_android_surface_swapchain 1 48 | #define XR_KHR_android_surface_swapchain_SPEC_VERSION 4 49 | #define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain" 50 | typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface); 51 | 52 | #ifndef XR_NO_PROTOTYPES 53 | XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR( 54 | XrSession session, 55 | const XrSwapchainCreateInfo* info, 56 | XrSwapchain* swapchain, 57 | jobject* surface); 58 | #endif 59 | #endif /* XR_USE_PLATFORM_ANDROID */ 60 | 61 | #ifdef XR_USE_PLATFORM_ANDROID 62 | 63 | #define XR_KHR_android_create_instance 1 64 | #define XR_KHR_android_create_instance_SPEC_VERSION 3 65 | #define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance" 66 | typedef struct XrInstanceCreateInfoAndroidKHR { 67 | XrStructureType type; 68 | const void* XR_MAY_ALIAS next; 69 | void* XR_MAY_ALIAS applicationVM; 70 | void* XR_MAY_ALIAS applicationActivity; 71 | } XrInstanceCreateInfoAndroidKHR; 72 | 73 | #endif /* XR_USE_PLATFORM_ANDROID */ 74 | 75 | #ifdef XR_USE_GRAPHICS_API_VULKAN 76 | 77 | #define XR_KHR_vulkan_swapchain_format_list 1 78 | #define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 2 79 | #define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list" 80 | typedef struct XrVulkanSwapchainFormatListCreateInfoKHR { 81 | XrStructureType type; 82 | const void* XR_MAY_ALIAS next; 83 | uint32_t viewFormatCount; 84 | const VkFormat* viewFormats; 85 | } XrVulkanSwapchainFormatListCreateInfoKHR; 86 | 87 | #endif /* XR_USE_GRAPHICS_API_VULKAN */ 88 | 89 | #ifdef XR_USE_GRAPHICS_API_OPENGL 90 | 91 | #define XR_KHR_opengl_enable 1 92 | #define XR_KHR_opengl_enable_SPEC_VERSION 8 93 | #define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable" 94 | #ifdef XR_USE_PLATFORM_WIN32 95 | typedef struct XrGraphicsBindingOpenGLWin32KHR { 96 | XrStructureType type; 97 | const void* XR_MAY_ALIAS next; 98 | HDC hDC; 99 | HGLRC hGLRC; 100 | } XrGraphicsBindingOpenGLWin32KHR; 101 | #endif // XR_USE_PLATFORM_WIN32 102 | 103 | #ifdef XR_USE_PLATFORM_XLIB 104 | typedef struct XrGraphicsBindingOpenGLXlibKHR { 105 | XrStructureType type; 106 | const void* XR_MAY_ALIAS next; 107 | Display* xDisplay; 108 | uint32_t visualid; 109 | GLXFBConfig glxFBConfig; 110 | GLXDrawable glxDrawable; 111 | GLXContext glxContext; 112 | } XrGraphicsBindingOpenGLXlibKHR; 113 | #endif // XR_USE_PLATFORM_XLIB 114 | 115 | #ifdef XR_USE_PLATFORM_XCB 116 | typedef struct XrGraphicsBindingOpenGLXcbKHR { 117 | XrStructureType type; 118 | const void* XR_MAY_ALIAS next; 119 | xcb_connection_t* connection; 120 | uint32_t screenNumber; 121 | xcb_glx_fbconfig_t fbconfigid; 122 | xcb_visualid_t visualid; 123 | xcb_glx_drawable_t glxDrawable; 124 | xcb_glx_context_t glxContext; 125 | } XrGraphicsBindingOpenGLXcbKHR; 126 | #endif // XR_USE_PLATFORM_XCB 127 | 128 | #ifdef XR_USE_PLATFORM_WAYLAND 129 | typedef struct XrGraphicsBindingOpenGLWaylandKHR { 130 | XrStructureType type; 131 | const void* XR_MAY_ALIAS next; 132 | struct wl_display* display; 133 | } XrGraphicsBindingOpenGLWaylandKHR; 134 | #endif // XR_USE_PLATFORM_WAYLAND 135 | 136 | typedef struct XrSwapchainImageOpenGLKHR { 137 | XrStructureType type; 138 | void* XR_MAY_ALIAS next; 139 | uint32_t image; 140 | } XrSwapchainImageOpenGLKHR; 141 | 142 | typedef struct XrGraphicsRequirementsOpenGLKHR { 143 | XrStructureType type; 144 | void* XR_MAY_ALIAS next; 145 | XrVersion minApiVersionSupported; 146 | XrVersion maxApiVersionSupported; 147 | } XrGraphicsRequirementsOpenGLKHR; 148 | 149 | typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements); 150 | 151 | #ifndef XR_NO_PROTOTYPES 152 | XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR( 153 | XrInstance instance, 154 | XrSystemId systemId, 155 | XrGraphicsRequirementsOpenGLKHR* graphicsRequirements); 156 | #endif 157 | #endif /* XR_USE_GRAPHICS_API_OPENGL */ 158 | 159 | #ifdef XR_USE_GRAPHICS_API_OPENGL_ES 160 | 161 | #define XR_KHR_opengl_es_enable 1 162 | #define XR_KHR_opengl_es_enable_SPEC_VERSION 6 163 | #define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable" 164 | #ifdef XR_USE_PLATFORM_ANDROID 165 | typedef struct XrGraphicsBindingOpenGLESAndroidKHR { 166 | XrStructureType type; 167 | const void* XR_MAY_ALIAS next; 168 | EGLDisplay display; 169 | EGLConfig config; 170 | EGLContext context; 171 | } XrGraphicsBindingOpenGLESAndroidKHR; 172 | #endif // XR_USE_PLATFORM_ANDROID 173 | 174 | typedef struct XrSwapchainImageOpenGLESKHR { 175 | XrStructureType type; 176 | void* XR_MAY_ALIAS next; 177 | uint32_t image; 178 | } XrSwapchainImageOpenGLESKHR; 179 | 180 | typedef struct XrGraphicsRequirementsOpenGLESKHR { 181 | XrStructureType type; 182 | void* XR_MAY_ALIAS next; 183 | XrVersion minApiVersionSupported; 184 | XrVersion maxApiVersionSupported; 185 | } XrGraphicsRequirementsOpenGLESKHR; 186 | 187 | typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements); 188 | 189 | #ifndef XR_NO_PROTOTYPES 190 | XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR( 191 | XrInstance instance, 192 | XrSystemId systemId, 193 | XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements); 194 | #endif 195 | #endif /* XR_USE_GRAPHICS_API_OPENGL_ES */ 196 | 197 | #ifdef XR_USE_GRAPHICS_API_VULKAN 198 | 199 | #define XR_KHR_vulkan_enable 1 200 | #define XR_KHR_vulkan_enable_SPEC_VERSION 6 201 | #define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable" 202 | typedef struct XrGraphicsBindingVulkanKHR { 203 | XrStructureType type; 204 | const void* XR_MAY_ALIAS next; 205 | VkInstance instance; 206 | VkPhysicalDevice physicalDevice; 207 | VkDevice device; 208 | uint32_t queueFamilyIndex; 209 | uint32_t queueIndex; 210 | } XrGraphicsBindingVulkanKHR; 211 | 212 | typedef struct XrSwapchainImageVulkanKHR { 213 | XrStructureType type; 214 | void* XR_MAY_ALIAS next; 215 | VkImage image; 216 | } XrSwapchainImageVulkanKHR; 217 | 218 | typedef struct XrGraphicsRequirementsVulkanKHR { 219 | XrStructureType type; 220 | void* XR_MAY_ALIAS next; 221 | XrVersion minApiVersionSupported; 222 | XrVersion maxApiVersionSupported; 223 | } XrGraphicsRequirementsVulkanKHR; 224 | 225 | typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer); 226 | typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer); 227 | typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice); 228 | typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements); 229 | 230 | #ifndef XR_NO_PROTOTYPES 231 | XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR( 232 | XrInstance instance, 233 | XrSystemId systemId, 234 | uint32_t bufferCapacityInput, 235 | uint32_t* bufferCountOutput, 236 | char* buffer); 237 | 238 | XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR( 239 | XrInstance instance, 240 | XrSystemId systemId, 241 | uint32_t bufferCapacityInput, 242 | uint32_t* bufferCountOutput, 243 | char* buffer); 244 | 245 | XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR( 246 | XrInstance instance, 247 | XrSystemId systemId, 248 | VkInstance vkInstance, 249 | VkPhysicalDevice* vkPhysicalDevice); 250 | 251 | XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR( 252 | XrInstance instance, 253 | XrSystemId systemId, 254 | XrGraphicsRequirementsVulkanKHR* graphicsRequirements); 255 | #endif 256 | #endif /* XR_USE_GRAPHICS_API_VULKAN */ 257 | 258 | #ifdef XR_USE_GRAPHICS_API_D3D11 259 | 260 | #define XR_KHR_D3D11_enable 1 261 | #define XR_KHR_D3D11_enable_SPEC_VERSION 4 262 | #define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable" 263 | typedef struct XrGraphicsBindingD3D11KHR { 264 | XrStructureType type; 265 | const void* XR_MAY_ALIAS next; 266 | ID3D11Device* device; 267 | } XrGraphicsBindingD3D11KHR; 268 | 269 | typedef struct XrSwapchainImageD3D11KHR { 270 | XrStructureType type; 271 | void* XR_MAY_ALIAS next; 272 | ID3D11Texture2D* texture; 273 | } XrSwapchainImageD3D11KHR; 274 | 275 | typedef struct XrGraphicsRequirementsD3D11KHR { 276 | XrStructureType type; 277 | void* XR_MAY_ALIAS next; 278 | LUID adapterLuid; 279 | D3D_FEATURE_LEVEL minFeatureLevel; 280 | } XrGraphicsRequirementsD3D11KHR; 281 | 282 | typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements); 283 | 284 | #ifndef XR_NO_PROTOTYPES 285 | XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR( 286 | XrInstance instance, 287 | XrSystemId systemId, 288 | XrGraphicsRequirementsD3D11KHR* graphicsRequirements); 289 | #endif 290 | #endif /* XR_USE_GRAPHICS_API_D3D11 */ 291 | 292 | #ifdef XR_USE_GRAPHICS_API_D3D12 293 | 294 | #define XR_KHR_D3D12_enable 1 295 | #define XR_KHR_D3D12_enable_SPEC_VERSION 6 296 | #define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable" 297 | typedef struct XrGraphicsBindingD3D12KHR { 298 | XrStructureType type; 299 | const void* XR_MAY_ALIAS next; 300 | ID3D12Device* device; 301 | ID3D12CommandQueue* queue; 302 | } XrGraphicsBindingD3D12KHR; 303 | 304 | typedef struct XrSwapchainImageD3D12KHR { 305 | XrStructureType type; 306 | void* XR_MAY_ALIAS next; 307 | ID3D12Resource* texture; 308 | } XrSwapchainImageD3D12KHR; 309 | 310 | typedef struct XrGraphicsRequirementsD3D12KHR { 311 | XrStructureType type; 312 | void* XR_MAY_ALIAS next; 313 | LUID adapterLuid; 314 | D3D_FEATURE_LEVEL minFeatureLevel; 315 | } XrGraphicsRequirementsD3D12KHR; 316 | 317 | typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements); 318 | 319 | #ifndef XR_NO_PROTOTYPES 320 | XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR( 321 | XrInstance instance, 322 | XrSystemId systemId, 323 | XrGraphicsRequirementsD3D12KHR* graphicsRequirements); 324 | #endif 325 | #endif /* XR_USE_GRAPHICS_API_D3D12 */ 326 | 327 | #ifdef XR_USE_PLATFORM_WIN32 328 | 329 | #define XR_KHR_win32_convert_performance_counter_time 1 330 | #define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1 331 | #define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time" 332 | typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time); 333 | typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter); 334 | 335 | #ifndef XR_NO_PROTOTYPES 336 | XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR( 337 | XrInstance instance, 338 | const LARGE_INTEGER* performanceCounter, 339 | XrTime* time); 340 | 341 | XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR( 342 | XrInstance instance, 343 | XrTime time, 344 | LARGE_INTEGER* performanceCounter); 345 | #endif 346 | #endif /* XR_USE_PLATFORM_WIN32 */ 347 | 348 | #ifdef XR_USE_TIMESPEC 349 | 350 | #define XR_KHR_convert_timespec_time 1 351 | #define XR_KHR_convert_timespec_time_SPEC_VERSION 1 352 | #define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time" 353 | typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time); 354 | typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime); 355 | 356 | #ifndef XR_NO_PROTOTYPES 357 | XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR( 358 | XrInstance instance, 359 | const struct timespec* timespecTime, 360 | XrTime* time); 361 | 362 | XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR( 363 | XrInstance instance, 364 | XrTime time, 365 | struct timespec* timespecTime); 366 | #endif 367 | #endif /* XR_USE_TIMESPEC */ 368 | 369 | #ifdef XR_USE_PLATFORM_EGL 370 | 371 | #define XR_MNDX_egl_enable 1 372 | #define XR_MNDX_egl_enable_SPEC_VERSION 1 373 | #define XR_MNDX_EGL_ENABLE_EXTENSION_NAME "XR_MNDX_egl_enable" 374 | typedef struct XrGraphicsBindingEGLMNDX { 375 | XrStructureType type; 376 | const void* XR_MAY_ALIAS next; 377 | PFNEGLGETPROCADDRESSPROC getProcAddress; 378 | EGLDisplay display; 379 | EGLConfig config; 380 | EGLContext context; 381 | } XrGraphicsBindingEGLMNDX; 382 | 383 | #endif /* XR_USE_PLATFORM_EGL */ 384 | 385 | #ifdef XR_USE_PLATFORM_WIN32 386 | 387 | #define XR_MSFT_holographic_window_attachment 1 388 | #define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1 389 | #define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment" 390 | #ifdef XR_USE_PLATFORM_WIN32 391 | typedef struct XrHolographicWindowAttachmentMSFT { 392 | XrStructureType type; 393 | const void* XR_MAY_ALIAS next; 394 | IUnknown* holographicSpace; 395 | IUnknown* coreWindow; 396 | } XrHolographicWindowAttachmentMSFT; 397 | #endif // XR_USE_PLATFORM_WIN32 398 | 399 | #endif /* XR_USE_PLATFORM_WIN32 */ 400 | 401 | #ifdef __cplusplus 402 | } 403 | #endif 404 | 405 | #endif 406 | -------------------------------------------------------------------------------- /openxr_headers/openxr_platform_defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2017-2020 The Khronos Group Inc. 3 | ** 4 | ** SPDX-License-Identifier: Apache-2.0 OR MIT 5 | */ 6 | 7 | #ifndef OPENXR_PLATFORM_DEFINES_H_ 8 | #define OPENXR_PLATFORM_DEFINES_H_ 1 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* Platform-specific calling convention macros. 15 | * 16 | * Platforms should define these so that OpenXR clients call OpenXR functions 17 | * with the same calling conventions that the OpenXR implementation expects. 18 | * 19 | * XRAPI_ATTR - Placed before the return type in function declarations. 20 | * Useful for C++11 and GCC/Clang-style function attribute syntax. 21 | * XRAPI_CALL - Placed after the return type in function declarations. 22 | * Useful for MSVC-style calling convention syntax. 23 | * XRAPI_PTR - Placed between the '(' and '*' in function pointer types. 24 | * 25 | * Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void); 26 | * Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void); 27 | */ 28 | #if defined(_WIN32) 29 | #define XRAPI_ATTR 30 | // On Windows, functions use the stdcall convention 31 | #define XRAPI_CALL __stdcall 32 | #define XRAPI_PTR XRAPI_CALL 33 | #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 34 | #error "API not supported for the 'armeabi' NDK ABI" 35 | #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) 36 | // On Android 32-bit ARM targets, functions use the "hardfloat" 37 | // calling convention, i.e. float parameters are passed in registers. This 38 | // is true even if the rest of the application passes floats on the stack, 39 | // as it does by default when compiling for the armeabi-v7a NDK ABI. 40 | #define XRAPI_ATTR __attribute__((pcs("aapcs-vfp"))) 41 | #define XRAPI_CALL 42 | #define XRAPI_PTR XRAPI_ATTR 43 | #else 44 | // On other platforms, use the default calling convention 45 | #define XRAPI_ATTR 46 | #define XRAPI_CALL 47 | #define XRAPI_PTR 48 | #endif 49 | 50 | #include 51 | 52 | #if !defined(XR_NO_STDINT_H) 53 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 54 | typedef signed __int8 int8_t; 55 | typedef unsigned __int8 uint8_t; 56 | typedef signed __int16 int16_t; 57 | typedef unsigned __int16 uint16_t; 58 | typedef signed __int32 int32_t; 59 | typedef unsigned __int32 uint32_t; 60 | typedef signed __int64 int64_t; 61 | typedef unsigned __int64 uint64_t; 62 | #else 63 | #include 64 | #endif 65 | #endif // !defined( XR_NO_STDINT_H ) 66 | 67 | // XR_PTR_SIZE (in bytes) 68 | #if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)) 69 | #define XR_PTR_SIZE 8 70 | #else 71 | #define XR_PTR_SIZE 4 72 | #endif 73 | 74 | // Needed so we can use clang __has_feature portably. 75 | #if !defined(XR_COMPILER_HAS_FEATURE) 76 | #if defined(__clang__) 77 | #define XR_COMPILER_HAS_FEATURE(x) __has_feature(x) 78 | #else 79 | #define XR_COMPILER_HAS_FEATURE(x) 0 80 | #endif 81 | #endif 82 | 83 | // Identifies if the current compiler has C++11 support enabled. 84 | // Does not by itself identify if any given C++11 feature is present. 85 | #if !defined(XR_CPP11_ENABLED) && defined(__cplusplus) 86 | #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) 87 | #define XR_CPP11_ENABLED 1 88 | #elif defined(_MSC_VER) && (_MSC_VER >= 1600) 89 | #define XR_CPP11_ENABLED 1 90 | #elif (__cplusplus >= 201103L) // 201103 is the first C++11 version. 91 | #define XR_CPP11_ENABLED 1 92 | #endif 93 | #endif 94 | 95 | // Identifies if the current compiler supports C++11 nullptr. 96 | #if !defined(XR_CPP_NULLPTR_SUPPORTED) 97 | #if defined(XR_CPP11_ENABLED) && \ 98 | ((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \ 99 | (defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \ 100 | (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \ 101 | (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) 102 | #define XR_CPP_NULLPTR_SUPPORTED 1 103 | #endif 104 | #endif 105 | 106 | #ifdef __cplusplus 107 | } 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /openxr_headers/openxr_reflection.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENXR_REFLECTION_H_ 2 | #define OPENXR_REFLECTION_H_ 1 3 | 4 | /* 5 | ** Copyright (c) 2017-2020 The Khronos Group Inc. 6 | ** 7 | ** SPDX-License-Identifier: Apache-2.0 OR MIT 8 | */ 9 | 10 | /* 11 | ** This header is generated from the Khronos OpenXR XML API Registry. 12 | ** 13 | */ 14 | 15 | #include "openxr.h" 16 | 17 | /* 18 | This file contains expansion macros (X Macros) for OpenXR enumerations and structures. 19 | Example of how to use expansion macros to make an enum-to-string function: 20 | 21 | #define XR_ENUM_CASE_STR(name, val) case name: return #name; 22 | #define XR_ENUM_STR(enumType) \ 23 | constexpr const char* XrEnumStr(enumType e) { \ 24 | switch (e) { \ 25 | XR_LIST_ENUM_##enumType(XR_ENUM_CASE_STR) \ 26 | default: return "Unknown"; \ 27 | } \ 28 | } \ 29 | 30 | XR_ENUM_STR(XrResult); 31 | */ 32 | 33 | #define XR_LIST_ENUM_XrResult(_) \ 34 | _(XR_SUCCESS, 0) \ 35 | _(XR_TIMEOUT_EXPIRED, 1) \ 36 | _(XR_SESSION_LOSS_PENDING, 3) \ 37 | _(XR_EVENT_UNAVAILABLE, 4) \ 38 | _(XR_SPACE_BOUNDS_UNAVAILABLE, 7) \ 39 | _(XR_SESSION_NOT_FOCUSED, 8) \ 40 | _(XR_FRAME_DISCARDED, 9) \ 41 | _(XR_ERROR_VALIDATION_FAILURE, -1) \ 42 | _(XR_ERROR_RUNTIME_FAILURE, -2) \ 43 | _(XR_ERROR_OUT_OF_MEMORY, -3) \ 44 | _(XR_ERROR_API_VERSION_UNSUPPORTED, -4) \ 45 | _(XR_ERROR_INITIALIZATION_FAILED, -6) \ 46 | _(XR_ERROR_FUNCTION_UNSUPPORTED, -7) \ 47 | _(XR_ERROR_FEATURE_UNSUPPORTED, -8) \ 48 | _(XR_ERROR_EXTENSION_NOT_PRESENT, -9) \ 49 | _(XR_ERROR_LIMIT_REACHED, -10) \ 50 | _(XR_ERROR_SIZE_INSUFFICIENT, -11) \ 51 | _(XR_ERROR_HANDLE_INVALID, -12) \ 52 | _(XR_ERROR_INSTANCE_LOST, -13) \ 53 | _(XR_ERROR_SESSION_RUNNING, -14) \ 54 | _(XR_ERROR_SESSION_NOT_RUNNING, -16) \ 55 | _(XR_ERROR_SESSION_LOST, -17) \ 56 | _(XR_ERROR_SYSTEM_INVALID, -18) \ 57 | _(XR_ERROR_PATH_INVALID, -19) \ 58 | _(XR_ERROR_PATH_COUNT_EXCEEDED, -20) \ 59 | _(XR_ERROR_PATH_FORMAT_INVALID, -21) \ 60 | _(XR_ERROR_PATH_UNSUPPORTED, -22) \ 61 | _(XR_ERROR_LAYER_INVALID, -23) \ 62 | _(XR_ERROR_LAYER_LIMIT_EXCEEDED, -24) \ 63 | _(XR_ERROR_SWAPCHAIN_RECT_INVALID, -25) \ 64 | _(XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED, -26) \ 65 | _(XR_ERROR_ACTION_TYPE_MISMATCH, -27) \ 66 | _(XR_ERROR_SESSION_NOT_READY, -28) \ 67 | _(XR_ERROR_SESSION_NOT_STOPPING, -29) \ 68 | _(XR_ERROR_TIME_INVALID, -30) \ 69 | _(XR_ERROR_REFERENCE_SPACE_UNSUPPORTED, -31) \ 70 | _(XR_ERROR_FILE_ACCESS_ERROR, -32) \ 71 | _(XR_ERROR_FILE_CONTENTS_INVALID, -33) \ 72 | _(XR_ERROR_FORM_FACTOR_UNSUPPORTED, -34) \ 73 | _(XR_ERROR_FORM_FACTOR_UNAVAILABLE, -35) \ 74 | _(XR_ERROR_API_LAYER_NOT_PRESENT, -36) \ 75 | _(XR_ERROR_CALL_ORDER_INVALID, -37) \ 76 | _(XR_ERROR_GRAPHICS_DEVICE_INVALID, -38) \ 77 | _(XR_ERROR_POSE_INVALID, -39) \ 78 | _(XR_ERROR_INDEX_OUT_OF_RANGE, -40) \ 79 | _(XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, -41) \ 80 | _(XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED, -42) \ 81 | _(XR_ERROR_NAME_DUPLICATED, -44) \ 82 | _(XR_ERROR_NAME_INVALID, -45) \ 83 | _(XR_ERROR_ACTIONSET_NOT_ATTACHED, -46) \ 84 | _(XR_ERROR_ACTIONSETS_ALREADY_ATTACHED, -47) \ 85 | _(XR_ERROR_LOCALIZED_NAME_DUPLICATED, -48) \ 86 | _(XR_ERROR_LOCALIZED_NAME_INVALID, -49) \ 87 | _(XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR, -1000003000) \ 88 | _(XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR, -1000003001) \ 89 | _(XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT, -1000039001) \ 90 | _(XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT, -1000053000) \ 91 | _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF) 92 | 93 | #define XR_LIST_ENUM_XrStructureType(_) \ 94 | _(XR_TYPE_UNKNOWN, 0) \ 95 | _(XR_TYPE_API_LAYER_PROPERTIES, 1) \ 96 | _(XR_TYPE_EXTENSION_PROPERTIES, 2) \ 97 | _(XR_TYPE_INSTANCE_CREATE_INFO, 3) \ 98 | _(XR_TYPE_SYSTEM_GET_INFO, 4) \ 99 | _(XR_TYPE_SYSTEM_PROPERTIES, 5) \ 100 | _(XR_TYPE_VIEW_LOCATE_INFO, 6) \ 101 | _(XR_TYPE_VIEW, 7) \ 102 | _(XR_TYPE_SESSION_CREATE_INFO, 8) \ 103 | _(XR_TYPE_SWAPCHAIN_CREATE_INFO, 9) \ 104 | _(XR_TYPE_SESSION_BEGIN_INFO, 10) \ 105 | _(XR_TYPE_VIEW_STATE, 11) \ 106 | _(XR_TYPE_FRAME_END_INFO, 12) \ 107 | _(XR_TYPE_HAPTIC_VIBRATION, 13) \ 108 | _(XR_TYPE_EVENT_DATA_BUFFER, 16) \ 109 | _(XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING, 17) \ 110 | _(XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED, 18) \ 111 | _(XR_TYPE_ACTION_STATE_BOOLEAN, 23) \ 112 | _(XR_TYPE_ACTION_STATE_FLOAT, 24) \ 113 | _(XR_TYPE_ACTION_STATE_VECTOR2F, 25) \ 114 | _(XR_TYPE_ACTION_STATE_POSE, 27) \ 115 | _(XR_TYPE_ACTION_SET_CREATE_INFO, 28) \ 116 | _(XR_TYPE_ACTION_CREATE_INFO, 29) \ 117 | _(XR_TYPE_INSTANCE_PROPERTIES, 32) \ 118 | _(XR_TYPE_FRAME_WAIT_INFO, 33) \ 119 | _(XR_TYPE_COMPOSITION_LAYER_PROJECTION, 35) \ 120 | _(XR_TYPE_COMPOSITION_LAYER_QUAD, 36) \ 121 | _(XR_TYPE_REFERENCE_SPACE_CREATE_INFO, 37) \ 122 | _(XR_TYPE_ACTION_SPACE_CREATE_INFO, 38) \ 123 | _(XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING, 40) \ 124 | _(XR_TYPE_VIEW_CONFIGURATION_VIEW, 41) \ 125 | _(XR_TYPE_SPACE_LOCATION, 42) \ 126 | _(XR_TYPE_SPACE_VELOCITY, 43) \ 127 | _(XR_TYPE_FRAME_STATE, 44) \ 128 | _(XR_TYPE_VIEW_CONFIGURATION_PROPERTIES, 45) \ 129 | _(XR_TYPE_FRAME_BEGIN_INFO, 46) \ 130 | _(XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW, 48) \ 131 | _(XR_TYPE_EVENT_DATA_EVENTS_LOST, 49) \ 132 | _(XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, 51) \ 133 | _(XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED, 52) \ 134 | _(XR_TYPE_INTERACTION_PROFILE_STATE, 53) \ 135 | _(XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, 55) \ 136 | _(XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, 56) \ 137 | _(XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, 57) \ 138 | _(XR_TYPE_ACTION_STATE_GET_INFO, 58) \ 139 | _(XR_TYPE_HAPTIC_ACTION_INFO, 59) \ 140 | _(XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO, 60) \ 141 | _(XR_TYPE_ACTIONS_SYNC_INFO, 61) \ 142 | _(XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO, 62) \ 143 | _(XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO, 63) \ 144 | _(XR_TYPE_COMPOSITION_LAYER_CUBE_KHR, 1000006000) \ 145 | _(XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, 1000008000) \ 146 | _(XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR, 1000010000) \ 147 | _(XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR, 1000014000) \ 148 | _(XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT, 1000015000) \ 149 | _(XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR, 1000017000) \ 150 | _(XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR, 1000018000) \ 151 | _(XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 1000019000) \ 152 | _(XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 1000019001) \ 153 | _(XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, 1000019002) \ 154 | _(XR_TYPE_DEBUG_UTILS_LABEL_EXT, 1000019003) \ 155 | _(XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, 1000023000) \ 156 | _(XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, 1000023001) \ 157 | _(XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR, 1000023002) \ 158 | _(XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR, 1000023003) \ 159 | _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR, 1000023004) \ 160 | _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR, 1000023005) \ 161 | _(XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, 1000024001) \ 162 | _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR, 1000024002) \ 163 | _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, 1000024003) \ 164 | _(XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, 1000025000) \ 165 | _(XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR, 1000025001) \ 166 | _(XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, 1000025002) \ 167 | _(XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, 1000027000) \ 168 | _(XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR, 1000027001) \ 169 | _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR, 1000027002) \ 170 | _(XR_TYPE_GRAPHICS_BINDING_D3D12_KHR, 1000028000) \ 171 | _(XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR, 1000028001) \ 172 | _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR, 1000028002) \ 173 | _(XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT, 1000030000) \ 174 | _(XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT, 1000030001) \ 175 | _(XR_TYPE_VISIBILITY_MASK_KHR, 1000031000) \ 176 | _(XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, 1000031001) \ 177 | _(XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX, 1000033000) \ 178 | _(XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX, 1000033003) \ 179 | _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT, 1000039000) \ 180 | _(XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT, 1000039001) \ 181 | _(XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT, 1000046000) \ 182 | _(XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, 1000048004) \ 183 | _(XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT, 1000049000) \ 184 | _(XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT, 1000051000) \ 185 | _(XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, 1000051001) \ 186 | _(XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT, 1000051002) \ 187 | _(XR_TYPE_HAND_JOINT_LOCATIONS_EXT, 1000051003) \ 188 | _(XR_TYPE_HAND_JOINT_VELOCITIES_EXT, 1000051004) \ 189 | _(XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT, 1000052000) \ 190 | _(XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT, 1000052001) \ 191 | _(XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT, 1000052002) \ 192 | _(XR_TYPE_HAND_MESH_MSFT, 1000052003) \ 193 | _(XR_TYPE_HAND_POSE_TYPE_INFO_MSFT, 1000052004) \ 194 | _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT, 1000053000) \ 195 | _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT, 1000053001) \ 196 | _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT, 1000053002) \ 197 | _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT, 1000053003) \ 198 | _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT, 1000053004) \ 199 | _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT, 1000053005) \ 200 | _(XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC, 1000059000) \ 201 | _(XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT, 1000063000) \ 202 | _(XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE, 1000079000) \ 203 | _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF) 204 | 205 | #define XR_LIST_ENUM_XrFormFactor(_) \ 206 | _(XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, 1) \ 207 | _(XR_FORM_FACTOR_HANDHELD_DISPLAY, 2) \ 208 | _(XR_FORM_FACTOR_MAX_ENUM, 0x7FFFFFFF) 209 | 210 | #define XR_LIST_ENUM_XrViewConfigurationType(_) \ 211 | _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO, 1) \ 212 | _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 2) \ 213 | _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO, 1000037000) \ 214 | _(XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT, 1000054000) \ 215 | _(XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM, 0x7FFFFFFF) 216 | 217 | #define XR_LIST_ENUM_XrEnvironmentBlendMode(_) \ 218 | _(XR_ENVIRONMENT_BLEND_MODE_OPAQUE, 1) \ 219 | _(XR_ENVIRONMENT_BLEND_MODE_ADDITIVE, 2) \ 220 | _(XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND, 3) \ 221 | _(XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM, 0x7FFFFFFF) 222 | 223 | #define XR_LIST_ENUM_XrReferenceSpaceType(_) \ 224 | _(XR_REFERENCE_SPACE_TYPE_VIEW, 1) \ 225 | _(XR_REFERENCE_SPACE_TYPE_LOCAL, 2) \ 226 | _(XR_REFERENCE_SPACE_TYPE_STAGE, 3) \ 227 | _(XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT, 1000038000) \ 228 | _(XR_REFERENCE_SPACE_TYPE_MAX_ENUM, 0x7FFFFFFF) 229 | 230 | #define XR_LIST_ENUM_XrActionType(_) \ 231 | _(XR_ACTION_TYPE_BOOLEAN_INPUT, 1) \ 232 | _(XR_ACTION_TYPE_FLOAT_INPUT, 2) \ 233 | _(XR_ACTION_TYPE_VECTOR2F_INPUT, 3) \ 234 | _(XR_ACTION_TYPE_POSE_INPUT, 4) \ 235 | _(XR_ACTION_TYPE_VIBRATION_OUTPUT, 100) \ 236 | _(XR_ACTION_TYPE_MAX_ENUM, 0x7FFFFFFF) 237 | 238 | #define XR_LIST_ENUM_XrEyeVisibility(_) \ 239 | _(XR_EYE_VISIBILITY_BOTH, 0) \ 240 | _(XR_EYE_VISIBILITY_LEFT, 1) \ 241 | _(XR_EYE_VISIBILITY_RIGHT, 2) \ 242 | _(XR_EYE_VISIBILITY_MAX_ENUM, 0x7FFFFFFF) 243 | 244 | #define XR_LIST_ENUM_XrSessionState(_) \ 245 | _(XR_SESSION_STATE_UNKNOWN, 0) \ 246 | _(XR_SESSION_STATE_IDLE, 1) \ 247 | _(XR_SESSION_STATE_READY, 2) \ 248 | _(XR_SESSION_STATE_SYNCHRONIZED, 3) \ 249 | _(XR_SESSION_STATE_VISIBLE, 4) \ 250 | _(XR_SESSION_STATE_FOCUSED, 5) \ 251 | _(XR_SESSION_STATE_STOPPING, 6) \ 252 | _(XR_SESSION_STATE_LOSS_PENDING, 7) \ 253 | _(XR_SESSION_STATE_EXITING, 8) \ 254 | _(XR_SESSION_STATE_MAX_ENUM, 0x7FFFFFFF) 255 | 256 | #define XR_LIST_ENUM_XrObjectType(_) \ 257 | _(XR_OBJECT_TYPE_UNKNOWN, 0) \ 258 | _(XR_OBJECT_TYPE_INSTANCE, 1) \ 259 | _(XR_OBJECT_TYPE_SESSION, 2) \ 260 | _(XR_OBJECT_TYPE_SWAPCHAIN, 3) \ 261 | _(XR_OBJECT_TYPE_SPACE, 4) \ 262 | _(XR_OBJECT_TYPE_ACTION_SET, 5) \ 263 | _(XR_OBJECT_TYPE_ACTION, 6) \ 264 | _(XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT, 1000019000) \ 265 | _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT, 1000039000) \ 266 | _(XR_OBJECT_TYPE_HAND_TRACKER_EXT, 1000051000) \ 267 | _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF) 268 | 269 | #define XR_LIST_ENUM_XrAndroidThreadTypeKHR(_) \ 270 | _(XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, 1) \ 271 | _(XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR, 2) \ 272 | _(XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, 3) \ 273 | _(XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR, 4) \ 274 | _(XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF) 275 | 276 | #define XR_LIST_ENUM_XrVisibilityMaskTypeKHR(_) \ 277 | _(XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR, 1) \ 278 | _(XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR, 2) \ 279 | _(XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR, 3) \ 280 | _(XR_VISIBILITY_MASK_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF) 281 | 282 | #define XR_LIST_ENUM_XrPerfSettingsDomainEXT(_) \ 283 | _(XR_PERF_SETTINGS_DOMAIN_CPU_EXT, 1) \ 284 | _(XR_PERF_SETTINGS_DOMAIN_GPU_EXT, 2) \ 285 | _(XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF) 286 | 287 | #define XR_LIST_ENUM_XrPerfSettingsSubDomainEXT(_) \ 288 | _(XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT, 1) \ 289 | _(XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT, 2) \ 290 | _(XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT, 3) \ 291 | _(XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF) 292 | 293 | #define XR_LIST_ENUM_XrPerfSettingsLevelEXT(_) \ 294 | _(XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT, 0) \ 295 | _(XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT, 25) \ 296 | _(XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT, 50) \ 297 | _(XR_PERF_SETTINGS_LEVEL_BOOST_EXT, 75) \ 298 | _(XR_PERF_SETTINGS_LEVEL_MAX_ENUM_EXT, 0x7FFFFFFF) 299 | 300 | #define XR_LIST_ENUM_XrPerfSettingsNotificationLevelEXT(_) \ 301 | _(XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT, 0) \ 302 | _(XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT, 25) \ 303 | _(XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT, 75) \ 304 | _(XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT, 0x7FFFFFFF) 305 | 306 | #define XR_LIST_ENUM_XrSpatialGraphNodeTypeMSFT(_) \ 307 | _(XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT, 1) \ 308 | _(XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT, 2) \ 309 | _(XR_SPATIAL_GRAPH_NODE_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF) 310 | 311 | #define XR_LIST_ENUM_XrHandEXT(_) \ 312 | _(XR_HAND_LEFT_EXT, 1) \ 313 | _(XR_HAND_RIGHT_EXT, 2) \ 314 | _(XR_HAND_MAX_ENUM_EXT, 0x7FFFFFFF) 315 | 316 | #define XR_LIST_ENUM_XrHandJointEXT(_) \ 317 | _(XR_HAND_JOINT_PALM_EXT, 0) \ 318 | _(XR_HAND_JOINT_WRIST_EXT, 1) \ 319 | _(XR_HAND_JOINT_THUMB_METACARPAL_EXT, 2) \ 320 | _(XR_HAND_JOINT_THUMB_PROXIMAL_EXT, 3) \ 321 | _(XR_HAND_JOINT_THUMB_DISTAL_EXT, 4) \ 322 | _(XR_HAND_JOINT_THUMB_TIP_EXT, 5) \ 323 | _(XR_HAND_JOINT_INDEX_METACARPAL_EXT, 6) \ 324 | _(XR_HAND_JOINT_INDEX_PROXIMAL_EXT, 7) \ 325 | _(XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT, 8) \ 326 | _(XR_HAND_JOINT_INDEX_DISTAL_EXT, 9) \ 327 | _(XR_HAND_JOINT_INDEX_TIP_EXT, 10) \ 328 | _(XR_HAND_JOINT_MIDDLE_METACARPAL_EXT, 11) \ 329 | _(XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT, 12) \ 330 | _(XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT, 13) \ 331 | _(XR_HAND_JOINT_MIDDLE_DISTAL_EXT, 14) \ 332 | _(XR_HAND_JOINT_MIDDLE_TIP_EXT, 15) \ 333 | _(XR_HAND_JOINT_RING_METACARPAL_EXT, 16) \ 334 | _(XR_HAND_JOINT_RING_PROXIMAL_EXT, 17) \ 335 | _(XR_HAND_JOINT_RING_INTERMEDIATE_EXT, 18) \ 336 | _(XR_HAND_JOINT_RING_DISTAL_EXT, 19) \ 337 | _(XR_HAND_JOINT_RING_TIP_EXT, 20) \ 338 | _(XR_HAND_JOINT_LITTLE_METACARPAL_EXT, 21) \ 339 | _(XR_HAND_JOINT_LITTLE_PROXIMAL_EXT, 22) \ 340 | _(XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT, 23) \ 341 | _(XR_HAND_JOINT_LITTLE_DISTAL_EXT, 24) \ 342 | _(XR_HAND_JOINT_LITTLE_TIP_EXT, 25) \ 343 | _(XR_HAND_JOINT_MAX_ENUM_EXT, 0x7FFFFFFF) 344 | 345 | #define XR_LIST_ENUM_XrHandJointSetEXT(_) \ 346 | _(XR_HAND_JOINT_SET_DEFAULT_EXT, 0) \ 347 | _(XR_HAND_JOINT_SET_MAX_ENUM_EXT, 0x7FFFFFFF) 348 | 349 | #define XR_LIST_ENUM_XrHandPoseTypeMSFT(_) \ 350 | _(XR_HAND_POSE_TYPE_TRACKED_MSFT, 0) \ 351 | _(XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT, 1) \ 352 | _(XR_HAND_POSE_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF) 353 | 354 | #define XR_LIST_BITS_XrInstanceCreateFlags(_) 355 | 356 | #define XR_LIST_BITS_XrSessionCreateFlags(_) 357 | 358 | #define XR_LIST_BITS_XrSpaceVelocityFlags(_) \ 359 | _(XR_SPACE_VELOCITY_LINEAR_VALID_BIT, 0x00000001) \ 360 | _(XR_SPACE_VELOCITY_ANGULAR_VALID_BIT, 0x00000002) \ 361 | 362 | #define XR_LIST_BITS_XrSpaceLocationFlags(_) \ 363 | _(XR_SPACE_LOCATION_ORIENTATION_VALID_BIT, 0x00000001) \ 364 | _(XR_SPACE_LOCATION_POSITION_VALID_BIT, 0x00000002) \ 365 | _(XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT, 0x00000004) \ 366 | _(XR_SPACE_LOCATION_POSITION_TRACKED_BIT, 0x00000008) \ 367 | 368 | #define XR_LIST_BITS_XrSwapchainCreateFlags(_) \ 369 | _(XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT, 0x00000001) \ 370 | _(XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT, 0x00000002) \ 371 | 372 | #define XR_LIST_BITS_XrSwapchainUsageFlags(_) \ 373 | _(XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, 0x00000001) \ 374 | _(XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0x00000002) \ 375 | _(XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT, 0x00000004) \ 376 | _(XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT, 0x00000008) \ 377 | _(XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT, 0x00000010) \ 378 | _(XR_SWAPCHAIN_USAGE_SAMPLED_BIT, 0x00000020) \ 379 | _(XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, 0x00000040) \ 380 | _(XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND, 0x00000080) \ 381 | 382 | #define XR_LIST_BITS_XrCompositionLayerFlags(_) \ 383 | _(XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, 0x00000001) \ 384 | _(XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT, 0x00000002) \ 385 | _(XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT, 0x00000004) \ 386 | 387 | #define XR_LIST_BITS_XrViewStateFlags(_) \ 388 | _(XR_VIEW_STATE_ORIENTATION_VALID_BIT, 0x00000001) \ 389 | _(XR_VIEW_STATE_POSITION_VALID_BIT, 0x00000002) \ 390 | _(XR_VIEW_STATE_ORIENTATION_TRACKED_BIT, 0x00000004) \ 391 | _(XR_VIEW_STATE_POSITION_TRACKED_BIT, 0x00000008) \ 392 | 393 | #define XR_LIST_BITS_XrInputSourceLocalizedNameFlags(_) \ 394 | _(XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT, 0x00000001) \ 395 | _(XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT, 0x00000002) \ 396 | _(XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT, 0x00000004) \ 397 | 398 | #define XR_LIST_BITS_XrDebugUtilsMessageSeverityFlagsEXT(_) \ 399 | _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, 0x00000001) \ 400 | _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, 0x00000010) \ 401 | _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, 0x00000100) \ 402 | _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 0x00001000) \ 403 | 404 | #define XR_LIST_BITS_XrDebugUtilsMessageTypeFlagsEXT(_) \ 405 | _(XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 0x00000001) \ 406 | _(XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, 0x00000002) \ 407 | _(XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, 0x00000004) \ 408 | _(XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT, 0x00000008) \ 409 | 410 | #define XR_LIST_BITS_XrOverlaySessionCreateFlagsEXTX(_) \ 411 | _(XR_OVERLAY_SESSION_CREATE_RELAXED_DISPLAY_TIME_BIT_EXTX, 0x00000001) \ 412 | 413 | #define XR_LIST_BITS_XrOverlayMainSessionFlagsEXTX(_) \ 414 | _(XR_OVERLAY_MAIN_SESSION_ENABLED_COMPOSITION_LAYER_INFO_DEPTH_BIT_EXTX, 0x00000001) \ 415 | 416 | #define XR_LIST_STRUCT_XrApiLayerProperties(_) \ 417 | _(type) \ 418 | _(next) \ 419 | _(layerName) \ 420 | _(specVersion) \ 421 | _(layerVersion) \ 422 | _(description) \ 423 | 424 | #define XR_LIST_STRUCT_XrExtensionProperties(_) \ 425 | _(type) \ 426 | _(next) \ 427 | _(extensionName) \ 428 | _(extensionVersion) \ 429 | 430 | #define XR_LIST_STRUCT_XrApplicationInfo(_) \ 431 | _(applicationName) \ 432 | _(applicationVersion) \ 433 | _(engineName) \ 434 | _(engineVersion) \ 435 | _(apiVersion) \ 436 | 437 | #define XR_LIST_STRUCT_XrInstanceCreateInfo(_) \ 438 | _(type) \ 439 | _(next) \ 440 | _(createFlags) \ 441 | _(applicationInfo) \ 442 | _(enabledApiLayerCount) \ 443 | _(enabledApiLayerNames) \ 444 | _(enabledExtensionCount) \ 445 | _(enabledExtensionNames) \ 446 | 447 | #define XR_LIST_STRUCT_XrInstanceProperties(_) \ 448 | _(type) \ 449 | _(next) \ 450 | _(runtimeVersion) \ 451 | _(runtimeName) \ 452 | 453 | #define XR_LIST_STRUCT_XrEventDataBuffer(_) \ 454 | _(type) \ 455 | _(next) \ 456 | _(varying) \ 457 | 458 | #define XR_LIST_STRUCT_XrSystemGetInfo(_) \ 459 | _(type) \ 460 | _(next) \ 461 | _(formFactor) \ 462 | 463 | #define XR_LIST_STRUCT_XrSystemGraphicsProperties(_) \ 464 | _(maxSwapchainImageHeight) \ 465 | _(maxSwapchainImageWidth) \ 466 | _(maxLayerCount) \ 467 | 468 | #define XR_LIST_STRUCT_XrSystemTrackingProperties(_) \ 469 | _(orientationTracking) \ 470 | _(positionTracking) \ 471 | 472 | #define XR_LIST_STRUCT_XrSystemProperties(_) \ 473 | _(type) \ 474 | _(next) \ 475 | _(systemId) \ 476 | _(vendorId) \ 477 | _(systemName) \ 478 | _(graphicsProperties) \ 479 | _(trackingProperties) \ 480 | 481 | #define XR_LIST_STRUCT_XrSessionCreateInfo(_) \ 482 | _(type) \ 483 | _(next) \ 484 | _(createFlags) \ 485 | _(systemId) \ 486 | 487 | #define XR_LIST_STRUCT_XrVector3f(_) \ 488 | _(x) \ 489 | _(y) \ 490 | _(z) \ 491 | 492 | #define XR_LIST_STRUCT_XrSpaceVelocity(_) \ 493 | _(type) \ 494 | _(next) \ 495 | _(velocityFlags) \ 496 | _(linearVelocity) \ 497 | _(angularVelocity) \ 498 | 499 | #define XR_LIST_STRUCT_XrQuaternionf(_) \ 500 | _(x) \ 501 | _(y) \ 502 | _(z) \ 503 | _(w) \ 504 | 505 | #define XR_LIST_STRUCT_XrPosef(_) \ 506 | _(orientation) \ 507 | _(position) \ 508 | 509 | #define XR_LIST_STRUCT_XrReferenceSpaceCreateInfo(_) \ 510 | _(type) \ 511 | _(next) \ 512 | _(referenceSpaceType) \ 513 | _(poseInReferenceSpace) \ 514 | 515 | #define XR_LIST_STRUCT_XrExtent2Df(_) \ 516 | _(width) \ 517 | _(height) \ 518 | 519 | #define XR_LIST_STRUCT_XrActionSpaceCreateInfo(_) \ 520 | _(type) \ 521 | _(next) \ 522 | _(action) \ 523 | _(subactionPath) \ 524 | _(poseInActionSpace) \ 525 | 526 | #define XR_LIST_STRUCT_XrSpaceLocation(_) \ 527 | _(type) \ 528 | _(next) \ 529 | _(locationFlags) \ 530 | _(pose) \ 531 | 532 | #define XR_LIST_STRUCT_XrViewConfigurationProperties(_) \ 533 | _(type) \ 534 | _(next) \ 535 | _(viewConfigurationType) \ 536 | _(fovMutable) \ 537 | 538 | #define XR_LIST_STRUCT_XrViewConfigurationView(_) \ 539 | _(type) \ 540 | _(next) \ 541 | _(recommendedImageRectWidth) \ 542 | _(maxImageRectWidth) \ 543 | _(recommendedImageRectHeight) \ 544 | _(maxImageRectHeight) \ 545 | _(recommendedSwapchainSampleCount) \ 546 | _(maxSwapchainSampleCount) \ 547 | 548 | #define XR_LIST_STRUCT_XrSwapchainCreateInfo(_) \ 549 | _(type) \ 550 | _(next) \ 551 | _(createFlags) \ 552 | _(usageFlags) \ 553 | _(format) \ 554 | _(sampleCount) \ 555 | _(width) \ 556 | _(height) \ 557 | _(faceCount) \ 558 | _(arraySize) \ 559 | _(mipCount) \ 560 | 561 | #define XR_LIST_STRUCT_XrSwapchainImageBaseHeader(_) \ 562 | _(type) \ 563 | _(next) \ 564 | 565 | #define XR_LIST_STRUCT_XrSwapchainImageAcquireInfo(_) \ 566 | _(type) \ 567 | _(next) \ 568 | 569 | #define XR_LIST_STRUCT_XrSwapchainImageWaitInfo(_) \ 570 | _(type) \ 571 | _(next) \ 572 | _(timeout) \ 573 | 574 | #define XR_LIST_STRUCT_XrSwapchainImageReleaseInfo(_) \ 575 | _(type) \ 576 | _(next) \ 577 | 578 | #define XR_LIST_STRUCT_XrSessionBeginInfo(_) \ 579 | _(type) \ 580 | _(next) \ 581 | _(primaryViewConfigurationType) \ 582 | 583 | #define XR_LIST_STRUCT_XrFrameWaitInfo(_) \ 584 | _(type) \ 585 | _(next) \ 586 | 587 | #define XR_LIST_STRUCT_XrFrameState(_) \ 588 | _(type) \ 589 | _(next) \ 590 | _(predictedDisplayTime) \ 591 | _(predictedDisplayPeriod) \ 592 | _(shouldRender) \ 593 | 594 | #define XR_LIST_STRUCT_XrFrameBeginInfo(_) \ 595 | _(type) \ 596 | _(next) \ 597 | 598 | #define XR_LIST_STRUCT_XrCompositionLayerBaseHeader(_) \ 599 | _(type) \ 600 | _(next) \ 601 | _(layerFlags) \ 602 | _(space) \ 603 | 604 | #define XR_LIST_STRUCT_XrFrameEndInfo(_) \ 605 | _(type) \ 606 | _(next) \ 607 | _(displayTime) \ 608 | _(environmentBlendMode) \ 609 | _(layerCount) \ 610 | _(layers) \ 611 | 612 | #define XR_LIST_STRUCT_XrViewLocateInfo(_) \ 613 | _(type) \ 614 | _(next) \ 615 | _(viewConfigurationType) \ 616 | _(displayTime) \ 617 | _(space) \ 618 | 619 | #define XR_LIST_STRUCT_XrViewState(_) \ 620 | _(type) \ 621 | _(next) \ 622 | _(viewStateFlags) \ 623 | 624 | #define XR_LIST_STRUCT_XrFovf(_) \ 625 | _(angleLeft) \ 626 | _(angleRight) \ 627 | _(angleUp) \ 628 | _(angleDown) \ 629 | 630 | #define XR_LIST_STRUCT_XrView(_) \ 631 | _(type) \ 632 | _(next) \ 633 | _(pose) \ 634 | _(fov) \ 635 | 636 | #define XR_LIST_STRUCT_XrActionSetCreateInfo(_) \ 637 | _(type) \ 638 | _(next) \ 639 | _(actionSetName) \ 640 | _(localizedActionSetName) \ 641 | _(priority) \ 642 | 643 | #define XR_LIST_STRUCT_XrActionCreateInfo(_) \ 644 | _(type) \ 645 | _(next) \ 646 | _(actionName) \ 647 | _(actionType) \ 648 | _(countSubactionPaths) \ 649 | _(subactionPaths) \ 650 | _(localizedActionName) \ 651 | 652 | #define XR_LIST_STRUCT_XrActionSuggestedBinding(_) \ 653 | _(action) \ 654 | _(binding) \ 655 | 656 | #define XR_LIST_STRUCT_XrInteractionProfileSuggestedBinding(_) \ 657 | _(type) \ 658 | _(next) \ 659 | _(interactionProfile) \ 660 | _(countSuggestedBindings) \ 661 | _(suggestedBindings) \ 662 | 663 | #define XR_LIST_STRUCT_XrSessionActionSetsAttachInfo(_) \ 664 | _(type) \ 665 | _(next) \ 666 | _(countActionSets) \ 667 | _(actionSets) \ 668 | 669 | #define XR_LIST_STRUCT_XrInteractionProfileState(_) \ 670 | _(type) \ 671 | _(next) \ 672 | _(interactionProfile) \ 673 | 674 | #define XR_LIST_STRUCT_XrActionStateGetInfo(_) \ 675 | _(type) \ 676 | _(next) \ 677 | _(action) \ 678 | _(subactionPath) \ 679 | 680 | #define XR_LIST_STRUCT_XrActionStateBoolean(_) \ 681 | _(type) \ 682 | _(next) \ 683 | _(currentState) \ 684 | _(changedSinceLastSync) \ 685 | _(lastChangeTime) \ 686 | _(isActive) \ 687 | 688 | #define XR_LIST_STRUCT_XrActionStateFloat(_) \ 689 | _(type) \ 690 | _(next) \ 691 | _(currentState) \ 692 | _(changedSinceLastSync) \ 693 | _(lastChangeTime) \ 694 | _(isActive) \ 695 | 696 | #define XR_LIST_STRUCT_XrVector2f(_) \ 697 | _(x) \ 698 | _(y) \ 699 | 700 | #define XR_LIST_STRUCT_XrActionStateVector2f(_) \ 701 | _(type) \ 702 | _(next) \ 703 | _(currentState) \ 704 | _(changedSinceLastSync) \ 705 | _(lastChangeTime) \ 706 | _(isActive) \ 707 | 708 | #define XR_LIST_STRUCT_XrActionStatePose(_) \ 709 | _(type) \ 710 | _(next) \ 711 | _(isActive) \ 712 | 713 | #define XR_LIST_STRUCT_XrActiveActionSet(_) \ 714 | _(actionSet) \ 715 | _(subactionPath) \ 716 | 717 | #define XR_LIST_STRUCT_XrActionsSyncInfo(_) \ 718 | _(type) \ 719 | _(next) \ 720 | _(countActiveActionSets) \ 721 | _(activeActionSets) \ 722 | 723 | #define XR_LIST_STRUCT_XrBoundSourcesForActionEnumerateInfo(_) \ 724 | _(type) \ 725 | _(next) \ 726 | _(action) \ 727 | 728 | #define XR_LIST_STRUCT_XrInputSourceLocalizedNameGetInfo(_) \ 729 | _(type) \ 730 | _(next) \ 731 | _(sourcePath) \ 732 | _(whichComponents) \ 733 | 734 | #define XR_LIST_STRUCT_XrHapticActionInfo(_) \ 735 | _(type) \ 736 | _(next) \ 737 | _(action) \ 738 | _(subactionPath) \ 739 | 740 | #define XR_LIST_STRUCT_XrHapticBaseHeader(_) \ 741 | _(type) \ 742 | _(next) \ 743 | 744 | #define XR_LIST_STRUCT_XrBaseInStructure(_) \ 745 | _(type) \ 746 | _(next) \ 747 | 748 | #define XR_LIST_STRUCT_XrBaseOutStructure(_) \ 749 | _(type) \ 750 | _(next) \ 751 | 752 | #define XR_LIST_STRUCT_XrOffset2Di(_) \ 753 | _(x) \ 754 | _(y) \ 755 | 756 | #define XR_LIST_STRUCT_XrExtent2Di(_) \ 757 | _(width) \ 758 | _(height) \ 759 | 760 | #define XR_LIST_STRUCT_XrRect2Di(_) \ 761 | _(offset) \ 762 | _(extent) \ 763 | 764 | #define XR_LIST_STRUCT_XrSwapchainSubImage(_) \ 765 | _(swapchain) \ 766 | _(imageRect) \ 767 | _(imageArrayIndex) \ 768 | 769 | #define XR_LIST_STRUCT_XrCompositionLayerProjectionView(_) \ 770 | _(type) \ 771 | _(next) \ 772 | _(pose) \ 773 | _(fov) \ 774 | _(subImage) \ 775 | 776 | #define XR_LIST_STRUCT_XrCompositionLayerProjection(_) \ 777 | _(type) \ 778 | _(next) \ 779 | _(layerFlags) \ 780 | _(space) \ 781 | _(viewCount) \ 782 | _(views) \ 783 | 784 | #define XR_LIST_STRUCT_XrCompositionLayerQuad(_) \ 785 | _(type) \ 786 | _(next) \ 787 | _(layerFlags) \ 788 | _(space) \ 789 | _(eyeVisibility) \ 790 | _(subImage) \ 791 | _(pose) \ 792 | _(size) \ 793 | 794 | #define XR_LIST_STRUCT_XrEventDataBaseHeader(_) \ 795 | _(type) \ 796 | _(next) \ 797 | 798 | #define XR_LIST_STRUCT_XrEventDataEventsLost(_) \ 799 | _(type) \ 800 | _(next) \ 801 | _(lostEventCount) \ 802 | 803 | #define XR_LIST_STRUCT_XrEventDataInstanceLossPending(_) \ 804 | _(type) \ 805 | _(next) \ 806 | _(lossTime) \ 807 | 808 | #define XR_LIST_STRUCT_XrEventDataSessionStateChanged(_) \ 809 | _(type) \ 810 | _(next) \ 811 | _(session) \ 812 | _(state) \ 813 | _(time) \ 814 | 815 | #define XR_LIST_STRUCT_XrEventDataReferenceSpaceChangePending(_) \ 816 | _(type) \ 817 | _(next) \ 818 | _(session) \ 819 | _(referenceSpaceType) \ 820 | _(changeTime) \ 821 | _(poseValid) \ 822 | _(poseInPreviousSpace) \ 823 | 824 | #define XR_LIST_STRUCT_XrEventDataInteractionProfileChanged(_) \ 825 | _(type) \ 826 | _(next) \ 827 | _(session) \ 828 | 829 | #define XR_LIST_STRUCT_XrHapticVibration(_) \ 830 | _(type) \ 831 | _(next) \ 832 | _(duration) \ 833 | _(frequency) \ 834 | _(amplitude) \ 835 | 836 | #define XR_LIST_STRUCT_XrOffset2Df(_) \ 837 | _(x) \ 838 | _(y) \ 839 | 840 | #define XR_LIST_STRUCT_XrRect2Df(_) \ 841 | _(offset) \ 842 | _(extent) \ 843 | 844 | #define XR_LIST_STRUCT_XrVector4f(_) \ 845 | _(x) \ 846 | _(y) \ 847 | _(z) \ 848 | _(w) \ 849 | 850 | #define XR_LIST_STRUCT_XrColor4f(_) \ 851 | _(r) \ 852 | _(g) \ 853 | _(b) \ 854 | _(a) \ 855 | 856 | #define XR_LIST_STRUCT_XrCompositionLayerCubeKHR(_) \ 857 | _(type) \ 858 | _(next) \ 859 | _(layerFlags) \ 860 | _(space) \ 861 | _(eyeVisibility) \ 862 | _(swapchain) \ 863 | _(imageArrayIndex) \ 864 | _(orientation) \ 865 | 866 | #define XR_LIST_STRUCT_XrInstanceCreateInfoAndroidKHR(_) \ 867 | _(type) \ 868 | _(next) \ 869 | _(applicationVM) \ 870 | _(applicationActivity) \ 871 | 872 | #define XR_LIST_STRUCT_XrCompositionLayerDepthInfoKHR(_) \ 873 | _(type) \ 874 | _(next) \ 875 | _(subImage) \ 876 | _(minDepth) \ 877 | _(maxDepth) \ 878 | _(nearZ) \ 879 | _(farZ) \ 880 | 881 | #define XR_LIST_STRUCT_XrVulkanSwapchainFormatListCreateInfoKHR(_) \ 882 | _(type) \ 883 | _(next) \ 884 | _(viewFormatCount) \ 885 | _(viewFormats) \ 886 | 887 | #define XR_LIST_STRUCT_XrCompositionLayerCylinderKHR(_) \ 888 | _(type) \ 889 | _(next) \ 890 | _(layerFlags) \ 891 | _(space) \ 892 | _(eyeVisibility) \ 893 | _(subImage) \ 894 | _(pose) \ 895 | _(radius) \ 896 | _(centralAngle) \ 897 | _(aspectRatio) \ 898 | 899 | #define XR_LIST_STRUCT_XrCompositionLayerEquirectKHR(_) \ 900 | _(type) \ 901 | _(next) \ 902 | _(layerFlags) \ 903 | _(space) \ 904 | _(eyeVisibility) \ 905 | _(subImage) \ 906 | _(pose) \ 907 | _(radius) \ 908 | _(scale) \ 909 | _(bias) \ 910 | 911 | #define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWin32KHR(_) \ 912 | _(type) \ 913 | _(next) \ 914 | _(hDC) \ 915 | _(hGLRC) \ 916 | 917 | #define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXlibKHR(_) \ 918 | _(type) \ 919 | _(next) \ 920 | _(xDisplay) \ 921 | _(visualid) \ 922 | _(glxFBConfig) \ 923 | _(glxDrawable) \ 924 | _(glxContext) \ 925 | 926 | #define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXcbKHR(_) \ 927 | _(type) \ 928 | _(next) \ 929 | _(connection) \ 930 | _(screenNumber) \ 931 | _(fbconfigid) \ 932 | _(visualid) \ 933 | _(glxDrawable) \ 934 | _(glxContext) \ 935 | 936 | #define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWaylandKHR(_) \ 937 | _(type) \ 938 | _(next) \ 939 | _(display) \ 940 | 941 | #define XR_LIST_STRUCT_XrSwapchainImageOpenGLKHR(_) \ 942 | _(type) \ 943 | _(next) \ 944 | _(image) \ 945 | 946 | #define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLKHR(_) \ 947 | _(type) \ 948 | _(next) \ 949 | _(minApiVersionSupported) \ 950 | _(maxApiVersionSupported) \ 951 | 952 | #define XR_LIST_STRUCT_XrGraphicsBindingOpenGLESAndroidKHR(_) \ 953 | _(type) \ 954 | _(next) \ 955 | _(display) \ 956 | _(config) \ 957 | _(context) \ 958 | 959 | #define XR_LIST_STRUCT_XrSwapchainImageOpenGLESKHR(_) \ 960 | _(type) \ 961 | _(next) \ 962 | _(image) \ 963 | 964 | #define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLESKHR(_) \ 965 | _(type) \ 966 | _(next) \ 967 | _(minApiVersionSupported) \ 968 | _(maxApiVersionSupported) \ 969 | 970 | #define XR_LIST_STRUCT_XrGraphicsBindingVulkanKHR(_) \ 971 | _(type) \ 972 | _(next) \ 973 | _(instance) \ 974 | _(physicalDevice) \ 975 | _(device) \ 976 | _(queueFamilyIndex) \ 977 | _(queueIndex) \ 978 | 979 | #define XR_LIST_STRUCT_XrSwapchainImageVulkanKHR(_) \ 980 | _(type) \ 981 | _(next) \ 982 | _(image) \ 983 | 984 | #define XR_LIST_STRUCT_XrGraphicsRequirementsVulkanKHR(_) \ 985 | _(type) \ 986 | _(next) \ 987 | _(minApiVersionSupported) \ 988 | _(maxApiVersionSupported) \ 989 | 990 | #define XR_LIST_STRUCT_XrGraphicsBindingD3D11KHR(_) \ 991 | _(type) \ 992 | _(next) \ 993 | _(device) \ 994 | 995 | #define XR_LIST_STRUCT_XrSwapchainImageD3D11KHR(_) \ 996 | _(type) \ 997 | _(next) \ 998 | _(texture) \ 999 | 1000 | #define XR_LIST_STRUCT_XrGraphicsRequirementsD3D11KHR(_) \ 1001 | _(type) \ 1002 | _(next) \ 1003 | _(adapterLuid) \ 1004 | _(minFeatureLevel) \ 1005 | 1006 | #define XR_LIST_STRUCT_XrGraphicsBindingD3D12KHR(_) \ 1007 | _(type) \ 1008 | _(next) \ 1009 | _(device) \ 1010 | _(queue) \ 1011 | 1012 | #define XR_LIST_STRUCT_XrSwapchainImageD3D12KHR(_) \ 1013 | _(type) \ 1014 | _(next) \ 1015 | _(texture) \ 1016 | 1017 | #define XR_LIST_STRUCT_XrGraphicsRequirementsD3D12KHR(_) \ 1018 | _(type) \ 1019 | _(next) \ 1020 | _(adapterLuid) \ 1021 | _(minFeatureLevel) \ 1022 | 1023 | #define XR_LIST_STRUCT_XrVisibilityMaskKHR(_) \ 1024 | _(type) \ 1025 | _(next) \ 1026 | _(vertexCapacityInput) \ 1027 | _(vertexCountOutput) \ 1028 | _(vertices) \ 1029 | _(indexCapacityInput) \ 1030 | _(indexCountOutput) \ 1031 | _(indices) \ 1032 | 1033 | #define XR_LIST_STRUCT_XrEventDataVisibilityMaskChangedKHR(_) \ 1034 | _(type) \ 1035 | _(next) \ 1036 | _(session) \ 1037 | _(viewConfigurationType) \ 1038 | _(viewIndex) \ 1039 | 1040 | #define XR_LIST_STRUCT_XrEventDataPerfSettingsEXT(_) \ 1041 | _(type) \ 1042 | _(next) \ 1043 | _(domain) \ 1044 | _(subDomain) \ 1045 | _(fromLevel) \ 1046 | _(toLevel) \ 1047 | 1048 | #define XR_LIST_STRUCT_XrDebugUtilsObjectNameInfoEXT(_) \ 1049 | _(type) \ 1050 | _(next) \ 1051 | _(objectType) \ 1052 | _(objectHandle) \ 1053 | _(objectName) \ 1054 | 1055 | #define XR_LIST_STRUCT_XrDebugUtilsLabelEXT(_) \ 1056 | _(type) \ 1057 | _(next) \ 1058 | _(labelName) \ 1059 | 1060 | #define XR_LIST_STRUCT_XrDebugUtilsMessengerCallbackDataEXT(_) \ 1061 | _(type) \ 1062 | _(next) \ 1063 | _(messageId) \ 1064 | _(functionName) \ 1065 | _(message) \ 1066 | _(objectCount) \ 1067 | _(objects) \ 1068 | _(sessionLabelCount) \ 1069 | _(sessionLabels) \ 1070 | 1071 | #define XR_LIST_STRUCT_XrDebugUtilsMessengerCreateInfoEXT(_) \ 1072 | _(type) \ 1073 | _(next) \ 1074 | _(messageSeverities) \ 1075 | _(messageTypes) \ 1076 | _(userCallback) \ 1077 | _(userData) \ 1078 | 1079 | #define XR_LIST_STRUCT_XrSystemEyeGazeInteractionPropertiesEXT(_) \ 1080 | _(type) \ 1081 | _(next) \ 1082 | _(supportsEyeGazeInteraction) \ 1083 | 1084 | #define XR_LIST_STRUCT_XrEyeGazeSampleTimeEXT(_) \ 1085 | _(type) \ 1086 | _(next) \ 1087 | _(time) \ 1088 | 1089 | #define XR_LIST_STRUCT_XrSessionCreateInfoOverlayEXTX(_) \ 1090 | _(type) \ 1091 | _(next) \ 1092 | _(createFlags) \ 1093 | _(sessionLayersPlacement) \ 1094 | 1095 | #define XR_LIST_STRUCT_XrEventDataMainSessionVisibilityChangedEXTX(_) \ 1096 | _(type) \ 1097 | _(next) \ 1098 | _(visible) \ 1099 | _(flags) \ 1100 | 1101 | #define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoMSFT(_) \ 1102 | _(type) \ 1103 | _(next) \ 1104 | _(space) \ 1105 | _(pose) \ 1106 | _(time) \ 1107 | 1108 | #define XR_LIST_STRUCT_XrSpatialAnchorSpaceCreateInfoMSFT(_) \ 1109 | _(type) \ 1110 | _(next) \ 1111 | _(anchor) \ 1112 | _(poseInAnchorSpace) \ 1113 | 1114 | #define XR_LIST_STRUCT_XrViewConfigurationDepthRangeEXT(_) \ 1115 | _(type) \ 1116 | _(next) \ 1117 | _(recommendedNearZ) \ 1118 | _(minNearZ) \ 1119 | _(recommendedFarZ) \ 1120 | _(maxFarZ) \ 1121 | 1122 | #define XR_LIST_STRUCT_XrGraphicsBindingEGLMNDX(_) \ 1123 | _(type) \ 1124 | _(next) \ 1125 | _(getProcAddress) \ 1126 | _(display) \ 1127 | _(config) \ 1128 | _(context) \ 1129 | 1130 | #define XR_LIST_STRUCT_XrSpatialGraphNodeSpaceCreateInfoMSFT(_) \ 1131 | _(type) \ 1132 | _(next) \ 1133 | _(nodeType) \ 1134 | _(nodeId) \ 1135 | _(pose) \ 1136 | 1137 | #define XR_LIST_STRUCT_XrSystemHandTrackingPropertiesEXT(_) \ 1138 | _(type) \ 1139 | _(next) \ 1140 | _(supportsHandTracking) \ 1141 | 1142 | #define XR_LIST_STRUCT_XrHandTrackerCreateInfoEXT(_) \ 1143 | _(type) \ 1144 | _(next) \ 1145 | _(hand) \ 1146 | _(handJointSet) \ 1147 | 1148 | #define XR_LIST_STRUCT_XrHandJointsLocateInfoEXT(_) \ 1149 | _(type) \ 1150 | _(next) \ 1151 | _(baseSpace) \ 1152 | _(time) \ 1153 | 1154 | #define XR_LIST_STRUCT_XrHandJointLocationEXT(_) \ 1155 | _(locationFlags) \ 1156 | _(pose) \ 1157 | _(radius) \ 1158 | 1159 | #define XR_LIST_STRUCT_XrHandJointVelocityEXT(_) \ 1160 | _(velocityFlags) \ 1161 | _(linearVelocity) \ 1162 | _(angularVelocity) \ 1163 | 1164 | #define XR_LIST_STRUCT_XrHandJointLocationsEXT(_) \ 1165 | _(type) \ 1166 | _(next) \ 1167 | _(isActive) \ 1168 | _(jointCount) \ 1169 | _(jointLocations) \ 1170 | 1171 | #define XR_LIST_STRUCT_XrHandJointVelocitiesEXT(_) \ 1172 | _(type) \ 1173 | _(next) \ 1174 | _(jointCount) \ 1175 | _(jointVelocities) \ 1176 | 1177 | #define XR_LIST_STRUCT_XrSystemHandTrackingMeshPropertiesMSFT(_) \ 1178 | _(type) \ 1179 | _(next) \ 1180 | _(supportsHandTrackingMesh) \ 1181 | _(maxHandMeshIndexCount) \ 1182 | _(maxHandMeshVertexCount) \ 1183 | 1184 | #define XR_LIST_STRUCT_XrHandMeshSpaceCreateInfoMSFT(_) \ 1185 | _(type) \ 1186 | _(next) \ 1187 | _(handPoseType) \ 1188 | _(poseInHandMeshSpace) \ 1189 | 1190 | #define XR_LIST_STRUCT_XrHandMeshUpdateInfoMSFT(_) \ 1191 | _(type) \ 1192 | _(next) \ 1193 | _(time) \ 1194 | _(handPoseType) \ 1195 | 1196 | #define XR_LIST_STRUCT_XrHandMeshIndexBufferMSFT(_) \ 1197 | _(indexBufferKey) \ 1198 | _(indexCapacityInput) \ 1199 | _(indexCountOutput) \ 1200 | _(indices) \ 1201 | 1202 | #define XR_LIST_STRUCT_XrHandMeshVertexMSFT(_) \ 1203 | _(position) \ 1204 | _(normal) \ 1205 | 1206 | #define XR_LIST_STRUCT_XrHandMeshVertexBufferMSFT(_) \ 1207 | _(vertexUpdateTime) \ 1208 | _(vertexCapacityInput) \ 1209 | _(vertexCountOutput) \ 1210 | _(vertices) \ 1211 | 1212 | #define XR_LIST_STRUCT_XrHandMeshMSFT(_) \ 1213 | _(type) \ 1214 | _(next) \ 1215 | _(isActive) \ 1216 | _(indexBufferChanged) \ 1217 | _(vertexBufferChanged) \ 1218 | _(indexBuffer) \ 1219 | _(vertexBuffer) \ 1220 | 1221 | #define XR_LIST_STRUCT_XrHandPoseTypeInfoMSFT(_) \ 1222 | _(type) \ 1223 | _(next) \ 1224 | _(handPoseType) \ 1225 | 1226 | #define XR_LIST_STRUCT_XrSecondaryViewConfigurationSessionBeginInfoMSFT(_) \ 1227 | _(type) \ 1228 | _(next) \ 1229 | _(viewConfigurationCount) \ 1230 | _(enabledViewConfigurationTypes) \ 1231 | 1232 | #define XR_LIST_STRUCT_XrSecondaryViewConfigurationStateMSFT(_) \ 1233 | _(type) \ 1234 | _(next) \ 1235 | _(viewConfigurationType) \ 1236 | _(active) \ 1237 | 1238 | #define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameStateMSFT(_) \ 1239 | _(type) \ 1240 | _(next) \ 1241 | _(viewConfigurationCount) \ 1242 | _(viewConfigurationStates) \ 1243 | 1244 | #define XR_LIST_STRUCT_XrSecondaryViewConfigurationLayerInfoMSFT(_) \ 1245 | _(type) \ 1246 | _(next) \ 1247 | _(viewConfigurationType) \ 1248 | _(environmentBlendMode) \ 1249 | _(layerCount) \ 1250 | _(layers) \ 1251 | 1252 | #define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameEndInfoMSFT(_) \ 1253 | _(type) \ 1254 | _(next) \ 1255 | _(viewConfigurationCount) \ 1256 | _(viewConfigurationLayersInfo) \ 1257 | 1258 | #define XR_LIST_STRUCT_XrSecondaryViewConfigurationSwapchainCreateInfoMSFT(_) \ 1259 | _(type) \ 1260 | _(next) \ 1261 | _(viewConfigurationType) \ 1262 | 1263 | #define XR_LIST_STRUCT_XrViewConfigurationViewFovEPIC(_) \ 1264 | _(type) \ 1265 | _(next) \ 1266 | _(recommendedFov) \ 1267 | _(maxMutableFov) \ 1268 | 1269 | #define XR_LIST_STRUCT_XrHolographicWindowAttachmentMSFT(_) \ 1270 | _(type) \ 1271 | _(next) \ 1272 | _(holographicSpace) \ 1273 | _(coreWindow) \ 1274 | 1275 | #define XR_LIST_STRUCT_XrInteractionProfileAnalogThresholdVALVE(_) \ 1276 | _(type) \ 1277 | _(next) \ 1278 | _(action) \ 1279 | _(binding) \ 1280 | _(onThreshold) \ 1281 | _(offThreshold) \ 1282 | _(onHaptic) \ 1283 | _(offHaptic) \ 1284 | 1285 | 1286 | 1287 | #define XR_LIST_STRUCTURE_TYPES_CORE(_) \ 1288 | _(XrApiLayerProperties, XR_TYPE_API_LAYER_PROPERTIES) \ 1289 | _(XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES) \ 1290 | _(XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO) \ 1291 | _(XrInstanceProperties, XR_TYPE_INSTANCE_PROPERTIES) \ 1292 | _(XrEventDataBuffer, XR_TYPE_EVENT_DATA_BUFFER) \ 1293 | _(XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO) \ 1294 | _(XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES) \ 1295 | _(XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO) \ 1296 | _(XrSpaceVelocity, XR_TYPE_SPACE_VELOCITY) \ 1297 | _(XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO) \ 1298 | _(XrActionSpaceCreateInfo, XR_TYPE_ACTION_SPACE_CREATE_INFO) \ 1299 | _(XrSpaceLocation, XR_TYPE_SPACE_LOCATION) \ 1300 | _(XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES) \ 1301 | _(XrViewConfigurationView, XR_TYPE_VIEW_CONFIGURATION_VIEW) \ 1302 | _(XrSwapchainCreateInfo, XR_TYPE_SWAPCHAIN_CREATE_INFO) \ 1303 | _(XrSwapchainImageAcquireInfo, XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO) \ 1304 | _(XrSwapchainImageWaitInfo, XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) \ 1305 | _(XrSwapchainImageReleaseInfo, XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO) \ 1306 | _(XrSessionBeginInfo, XR_TYPE_SESSION_BEGIN_INFO) \ 1307 | _(XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO) \ 1308 | _(XrFrameState, XR_TYPE_FRAME_STATE) \ 1309 | _(XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO) \ 1310 | _(XrFrameEndInfo, XR_TYPE_FRAME_END_INFO) \ 1311 | _(XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO) \ 1312 | _(XrViewState, XR_TYPE_VIEW_STATE) \ 1313 | _(XrView, XR_TYPE_VIEW) \ 1314 | _(XrActionSetCreateInfo, XR_TYPE_ACTION_SET_CREATE_INFO) \ 1315 | _(XrActionCreateInfo, XR_TYPE_ACTION_CREATE_INFO) \ 1316 | _(XrInteractionProfileSuggestedBinding, XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING) \ 1317 | _(XrSessionActionSetsAttachInfo, XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO) \ 1318 | _(XrInteractionProfileState, XR_TYPE_INTERACTION_PROFILE_STATE) \ 1319 | _(XrActionStateGetInfo, XR_TYPE_ACTION_STATE_GET_INFO) \ 1320 | _(XrActionStateBoolean, XR_TYPE_ACTION_STATE_BOOLEAN) \ 1321 | _(XrActionStateFloat, XR_TYPE_ACTION_STATE_FLOAT) \ 1322 | _(XrActionStateVector2f, XR_TYPE_ACTION_STATE_VECTOR2F) \ 1323 | _(XrActionStatePose, XR_TYPE_ACTION_STATE_POSE) \ 1324 | _(XrActionsSyncInfo, XR_TYPE_ACTIONS_SYNC_INFO) \ 1325 | _(XrBoundSourcesForActionEnumerateInfo, XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO) \ 1326 | _(XrInputSourceLocalizedNameGetInfo, XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO) \ 1327 | _(XrHapticActionInfo, XR_TYPE_HAPTIC_ACTION_INFO) \ 1328 | _(XrCompositionLayerProjectionView, XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) \ 1329 | _(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \ 1330 | _(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \ 1331 | _(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \ 1332 | _(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \ 1333 | _(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \ 1334 | _(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \ 1335 | _(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \ 1336 | _(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \ 1337 | _(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \ 1338 | _(XrCompositionLayerDepthInfoKHR, XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR) \ 1339 | _(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \ 1340 | _(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \ 1341 | _(XrVisibilityMaskKHR, XR_TYPE_VISIBILITY_MASK_KHR) \ 1342 | _(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \ 1343 | _(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \ 1344 | _(XrDebugUtilsObjectNameInfoEXT, XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT) \ 1345 | _(XrDebugUtilsLabelEXT, XR_TYPE_DEBUG_UTILS_LABEL_EXT) \ 1346 | _(XrDebugUtilsMessengerCallbackDataEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT) \ 1347 | _(XrDebugUtilsMessengerCreateInfoEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) \ 1348 | _(XrSystemEyeGazeInteractionPropertiesEXT, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT) \ 1349 | _(XrEyeGazeSampleTimeEXT, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT) \ 1350 | _(XrSessionCreateInfoOverlayEXTX, XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX) \ 1351 | _(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \ 1352 | _(XrSpatialAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT) \ 1353 | _(XrSpatialAnchorSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT) \ 1354 | _(XrViewConfigurationDepthRangeEXT, XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT) \ 1355 | _(XrSpatialGraphNodeSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT) \ 1356 | _(XrSystemHandTrackingPropertiesEXT, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT) \ 1357 | _(XrHandTrackerCreateInfoEXT, XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT) \ 1358 | _(XrHandJointsLocateInfoEXT, XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT) \ 1359 | _(XrHandJointLocationsEXT, XR_TYPE_HAND_JOINT_LOCATIONS_EXT) \ 1360 | _(XrHandJointVelocitiesEXT, XR_TYPE_HAND_JOINT_VELOCITIES_EXT) \ 1361 | _(XrSystemHandTrackingMeshPropertiesMSFT, XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT) \ 1362 | _(XrHandMeshSpaceCreateInfoMSFT, XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT) \ 1363 | _(XrHandMeshUpdateInfoMSFT, XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT) \ 1364 | _(XrHandMeshMSFT, XR_TYPE_HAND_MESH_MSFT) \ 1365 | _(XrHandPoseTypeInfoMSFT, XR_TYPE_HAND_POSE_TYPE_INFO_MSFT) \ 1366 | _(XrSecondaryViewConfigurationSessionBeginInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT) \ 1367 | _(XrSecondaryViewConfigurationStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT) \ 1368 | _(XrSecondaryViewConfigurationFrameStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT) \ 1369 | _(XrSecondaryViewConfigurationLayerInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT) \ 1370 | _(XrSecondaryViewConfigurationFrameEndInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT) \ 1371 | _(XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT) \ 1372 | _(XrViewConfigurationViewFovEPIC, XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC) \ 1373 | _(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \ 1374 | 1375 | 1376 | 1377 | 1378 | #if defined(XR_USE_GRAPHICS_API_D3D11) 1379 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \ 1380 | _(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \ 1381 | _(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \ 1382 | _(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \ 1383 | 1384 | 1385 | #else 1386 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) 1387 | #endif 1388 | 1389 | #if defined(XR_USE_GRAPHICS_API_D3D12) 1390 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \ 1391 | _(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \ 1392 | _(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \ 1393 | _(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \ 1394 | 1395 | 1396 | #else 1397 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) 1398 | #endif 1399 | 1400 | #if defined(XR_USE_GRAPHICS_API_OPENGL) 1401 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \ 1402 | _(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \ 1403 | _(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \ 1404 | 1405 | 1406 | #else 1407 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) 1408 | #endif 1409 | 1410 | #if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB) 1411 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \ 1412 | _(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \ 1413 | 1414 | 1415 | #else 1416 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) 1417 | #endif 1418 | 1419 | #if defined(XR_USE_GRAPHICS_API_OPENGL_ES) 1420 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \ 1421 | _(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \ 1422 | _(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \ 1423 | 1424 | 1425 | #else 1426 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) 1427 | #endif 1428 | 1429 | #if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID) 1430 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \ 1431 | _(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \ 1432 | 1433 | 1434 | #else 1435 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) 1436 | #endif 1437 | 1438 | #if defined(XR_USE_GRAPHICS_API_VULKAN) 1439 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \ 1440 | _(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \ 1441 | _(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \ 1442 | _(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \ 1443 | _(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \ 1444 | 1445 | 1446 | #else 1447 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) 1448 | #endif 1449 | 1450 | #if defined(XR_USE_PLATFORM_ANDROID) 1451 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \ 1452 | _(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \ 1453 | 1454 | 1455 | #else 1456 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) 1457 | #endif 1458 | 1459 | #if defined(XR_USE_PLATFORM_EGL) 1460 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \ 1461 | _(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \ 1462 | 1463 | 1464 | #else 1465 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) 1466 | #endif 1467 | 1468 | #if defined(XR_USE_PLATFORM_WAYLAND) && defined(XR_USE_GRAPHICS_API_OPENGL) 1469 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WAYLAND_XR_USE_GRAPHICS_API_OPENGL(_) \ 1470 | _(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \ 1471 | 1472 | 1473 | #else 1474 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WAYLAND_XR_USE_GRAPHICS_API_OPENGL(_) 1475 | #endif 1476 | 1477 | #if defined(XR_USE_PLATFORM_WIN32) 1478 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \ 1479 | _(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \ 1480 | 1481 | 1482 | #else 1483 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) 1484 | #endif 1485 | 1486 | #if defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL) 1487 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32_XR_USE_GRAPHICS_API_OPENGL(_) \ 1488 | _(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \ 1489 | 1490 | 1491 | #else 1492 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32_XR_USE_GRAPHICS_API_OPENGL(_) 1493 | #endif 1494 | 1495 | #if defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL) 1496 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_XLIB_XR_USE_GRAPHICS_API_OPENGL(_) \ 1497 | _(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \ 1498 | 1499 | 1500 | #else 1501 | #define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_XLIB_XR_USE_GRAPHICS_API_OPENGL(_) 1502 | #endif 1503 | 1504 | #define XR_LIST_STRUCTURE_TYPES(_) \ 1505 | XR_LIST_STRUCTURE_TYPES_CORE(_) \ 1506 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \ 1507 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \ 1508 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \ 1509 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \ 1510 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \ 1511 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \ 1512 | XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \ 1513 | XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \ 1514 | XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \ 1515 | XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WAYLAND_XR_USE_GRAPHICS_API_OPENGL(_) \ 1516 | XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \ 1517 | XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32_XR_USE_GRAPHICS_API_OPENGL(_) \ 1518 | XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_XLIB_XR_USE_GRAPHICS_API_OPENGL(_) \ 1519 | 1520 | 1521 | #define XR_LIST_EXTENSIONS(_) \ 1522 | _(XR_KHR_android_thread_settings, 4) \ 1523 | _(XR_KHR_android_surface_swapchain, 5) \ 1524 | _(XR_KHR_composition_layer_cube, 7) \ 1525 | _(XR_KHR_android_create_instance, 9) \ 1526 | _(XR_KHR_composition_layer_depth, 11) \ 1527 | _(XR_KHR_vulkan_swapchain_format_list, 15) \ 1528 | _(XR_EXT_performance_settings, 16) \ 1529 | _(XR_EXT_thermal_query, 17) \ 1530 | _(XR_KHR_composition_layer_cylinder, 18) \ 1531 | _(XR_KHR_composition_layer_equirect, 19) \ 1532 | _(XR_EXT_debug_utils, 20) \ 1533 | _(XR_KHR_opengl_enable, 24) \ 1534 | _(XR_KHR_opengl_es_enable, 25) \ 1535 | _(XR_KHR_vulkan_enable, 26) \ 1536 | _(XR_KHR_D3D11_enable, 28) \ 1537 | _(XR_KHR_D3D12_enable, 29) \ 1538 | _(XR_EXT_eye_gaze_interaction, 31) \ 1539 | _(XR_KHR_visibility_mask, 32) \ 1540 | _(XR_EXTX_overlay, 34) \ 1541 | _(XR_KHR_win32_convert_performance_counter_time, 36) \ 1542 | _(XR_KHR_convert_timespec_time, 37) \ 1543 | _(XR_VARJO_quad_views, 38) \ 1544 | _(XR_MSFT_unbounded_reference_space, 39) \ 1545 | _(XR_MSFT_spatial_anchor, 40) \ 1546 | _(XR_MND_headless, 43) \ 1547 | _(XR_OCULUS_android_session_state_enable, 45) \ 1548 | _(XR_EXT_view_configuration_depth_range, 47) \ 1549 | _(XR_EXT_conformance_automation, 48) \ 1550 | _(XR_MNDX_egl_enable, 49) \ 1551 | _(XR_MSFT_spatial_graph_bridge, 50) \ 1552 | _(XR_MSFT_hand_interaction, 51) \ 1553 | _(XR_EXT_hand_tracking, 52) \ 1554 | _(XR_MSFT_hand_tracking_mesh, 53) \ 1555 | _(XR_MSFT_secondary_view_configuration, 54) \ 1556 | _(XR_MSFT_first_person_observer, 55) \ 1557 | _(XR_EXT_win32_appcontainer_compatible, 58) \ 1558 | _(XR_EPIC_view_configuration_fov, 60) \ 1559 | _(XR_MSFT_holographic_window_attachment, 64) \ 1560 | _(XR_HUAWEI_controller_interaction, 70) \ 1561 | _(XR_VALVE_analog_threshold, 80) \ 1562 | _(XR_EXT_samsung_odyssey_controller, 95) \ 1563 | _(XR_EXT_hp_mixed_reality_controller, 96) \ 1564 | _(XR_MND_swapchain_usage_input_attachment_bit, 97) \ 1565 | 1566 | 1567 | #endif 1568 | 1569 | -------------------------------------------------------------------------------- /xrmath.h: -------------------------------------------------------------------------------- 1 | // adapted from 2 | 3 | // Copyright (c) 2017 The Khronos Group Inc. 4 | // Copyright (c) 2016 Oculus VR, LLC. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | // 18 | // Author: J.M.P. van Waveren 19 | 20 | #pragma once 21 | 22 | #include "openxr_headers/openxr.h" 23 | #include 24 | 25 | typedef enum 26 | { 27 | GRAPHICS_VULKAN, 28 | GRAPHICS_OPENGL, 29 | GRAPHICS_OPENGL_ES 30 | } GraphicsAPI; 31 | 32 | typedef struct XrMatrix4x4f 33 | { 34 | float m[16]; 35 | } XrMatrix4x4f; 36 | 37 | inline static void 38 | XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f *result, 39 | GraphicsAPI graphicsApi, 40 | const XrFovf fov, 41 | const float nearZ, 42 | const float farZ) 43 | { 44 | const float tanAngleLeft = tanf(fov.angleLeft); 45 | const float tanAngleRight = tanf(fov.angleRight); 46 | 47 | const float tanAngleDown = tanf(fov.angleDown); 48 | const float tanAngleUp = tanf(fov.angleUp); 49 | 50 | const float tanAngleWidth = tanAngleRight - tanAngleLeft; 51 | 52 | // Set to tanAngleDown - tanAngleUp for a clip space with positive Y 53 | // down (Vulkan). Set to tanAngleUp - tanAngleDown for a clip space with 54 | // positive Y up (OpenGL / D3D / Metal). 55 | const float tanAngleHeight = 56 | graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown); 57 | 58 | // Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES). 59 | // Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal). 60 | const float offsetZ = 61 | (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0; 62 | 63 | if (farZ <= nearZ) { 64 | // place the far plane at infinity 65 | result->m[0] = 2 / tanAngleWidth; 66 | result->m[4] = 0; 67 | result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth; 68 | result->m[12] = 0; 69 | 70 | result->m[1] = 0; 71 | result->m[5] = 2 / tanAngleHeight; 72 | result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight; 73 | result->m[13] = 0; 74 | 75 | result->m[2] = 0; 76 | result->m[6] = 0; 77 | result->m[10] = -1; 78 | result->m[14] = -(nearZ + offsetZ); 79 | 80 | result->m[3] = 0; 81 | result->m[7] = 0; 82 | result->m[11] = -1; 83 | result->m[15] = 0; 84 | } else { 85 | // normal projection 86 | result->m[0] = 2 / tanAngleWidth; 87 | result->m[4] = 0; 88 | result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth; 89 | result->m[12] = 0; 90 | 91 | result->m[1] = 0; 92 | result->m[5] = 2 / tanAngleHeight; 93 | result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight; 94 | result->m[13] = 0; 95 | 96 | result->m[2] = 0; 97 | result->m[6] = 0; 98 | result->m[10] = -(farZ + offsetZ) / (farZ - nearZ); 99 | result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ); 100 | 101 | result->m[3] = 0; 102 | result->m[7] = 0; 103 | result->m[11] = -1; 104 | result->m[15] = 0; 105 | } 106 | } 107 | 108 | inline static void 109 | XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f *result, const XrQuaternionf *quat) 110 | { 111 | const float x2 = quat->x + quat->x; 112 | const float y2 = quat->y + quat->y; 113 | const float z2 = quat->z + quat->z; 114 | 115 | const float xx2 = quat->x * x2; 116 | const float yy2 = quat->y * y2; 117 | const float zz2 = quat->z * z2; 118 | 119 | const float yz2 = quat->y * z2; 120 | const float wx2 = quat->w * x2; 121 | const float xy2 = quat->x * y2; 122 | const float wz2 = quat->w * z2; 123 | const float xz2 = quat->x * z2; 124 | const float wy2 = quat->w * y2; 125 | 126 | result->m[0] = 1.0f - yy2 - zz2; 127 | result->m[1] = xy2 + wz2; 128 | result->m[2] = xz2 - wy2; 129 | result->m[3] = 0.0f; 130 | 131 | result->m[4] = xy2 - wz2; 132 | result->m[5] = 1.0f - xx2 - zz2; 133 | result->m[6] = yz2 + wx2; 134 | result->m[7] = 0.0f; 135 | 136 | result->m[8] = xz2 + wy2; 137 | result->m[9] = yz2 - wx2; 138 | result->m[10] = 1.0f - xx2 - yy2; 139 | result->m[11] = 0.0f; 140 | 141 | result->m[12] = 0.0f; 142 | result->m[13] = 0.0f; 143 | result->m[14] = 0.0f; 144 | result->m[15] = 1.0f; 145 | } 146 | 147 | inline static void 148 | XrMatrix4x4f_CreateTranslation(XrMatrix4x4f *result, const float x, const float y, const float z) 149 | { 150 | result->m[0] = 1.0f; 151 | result->m[1] = 0.0f; 152 | result->m[2] = 0.0f; 153 | result->m[3] = 0.0f; 154 | result->m[4] = 0.0f; 155 | result->m[5] = 1.0f; 156 | result->m[6] = 0.0f; 157 | result->m[7] = 0.0f; 158 | result->m[8] = 0.0f; 159 | result->m[9] = 0.0f; 160 | result->m[10] = 1.0f; 161 | result->m[11] = 0.0f; 162 | result->m[12] = x; 163 | result->m[13] = y; 164 | result->m[14] = z; 165 | result->m[15] = 1.0f; 166 | } 167 | 168 | inline static void 169 | XrMatrix4x4f_Multiply(XrMatrix4x4f *result, const XrMatrix4x4f *a, const XrMatrix4x4f *b) 170 | { 171 | result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3]; 172 | result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3]; 173 | result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3]; 174 | result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3]; 175 | 176 | result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7]; 177 | result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7]; 178 | result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7]; 179 | result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7]; 180 | 181 | result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11]; 182 | result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11]; 183 | result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11]; 184 | result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11]; 185 | 186 | result->m[12] = 187 | a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15]; 188 | result->m[13] = 189 | a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15]; 190 | result->m[14] = 191 | a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15]; 192 | result->m[15] = 193 | a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15]; 194 | } 195 | 196 | inline static void 197 | XrMatrix4x4f_Invert(XrMatrix4x4f *result, const XrMatrix4x4f *src) 198 | { 199 | result->m[0] = src->m[0]; 200 | result->m[1] = src->m[4]; 201 | result->m[2] = src->m[8]; 202 | result->m[3] = 0.0f; 203 | result->m[4] = src->m[1]; 204 | result->m[5] = src->m[5]; 205 | result->m[6] = src->m[9]; 206 | result->m[7] = 0.0f; 207 | result->m[8] = src->m[2]; 208 | result->m[9] = src->m[6]; 209 | result->m[10] = src->m[10]; 210 | result->m[11] = 0.0f; 211 | result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]); 212 | result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]); 213 | result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]); 214 | result->m[15] = 1.0f; 215 | } 216 | 217 | inline static void 218 | XrMatrix4x4f_CreateViewMatrix(XrMatrix4x4f *result, 219 | const XrVector3f *translation, 220 | const XrQuaternionf *rotation) 221 | { 222 | 223 | XrMatrix4x4f rotationMatrix; 224 | XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation); 225 | 226 | XrMatrix4x4f translationMatrix; 227 | XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, 228 | translation->z); 229 | 230 | XrMatrix4x4f viewMatrix; 231 | XrMatrix4x4f_Multiply(&viewMatrix, &translationMatrix, &rotationMatrix); 232 | 233 | XrMatrix4x4f_Invert(result, &viewMatrix); 234 | } 235 | 236 | // Creates a scale matrix. 237 | inline static void 238 | XrMatrix4x4f_CreateScale(XrMatrix4x4f *result, const float x, const float y, const float z) 239 | { 240 | result->m[0] = x; 241 | result->m[1] = 0.0f; 242 | result->m[2] = 0.0f; 243 | result->m[3] = 0.0f; 244 | result->m[4] = 0.0f; 245 | result->m[5] = y; 246 | result->m[6] = 0.0f; 247 | result->m[7] = 0.0f; 248 | result->m[8] = 0.0f; 249 | result->m[9] = 0.0f; 250 | result->m[10] = z; 251 | result->m[11] = 0.0f; 252 | result->m[12] = 0.0f; 253 | result->m[13] = 0.0f; 254 | result->m[14] = 0.0f; 255 | result->m[15] = 1.0f; 256 | } 257 | 258 | inline static void 259 | XrMatrix4x4f_CreateModelMatrix(XrMatrix4x4f *result, 260 | const XrVector3f *translation, 261 | const XrQuaternionf *rotation, 262 | const XrVector3f *scale) 263 | { 264 | XrMatrix4x4f scaleMatrix; 265 | XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z); 266 | 267 | XrMatrix4x4f rotationMatrix; 268 | XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation); 269 | 270 | XrMatrix4x4f translationMatrix; 271 | XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, 272 | translation->z); 273 | 274 | XrMatrix4x4f combinedMatrix; 275 | XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix); 276 | XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix); 277 | } 278 | 279 | inline static void 280 | printXrMatrix4x4(XrMatrix4x4f matrix) 281 | { 282 | printf( 283 | "%6.1f %6.1f %6.1f %6.1f\n%6.1f %6.1f %6.1f %6.1f\n%6.1f %6.1f " 284 | "%6.1f %6.1f\n%6.1f %6.1f %6.1f %6.1f\n", 285 | matrix.m[0], matrix.m[1], matrix.m[2], matrix.m[3], matrix.m[4], matrix.m[5], matrix.m[6], 286 | matrix.m[7], matrix.m[8], matrix.m[9], matrix.m[10], matrix.m[11], matrix.m[12], matrix.m[13], 287 | matrix.m[14], matrix.m[15]); 288 | } 289 | --------------------------------------------------------------------------------