mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-21 06:01:43 +00:00
d/wmr: Add render distortion configuration
Take the parameters from the headset configuration and the existing render FoV, and use them to instantiate a distortion mesh. TODO: Reverse the distortion in order to calculate good FoV range that covers the full view for each headset.
This commit is contained in:
parent
f663727b07
commit
0cf7b4a9b3
|
@ -447,12 +447,64 @@ wmr_hmd_destroy(struct xrt_device *xdev)
|
|||
free(wh);
|
||||
}
|
||||
|
||||
static bool
|
||||
compute_distortion_wmr(struct xrt_device *xdev, int view, float u, float v, struct xrt_uv_triplet *result)
|
||||
{
|
||||
struct wmr_hmd *wh = wmr_hmd(xdev);
|
||||
|
||||
assert(view == 0 || view == 1);
|
||||
|
||||
const struct wmr_distortion_eye_config *ec = wh->config.eye_params + view;
|
||||
struct wmr_hmd_distortion_params *distortion_params = wh->distortion_params + view;
|
||||
|
||||
// Results r/g/b.
|
||||
struct xrt_vec2 tc[3];
|
||||
|
||||
// Dear compiler, please vectorize.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const struct wmr_distortion_3K *distortion3K = ec->distortion3K + i;
|
||||
|
||||
/* Scale the 0..1 input UV back to pixels relative to the distortion center,
|
||||
* accounting for the right eye starting at X = panel_width / 2.0 */
|
||||
struct xrt_vec2 pix_coord = {(u + 1.0 * view) * (ec->display_size.x / 2.0) - distortion3K->eye_center.x,
|
||||
v * ec->display_size.y - distortion3K->eye_center.y};
|
||||
|
||||
float r2 = m_vec2_dot(pix_coord, pix_coord);
|
||||
float k1 = distortion3K->k[0];
|
||||
float k2 = distortion3K->k[1];
|
||||
float k3 = distortion3K->k[2];
|
||||
|
||||
float d = 1.0 + r2 * (k1 + r2 * (k2 + r2 * k3));
|
||||
|
||||
/* Map the distorted pixel coordinate back to normalised view plane coords using the inverse affine
|
||||
* xform */
|
||||
struct xrt_vec3 p = {(pix_coord.x * d + distortion3K->eye_center.x),
|
||||
(pix_coord.y * d + distortion3K->eye_center.y), 1.0};
|
||||
struct xrt_vec3 vp;
|
||||
math_matrix_3x3_transform_vec3(&distortion_params->inv_affine_xform, &p, &vp);
|
||||
|
||||
/* Finally map back to the input texture 0..1 range based on the render FoV (from tex_N_range.x ..
|
||||
* tex_N_range.y) */
|
||||
tc[i].x = ((vp.x / vp.z) - distortion_params->tex_x_range.x) /
|
||||
(distortion_params->tex_x_range.y - distortion_params->tex_x_range.x);
|
||||
tc[i].y = ((vp.y / vp.z) - distortion_params->tex_y_range.x) /
|
||||
(distortion_params->tex_y_range.y - distortion_params->tex_y_range.x);
|
||||
}
|
||||
|
||||
result->r = tc[0];
|
||||
result->g = tc[1];
|
||||
result->b = tc[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct xrt_device *
|
||||
wmr_hmd_create(struct os_hid_device *hid_holo, struct os_hid_device *hid_ctrl, enum u_logging_level ll)
|
||||
{
|
||||
enum u_device_alloc_flags flags =
|
||||
(enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE);
|
||||
int ret = 0;
|
||||
int eye;
|
||||
|
||||
struct wmr_hmd *wh = U_DEVICE_ALLOCATE(struct wmr_hmd, flags, 1, 0);
|
||||
if (!wh) {
|
||||
|
@ -542,7 +594,19 @@ wmr_hmd_create(struct os_hid_device *hid_holo, struct os_hid_device *hid_ctrl, e
|
|||
u_var_add_log_level(wh, &wh->log_level, "log_level");
|
||||
|
||||
// Distortion information, fills in xdev->compute_distortion().
|
||||
u_distortion_mesh_set_none(&wh->base);
|
||||
for (eye = 0; eye < 2; eye++) {
|
||||
math_matrix_3x3_inverse(&wh->config.eye_params[eye].affine_xform,
|
||||
&wh->distortion_params[eye].inv_affine_xform);
|
||||
wh->distortion_params[eye].tex_x_range.x = tan(wh->base.hmd->views[eye].fov.angle_left);
|
||||
wh->distortion_params[eye].tex_x_range.y = tan(wh->base.hmd->views[eye].fov.angle_right);
|
||||
wh->distortion_params[eye].tex_y_range.x = tan(wh->base.hmd->views[eye].fov.angle_down);
|
||||
wh->distortion_params[eye].tex_y_range.y = tan(wh->base.hmd->views[eye].fov.angle_up);
|
||||
}
|
||||
|
||||
wh->base.hmd->distortion.models = XRT_DISTORTION_MODEL_COMPUTE;
|
||||
wh->base.hmd->distortion.preferred = XRT_DISTORTION_MODEL_COMPUTE;
|
||||
wh->base.compute_distortion = compute_distortion_wmr;
|
||||
u_distortion_mesh_fill_in_compute(&wh->base);
|
||||
|
||||
// Hand over hololens sensor device to reading thread.
|
||||
ret = os_thread_helper_start(&wh->oth, wmr_run_thread, wh);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "os/os_threading.h"
|
||||
#include "math/m_imu_3dof.h"
|
||||
#include "util/u_logging.h"
|
||||
#include "util/u_distortion_mesh.h"
|
||||
|
||||
#include "wmr_protocol.h"
|
||||
#include "wmr_config.h"
|
||||
|
@ -41,6 +42,18 @@ enum rvb_g1_status_bits
|
|||
// clang-format on
|
||||
};
|
||||
|
||||
struct wmr_hmd_distortion_params
|
||||
{
|
||||
/* Inverse affine transform to move from (undistorted) pixels
|
||||
* to image plane / normalised image coordinates
|
||||
*/
|
||||
struct xrt_matrix_3x3 inv_affine_xform;
|
||||
|
||||
/* tan(angle) FoV min/max for X and Y in the input texture */
|
||||
struct xrt_vec2 tex_x_range;
|
||||
struct xrt_vec2 tex_y_range;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @implements xrt_device
|
||||
*/
|
||||
|
@ -70,6 +83,9 @@ struct wmr_hmd
|
|||
//! Latest raw IPD value from the device.
|
||||
uint16_t raw_ipd;
|
||||
|
||||
/* Distortion related parameters */
|
||||
struct wmr_hmd_distortion_params distortion_params[2];
|
||||
|
||||
struct hololens_sensors_packet packet;
|
||||
|
||||
struct
|
||||
|
|
Loading…
Reference in a new issue