The open source OpenXR runtime
at main 498 lines 19 kB view raw
1// Copyright 2025, Beyley Cardellio 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Handles calculating the distortion profile for Oculus Rift devices. 6 * @author Beyley Cardellio <ep1cm1n10n123@gmail.com> 7 * @ingroup drv_rift 8 */ 9 10#include "rift_distortion.h" 11 12#include "math/m_vec2.h" 13 14#define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__) 15#define HMD_DEBUG(hmd, ...) U_LOG_XDEV_IFL_D(&hmd->base, hmd->log_level, __VA_ARGS__) 16#define HMD_INFO(hmd, ...) U_LOG_XDEV_IFL_I(&hmd->base, hmd->log_level, __VA_ARGS__) 17#define HMD_WARN(hmd, ...) U_LOG_XDEV_IFL_W(&hmd->base, hmd->log_level, __VA_ARGS__) 18#define HMD_ERROR(hmd, ...) U_LOG_XDEV_IFL_E(&hmd->base, hmd->log_level, __VA_ARGS__) 19 20static float 21rift_catmull_rom_spline(struct rift_catmull_rom_distortion_data *catmull, float scaled_value) 22{ 23 float scaled_value_floor = floorf(scaled_value); 24 scaled_value_floor = CLAMP(scaled_value_floor, 0, CATMULL_COEFFICIENTS - 1); 25 26 float t = scaled_value - scaled_value_floor; 27 int k = (int)scaled_value_floor; 28 29 float p0, p1, m0, m1; 30 switch (k) { 31 case 0: 32 p0 = 1.0f; 33 m0 = (catmull->k[1] - catmull->k[0]); 34 p1 = catmull->k[1]; 35 m1 = 0.5f * (catmull->k[2] - catmull->k[0]); 36 break; 37 default: 38 p0 = catmull->k[k]; 39 m0 = 0.5f * (catmull->k[k + 1] - catmull->k[k - 1]); 40 p1 = catmull->k[k + 1]; 41 m1 = 0.5f * (catmull->k[k + 2] - catmull->k[k]); 42 break; 43 case CATMULL_COEFFICIENTS - 2: 44 p0 = catmull->k[CATMULL_COEFFICIENTS - 2]; 45 m0 = 0.5f * (catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2]); 46 p1 = catmull->k[CATMULL_COEFFICIENTS - 1]; 47 m1 = catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2]; 48 break; 49 case CATMULL_COEFFICIENTS - 1: 50 p0 = catmull->k[CATMULL_COEFFICIENTS - 1]; 51 m0 = catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2]; 52 p1 = p0 + m0; 53 m1 = m0; 54 break; 55 } 56 57 float omt = 1.0f - t; 58 59 float res = (p0 * (1.0f + 2.0f * t) + m0 * t) * omt * omt + (p1 * (1.0f + 2.0f * omt) - m1 * omt) * t * t; 60 61 return res; 62} 63 64static float 65rift_distortion_distance_scale_squared(struct rift_lens_distortion *lens_distortion, float distance_squared) 66{ 67 float scale = 1.0f; 68 69 switch (lens_distortion->distortion_version) { 70 case RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1: { 71 struct rift_catmull_rom_distortion_data data = lens_distortion->data.lcsv_catmull_rom_10; 72 73 float scaled_distance_squared = 74 (float)(CATMULL_COEFFICIENTS - 1) * distance_squared / (data.max_r * data.max_r); 75 76 return rift_catmull_rom_spline(&data, scaled_distance_squared); 77 } 78 default: return scale; 79 } 80} 81 82struct xrt_vec3 83rift_distortion_distance_scale_squared_split_chroma(struct rift_lens_distortion *lens_distortion, 84 float distance_squared) 85{ 86 float scale = rift_distortion_distance_scale_squared(lens_distortion, distance_squared); 87 88 struct xrt_vec3 scale_split; 89 scale_split.x = scale; 90 scale_split.y = scale; 91 scale_split.z = scale; 92 93 switch (lens_distortion->distortion_version) { 94 case RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1: { 95 struct rift_catmull_rom_distortion_data data = lens_distortion->data.lcsv_catmull_rom_10; 96 97 scale_split.x *= 1.0f + data.chromatic_abberation[0] + distance_squared * data.chromatic_abberation[1]; 98 scale_split.z *= 1.0f + data.chromatic_abberation[2] + distance_squared * data.chromatic_abberation[3]; 99 break; 100 } 101 } 102 103 return scale_split; 104} 105 106struct rift_distortion_render_info 107rift_get_distortion_render_info(struct rift_hmd *hmd, uint32_t view) 108{ 109 struct rift_lens_distortion *distortion = &hmd->lens_distortions[hmd->distortion_in_use]; 110 111 float display_width_meters = MICROMETERS_TO_METERS(hmd->display_info.display_width); 112 float display_height_meters = MICROMETERS_TO_METERS(hmd->display_info.display_height); 113 114 float lens_separation_meters = MICROMETERS_TO_METERS(hmd->display_info.lens_separation); 115 float center_from_top_meters = MICROMETERS_TO_METERS(hmd->display_info.center_v); 116 117 struct xrt_vec2 pixels_per_meter; 118 pixels_per_meter.x = 119 (float)hmd->display_info.resolution_x / (display_width_meters - hmd->extra_display_info.screen_gap_meters); 120 pixels_per_meter.y = (float)hmd->display_info.resolution_y / display_height_meters; 121 122 struct xrt_vec2 pixels_per_tan_angle_at_center; 123 pixels_per_tan_angle_at_center.x = 124 pixels_per_meter.x * distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center; 125 pixels_per_tan_angle_at_center.y = 126 pixels_per_meter.y * distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center; 127 128 struct xrt_vec2 tan_eye_angle_scale; 129 tan_eye_angle_scale.x = 130 0.25f * (display_width_meters / distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center); 131 tan_eye_angle_scale.y = 132 0.5f * (display_height_meters / distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center); 133 134 float visible_width_of_one_eye = 0.5f * (display_width_meters - hmd->extra_display_info.screen_gap_meters); 135 float center_from_left_meters = (display_width_meters - lens_separation_meters) * 0.5f; 136 137 struct xrt_vec2 lens_center; 138 lens_center.x = (center_from_left_meters / visible_width_of_one_eye) * 2.0f - 1.0f; 139 lens_center.y = (center_from_top_meters / display_height_meters) * 2.0f - 1.0f; 140 141 // if we're on the right eye, flip the lens center 142 if (view != 0) { 143 lens_center.x *= -1; 144 } 145 146 return (struct rift_distortion_render_info){ 147 .distortion = distortion, 148 .lens_center = lens_center, 149 .pixels_per_tan_angle_at_center = pixels_per_tan_angle_at_center, 150 .tan_eye_angle_scale = tan_eye_angle_scale, 151 }; 152} 153 154static struct rift_viewport_fov_tan 155rift_calculate_fov_from_eye_position( 156 float eye_relief, float offset_to_right, float offset_downwards, float lens_diameter, float extra_eye_rotation) 157{ 158 float half_lens_diameter = lens_diameter * 0.5f; 159 160 struct rift_viewport_fov_tan fov_port; 161 fov_port.up_tan = (half_lens_diameter + offset_downwards) / eye_relief; 162 fov_port.down_tan = (half_lens_diameter - offset_downwards) / eye_relief; 163 fov_port.left_tan = (half_lens_diameter + offset_to_right) / eye_relief; 164 fov_port.right_tan = (half_lens_diameter - offset_to_right) / eye_relief; 165 166 if (extra_eye_rotation > 0.0f) { 167 extra_eye_rotation = CLAMP(extra_eye_rotation, 0, 30.0f); 168 169 float eyeball_center_to_pupil = 0.0135f; 170 float eyeball_lateral_pull = 0.001f * (extra_eye_rotation / DEG_TO_RAD(30.0f)); 171 float extra_translation = eyeball_center_to_pupil * sinf(extra_eye_rotation) + eyeball_lateral_pull; 172 float extra_relief = eyeball_center_to_pupil * (1.0f - cosf(extra_eye_rotation)); 173 174 fov_port.up_tan = fmaxf(fov_port.up_tan, (half_lens_diameter + offset_downwards + extra_translation) / 175 (eye_relief + extra_relief)); 176 fov_port.down_tan = 177 fmaxf(fov_port.down_tan, 178 (half_lens_diameter - offset_downwards + extra_translation) / (eye_relief + extra_relief)); 179 fov_port.left_tan = 180 fmaxf(fov_port.left_tan, 181 (half_lens_diameter + offset_to_right + extra_translation) / (eye_relief + extra_relief)); 182 fov_port.right_tan = 183 fmaxf(fov_port.right_tan, 184 (half_lens_diameter - offset_to_right + extra_translation) / (eye_relief + extra_relief)); 185 } 186 187 return fov_port; 188} 189 190static struct xrt_vec2 191rift_transform_screen_ndc_to_tan_fov_space(struct rift_distortion_render_info *distortion, struct xrt_vec2 screen_ndc) 192{ 193 struct xrt_vec2 tan_eye_angle_distorted = { 194 (screen_ndc.x - distortion->lens_center.x) * distortion->tan_eye_angle_scale.x, 195 (screen_ndc.y - distortion->lens_center.y) * distortion->tan_eye_angle_scale.y}; 196 197 float distance_squared = (tan_eye_angle_distorted.x * tan_eye_angle_distorted.x) + 198 (tan_eye_angle_distorted.y * tan_eye_angle_distorted.y); 199 200 float distortion_scale = rift_distortion_distance_scale_squared(distortion->distortion, distance_squared); 201 202 return m_vec2_mul_scalar(tan_eye_angle_distorted, distortion_scale); 203} 204 205static struct rift_viewport_fov_tan 206rift_fov_find_range(struct xrt_vec2 from, 207 struct xrt_vec2 to, 208 int num_steps, 209 struct rift_distortion_render_info *distortion) 210{ 211 struct rift_viewport_fov_tan fov_port = {0.0f, 0.0f, 0.0f, 0.0f}; 212 213 float step_scale = 1.0f / (num_steps - 1); 214 for (int step = 0; step < num_steps; step++) { 215 float lerp_factor = step_scale * (float)step; 216 struct xrt_vec2 sample = m_vec2_add(from, m_vec2_mul_scalar(m_vec2_sub(to, from), lerp_factor)); 217 struct xrt_vec2 tan_eye_angle = rift_transform_screen_ndc_to_tan_fov_space(distortion, sample); 218 219 fov_port.left_tan = fmaxf(fov_port.left_tan, -tan_eye_angle.x); 220 fov_port.right_tan = fmaxf(fov_port.right_tan, tan_eye_angle.x); 221 fov_port.up_tan = fmaxf(fov_port.up_tan, -tan_eye_angle.y); 222 fov_port.down_tan = fmaxf(fov_port.down_tan, tan_eye_angle.y); 223 } 224 225 return fov_port; 226} 227 228static struct rift_viewport_fov_tan 229rift_get_physical_screen_fov(struct rift_distortion_render_info *distortion) 230{ 231 struct xrt_vec2 lens_center = distortion->lens_center; 232 233 struct rift_viewport_fov_tan left_fov_port = 234 rift_fov_find_range(lens_center, (struct xrt_vec2){-1.0f, lens_center.y}, 10, distortion); 235 236 struct rift_viewport_fov_tan right_fov_port = 237 rift_fov_find_range(lens_center, (struct xrt_vec2){1.0f, lens_center.y}, 10, distortion); 238 239 struct rift_viewport_fov_tan up_fov_port = 240 rift_fov_find_range(lens_center, (struct xrt_vec2){lens_center.x, -1.0f}, 10, distortion); 241 242 struct rift_viewport_fov_tan down_fov_port = 243 rift_fov_find_range(lens_center, (struct xrt_vec2){lens_center.x, 1.0f}, 10, distortion); 244 245 return (struct rift_viewport_fov_tan){.left_tan = left_fov_port.left_tan, 246 .right_tan = right_fov_port.right_tan, 247 .up_tan = up_fov_port.up_tan, 248 .down_tan = down_fov_port.down_tan}; 249} 250 251static struct rift_viewport_fov_tan 252rift_clamp_fov_to_physical_screen_fov(struct rift_distortion_render_info *distortion, 253 struct rift_viewport_fov_tan fov_port) 254{ 255 struct rift_viewport_fov_tan result_fov_port; 256 struct rift_viewport_fov_tan physical_fov_port = rift_get_physical_screen_fov(distortion); 257 258 result_fov_port.left_tan = fminf(fov_port.left_tan, physical_fov_port.left_tan); 259 result_fov_port.right_tan = fminf(fov_port.right_tan, physical_fov_port.right_tan); 260 result_fov_port.up_tan = fminf(fov_port.up_tan, physical_fov_port.up_tan); 261 result_fov_port.down_tan = fminf(fov_port.down_tan, physical_fov_port.down_tan); 262 263 return result_fov_port; 264} 265 266struct rift_viewport_fov_tan 267rift_calculate_fov_from_hmd(struct rift_hmd *hmd, struct rift_distortion_render_info *distortion, uint32_t view) 268{ 269 float eye_relief = distortion->distortion->eye_relief; 270 271 struct rift_viewport_fov_tan fov_port; 272 fov_port = rift_calculate_fov_from_eye_position(eye_relief, 0, 0, hmd->extra_display_info.lens_diameter_meters, 273 DEFAULT_EXTRA_EYE_ROTATION); 274 275 fov_port = rift_clamp_fov_to_physical_screen_fov(distortion, fov_port); 276 277 return fov_port; 278} 279 280struct rift_scale_and_offset 281rift_calculate_ndc_scale_and_offset_from_fov(struct rift_viewport_fov_tan *fov) 282{ 283 struct xrt_vec2 proj_scale = {.x = 2.0f / (fov->left_tan + fov->right_tan), 284 .y = 2.0f / (fov->up_tan + fov->down_tan)}; 285 286 struct xrt_vec2 proj_offset = {.x = (fov->left_tan - fov->right_tan) * proj_scale.x * 0.5, 287 .y = (fov->up_tan - fov->down_tan) * proj_scale.y * 0.5f}; 288 289 return (struct rift_scale_and_offset){.scale = proj_scale, .offset = proj_offset}; 290} 291 292struct rift_scale_and_offset 293rift_calculate_uv_scale_and_offset_from_ndc_scale_and_offset(struct rift_scale_and_offset eye_to_source_ndc) 294{ 295 struct rift_scale_and_offset result = eye_to_source_ndc; 296 result.scale = m_vec2_mul_scalar(result.scale, 0.5f); 297 result.offset = m_vec2_add_scalar(m_vec2_mul_scalar(result.offset, 0.5f), 0.5f); 298 return result; 299} 300 301static struct xrt_uv_triplet 302rift_transform_screen_ndc_to_tan_fov_space_chroma(struct rift_distortion_render_info *distortion, 303 struct xrt_vec2 screen_ndc) 304{ 305 struct xrt_vec2 tan_eye_angle_distorted = { 306 (screen_ndc.x - distortion->lens_center.x) * distortion->tan_eye_angle_scale.x, 307 (screen_ndc.y - distortion->lens_center.y) * distortion->tan_eye_angle_scale.y}; 308 309 float distance_squared = (tan_eye_angle_distorted.x * tan_eye_angle_distorted.x) + 310 (tan_eye_angle_distorted.y * tan_eye_angle_distorted.y); 311 312 struct xrt_vec3 distortion_scales = 313 rift_distortion_distance_scale_squared_split_chroma(distortion->distortion, distance_squared); 314 315 return (struct xrt_uv_triplet){ 316 .r = {tan_eye_angle_distorted.x * distortion_scales.x, tan_eye_angle_distorted.y * distortion_scales.x}, 317 .g = {tan_eye_angle_distorted.x * distortion_scales.y, tan_eye_angle_distorted.y * distortion_scales.y}, 318 .b = {tan_eye_angle_distorted.x * distortion_scales.z, tan_eye_angle_distorted.y * distortion_scales.z}, 319 }; 320} 321 322// unused math functions which may be useful in the future for stuff like calculating FOV. 323// disabled to not give unused warnings 324#if 0 325static float 326rift_distortion(struct rift_lens_distortion *lens_distortion, float distance) 327{ 328 return distance * rift_distortion_distance_scale_squared(lens_distortion, distance * distance); 329} 330 331static float 332rift_distortion_distance_inverse(struct rift_lens_distortion *lens_distortion, float distance) 333{ 334 assert(distance <= 20.0f); 335 336 float delta = distance * 0.25f; 337 338 float s = distance * 0.25f; 339 float d = fabsf(distance - rift_distortion(lens_distortion, s)); 340 341 for (int i = 0; i < 20; i++) { 342 float s_up = s + delta; 343 float s_down = s - delta; 344 float d_up = fabsf(distance - rift_distortion(lens_distortion, s_up)); 345 float d_down = fabsf(distance - rift_distortion(lens_distortion, s_down)); 346 347 if (d_up < d) { 348 s = s_up; 349 d = d_up; 350 } else if (d_down < d) { 351 s = s_down; 352 d = d_down; 353 } else { 354 delta *= 0.5f; 355 } 356 } 357 358 return s; 359} 360 361static struct xrt_vec2 362rift_transform_tan_fov_space_to_render_target_tex_uv(struct rift_scale_and_offset *eye_to_source_uv, 363 struct xrt_vec2 tan_eye_angle) 364{ 365 return m_vec2_add(m_vec2_mul(tan_eye_angle, eye_to_source_uv->scale), eye_to_source_uv->offset); 366} 367 368static struct xrt_vec2 369rift_transform_render_target_ndc_to_tan_fov_space(struct rift_scale_and_offset *eye_to_source_ndc, struct xrt_vec2 ndc) 370{ 371 return m_vec2_div(m_vec2_sub(ndc, eye_to_source_ndc->offset), eye_to_source_ndc->scale); 372} 373 374static struct xrt_vec2 375rift_transform_tan_fov_space_to_screen_ndc(struct rift_distortion_render_info *distortion, 376 struct xrt_vec2 tan_eye_angle) 377{ 378 float tan_eye_angle_radius = m_vec2_len(tan_eye_angle); 379 float tan_eye_angle_distorted_radius = 380 rift_distortion_distance_inverse(distortion->distortion, tan_eye_angle_radius); 381 382 struct xrt_vec2 tan_eye_angle_distorted = tan_eye_angle; 383 if (tan_eye_angle_radius > 0) { 384 tan_eye_angle_distorted = 385 m_vec2_mul_scalar(tan_eye_angle, tan_eye_angle_distorted_radius / tan_eye_angle_radius); 386 } 387 388 return m_vec2_add(m_vec2_div(tan_eye_angle_distorted, distortion->tan_eye_angle_scale), 389 distortion->lens_center); 390} 391#endif 392 393xrt_result_t 394rift_hmd_compute_distortion(struct xrt_device *dev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) 395{ 396#define TO_NDC(x) ((x * 2) - 1) 397 398 struct rift_hmd *hmd = rift_hmd(dev); 399 400 struct xrt_vec2 source_ndc = {TO_NDC(u), TO_NDC(v)}; 401 402 struct rift_distortion_render_info distortion_render_info = rift_get_distortion_render_info(hmd, 0); 403 404 struct rift_scale_and_offset *eye_to_source_uv = &hmd->extra_display_info.eye_to_source_uv; 405 406 struct xrt_uv_triplet tan_fov_chroma = 407 rift_transform_screen_ndc_to_tan_fov_space_chroma(&distortion_render_info, source_ndc); 408 409#if 0 // no distortion (green channel doesn't have any chromatic aberration correction) 410 struct xrt_uv_triplet sample_tex_coord = { 411 .r = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset), 412 .g = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset), 413 .b = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset)}; 414#else 415 struct xrt_uv_triplet sample_tex_coord = { 416 .r = m_vec2_add(m_vec2_mul(tan_fov_chroma.r, eye_to_source_uv->scale), eye_to_source_uv->offset), 417 .g = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset), 418 .b = m_vec2_add(m_vec2_mul(tan_fov_chroma.b, eye_to_source_uv->scale), eye_to_source_uv->offset)}; 419#endif 420 421 *out_result = sample_tex_coord; 422 423 return XRT_SUCCESS; 424 425#undef TO_NDC 426} 427 428void 429rift_fill_in_default_distortions(struct rift_hmd *hmd) 430{ 431 hmd->num_lens_distortions = 2; 432 hmd->lens_distortions = calloc(hmd->num_lens_distortions, sizeof(struct rift_lens_distortion)); 433 434 uint16_t i = 0; 435 436 struct rift_catmull_rom_distortion_data distortion_data; 437 438 // TODO: dump these from the latest oculus runtime 439 // TODO: select the right distorions based on rift variant, right now this is hard-coded to the DK2 440 441 hmd->lens_distortions[i].distortion_version = RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1; 442 hmd->lens_distortions[i].eye_relief = 0.008f; 443 444 distortion_data.meters_per_tan_angle_at_center = 0.036f; 445 distortion_data.max_r = 1.0f; 446 447 distortion_data.k[0] = 1.003f; 448 distortion_data.k[1] = 1.02f; 449 distortion_data.k[2] = 1.042f; 450 distortion_data.k[3] = 1.066f; 451 distortion_data.k[4] = 1.094f; 452 distortion_data.k[5] = 1.126f; 453 distortion_data.k[6] = 1.162f; 454 distortion_data.k[7] = 1.203f; 455 distortion_data.k[8] = 1.25f; 456 distortion_data.k[9] = 1.31f; 457 distortion_data.k[10] = 1.38f; 458 459 distortion_data.chromatic_abberation[0] = -0.0112f; 460 distortion_data.chromatic_abberation[1] = -0.015f; 461 distortion_data.chromatic_abberation[2] = 0.0187f; 462 distortion_data.chromatic_abberation[3] = 0.015f; 463 464 hmd->lens_distortions[i].data.lcsv_catmull_rom_10 = distortion_data; 465 466 i += 1; 467 468 hmd->lens_distortions[i].distortion_version = RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1; 469 hmd->lens_distortions[i].eye_relief = 0.018f; 470 471 distortion_data.meters_per_tan_angle_at_center = 0.036f; 472 distortion_data.max_r = 1.0f; 473 474 distortion_data.k[0] = 1.003f; 475 distortion_data.k[1] = 1.02f; 476 distortion_data.k[2] = 1.042f; 477 distortion_data.k[3] = 1.066f; 478 distortion_data.k[4] = 1.094f; 479 distortion_data.k[5] = 1.126f; 480 distortion_data.k[6] = 1.162f; 481 distortion_data.k[7] = 1.203f; 482 distortion_data.k[8] = 1.25f; 483 distortion_data.k[9] = 1.31f; 484 distortion_data.k[10] = 1.38f; 485 486 distortion_data.chromatic_abberation[0] = -0.015f; 487 distortion_data.chromatic_abberation[1] = -0.02f; 488 distortion_data.chromatic_abberation[2] = 0.025f; 489 distortion_data.chromatic_abberation[3] = 0.02f; 490 491 hmd->lens_distortions[i].data.lcsv_catmull_rom_10 = distortion_data; 492 493 i += 1; 494 495 // TODO: let the user specify which distortion is in use with an env var, 496 // and interpolate the distortions for the user's specific eye relief setting 497 hmd->distortion_in_use = 1; 498}