mirror of
https://github.com/lbgos/rift-s-linux.git
synced 2026-10-28 08:01:21 +01:00
d/rift: Fix distortion and render parameters
This appears to be fully correct on DK2 now. There are still some fixes to this code required for CV1 (which is slightly off-center, and there's a bug in this code making that not work correctly), but those will be upstreamed at a later point, since it isn't relevant to DK2 specifically, and would be hard to cherry-pick. Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2428>
This commit is contained in:
1 parent
0714e012eb
commit
1250f8a9ff
5 files changed
+677
-173
No files matched your search
@@ -244,6 +244,7 @@ if(XRT_BUILD_DRIVER_RIFT)
|
||||
add_library(
|
||||
drv_rift STATIC
|
||||
rift/rift_hmd.c
|
||||
rift/rift_distortion.c
|
||||
rift/rift_prober.c
|
||||
)
|
||||
target_include_directories(drv_rift SYSTEM PRIVATE)
|
||||
|
||||
@@ -0,0 +1,498 @@
|
||||
// Copyright 2025, Beyley Cardellio
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Handles calculating the distortion profile for Oculus Rift devices.
|
||||
* @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
|
||||
* @ingroup drv_rift
|
||||
*/
|
||||
|
||||
#include "rift_distortion.h"
|
||||
|
||||
#include "math/m_vec2.h"
|
||||
|
||||
#define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__)
|
||||
#define HMD_DEBUG(hmd, ...) U_LOG_XDEV_IFL_D(&hmd->base, hmd->log_level, __VA_ARGS__)
|
||||
#define HMD_INFO(hmd, ...) U_LOG_XDEV_IFL_I(&hmd->base, hmd->log_level, __VA_ARGS__)
|
||||
#define HMD_WARN(hmd, ...) U_LOG_XDEV_IFL_W(&hmd->base, hmd->log_level, __VA_ARGS__)
|
||||
#define HMD_ERROR(hmd, ...) U_LOG_XDEV_IFL_E(&hmd->base, hmd->log_level, __VA_ARGS__)
|
||||
|
||||
static float
|
||||
rift_catmull_rom_spline(struct rift_catmull_rom_distortion_data *catmull, float scaled_value)
|
||||
{
|
||||
float scaled_value_floor = floorf(scaled_value);
|
||||
scaled_value_floor = CLAMP(scaled_value_floor, 0, CATMULL_COEFFICIENTS - 1);
|
||||
|
||||
float t = scaled_value - scaled_value_floor;
|
||||
int k = (int)scaled_value_floor;
|
||||
|
||||
float p0, p1, m0, m1;
|
||||
switch (k) {
|
||||
case 0:
|
||||
p0 = 1.0f;
|
||||
m0 = (catmull->k[1] - catmull->k[0]);
|
||||
p1 = catmull->k[1];
|
||||
m1 = 0.5f * (catmull->k[2] - catmull->k[0]);
|
||||
break;
|
||||
default:
|
||||
p0 = catmull->k[k];
|
||||
m0 = 0.5f * (catmull->k[k + 1] - catmull->k[k - 1]);
|
||||
p1 = catmull->k[k + 1];
|
||||
m1 = 0.5f * (catmull->k[k + 2] - catmull->k[k]);
|
||||
break;
|
||||
case CATMULL_COEFFICIENTS - 2:
|
||||
p0 = catmull->k[CATMULL_COEFFICIENTS - 2];
|
||||
m0 = 0.5f * (catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2]);
|
||||
p1 = catmull->k[CATMULL_COEFFICIENTS - 1];
|
||||
m1 = catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2];
|
||||
break;
|
||||
case CATMULL_COEFFICIENTS - 1:
|
||||
p0 = catmull->k[CATMULL_COEFFICIENTS - 1];
|
||||
m0 = catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2];
|
||||
p1 = p0 + m0;
|
||||
m1 = m0;
|
||||
break;
|
||||
}
|
||||
|
||||
float omt = 1.0f - t;
|
||||
|
||||
float res = (p0 * (1.0f + 2.0f * t) + m0 * t) * omt * omt + (p1 * (1.0f + 2.0f * omt) - m1 * omt) * t * t;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static float
|
||||
rift_distortion_distance_scale_squared(struct rift_lens_distortion *lens_distortion, float distance_squared)
|
||||
{
|
||||
float scale = 1.0f;
|
||||
|
||||
switch (lens_distortion->distortion_version) {
|
||||
case RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1: {
|
||||
struct rift_catmull_rom_distortion_data data = lens_distortion->data.lcsv_catmull_rom_10;
|
||||
|
||||
float scaled_distance_squared =
|
||||
(float)(CATMULL_COEFFICIENTS - 1) * distance_squared / (data.max_r * data.max_r);
|
||||
|
||||
return rift_catmull_rom_spline(&data, scaled_distance_squared);
|
||||
}
|
||||
default: return scale;
|
||||
}
|
||||
}
|
||||
|
||||
struct xrt_vec3
|
||||
rift_distortion_distance_scale_squared_split_chroma(struct rift_lens_distortion *lens_distortion,
|
||||
float distance_squared)
|
||||
{
|
||||
float scale = rift_distortion_distance_scale_squared(lens_distortion, distance_squared);
|
||||
|
||||
struct xrt_vec3 scale_split;
|
||||
scale_split.x = scale;
|
||||
scale_split.y = scale;
|
||||
scale_split.z = scale;
|
||||
|
||||
switch (lens_distortion->distortion_version) {
|
||||
case RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1: {
|
||||
struct rift_catmull_rom_distortion_data data = lens_distortion->data.lcsv_catmull_rom_10;
|
||||
|
||||
scale_split.x *= 1.0f + data.chromatic_abberation[0] + distance_squared * data.chromatic_abberation[1];
|
||||
scale_split.z *= 1.0f + data.chromatic_abberation[2] + distance_squared * data.chromatic_abberation[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return scale_split;
|
||||
}
|
||||
|
||||
struct rift_distortion_render_info
|
||||
rift_get_distortion_render_info(struct rift_hmd *hmd, uint32_t view)
|
||||
{
|
||||
struct rift_lens_distortion *distortion = &hmd->lens_distortions[hmd->distortion_in_use];
|
||||
|
||||
float display_width_meters = MICROMETERS_TO_METERS(hmd->display_info.display_width);
|
||||
float display_height_meters = MICROMETERS_TO_METERS(hmd->display_info.display_height);
|
||||
|
||||
float lens_separation_meters = MICROMETERS_TO_METERS(hmd->display_info.lens_separation);
|
||||
float center_from_top_meters = MICROMETERS_TO_METERS(hmd->display_info.center_v);
|
||||
|
||||
struct xrt_vec2 pixels_per_meter;
|
||||
pixels_per_meter.x =
|
||||
(float)hmd->display_info.resolution_x / (display_width_meters - hmd->extra_display_info.screen_gap_meters);
|
||||
pixels_per_meter.y = (float)hmd->display_info.resolution_y / display_height_meters;
|
||||
|
||||
struct xrt_vec2 pixels_per_tan_angle_at_center;
|
||||
pixels_per_tan_angle_at_center.x =
|
||||
pixels_per_meter.x * distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center;
|
||||
pixels_per_tan_angle_at_center.y =
|
||||
pixels_per_meter.y * distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center;
|
||||
|
||||
struct xrt_vec2 tan_eye_angle_scale;
|
||||
tan_eye_angle_scale.x =
|
||||
0.25f * (display_width_meters / distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center);
|
||||
tan_eye_angle_scale.y =
|
||||
0.5f * (display_height_meters / distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center);
|
||||
|
||||
float visible_width_of_one_eye = 0.5f * (display_width_meters - hmd->extra_display_info.screen_gap_meters);
|
||||
float center_from_left_meters = (display_width_meters - lens_separation_meters) * 0.5f;
|
||||
|
||||
struct xrt_vec2 lens_center;
|
||||
lens_center.x = (center_from_left_meters / visible_width_of_one_eye) * 2.0f - 1.0f;
|
||||
lens_center.y = (center_from_top_meters / display_height_meters) * 2.0f - 1.0f;
|
||||
|
||||
// if we're on the right eye, flip the lens center
|
||||
if (view != 0) {
|
||||
lens_center.x *= -1;
|
||||
}
|
||||
|
||||
return (struct rift_distortion_render_info){
|
||||
.distortion = distortion,
|
||||
.lens_center = lens_center,
|
||||
.pixels_per_tan_angle_at_center = pixels_per_tan_angle_at_center,
|
||||
.tan_eye_angle_scale = tan_eye_angle_scale,
|
||||
};
|
||||
}
|
||||
|
||||
static struct rift_viewport_fov_tan
|
||||
rift_calculate_fov_from_eye_position(
|
||||
float eye_relief, float offset_to_right, float offset_downwards, float lens_diameter, float extra_eye_rotation)
|
||||
{
|
||||
float half_lens_diameter = lens_diameter * 0.5f;
|
||||
|
||||
struct rift_viewport_fov_tan fov_port;
|
||||
fov_port.up_tan = (half_lens_diameter + offset_downwards) / eye_relief;
|
||||
fov_port.down_tan = (half_lens_diameter - offset_downwards) / eye_relief;
|
||||
fov_port.left_tan = (half_lens_diameter + offset_to_right) / eye_relief;
|
||||
fov_port.right_tan = (half_lens_diameter - offset_to_right) / eye_relief;
|
||||
|
||||
if (extra_eye_rotation > 0.0f) {
|
||||
extra_eye_rotation = CLAMP(extra_eye_rotation, 0, 30.0f);
|
||||
|
||||
float eyeball_center_to_pupil = 0.0135f;
|
||||
float eyeball_lateral_pull = 0.001f * (extra_eye_rotation / DEG_TO_RAD(30.0f));
|
||||
float extra_translation = eyeball_center_to_pupil * sinf(extra_eye_rotation) + eyeball_lateral_pull;
|
||||
float extra_relief = eyeball_center_to_pupil * (1.0f - cosf(extra_eye_rotation));
|
||||
|
||||
fov_port.up_tan = fmaxf(fov_port.up_tan, (half_lens_diameter + offset_downwards + extra_translation) /
|
||||
(eye_relief + extra_relief));
|
||||
fov_port.down_tan =
|
||||
fmaxf(fov_port.down_tan,
|
||||
(half_lens_diameter - offset_downwards + extra_translation) / (eye_relief + extra_relief));
|
||||
fov_port.left_tan =
|
||||
fmaxf(fov_port.left_tan,
|
||||
(half_lens_diameter + offset_to_right + extra_translation) / (eye_relief + extra_relief));
|
||||
fov_port.right_tan =
|
||||
fmaxf(fov_port.right_tan,
|
||||
(half_lens_diameter - offset_to_right + extra_translation) / (eye_relief + extra_relief));
|
||||
}
|
||||
|
||||
return fov_port;
|
||||
}
|
||||
|
||||
static struct xrt_vec2
|
||||
rift_transform_screen_ndc_to_tan_fov_space(struct rift_distortion_render_info *distortion, struct xrt_vec2 screen_ndc)
|
||||
{
|
||||
struct xrt_vec2 tan_eye_angle_distorted = {
|
||||
(screen_ndc.x - distortion->lens_center.x) * distortion->tan_eye_angle_scale.x,
|
||||
(screen_ndc.y - distortion->lens_center.y) * distortion->tan_eye_angle_scale.y};
|
||||
|
||||
float distance_squared = (tan_eye_angle_distorted.x * tan_eye_angle_distorted.x) +
|
||||
(tan_eye_angle_distorted.y * tan_eye_angle_distorted.y);
|
||||
|
||||
float distortion_scale = rift_distortion_distance_scale_squared(distortion->distortion, distance_squared);
|
||||
|
||||
return m_vec2_mul_scalar(tan_eye_angle_distorted, distortion_scale);
|
||||
}
|
||||
|
||||
static struct rift_viewport_fov_tan
|
||||
rift_fov_find_range(struct xrt_vec2 from,
|
||||
struct xrt_vec2 to,
|
||||
int num_steps,
|
||||
struct rift_distortion_render_info *distortion)
|
||||
{
|
||||
struct rift_viewport_fov_tan fov_port = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
float step_scale = 1.0f / (num_steps - 1);
|
||||
for (int step = 0; step < num_steps; step++) {
|
||||
float lerp_factor = step_scale * (float)step;
|
||||
struct xrt_vec2 sample = m_vec2_add(from, m_vec2_mul_scalar(m_vec2_sub(to, from), lerp_factor));
|
||||
struct xrt_vec2 tan_eye_angle = rift_transform_screen_ndc_to_tan_fov_space(distortion, sample);
|
||||
|
||||
fov_port.left_tan = fmaxf(fov_port.left_tan, -tan_eye_angle.x);
|
||||
fov_port.right_tan = fmaxf(fov_port.right_tan, tan_eye_angle.x);
|
||||
fov_port.up_tan = fmaxf(fov_port.up_tan, -tan_eye_angle.y);
|
||||
fov_port.down_tan = fmaxf(fov_port.down_tan, tan_eye_angle.y);
|
||||
}
|
||||
|
||||
return fov_port;
|
||||
}
|
||||
|
||||
static struct rift_viewport_fov_tan
|
||||
rift_get_physical_screen_fov(struct rift_distortion_render_info *distortion)
|
||||
{
|
||||
struct xrt_vec2 lens_center = distortion->lens_center;
|
||||
|
||||
struct rift_viewport_fov_tan left_fov_port =
|
||||
rift_fov_find_range(lens_center, (struct xrt_vec2){-1.0f, lens_center.y}, 10, distortion);
|
||||
|
||||
struct rift_viewport_fov_tan right_fov_port =
|
||||
rift_fov_find_range(lens_center, (struct xrt_vec2){1.0f, lens_center.y}, 10, distortion);
|
||||
|
||||
struct rift_viewport_fov_tan up_fov_port =
|
||||
rift_fov_find_range(lens_center, (struct xrt_vec2){lens_center.x, -1.0f}, 10, distortion);
|
||||
|
||||
struct rift_viewport_fov_tan down_fov_port =
|
||||
rift_fov_find_range(lens_center, (struct xrt_vec2){lens_center.x, 1.0f}, 10, distortion);
|
||||
|
||||
return (struct rift_viewport_fov_tan){.left_tan = left_fov_port.left_tan,
|
||||
.right_tan = right_fov_port.right_tan,
|
||||
.up_tan = up_fov_port.up_tan,
|
||||
.down_tan = down_fov_port.down_tan};
|
||||
}
|
||||
|
||||
static struct rift_viewport_fov_tan
|
||||
rift_clamp_fov_to_physical_screen_fov(struct rift_distortion_render_info *distortion,
|
||||
struct rift_viewport_fov_tan fov_port)
|
||||
{
|
||||
struct rift_viewport_fov_tan result_fov_port;
|
||||
struct rift_viewport_fov_tan physical_fov_port = rift_get_physical_screen_fov(distortion);
|
||||
|
||||
result_fov_port.left_tan = fminf(fov_port.left_tan, physical_fov_port.left_tan);
|
||||
result_fov_port.right_tan = fminf(fov_port.right_tan, physical_fov_port.right_tan);
|
||||
result_fov_port.up_tan = fminf(fov_port.up_tan, physical_fov_port.up_tan);
|
||||
result_fov_port.down_tan = fminf(fov_port.down_tan, physical_fov_port.down_tan);
|
||||
|
||||
return result_fov_port;
|
||||
}
|
||||
|
||||
struct rift_viewport_fov_tan
|
||||
rift_calculate_fov_from_hmd(struct rift_hmd *hmd, struct rift_distortion_render_info *distortion, uint32_t view)
|
||||
{
|
||||
float eye_relief = distortion->distortion->eye_relief;
|
||||
|
||||
struct rift_viewport_fov_tan fov_port;
|
||||
fov_port = rift_calculate_fov_from_eye_position(eye_relief, 0, 0, hmd->extra_display_info.lens_diameter_meters,
|
||||
DEFAULT_EXTRA_EYE_ROTATION);
|
||||
|
||||
fov_port = rift_clamp_fov_to_physical_screen_fov(distortion, fov_port);
|
||||
|
||||
return fov_port;
|
||||
}
|
||||
|
||||
struct rift_scale_and_offset
|
||||
rift_calculate_ndc_scale_and_offset_from_fov(struct rift_viewport_fov_tan *fov)
|
||||
{
|
||||
struct xrt_vec2 proj_scale = {.x = 2.0f / (fov->left_tan + fov->right_tan),
|
||||
.y = 2.0f / (fov->up_tan + fov->down_tan)};
|
||||
|
||||
struct xrt_vec2 proj_offset = {.x = (fov->left_tan - fov->right_tan) * proj_scale.x * 0.5,
|
||||
.y = (fov->up_tan - fov->down_tan) * proj_scale.y * 0.5f};
|
||||
|
||||
return (struct rift_scale_and_offset){.scale = proj_scale, .offset = proj_offset};
|
||||
}
|
||||
|
||||
struct rift_scale_and_offset
|
||||
rift_calculate_uv_scale_and_offset_from_ndc_scale_and_offset(struct rift_scale_and_offset eye_to_source_ndc)
|
||||
{
|
||||
struct rift_scale_and_offset result = eye_to_source_ndc;
|
||||
result.scale = m_vec2_mul_scalar(result.scale, 0.5f);
|
||||
result.offset = m_vec2_add_scalar(m_vec2_mul_scalar(result.offset, 0.5f), 0.5f);
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct xrt_uv_triplet
|
||||
rift_transform_screen_ndc_to_tan_fov_space_chroma(struct rift_distortion_render_info *distortion,
|
||||
struct xrt_vec2 screen_ndc)
|
||||
{
|
||||
struct xrt_vec2 tan_eye_angle_distorted = {
|
||||
(screen_ndc.x - distortion->lens_center.x) * distortion->tan_eye_angle_scale.x,
|
||||
(screen_ndc.y - distortion->lens_center.y) * distortion->tan_eye_angle_scale.y};
|
||||
|
||||
float distance_squared = (tan_eye_angle_distorted.x * tan_eye_angle_distorted.x) +
|
||||
(tan_eye_angle_distorted.y * tan_eye_angle_distorted.y);
|
||||
|
||||
struct xrt_vec3 distortion_scales =
|
||||
rift_distortion_distance_scale_squared_split_chroma(distortion->distortion, distance_squared);
|
||||
|
||||
return (struct xrt_uv_triplet){
|
||||
.r = {tan_eye_angle_distorted.x * distortion_scales.x, tan_eye_angle_distorted.y * distortion_scales.x},
|
||||
.g = {tan_eye_angle_distorted.x * distortion_scales.y, tan_eye_angle_distorted.y * distortion_scales.y},
|
||||
.b = {tan_eye_angle_distorted.x * distortion_scales.z, tan_eye_angle_distorted.y * distortion_scales.z},
|
||||
};
|
||||
}
|
||||
|
||||
// unused math functions which may be useful in the future for stuff like calculating FOV.
|
||||
// disabled to not give unused warnings
|
||||
#if 0
|
||||
static float
|
||||
rift_distortion(struct rift_lens_distortion *lens_distortion, float distance)
|
||||
{
|
||||
return distance * rift_distortion_distance_scale_squared(lens_distortion, distance * distance);
|
||||
}
|
||||
|
||||
static float
|
||||
rift_distortion_distance_inverse(struct rift_lens_distortion *lens_distortion, float distance)
|
||||
{
|
||||
assert(distance <= 20.0f);
|
||||
|
||||
float delta = distance * 0.25f;
|
||||
|
||||
float s = distance * 0.25f;
|
||||
float d = fabsf(distance - rift_distortion(lens_distortion, s));
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
float s_up = s + delta;
|
||||
float s_down = s - delta;
|
||||
float d_up = fabsf(distance - rift_distortion(lens_distortion, s_up));
|
||||
float d_down = fabsf(distance - rift_distortion(lens_distortion, s_down));
|
||||
|
||||
if (d_up < d) {
|
||||
s = s_up;
|
||||
d = d_up;
|
||||
} else if (d_down < d) {
|
||||
s = s_down;
|
||||
d = d_down;
|
||||
} else {
|
||||
delta *= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct xrt_vec2
|
||||
rift_transform_tan_fov_space_to_render_target_tex_uv(struct rift_scale_and_offset *eye_to_source_uv,
|
||||
struct xrt_vec2 tan_eye_angle)
|
||||
{
|
||||
return m_vec2_add(m_vec2_mul(tan_eye_angle, eye_to_source_uv->scale), eye_to_source_uv->offset);
|
||||
}
|
||||
|
||||
static struct xrt_vec2
|
||||
rift_transform_render_target_ndc_to_tan_fov_space(struct rift_scale_and_offset *eye_to_source_ndc, struct xrt_vec2 ndc)
|
||||
{
|
||||
return m_vec2_div(m_vec2_sub(ndc, eye_to_source_ndc->offset), eye_to_source_ndc->scale);
|
||||
}
|
||||
|
||||
static struct xrt_vec2
|
||||
rift_transform_tan_fov_space_to_screen_ndc(struct rift_distortion_render_info *distortion,
|
||||
struct xrt_vec2 tan_eye_angle)
|
||||
{
|
||||
float tan_eye_angle_radius = m_vec2_len(tan_eye_angle);
|
||||
float tan_eye_angle_distorted_radius =
|
||||
rift_distortion_distance_inverse(distortion->distortion, tan_eye_angle_radius);
|
||||
|
||||
struct xrt_vec2 tan_eye_angle_distorted = tan_eye_angle;
|
||||
if (tan_eye_angle_radius > 0) {
|
||||
tan_eye_angle_distorted =
|
||||
m_vec2_mul_scalar(tan_eye_angle, tan_eye_angle_distorted_radius / tan_eye_angle_radius);
|
||||
}
|
||||
|
||||
return m_vec2_add(m_vec2_div(tan_eye_angle_distorted, distortion->tan_eye_angle_scale),
|
||||
distortion->lens_center);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
rift_hmd_compute_distortion(struct xrt_device *dev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result)
|
||||
{
|
||||
#define TO_NDC(x) ((x * 2) - 1)
|
||||
|
||||
struct rift_hmd *hmd = rift_hmd(dev);
|
||||
|
||||
struct xrt_vec2 source_ndc = {TO_NDC(u), TO_NDC(v)};
|
||||
|
||||
struct rift_distortion_render_info distortion_render_info = rift_get_distortion_render_info(hmd, 0);
|
||||
|
||||
struct rift_scale_and_offset *eye_to_source_uv = &hmd->extra_display_info.eye_to_source_uv;
|
||||
|
||||
struct xrt_uv_triplet tan_fov_chroma =
|
||||
rift_transform_screen_ndc_to_tan_fov_space_chroma(&distortion_render_info, source_ndc);
|
||||
|
||||
#if 0 // no distortion
|
||||
struct xrt_uv_triplet sample_tex_coord = {
|
||||
.r = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset),
|
||||
.g = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset),
|
||||
.b = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset)};
|
||||
#else
|
||||
struct xrt_uv_triplet sample_tex_coord = {
|
||||
.r = m_vec2_add(m_vec2_mul(tan_fov_chroma.r, eye_to_source_uv->scale), eye_to_source_uv->offset),
|
||||
.g = m_vec2_add(m_vec2_mul(tan_fov_chroma.g, eye_to_source_uv->scale), eye_to_source_uv->offset),
|
||||
.b = m_vec2_add(m_vec2_mul(tan_fov_chroma.b, eye_to_source_uv->scale), eye_to_source_uv->offset)};
|
||||
#endif
|
||||
|
||||
*out_result = sample_tex_coord;
|
||||
|
||||
return true;
|
||||
|
||||
#undef TO_NDC
|
||||
}
|
||||
|
||||
void
|
||||
rift_fill_in_default_distortions(struct rift_hmd *hmd)
|
||||
{
|
||||
hmd->num_lens_distortions = 2;
|
||||
hmd->lens_distortions = calloc(hmd->num_lens_distortions, sizeof(struct rift_lens_distortion));
|
||||
|
||||
uint16_t i = 0;
|
||||
|
||||
struct rift_catmull_rom_distortion_data distortion_data;
|
||||
|
||||
// TODO: dump these from the latest oculus runtime
|
||||
// TODO: select the right distorions based on rift variant, right now this is hard-coded to the DK2
|
||||
|
||||
hmd->lens_distortions[i].distortion_version = RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1;
|
||||
hmd->lens_distortions[i].eye_relief = 0.008f;
|
||||
|
||||
distortion_data.meters_per_tan_angle_at_center = 0.036f;
|
||||
distortion_data.max_r = 1.0f;
|
||||
|
||||
distortion_data.k[0] = 1.003f;
|
||||
distortion_data.k[1] = 1.02f;
|
||||
distortion_data.k[2] = 1.042f;
|
||||
distortion_data.k[3] = 1.066f;
|
||||
distortion_data.k[4] = 1.094f;
|
||||
distortion_data.k[5] = 1.126f;
|
||||
distortion_data.k[6] = 1.162f;
|
||||
distortion_data.k[7] = 1.203f;
|
||||
distortion_data.k[8] = 1.25f;
|
||||
distortion_data.k[9] = 1.31f;
|
||||
distortion_data.k[10] = 1.38f;
|
||||
|
||||
distortion_data.chromatic_abberation[0] = -0.0112f;
|
||||
distortion_data.chromatic_abberation[1] = -0.015f;
|
||||
distortion_data.chromatic_abberation[2] = 0.0187f;
|
||||
distortion_data.chromatic_abberation[3] = 0.015f;
|
||||
|
||||
hmd->lens_distortions[i].data.lcsv_catmull_rom_10 = distortion_data;
|
||||
|
||||
i += 1;
|
||||
|
||||
hmd->lens_distortions[i].distortion_version = RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1;
|
||||
hmd->lens_distortions[i].eye_relief = 0.018f;
|
||||
|
||||
distortion_data.meters_per_tan_angle_at_center = 0.036f;
|
||||
distortion_data.max_r = 1.0f;
|
||||
|
||||
distortion_data.k[0] = 1.003f;
|
||||
distortion_data.k[1] = 1.02f;
|
||||
distortion_data.k[2] = 1.042f;
|
||||
distortion_data.k[3] = 1.066f;
|
||||
distortion_data.k[4] = 1.094f;
|
||||
distortion_data.k[5] = 1.126f;
|
||||
distortion_data.k[6] = 1.162f;
|
||||
distortion_data.k[7] = 1.203f;
|
||||
distortion_data.k[8] = 1.25f;
|
||||
distortion_data.k[9] = 1.31f;
|
||||
distortion_data.k[10] = 1.38f;
|
||||
|
||||
distortion_data.chromatic_abberation[0] = -0.015f;
|
||||
distortion_data.chromatic_abberation[1] = -0.02f;
|
||||
distortion_data.chromatic_abberation[2] = 0.025f;
|
||||
distortion_data.chromatic_abberation[3] = 0.02f;
|
||||
|
||||
hmd->lens_distortions[i].data.lcsv_catmull_rom_10 = distortion_data;
|
||||
|
||||
i += 1;
|
||||
|
||||
// TODO: let the user specify which distortion is in use with an env var,
|
||||
// and interpolate the distortions for the user's specific eye relief setting
|
||||
hmd->distortion_in_use = 1;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2025, Beyley Cardellio
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Public functions for the Oculus Rift distortion correction.
|
||||
* @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
|
||||
* @ingroup drv_rift
|
||||
*/
|
||||
|
||||
#include "rift_interface.h"
|
||||
|
||||
struct rift_distortion_render_info
|
||||
{
|
||||
struct rift_lens_distortion *distortion;
|
||||
struct xrt_vec2 lens_center;
|
||||
struct xrt_vec2 tan_eye_angle_scale;
|
||||
struct xrt_vec2 pixels_per_tan_angle_at_center;
|
||||
};
|
||||
|
||||
struct rift_distortion_render_info
|
||||
rift_get_distortion_render_info(struct rift_hmd *hmd, uint32_t view);
|
||||
|
||||
struct xrt_vec3
|
||||
rift_distortion_distance_scale_squared_split_chroma(struct rift_lens_distortion *lens_distortion,
|
||||
float distance_squared);
|
||||
|
||||
struct rift_viewport_fov_tan
|
||||
rift_calculate_fov_from_hmd(struct rift_hmd *hmd, struct rift_distortion_render_info *distortion, uint32_t view);
|
||||
|
||||
struct rift_scale_and_offset
|
||||
rift_calculate_ndc_scale_and_offset_from_fov(struct rift_viewport_fov_tan *fov);
|
||||
|
||||
struct rift_scale_and_offset
|
||||
rift_calculate_uv_scale_and_offset_from_ndc_scale_and_offset(struct rift_scale_and_offset eye_to_source_ndc);
|
||||
|
||||
void
|
||||
rift_fill_in_default_distortions(struct rift_hmd *hmd);
|
||||
|
||||
bool
|
||||
rift_hmd_compute_distortion(struct xrt_device *dev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result);
|
||||
+83
-169
@@ -16,10 +16,13 @@
|
||||
#include "os/os_time.h"
|
||||
#include "xrt/xrt_defines.h"
|
||||
#include "xrt/xrt_device.h"
|
||||
|
||||
#include "rift_interface.h"
|
||||
#include "rift_distortion.h"
|
||||
|
||||
#include "math/m_relation_history.h"
|
||||
#include "math/m_api.h"
|
||||
#include "math/m_vec2.h"
|
||||
#include "math/m_mathinclude.h" // IWYU pragma: keep
|
||||
|
||||
#include "util/u_debug.h"
|
||||
@@ -42,13 +45,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/// Casting helper function
|
||||
static inline struct rift_hmd *
|
||||
rift_hmd(struct xrt_device *xdev)
|
||||
{
|
||||
return (struct rift_hmd *)xdev;
|
||||
}
|
||||
|
||||
DEBUG_GET_ONCE_LOG_OPTION(rift_log, "RIFT_LOG", U_LOGGING_WARN)
|
||||
|
||||
#define HMD_TRACE(hmd, ...) U_LOG_XDEV_IFL_T(&hmd->base, hmd->log_level, __VA_ARGS__)
|
||||
@@ -96,8 +92,7 @@ rift_send_keepalive(struct rift_hmd *hmd)
|
||||
struct dk2_report_keepalive_mux report = {0, IN_REPORT_DK2,
|
||||
KEEPALIVE_INTERVAL_NS / 1000000}; // convert ns to ms
|
||||
|
||||
int result =
|
||||
rift_send_report(hmd, FEATURE_REPORT_KEEPALIVE_MUX, &report, sizeof(report));
|
||||
int result = rift_send_report(hmd, FEATURE_REPORT_KEEPALIVE_MUX, &report, sizeof(report));
|
||||
|
||||
if (result < 0) {
|
||||
return result;
|
||||
@@ -236,18 +231,15 @@ rift_hmd_get_view_poses(struct xrt_device *xdev,
|
||||
struct xrt_fov *out_fovs,
|
||||
struct xrt_pose *out_poses)
|
||||
{
|
||||
/*
|
||||
* For HMDs you can call this function or directly set
|
||||
* the `get_view_poses` function on the device to it.
|
||||
*/
|
||||
return u_device_get_view_poses( //
|
||||
xdev, //
|
||||
default_eye_relation, //
|
||||
at_timestamp_ns, //
|
||||
view_count, //
|
||||
out_head_relation, //
|
||||
out_fovs, //
|
||||
out_poses); //
|
||||
struct rift_hmd *hmd = rift_hmd(xdev);
|
||||
|
||||
return u_device_get_view_poses(xdev, //
|
||||
&(struct xrt_vec3){hmd->extra_display_info.icd, 0.0f, 0.0f}, //
|
||||
at_timestamp_ns, //
|
||||
view_count, //
|
||||
out_head_relation, //
|
||||
out_fovs, //
|
||||
out_poses);
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
@@ -261,129 +253,6 @@ rift_hmd_get_visibility_mask(struct xrt_device *xdev,
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static float
|
||||
rift_catmull_rom_spline(struct rift_catmull_rom_distortion_data *catmull, float scaled_value)
|
||||
{
|
||||
float scaled_value_floor = floorf(scaled_value);
|
||||
scaled_value_floor = CLAMP(scaled_value_floor, 0, CATMULL_COEFFICIENTS - 1);
|
||||
|
||||
float t = scaled_value - scaled_value_floor;
|
||||
int k = (int)scaled_value_floor;
|
||||
|
||||
float p0, p1, m0, m1;
|
||||
switch (k) {
|
||||
case 0:
|
||||
p0 = 1.0f;
|
||||
m0 = (catmull->k[1] - catmull->k[0]);
|
||||
p1 = catmull->k[1];
|
||||
m1 = 0.5f * (catmull->k[2] - catmull->k[0]);
|
||||
break;
|
||||
default:
|
||||
p0 = catmull->k[k];
|
||||
m0 = 0.5f * (catmull->k[k + 1] - catmull->k[k - 1]);
|
||||
p1 = catmull->k[k + 1];
|
||||
m1 = 0.5f * (catmull->k[k + 2] - catmull->k[k]);
|
||||
break;
|
||||
case CATMULL_COEFFICIENTS - 2:
|
||||
p0 = catmull->k[CATMULL_COEFFICIENTS - 2];
|
||||
m0 = 0.5f * (catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2]);
|
||||
p1 = catmull->k[CATMULL_COEFFICIENTS - 1];
|
||||
m1 = catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2];
|
||||
break;
|
||||
case CATMULL_COEFFICIENTS - 1:
|
||||
p0 = catmull->k[CATMULL_COEFFICIENTS - 1];
|
||||
m0 = catmull->k[CATMULL_COEFFICIENTS - 1] - catmull->k[CATMULL_COEFFICIENTS - 2];
|
||||
p1 = p0 + m0;
|
||||
m1 = m0;
|
||||
break;
|
||||
}
|
||||
|
||||
float omt = 1.0f - t;
|
||||
|
||||
float res = (p0 * (1.0f + 2.0f * t) + m0 * t) * omt * omt + (p1 * (1.0f + 2.0f * omt) - m1 * omt) * t * t;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static float
|
||||
rift_distortion_distance_squared(struct rift_lens_distortion *lens_distortion, float distance_squared)
|
||||
{
|
||||
float scale = 1.0f;
|
||||
|
||||
switch (lens_distortion->distortion_version) {
|
||||
case RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1: {
|
||||
struct rift_catmull_rom_distortion_data data = lens_distortion->data.lcsv_catmull_rom_10;
|
||||
|
||||
float scaled_distance_squared =
|
||||
(float)(CATMULL_COEFFICIENTS - 1) * distance_squared / (data.max_r * data.max_r);
|
||||
|
||||
return rift_catmull_rom_spline(&data, scaled_distance_squared);
|
||||
}
|
||||
default: return scale;
|
||||
}
|
||||
}
|
||||
|
||||
static struct xrt_vec3
|
||||
rift_distortion_distance_squared_split_chroma(struct rift_lens_distortion *lens_distortion, float distance_squared)
|
||||
{
|
||||
float scale = rift_distortion_distance_squared(lens_distortion, distance_squared);
|
||||
|
||||
struct xrt_vec3 scale_split;
|
||||
scale_split.x = scale;
|
||||
scale_split.y = scale;
|
||||
scale_split.z = scale;
|
||||
|
||||
switch (lens_distortion->distortion_version) {
|
||||
case RIFT_LENS_DISTORTION_LCSV_CATMULL_ROM_10_VERSION_1: {
|
||||
struct rift_catmull_rom_distortion_data data = lens_distortion->data.lcsv_catmull_rom_10;
|
||||
|
||||
scale_split.x *= 1.0f + data.chromatic_abberation[0] + distance_squared * data.chromatic_abberation[1];
|
||||
scale_split.z *= 1.0f + data.chromatic_abberation[2] + distance_squared * data.chromatic_abberation[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return scale_split;
|
||||
}
|
||||
|
||||
static bool
|
||||
rift_hmd_compute_distortion(struct xrt_device *dev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result)
|
||||
{
|
||||
#define ZERO_ONE_TO_N_ONE_ONE(x) ((x * 2) - 1)
|
||||
#define N_ONE_ONE_TO_ZERO_ONE(x) ((x + 1) / 2)
|
||||
|
||||
struct rift_hmd *hmd = rift_hmd(dev);
|
||||
|
||||
struct rift_lens_distortion *distortion = &hmd->lens_distortions[0];
|
||||
|
||||
float display_width_meters = (float)hmd->display_info.display_width / 1000000.0f;
|
||||
float display_height_meters = (float)hmd->display_info.display_height / 1000000.0f;
|
||||
|
||||
float tan_eye_angle_scale_x =
|
||||
display_width_meters / distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center * 0.25f;
|
||||
float tan_eye_angle_scale_y =
|
||||
display_height_meters / distortion->data.lcsv_catmull_rom_10.meters_per_tan_angle_at_center * 0.5f;
|
||||
|
||||
u = ZERO_ONE_TO_N_ONE_ONE(u) * tan_eye_angle_scale_x;
|
||||
v = ZERO_ONE_TO_N_ONE_ONE(v) * tan_eye_angle_scale_y;
|
||||
|
||||
float distance_squared = fabsf(u * u + v * v);
|
||||
|
||||
struct xrt_vec3 chroma_distortions =
|
||||
rift_distortion_distance_squared_split_chroma(distortion, distance_squared);
|
||||
|
||||
out_result->r = (struct xrt_vec2){N_ONE_ONE_TO_ZERO_ONE(u * chroma_distortions.x),
|
||||
N_ONE_ONE_TO_ZERO_ONE(v * chroma_distortions.x)};
|
||||
out_result->g = (struct xrt_vec2){N_ONE_ONE_TO_ZERO_ONE(u * chroma_distortions.y),
|
||||
N_ONE_ONE_TO_ZERO_ONE(v * chroma_distortions.y)};
|
||||
out_result->b = (struct xrt_vec2){N_ONE_ONE_TO_ZERO_ONE(u * chroma_distortions.z),
|
||||
N_ONE_ONE_TO_ZERO_ONE(v * chroma_distortions.z)};
|
||||
|
||||
return true;
|
||||
#undef ZERO_ONE_TO_N_ONE_ONE
|
||||
#undef N_ONE_ONE_TO_ZERO_ONE
|
||||
}
|
||||
|
||||
static float
|
||||
rift_decode_fixed_point_uint16(uint16_t value, uint16_t zero_value, int fractional_bits)
|
||||
{
|
||||
@@ -403,6 +272,8 @@ rift_parse_distortion_report(struct rift_lens_distortion_report *report, struct
|
||||
struct rift_catmull_rom_distortion_report_data report_data = report->data.lcsv_catmull_rom_10;
|
||||
struct rift_catmull_rom_distortion_data data;
|
||||
|
||||
out->eye_relief = MICROMETERS_TO_METERS(report_data.eye_relief);
|
||||
|
||||
for (uint16_t i = 0; i < CATMULL_COEFFICIENTS; i += 1) {
|
||||
data.k[i] = rift_decode_fixed_point_uint16(report_data.k[i], 0, 14);
|
||||
}
|
||||
@@ -614,30 +485,56 @@ rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *devi
|
||||
}
|
||||
HMD_INFO(hmd, "After writing, HMD has config flags: %X", hmd->config.config_flags);
|
||||
|
||||
// get the lens distortions
|
||||
struct rift_lens_distortion_report lens_distortion;
|
||||
result = rift_get_lens_distortion(hmd, &lens_distortion);
|
||||
if (result < 0) {
|
||||
HMD_ERROR(hmd, "Failed to get lens distortion, reason %d", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hmd->num_lens_distortions = lens_distortion.num_distortions;
|
||||
hmd->lens_distortions = calloc(lens_distortion.num_distortions, sizeof(struct rift_lens_distortion));
|
||||
|
||||
rift_parse_distortion_report(&lens_distortion, &hmd->lens_distortions[lens_distortion.distortion_idx]);
|
||||
// TODO: actually verify we initialize all the distortions. if the headset is working correctly, this should
|
||||
// have happened, but you never know.
|
||||
for (uint16_t i = 1; i < hmd->num_lens_distortions; i++) {
|
||||
if (getenv("RIFT_USE_FIRMWARE_DISTORTION") != NULL) {
|
||||
// get the lens distortions
|
||||
struct rift_lens_distortion_report lens_distortion;
|
||||
result = rift_get_lens_distortion(hmd, &lens_distortion);
|
||||
if (result < 0) {
|
||||
HMD_ERROR(hmd, "Failed to get lens distortion idx %d, reason %d", i, result);
|
||||
HMD_ERROR(hmd, "Failed to get lens distortion, reason %d", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hmd->num_lens_distortions = lens_distortion.num_distortions;
|
||||
hmd->lens_distortions = calloc(lens_distortion.num_distortions, sizeof(struct rift_lens_distortion));
|
||||
|
||||
rift_parse_distortion_report(&lens_distortion, &hmd->lens_distortions[lens_distortion.distortion_idx]);
|
||||
// TODO: actually verify we initialize all the distortions. if the headset is working correctly, this
|
||||
// should have happened, but you never know.
|
||||
for (uint16_t i = 1; i < hmd->num_lens_distortions; i++) {
|
||||
result = rift_get_lens_distortion(hmd, &lens_distortion);
|
||||
if (result < 0) {
|
||||
HMD_ERROR(hmd, "Failed to get lens distortion idx %d, reason %d", i, result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
rift_parse_distortion_report(&lens_distortion,
|
||||
&hmd->lens_distortions[lens_distortion.distortion_idx]);
|
||||
}
|
||||
|
||||
// TODO: pick the correct distortion for the eye relief setting the user has picked
|
||||
hmd->distortion_in_use = 0;
|
||||
} else {
|
||||
rift_fill_in_default_distortions(hmd);
|
||||
}
|
||||
|
||||
// fill in extra display info about the headset
|
||||
|
||||
switch (hmd->variant) {
|
||||
case RIFT_VARIANT_DK2:
|
||||
hmd->extra_display_info.screen_gap_meters = 0.0f;
|
||||
hmd->extra_display_info.lens_diameter_meters = 0.04f;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// hardcode left eye, probably not ideal, but sure, why not
|
||||
struct rift_distortion_render_info distortion_render_info = rift_get_distortion_render_info(hmd, 0);
|
||||
hmd->extra_display_info.fov = rift_calculate_fov_from_hmd(hmd, &distortion_render_info, 0);
|
||||
hmd->extra_display_info.eye_to_source_ndc =
|
||||
rift_calculate_ndc_scale_and_offset_from_fov(&hmd->extra_display_info.fov);
|
||||
hmd->extra_display_info.eye_to_source_uv =
|
||||
rift_calculate_uv_scale_and_offset_from_ndc_scale_and_offset(hmd->extra_display_info.eye_to_source_ndc);
|
||||
|
||||
// This list should be ordered, most preferred first.
|
||||
size_t idx = 0;
|
||||
hmd->base.hmd->blend_modes[idx++] = XRT_BLEND_MODE_OPAQUE;
|
||||
@@ -674,24 +571,40 @@ rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *devi
|
||||
struct u_device_simple_info info;
|
||||
info.display.w_pixels = hmd->display_info.resolution_x;
|
||||
info.display.h_pixels = hmd->display_info.resolution_y;
|
||||
info.display.w_meters = (float)hmd->display_info.display_width / 1000000.0f; // micrometers -> meters
|
||||
info.display.h_meters = (float)hmd->display_info.display_height / 1000000.0f;
|
||||
info.display.w_meters = MICROMETERS_TO_METERS(hmd->display_info.display_width);
|
||||
info.display.h_meters = MICROMETERS_TO_METERS(hmd->display_info.display_height);
|
||||
|
||||
info.lens_horizontal_separation_meters = (float)hmd->display_info.lens_separation / 1000000.0f;
|
||||
info.lens_horizontal_separation_meters = MICROMETERS_TO_METERS(hmd->display_info.lens_separation);
|
||||
info.lens_vertical_position_meters = MICROMETERS_TO_METERS(hmd->display_info.center_v);
|
||||
|
||||
// TODO: this is per eye on the headset, but we're just taking the left eye for this, we should be using both
|
||||
// eyes, ideally
|
||||
info.lens_vertical_position_meters = (float)hmd->display_info.lens_distance_l / 1000000.0f;
|
||||
hmd->extra_display_info.icd = info.lens_horizontal_separation_meters;
|
||||
|
||||
// TODO: calculate this
|
||||
info.fov[0] = (float)(93.0 * (M_PI / 180.0));
|
||||
info.fov[1] = (float)(99.0 * (M_PI / 180.0));
|
||||
for (int i = 0; i < 2; i++) {
|
||||
info.fov[i] = 93;
|
||||
}
|
||||
|
||||
if (!u_device_setup_split_side_by_side(&hmd->base, &info)) {
|
||||
HMD_ERROR(hmd, "Failed to setup basic device info");
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (hmd->variant) {
|
||||
case RIFT_VARIANT_DK2:
|
||||
// TODO: figure out how to calculate this programatically, right now this is hardcoded with data dumped
|
||||
// from oculus' OpenXR runtime
|
||||
hmd->base.hmd->distortion.fov[0].angle_up = 0.92667186;
|
||||
hmd->base.hmd->distortion.fov[0].angle_down = -0.92667186;
|
||||
hmd->base.hmd->distortion.fov[0].angle_left = -0.8138836;
|
||||
hmd->base.hmd->distortion.fov[0].angle_right = 0.82951474;
|
||||
|
||||
hmd->base.hmd->distortion.fov[1].angle_up = 0.92667186;
|
||||
hmd->base.hmd->distortion.fov[1].angle_down = -0.92667186;
|
||||
hmd->base.hmd->distortion.fov[1].angle_left = -0.82951474;
|
||||
hmd->base.hmd->distortion.fov[1].angle_right = 0.8138836;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Just put an initial identity value in the tracker
|
||||
struct xrt_space_relation identity = XRT_SPACE_RELATION_ZERO;
|
||||
identity.relation_flags = (enum xrt_space_relation_flags)(XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT |
|
||||
@@ -718,6 +631,7 @@ rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *devi
|
||||
// Setup variable tracker: Optional but useful for debugging
|
||||
u_var_add_root(hmd, "Rift HMD", true);
|
||||
u_var_add_log_level(hmd, &hmd->log_level, "log_level");
|
||||
m_imu_3dof_add_vars(&hmd->fusion, hmd, "3dof_");
|
||||
|
||||
return hmd;
|
||||
error:
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "util/u_logging.h"
|
||||
|
||||
#include "math/m_imu_3dof.h"
|
||||
#include "math/m_api.h"
|
||||
#include "math/m_mathinclude.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -28,11 +30,19 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define REPORT_MAX_SIZE 69 // max size of a feature report (FEATURE_REPORT_CALIBRATE)
|
||||
#define REPORT_MAX_SIZE 69 // max size of a feature report (FEATURE_REPORT_CALIBRATE)
|
||||
#define KEEPALIVE_INTERVAL_NS 10000000000 // 10 seconds
|
||||
#define KEEPALIVE_SEND_RATE_NS (KEEPALIVE_INTERVAL_NS * 19) / 20 // give a 5% breathing room (at 10 seconds, this is 500 milliseconds of breathing room)
|
||||
#define KEEPALIVE_SEND_RATE_NS \
|
||||
(KEEPALIVE_INTERVAL_NS * 19) / \
|
||||
20 // give a 5% breathing room (at 10 seconds, this is 500 milliseconds of breathing room)
|
||||
#define IMU_SAMPLE_RATE 1000
|
||||
|
||||
#define DEG_TO_RAD(DEG) (DEG * M_PI / 180.0)
|
||||
#define MICROMETERS_TO_METERS(microns) (float)microns / 1000000.0f
|
||||
|
||||
// value taken from LibOVR 0.4.4
|
||||
#define DEFAULT_EXTRA_EYE_ROTATION DEG_TO_RAD(30.0f)
|
||||
|
||||
enum rift_feature_reports
|
||||
{
|
||||
// DK1
|
||||
@@ -148,8 +158,7 @@ struct rift_display_info_report
|
||||
uint32_t center_v;
|
||||
// the separation between the two lenses, in micrometers
|
||||
uint32_t lens_separation;
|
||||
uint32_t lens_distance_l;
|
||||
uint32_t lens_distance_r;
|
||||
uint32_t lens_distance[2];
|
||||
float distortion[6];
|
||||
} RIFT_PACKED;
|
||||
|
||||
@@ -239,12 +248,44 @@ struct rift_lens_distortion
|
||||
{
|
||||
// the version of the lens distortion data
|
||||
uint16_t distortion_version;
|
||||
// eye relief setting, in meters from surface of lens
|
||||
float eye_relief;
|
||||
|
||||
union {
|
||||
struct rift_catmull_rom_distortion_data lcsv_catmull_rom_10;
|
||||
} RIFT_PACKED data;
|
||||
};
|
||||
|
||||
struct rift_scale_and_offset
|
||||
{
|
||||
struct xrt_vec2 scale;
|
||||
struct xrt_vec2 offset;
|
||||
};
|
||||
|
||||
struct rift_viewport_fov_tan
|
||||
{
|
||||
float up_tan;
|
||||
float down_tan;
|
||||
float left_tan;
|
||||
float right_tan;
|
||||
};
|
||||
|
||||
struct rift_extra_display_info
|
||||
{
|
||||
// gap left between the two eyes
|
||||
float screen_gap_meters;
|
||||
// the diameter of the lenses, may need to be extended to an array
|
||||
float lens_diameter_meters;
|
||||
// ipd of the headset
|
||||
float icd;
|
||||
|
||||
// the fov of the headset
|
||||
struct rift_viewport_fov_tan fov;
|
||||
// mapping from tan-angle space to target NDC space
|
||||
struct rift_scale_and_offset eye_to_source_ndc;
|
||||
struct rift_scale_and_offset eye_to_source_uv;
|
||||
};
|
||||
|
||||
enum rift_variant
|
||||
{
|
||||
RIFT_VARIANT_DK1,
|
||||
@@ -296,8 +337,18 @@ struct rift_hmd
|
||||
|
||||
struct rift_lens_distortion *lens_distortions;
|
||||
uint16_t num_lens_distortions;
|
||||
uint16_t distortion_in_use;
|
||||
|
||||
struct rift_extra_display_info extra_display_info;
|
||||
};
|
||||
|
||||
/// Casting helper function
|
||||
static inline struct rift_hmd *
|
||||
rift_hmd(struct xrt_device *xdev)
|
||||
{
|
||||
return (struct rift_hmd *)xdev;
|
||||
}
|
||||
|
||||
struct rift_hmd *
|
||||
rift_hmd_create(struct os_hid_device *dev, enum rift_variant variant, char *device_name, char *serial_number);
|
||||
|
||||
|
||||
Reference in new issue
Block a user