xrt: Remove all but mesh distortion values from xrt_hmd_parts::distortion

Move vive values to struct u_vive_values in u_distortion_mesh.
Move openhmd values to private struct inside ohmd driver.
This commit is contained in:
Christoph Haag 2020-09-29 03:55:38 +02:00
parent c5209c5ed4
commit 29188d681c
8 changed files with 138 additions and 129 deletions

View file

@ -51,6 +51,26 @@ struct u_panotools_values
struct xrt_vec2 viewport_size;
};
/*!
* Values to create a distortion mesh from Vive configuration values.
*
* @ingroup aux_util
*/
struct u_vive_values
{
float aspect_x_over_y;
float grow_for_undistort;
//! Left/right
float undistort_r2_cutoff[2];
//! Left/right, x/y
float center[2][2];
//! left/right, r/g/b, a/b/c
float coefficients[2][3][3];
};
/*!
* Distortion correction implementation for Panotools distortion values.
*

View file

@ -31,7 +31,6 @@
#include "util/u_debug.h"
#include "util/u_device.h"
#include "util/u_time.h"
#include "util/u_distortion_mesh.h"
#include "oh_device.h"
@ -431,6 +430,8 @@ compute_distortion_openhmd(struct xrt_device *xdev,
float v,
struct xrt_vec2_triplet *result)
{
struct oh_device *ohd = oh_device(xdev);
struct xrt_hmd_parts *hmd = xdev->hmd;
struct xrt_vec2 lens_center = {
.x = hmd->views[view].lens_center.x_meters,
@ -442,9 +443,9 @@ compute_distortion_openhmd(struct xrt_device *xdev,
//! @todo: support distortion per view
return u_compute_distortion_openhmd(
hmd->distortion.openhmd.distortion_k,
hmd->distortion.openhmd.aberration_k,
hmd->distortion.openhmd.warp_scale, lens_center, viewport_size, u,
ohd->distortion.openhmd.distortion_k,
ohd->distortion.openhmd.aberration_k,
ohd->distortion.openhmd.warp_scale, lens_center, viewport_size, u,
v, result);
}
@ -455,13 +456,13 @@ compute_distortion_vive(struct xrt_device *xdev,
float v,
struct xrt_vec2_triplet *result)
{
struct xrt_hmd_parts *hmd = xdev->hmd;
struct oh_device *ohd = oh_device(xdev);
return u_compute_distortion_vive(
hmd->distortion.vive.aspect_x_over_y,
hmd->distortion.vive.grow_for_undistort,
hmd->distortion.vive.undistort_r2_cutoff[view],
hmd->distortion.vive.center[view],
hmd->distortion.vive.coefficients[view], u, v, result);
ohd->distortion.vive.aspect_x_over_y,
ohd->distortion.vive.grow_for_undistort,
ohd->distortion.vive.undistort_r2_cutoff[view],
ohd->distortion.vive.center[view],
ohd->distortion.vive.coefficients[view], u, v, result);
}
struct oh_device *
@ -524,14 +525,14 @@ oh_device_create(ohmd_context *ctx,
ohd->base.hmd->screens[0].w_pixels = info.display.w_pixels;
ohd->base.hmd->screens[0].h_pixels = info.display.h_pixels;
ohd->base.hmd->screens[0].nominal_frame_interval_ns = info.display.nominal_frame_interval_ns;
ohd->base.hmd->distortion.openhmd.distortion_k[0] = info.pano_distortion_k[0];
ohd->base.hmd->distortion.openhmd.distortion_k[1] = info.pano_distortion_k[1];
ohd->base.hmd->distortion.openhmd.distortion_k[2] = info.pano_distortion_k[2];
ohd->base.hmd->distortion.openhmd.distortion_k[3] = info.pano_distortion_k[3];
ohd->base.hmd->distortion.openhmd.aberration_k[0] = info.pano_aberration_k[0];
ohd->base.hmd->distortion.openhmd.aberration_k[1] = info.pano_aberration_k[1];
ohd->base.hmd->distortion.openhmd.aberration_k[2] = info.pano_aberration_k[2];
ohd->base.hmd->distortion.openhmd.warp_scale = info.pano_warp_scale;
ohd->distortion.openhmd.distortion_k[0] = info.pano_distortion_k[0];
ohd->distortion.openhmd.distortion_k[1] = info.pano_distortion_k[1];
ohd->distortion.openhmd.distortion_k[2] = info.pano_distortion_k[2];
ohd->distortion.openhmd.distortion_k[3] = info.pano_distortion_k[3];
ohd->distortion.openhmd.aberration_k[0] = info.pano_aberration_k[0];
ohd->distortion.openhmd.aberration_k[1] = info.pano_aberration_k[1];
ohd->distortion.openhmd.aberration_k[2] = info.pano_aberration_k[2];
ohd->distortion.openhmd.warp_scale = info.pano_warp_scale;
// Left
ohd->base.hmd->views[0].display.w_meters = info.views[0].display.w_meters;
@ -574,46 +575,46 @@ oh_device_create(ohmd_context *ctx,
if (info.quirks.video_distortion_vive) {
// clang-format off
// These need to be acquired from the vive config
ohd->base.hmd->distortion.vive.aspect_x_over_y = 0.8999999761581421f;
ohd->base.hmd->distortion.vive.grow_for_undistort = 0.6000000238418579f;
ohd->base.hmd->distortion.vive.undistort_r2_cutoff[0] = 1.11622154712677f;
ohd->base.hmd->distortion.vive.undistort_r2_cutoff[1] = 1.101870775222778f;
ohd->base.hmd->distortion.vive.center[0][0] = 0.08946027017045266f;
ohd->base.hmd->distortion.vive.center[0][1] = -0.009002181016260827f;
ohd->base.hmd->distortion.vive.center[1][0] = -0.08933516629552526f;
ohd->base.hmd->distortion.vive.center[1][1] = -0.006014565287238661f;
ohd->distortion.vive.aspect_x_over_y = 0.8999999761581421f;
ohd->distortion.vive.grow_for_undistort = 0.6000000238418579f;
ohd->distortion.vive.undistort_r2_cutoff[0] = 1.11622154712677f;
ohd->distortion.vive.undistort_r2_cutoff[1] = 1.101870775222778f;
ohd->distortion.vive.center[0][0] = 0.08946027017045266f;
ohd->distortion.vive.center[0][1] = -0.009002181016260827f;
ohd->distortion.vive.center[1][0] = -0.08933516629552526f;
ohd->distortion.vive.center[1][1] = -0.006014565287238661f;
// left
// green
ohd->base.hmd->distortion.vive.coefficients[0][0][0] = -0.188236068524731f;
ohd->base.hmd->distortion.vive.coefficients[0][0][1] = -0.221086205321053f;
ohd->base.hmd->distortion.vive.coefficients[0][0][2] = -0.2537849057915209f;
ohd->distortion.vive.coefficients[0][0][0] = -0.188236068524731f;
ohd->distortion.vive.coefficients[0][0][1] = -0.221086205321053f;
ohd->distortion.vive.coefficients[0][0][2] = -0.2537849057915209f;
// blue
ohd->base.hmd->distortion.vive.coefficients[0][1][0] = -0.07316590815739493f;
ohd->base.hmd->distortion.vive.coefficients[0][1][1] = -0.02332400789561968f;
ohd->base.hmd->distortion.vive.coefficients[0][1][2] = 0.02469959434698275f;
ohd->distortion.vive.coefficients[0][1][0] = -0.07316590815739493f;
ohd->distortion.vive.coefficients[0][1][1] = -0.02332400789561968f;
ohd->distortion.vive.coefficients[0][1][2] = 0.02469959434698275f;
// red
ohd->base.hmd->distortion.vive.coefficients[0][2][0] = -0.02223805567703767f;
ohd->base.hmd->distortion.vive.coefficients[0][2][1] = -0.04931309279533211f;
ohd->base.hmd->distortion.vive.coefficients[0][2][2] = -0.07862881939243466f;
ohd->distortion.vive.coefficients[0][2][0] = -0.02223805567703767f;
ohd->distortion.vive.coefficients[0][2][1] = -0.04931309279533211f;
ohd->distortion.vive.coefficients[0][2][2] = -0.07862881939243466f;
// right
// green
ohd->base.hmd->distortion.vive.coefficients[1][0][0] = -0.1906209981894497f;
ohd->base.hmd->distortion.vive.coefficients[1][0][1] = -0.2248896677207884f;
ohd->base.hmd->distortion.vive.coefficients[1][0][2] = -0.2721364516782803f;
ohd->distortion.vive.coefficients[1][0][0] = -0.1906209981894497f;
ohd->distortion.vive.coefficients[1][0][1] = -0.2248896677207884f;
ohd->distortion.vive.coefficients[1][0][2] = -0.2721364516782803f;
// blue
ohd->base.hmd->distortion.vive.coefficients[1][1][0] = -0.07346071902951497f;
ohd->base.hmd->distortion.vive.coefficients[1][1][1] = -0.02189527566250131f;
ohd->base.hmd->distortion.vive.coefficients[1][1][2] = 0.0581378652359256f;
ohd->distortion.vive.coefficients[1][1][0] = -0.07346071902951497f;
ohd->distortion.vive.coefficients[1][1][1] = -0.02189527566250131f;
ohd->distortion.vive.coefficients[1][1][2] = 0.0581378652359256f;
// red
ohd->base.hmd->distortion.vive.coefficients[1][2][0] = -0.01755850332081247f;
ohd->base.hmd->distortion.vive.coefficients[1][2][1] = -0.04517245633373419f;
ohd->base.hmd->distortion.vive.coefficients[1][2][2] = -0.0928909347763f;
ohd->distortion.vive.coefficients[1][2][0] = -0.01755850332081247f;
ohd->distortion.vive.coefficients[1][2][1] = -0.04517245633373419f;
ohd->distortion.vive.coefficients[1][2][2] = -0.0928909347763f;
// clang-format on
ohd->base.compute_distortion = compute_distortion_vive;
@ -626,7 +627,7 @@ oh_device_create(ohmd_context *ctx,
}
if (info.quirks.left_center_pano_scale) {
ohd->base.hmd->distortion.openhmd.warp_scale =
ohd->distortion.openhmd.warp_scale =
info.views[0].lens_center_x_meters;
}

View file

@ -12,6 +12,8 @@
#include "math/m_api.h"
#include "xrt/xrt_device.h"
#include "util/u_distortion_mesh.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -36,6 +38,20 @@ struct oh_device
bool print_spew;
bool print_debug;
bool enable_finite_difference;
struct
{
struct
{
//! Panotools universal distortion k.
float distortion_k[4];
//! Panotools post distortion scale, <r, g, b, _>.
float aberration_k[4];
//! Panotools warp scale.
float warp_scale;
} openhmd;
struct u_vive_values vive;
} distortion;
};
static inline struct oh_device *

View file

@ -163,6 +163,7 @@ struct survive_device
uint64_t curl_ts[FINGER_LAST];
} ctrl;
};
struct u_vive_values distortion;
};
//! @todo support more devices (trackers, ...)
@ -817,7 +818,7 @@ _json_get_int(const cJSON *json, const char *name)
}
static void
_get_color_coeffs(struct xrt_hmd_parts *hmd,
_get_color_coeffs(struct u_vive_values *values,
const cJSON *coeffs,
uint8_t eye,
uint8_t channel)
@ -829,7 +830,7 @@ _get_color_coeffs(struct xrt_hmd_parts *hmd,
size_t i = 0;
cJSON_ArrayForEach(item, coeffs)
{
hmd->distortion.vive.coefficients[eye][i][channel] =
values->coefficients[eye][i][channel] =
(float)item->valuedouble;
++i;
if (i == 3) {
@ -839,7 +840,7 @@ _get_color_coeffs(struct xrt_hmd_parts *hmd,
}
static void
_get_color_coeffs_lookup(struct xrt_hmd_parts *hmd,
_get_color_coeffs_lookup(struct u_vive_values *values,
const cJSON *eye_json,
const char *name,
uint8_t eye,
@ -857,7 +858,7 @@ _get_color_coeffs_lookup(struct xrt_hmd_parts *hmd,
return;
}
_get_color_coeffs(hmd, coeffs, eye, channel);
_get_color_coeffs(values, coeffs, eye, channel);
}
static void
@ -865,8 +866,6 @@ get_distortion_properties(struct survive_device *d,
const cJSON *eye_transform_json,
uint8_t eye)
{
struct xrt_hmd_parts *hmd = d->base.hmd;
const cJSON *eye_json = cJSON_GetArrayItem(eye_transform_json, eye);
if (eye_json == NULL) {
return;
@ -879,8 +878,8 @@ get_distortion_properties(struct survive_device *d,
// TODO: store grow_for_undistort per eye
// clang-format off
hmd->distortion.vive.grow_for_undistort = _json_get_float(eye_json, "grow_for_undistort");
hmd->distortion.vive.undistort_r2_cutoff[eye] = _json_get_float(eye_json, "undistort_r2_cutoff");
d->distortion.grow_for_undistort = _json_get_float(eye_json, "grow_for_undistort");
d->distortion.undistort_r2_cutoff[eye] = _json_get_float(eye_json, "undistort_r2_cutoff");
// clang-format on
const cJSON *distortion =
@ -888,20 +887,22 @@ get_distortion_properties(struct survive_device *d,
if (distortion != NULL) {
// TODO: store center per color
// clang-format off
hmd->distortion.vive.center[eye][0] = _json_get_float(distortion, "center_x");
hmd->distortion.vive.center[eye][1] = _json_get_float(distortion, "center_y");
d->distortion.center[eye][0] = _json_get_float(distortion, "center_x");
d->distortion.center[eye][1] = _json_get_float(distortion, "center_y");
// clang-format on
// green
const cJSON *coeffs =
cJSON_GetObjectItemCaseSensitive(distortion, "coeffs");
if (coeffs != NULL) {
_get_color_coeffs(hmd, coeffs, eye, 1);
_get_color_coeffs(&d->distortion, coeffs, eye, 1);
}
}
_get_color_coeffs_lookup(hmd, eye_json, "distortion_red", eye, 0);
_get_color_coeffs_lookup(hmd, eye_json, "distortion_blue", eye, 2);
_get_color_coeffs_lookup(&d->distortion, eye_json, "distortion_red",
eye, 0);
_get_color_coeffs_lookup(&d->distortion, eye_json, "distortion_blue",
eye, 2);
}
static bool
@ -911,13 +912,11 @@ compute_distortion(struct xrt_device *xdev,
float v,
struct xrt_vec2_triplet *result)
{
struct xrt_hmd_parts *hmd = xdev->hmd;
struct survive_device *d = (struct survive_device *)xdev;
return u_compute_distortion_vive(
hmd->distortion.vive.aspect_x_over_y,
hmd->distortion.vive.grow_for_undistort,
hmd->distortion.vive.undistort_r2_cutoff[view],
hmd->distortion.vive.center[view],
hmd->distortion.vive.coefficients[view], u, v, result);
d->distortion.aspect_x_over_y, d->distortion.grow_for_undistort,
d->distortion.undistort_r2_cutoff[view], d->distortion.center[view],
d->distortion.coefficients[view], u, v, result);
}
static bool
@ -998,11 +997,10 @@ _create_hmd_device(struct survive_system *sys, enum VIVE_VARIANT variant)
double fov = 2 * atan2(w_meters - lens_horizontal_separation / 2.0,
eye_to_screen_distance);
survive->base.hmd->distortion.vive.aspect_x_over_y =
0.89999997615814209f;
survive->base.hmd->distortion.vive.grow_for_undistort = 0.5f;
survive->base.hmd->distortion.vive.undistort_r2_cutoff[0] = 1.0f;
survive->base.hmd->distortion.vive.undistort_r2_cutoff[1] = 1.0f;
survive->distortion.aspect_x_over_y = 0.89999997615814209f;
survive->distortion.grow_for_undistort = 0.5f;
survive->distortion.undistort_r2_cutoff[0] = 1.0f;
survive->distortion.undistort_r2_cutoff[1] = 1.0f;
survive->hmd.rot[0].w = 1.0f;
survive->hmd.rot[1].w = 1.0f;
@ -1017,9 +1015,8 @@ _create_hmd_device(struct survive_system *sys, enum VIVE_VARIANT variant)
cJSON_GetObjectItemCaseSensitive(json, "device");
if (device_json) {
if (survive->variant != VIVE_VARIANT_VALVE_INDEX) {
survive->base.hmd->distortion.vive.aspect_x_over_y =
_json_get_float(device_json,
"physical_aspect_x_over_y");
survive->distortion.aspect_x_over_y = _json_get_float(
device_json, "physical_aspect_x_over_y");
//! @todo: fov calculation needs to be fixed, only works
//! with hardcoded value

View file

@ -12,6 +12,8 @@
#include "vive_config.h"
#include "util/u_json.h"
#include "util/u_distortion_mesh.h"
#include "math/m_api.h"
#include "vive.h"
@ -27,7 +29,7 @@
u_json_get_string_into_array(u_json_get(a, b), c, sizeof(c))
static void
_get_color_coeffs(struct xrt_hmd_parts *hmd,
_get_color_coeffs(struct u_vive_values *values,
const cJSON *coeffs,
uint8_t eye,
uint8_t channel)
@ -39,7 +41,7 @@ _get_color_coeffs(struct xrt_hmd_parts *hmd,
size_t i = 0;
cJSON_ArrayForEach(item, coeffs)
{
hmd->distortion.vive.coefficients[eye][i][channel] =
values->coefficients[eye][i][channel] =
(float)item->valuedouble;
++i;
if (i == 3) {
@ -49,7 +51,7 @@ _get_color_coeffs(struct xrt_hmd_parts *hmd,
}
static void
_get_color_coeffs_lookup(struct xrt_hmd_parts *hmd,
_get_color_coeffs_lookup(struct u_vive_values *values,
const cJSON *eye_json,
const char *name,
uint8_t eye,
@ -67,7 +69,7 @@ _get_color_coeffs_lookup(struct xrt_hmd_parts *hmd,
return;
}
_get_color_coeffs(hmd, coeffs, eye, channel);
_get_color_coeffs(values, coeffs, eye, channel);
}
static void
@ -86,8 +88,6 @@ _get_distortion_properties(struct vive_device *d,
const cJSON *eye_transform_json,
uint8_t eye)
{
struct xrt_hmd_parts *hmd = d->base.hmd;
const cJSON *eye_json = cJSON_GetArrayItem(eye_transform_json, eye);
if (eye_json == NULL) {
return;
@ -100,8 +100,8 @@ _get_distortion_properties(struct vive_device *d,
// TODO: store grow_for_undistort per eye
// clang-format off
JSON_FLOAT(eye_json, "grow_for_undistort", &hmd->distortion.vive.grow_for_undistort);
JSON_FLOAT(eye_json, "undistort_r2_cutoff", &hmd->distortion.vive.undistort_r2_cutoff[eye]);
JSON_FLOAT(eye_json, "grow_for_undistort", &d->distortion.grow_for_undistort);
JSON_FLOAT(eye_json, "undistort_r2_cutoff", &d->distortion.undistort_r2_cutoff[eye]);
// clang-format on
const cJSON *distortion =
@ -109,20 +109,22 @@ _get_distortion_properties(struct vive_device *d,
if (distortion != NULL) {
// TODO: store center per color
// clang-format off
JSON_FLOAT(eye_json, "center_x", &hmd->distortion.vive.center[eye][0]);
JSON_FLOAT(eye_json, "center_y", &hmd->distortion.vive.center[eye][1]);
JSON_FLOAT(eye_json, "center_x", &d->distortion.center[eye][0]);
JSON_FLOAT(eye_json, "center_y", &d->distortion.center[eye][1]);
// clang-format on
// green
const cJSON *coeffs =
cJSON_GetObjectItemCaseSensitive(distortion, "coeffs");
if (coeffs != NULL) {
_get_color_coeffs(hmd, coeffs, eye, 1);
_get_color_coeffs(&d->distortion, coeffs, eye, 1);
}
}
_get_color_coeffs_lookup(hmd, eye_json, "distortion_red", eye, 0);
_get_color_coeffs_lookup(hmd, eye_json, "distortion_blue", eye, 2);
_get_color_coeffs_lookup(&d->distortion, eye_json, "distortion_red",
eye, 0);
_get_color_coeffs_lookup(&d->distortion, eye_json, "distortion_blue",
eye, 2);
}
static void
@ -286,9 +288,8 @@ vive_config_parse(struct vive_device *d, char *json_string)
if (d->variant != VIVE_VARIANT_INDEX) {
JSON_DOUBLE(device_json, "persistence",
&d->display.persistence);
JSON_FLOAT(
device_json, "physical_aspect_x_over_y",
&d->base.hmd->distortion.vive.aspect_x_over_y);
JSON_FLOAT(device_json, "physical_aspect_x_over_y",
&d->distortion.aspect_x_over_y);
}
JSON_INT(device_json, "eye_target_height_in_pixels",
&d->display.eye_target_height_in_pixels);
@ -310,7 +311,7 @@ vive_config_parse(struct vive_device *d, char *json_string)
VIVE_DEBUG(d, "= Vive configuration =");
VIVE_DEBUG(d, "lens_separation: %f", d->display.lens_separation);
VIVE_DEBUG(d, "persistence: %f", d->display.persistence);
VIVE_DEBUG(d, "physical_aspect_x_over_y: %f", (double)d->base.hmd->distortion.vive.aspect_x_over_y);
VIVE_DEBUG(d, "physical_aspect_x_over_y: %f", (double)d->distortion.aspect_x_over_y);
VIVE_DEBUG(d, "model_number: %s", d->firmware.model_number);
VIVE_DEBUG(d, "mb_serial_number: %s", d->firmware.mb_serial_number);
@ -326,10 +327,10 @@ vive_config_parse(struct vive_device *d, char *json_string)
_print_vec3("gyro_scale", &d->imu.gyro_scale);
}
VIVE_DEBUG(d, "grow_for_undistort: %f", (double)d->base.hmd->distortion.vive.grow_for_undistort);
VIVE_DEBUG(d, "grow_for_undistort: %f", (double)d->distortion.grow_for_undistort);
VIVE_DEBUG(d, "undistort_r2_cutoff 0: %f", (double)d->base.hmd->distortion.vive.undistort_r2_cutoff[0]);
VIVE_DEBUG(d, "undistort_r2_cutoff 1: %f", (double)d->base.hmd->distortion.vive.undistort_r2_cutoff[1]);
VIVE_DEBUG(d, "undistort_r2_cutoff 0: %f", (double)d->distortion.undistort_r2_cutoff[0]);
VIVE_DEBUG(d, "undistort_r2_cutoff 1: %f", (double)d->distortion.undistort_r2_cutoff[1]);
// clang-format on
return true;

View file

@ -17,7 +17,6 @@
#include "util/u_debug.h"
#include "util/u_var.h"
#include "util/u_time.h"
#include "util/u_distortion_mesh.h"
#include "math/m_api.h"
@ -788,11 +787,10 @@ vive_init_defaults(struct vive_device *d)
d->rot_filtered.w = 1.0f;
struct xrt_hmd_parts *hmd = d->base.hmd;
hmd->distortion.vive.aspect_x_over_y = 0.89999997615814209f;
hmd->distortion.vive.grow_for_undistort = 0.5f;
hmd->distortion.vive.undistort_r2_cutoff[0] = 1.0f;
hmd->distortion.vive.undistort_r2_cutoff[1] = 1.0f;
d->distortion.aspect_x_over_y = 0.89999997615814209f;
d->distortion.grow_for_undistort = 0.5f;
d->distortion.undistort_r2_cutoff[0] = 1.0f;
d->distortion.undistort_r2_cutoff[1] = 1.0f;
}
@ -803,13 +801,11 @@ compute_distortion(struct xrt_device *xdev,
float v,
struct xrt_vec2_triplet *result)
{
struct xrt_hmd_parts *hmd = xdev->hmd;
struct vive_device *d = vive_device(xdev);
return u_compute_distortion_vive(
hmd->distortion.vive.aspect_x_over_y,
hmd->distortion.vive.grow_for_undistort,
hmd->distortion.vive.undistort_r2_cutoff[view],
hmd->distortion.vive.center[view],
hmd->distortion.vive.coefficients[view], u, v, result);
d->distortion.aspect_x_over_y, d->distortion.grow_for_undistort,
d->distortion.undistort_r2_cutoff[view], d->distortion.center[view],
d->distortion.coefficients[view], u, v, result);
}
struct vive_device *

View file

@ -13,6 +13,7 @@
#include "math/m_imu_3dof.h"
#include "os/os_threading.h"
#include "util/u_logging.h"
#include "util/u_distortion_mesh.h"
#include "vive_lighthouse.h"
@ -141,6 +142,8 @@ struct vive_device
bool calibration;
bool last;
} gui;
struct u_vive_values distortion;
};
struct vive_device *

View file

@ -127,31 +127,6 @@ struct xrt_hmd_parts
//! Preferred disortion model, single value.
enum xrt_distortion_model preferred;
struct
{
//! Panotools universal distortion k.
float distortion_k[4];
//! Panotools post distortion scale, <r, g, b, _>.
float aberration_k[4];
//! Panotools warp scale.
float warp_scale;
} openhmd;
struct
{
float aspect_x_over_y;
float grow_for_undistort;
//! Left/right
float undistort_r2_cutoff[2];
//! Left/right, x/y
float center[2][2];
//! left/right, r/g/b, a/b/c
float coefficients[2][3][3];
} vive;
struct
{
//! Data.