st/oxr: Rework composition of head relation for xrLocateViews

This commit is contained in:
Christoph Haag 2022-02-14 00:17:06 +01:00 committed by Jakob Bornecrantz
parent 9b656cde77
commit 9cd3b47f94
3 changed files with 137 additions and 92 deletions

View file

@ -649,7 +649,8 @@ XrResult
oxr_session_get_view_relation_at(struct oxr_logger *, oxr_session_get_view_relation_at(struct oxr_logger *,
struct oxr_session *sess, struct oxr_session *sess,
XrTime at_time, XrTime at_time,
struct xrt_space_relation *out_relation); struct xrt_space_relation *out_relation,
struct xrt_device **out_xdev);
XrResult XrResult
oxr_session_locate_views(struct oxr_logger *log, oxr_session_locate_views(struct oxr_logger *log,
@ -710,8 +711,17 @@ oxr_space_locate(
XrResult XrResult
oxr_space_ref_relation(struct oxr_logger *log, oxr_space_ref_relation(struct oxr_logger *log,
struct oxr_session *sess, struct oxr_session *sess,
XrReferenceSpaceType space, struct oxr_space *space,
XrReferenceSpaceType baseSpc, struct oxr_space *baseSpc,
XrTime time,
struct xrt_space_relation *out_relation);
XrResult
oxr_view_relation_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
struct xrt_space_relation *view_relation,
struct xrt_device *view_xdev,
struct oxr_space *baseSpc,
XrTime time, XrTime time,
struct xrt_space_relation *out_relation); struct xrt_space_relation *out_relation);

View file

@ -262,11 +262,16 @@ oxr_session_poll(struct oxr_logger *log, struct oxr_session *sess)
} }
} }
/**
* Gets the view relation in global space. Even though @out_xdev is returned, the tracking origin offset is already
* applied.
*/
XrResult XrResult
oxr_session_get_view_relation_at(struct oxr_logger *log, oxr_session_get_view_relation_at(struct oxr_logger *log,
struct oxr_session *sess, struct oxr_session *sess,
XrTime at_time, XrTime at_time,
struct xrt_space_relation *out_relation) struct xrt_space_relation *out_relation,
struct xrt_device **out_xdev)
{ {
// @todo This function needs to be massively expanded to support all // @todo This function needs to be massively expanded to support all
// use cases this drive. The main use of this function is to get // use cases this drive. The main use of this function is to get
@ -285,6 +290,8 @@ oxr_session_get_view_relation_at(struct oxr_logger *log,
oxr_xdev_get_relation_chain(log, sess->sys->inst, xdev, XRT_INPUT_GENERIC_HEAD_POSE, at_time, &xrc); oxr_xdev_get_relation_chain(log, sess->sys->inst, xdev, XRT_INPUT_GENERIC_HEAD_POSE, at_time, &xrc);
m_relation_chain_resolve(&xrc, out_relation); m_relation_chain_resolve(&xrc, out_relation);
*out_xdev = xdev;
return oxr_session_success_result(sess); return oxr_session_success_result(sess);
} }
@ -378,7 +385,7 @@ oxr_session_locate_views(struct oxr_logger *log,
const uint64_t xdisplay_time = const uint64_t xdisplay_time =
time_state_ts_to_monotonic_ns(sess->sys->inst->timekeeping, viewLocateInfo->displayTime); time_state_ts_to_monotonic_ns(sess->sys->inst->timekeeping, viewLocateInfo->displayTime);
//! @todo Head relation currently not used.
struct xrt_space_relation head_relation = XRT_SPACE_RELATION_ZERO; struct xrt_space_relation head_relation = XRT_SPACE_RELATION_ZERO;
struct xrt_fov fovs[2] = {0}; struct xrt_fov fovs[2] = {0};
struct xrt_pose poses[2] = {0}; struct xrt_pose poses[2] = {0};
@ -392,26 +399,16 @@ oxr_session_locate_views(struct oxr_logger *log,
fovs, // fovs, //
poses); poses);
// head_relation is in xdev space. Bring it into global space by applying tracking origin offset.
struct xrt_relation_chain xrc = {0};
m_relation_chain_push_relation(&xrc, &head_relation);
m_relation_chain_push_pose_if_not_identity(&xrc, &xdev->tracking_origin->offset);
m_relation_chain_resolve(&xrc, &head_relation);
/* // transform head_relation into base_space
* Get the pure_relation if needed. struct xrt_space_relation base_spc_head_relation;
*/ oxr_view_relation_ref_relation(log, sess, &head_relation, xdev, baseSpc, viewLocateInfo->displayTime,
&base_spc_head_relation);
// Get the viewLocateInfo->space to view space relation.
struct xrt_space_relation pure_relation;
/*!
* @todo Introduce oxr_space_ref_relation_with_relation that takes
* relation and transforms it into the correct relationship.
*/
// If we are going from stage space use the head pose.
oxr_space_ref_relation( //
log, //
sess, //
XR_REFERENCE_SPACE_TYPE_VIEW, //
baseSpc->type, //
viewLocateInfo->displayTime, //
&pure_relation); //
// @todo the fov information that we get from xdev->hmd->views[i].fov is // @todo the fov information that we get from xdev->hmd->views[i].fov is
// not properly filled out in oh_device.c, fix before wasting time // not properly filled out in oh_device.c, fix before wasting time
@ -432,8 +429,8 @@ oxr_session_locate_views(struct oxr_logger *log,
struct xrt_space_relation result = {0}; struct xrt_space_relation result = {0};
struct xrt_relation_chain xrc = {0}; struct xrt_relation_chain xrc = {0};
m_relation_chain_push_pose_if_not_identity(&xrc, &view_pose); m_relation_chain_push_pose_if_not_identity(&xrc, &view_pose);
m_relation_chain_push_relation(&xrc, &pure_relation); m_relation_chain_push_relation(&xrc, &base_spc_head_relation);
m_relation_chain_push_pose_if_not_identity(&xrc, &baseSpc->pose); m_relation_chain_push_inverted_pose_if_not_identity(&xrc, &baseSpc->pose);
m_relation_chain_resolve(&xrc, &result); m_relation_chain_resolve(&xrc, &result);
union { union {
struct xrt_pose xrt; struct xrt_pose xrt;
@ -908,17 +905,17 @@ oxr_session_hand_joints(struct oxr_logger *log,
/*! @todo: testing, relating to view space unsupported /*! @todo: testing, relating to view space unsupported
* in other parts of monado */ * in other parts of monado */
struct xrt_device *head_xdev = GET_XDEV_BY_ROLE(sess->sys, head); struct xrt_device *view_xdev = NULL;
struct xrt_space_relation view_relation; struct xrt_space_relation view_relation;
oxr_session_get_view_relation_at(log, sess, at_time, &view_relation); oxr_session_get_view_relation_at(log, sess, at_time, &view_relation, &view_xdev);
m_relation_chain_push_relation(&chain, &value.hand_pose); m_relation_chain_push_relation(&chain, &value.hand_pose);
m_relation_chain_push_pose_if_not_identity(&chain, tracking_origin_offset); m_relation_chain_push_pose_if_not_identity(&chain, tracking_origin_offset);
m_relation_chain_push_inverted_relation(&chain, &view_relation); m_relation_chain_push_inverted_relation(&chain, &view_relation);
m_relation_chain_push_inverted_pose_if_not_identity(&chain, m_relation_chain_push_inverted_pose_if_not_identity(&chain,
&head_xdev->tracking_origin->offset); &view_xdev->tracking_origin->offset);
} else if (!baseSpc->is_reference) { } else if (!baseSpc->is_reference) {
// action space // action space

View file

@ -166,77 +166,115 @@ global_to_local_space(struct oxr_session *sess, struct xrt_space_relation *rel)
} }
/*! /*!
* This returns only the relation between two spaces without any of the app * Transform @view_relation given in global space into baseSpc without the app given offset pose for baseSpc
* given relations applied, assumes that both spaces are reference spaces. * applied.
*/ */
XrResult XrResult
oxr_space_ref_relation(struct oxr_logger *log, oxr_view_relation_ref_relation(struct oxr_logger *log,
struct oxr_session *sess, struct oxr_session *sess,
XrReferenceSpaceType space, struct xrt_space_relation *view_relation,
XrReferenceSpaceType baseSpc, struct xrt_device *view_xdev,
struct oxr_space *baseSpc,
XrTime time, XrTime time,
struct xrt_space_relation *out_relation) struct xrt_space_relation *out_relation)
{ {
*out_relation = *view_relation;
//! @todo: find a central place to set up local space
if (!ensure_initial_head_relation(log, sess, out_relation)) {
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_STAGE) {
// device poses are already in stage = "global" space
} else if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_LOCAL) {
global_to_local_space(sess, out_relation);
} else if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_VIEW) {
// view relation in view space should be identity
m_space_relation_ident(out_relation); m_space_relation_ident(out_relation);
if (space == baseSpc) {
// m_space_relation_ident() sets to identity.
} else if (space == XR_REFERENCE_SPACE_TYPE_VIEW) {
oxr_session_get_view_relation_at(log, sess, time, out_relation);
if (!ensure_initial_head_relation(log, sess, out_relation)) {
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
if (baseSpc == XR_REFERENCE_SPACE_TYPE_STAGE) {
// device poses are already in stage = "global" space
} else if (baseSpc == XR_REFERENCE_SPACE_TYPE_LOCAL) {
global_to_local_space(sess, out_relation);
} else if (baseSpc == XR_REFERENCE_SPACE_TYPE_VIEW) {
} else { } else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation"); OXR_WARN_ONCE(log, "unsupported base reference space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE; out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS; return XR_SUCCESS;
} }
} else if (baseSpc == XR_REFERENCE_SPACE_TYPE_VIEW) {
oxr_session_get_view_relation_at(log, sess, time, out_relation);
if (!ensure_initial_head_relation(log, sess, out_relation)) {
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS; return XR_SUCCESS;
} }
if (space == XR_REFERENCE_SPACE_TYPE_STAGE) {
// device poses are already in stage = "global" space
} else if (space == XR_REFERENCE_SPACE_TYPE_LOCAL) {
global_to_local_space(sess, out_relation);
} else if (space == XR_REFERENCE_SPACE_TYPE_VIEW) {
} else { static XrResult
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation"); oxr_view_ref_relation(struct oxr_logger *log,
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE; struct oxr_session *sess,
return XR_SUCCESS; struct oxr_space *baseSpc,
XrTime time,
struct xrt_space_relation *out_relation)
{
struct xrt_device *view_xdev = NULL;
struct xrt_space_relation view_relation;
oxr_session_get_view_relation_at(log, sess, time, &view_relation, &view_xdev);
return oxr_view_relation_ref_relation(log, sess, &view_relation, view_xdev, baseSpc, time, out_relation);
} }
math_pose_invert(&out_relation->pose, &out_relation->pose);
} else if (space == XR_REFERENCE_SPACE_TYPE_STAGE) { static XrResult
if (baseSpc == XR_REFERENCE_SPACE_TYPE_LOCAL) { oxr_stage_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
struct oxr_space *baseSpc,
XrTime time,
struct xrt_space_relation *out_relation)
{
if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_LOCAL) {
math_pose_invert(&sess->initial_head_relation.pose, &out_relation->pose); math_pose_invert(&sess->initial_head_relation.pose, &out_relation->pose);
} else { } else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation"); OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE; out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS; return XR_SUCCESS;
} }
} else if (space == XR_REFERENCE_SPACE_TYPE_LOCAL) { return XR_SUCCESS;
if (baseSpc == XR_REFERENCE_SPACE_TYPE_STAGE) { }
static XrResult
oxr_locale_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
struct oxr_space *baseSpc,
XrTime time,
struct xrt_space_relation *out_relation)
{
if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_STAGE) {
out_relation->pose = sess->initial_head_relation.pose; out_relation->pose = sess->initial_head_relation.pose;
} else { } else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation"); OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE; out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS; return XR_SUCCESS;
} }
return XR_SUCCESS;
}
/*!
* This returns only the relation between two spaces without any of the app
* given relations applied, assumes that both spaces are reference spaces.
*/
XrResult
oxr_space_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
struct oxr_space *space,
struct oxr_space *baseSpc,
XrTime time,
struct xrt_space_relation *out_relation)
{
m_space_relation_ident(out_relation);
if (space->type == baseSpc->type) {
// m_space_relation_ident() already set this to identity.
} else if (space->type == XR_REFERENCE_SPACE_TYPE_VIEW) {
oxr_view_ref_relation(log, sess, baseSpc, time, out_relation);
} else if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_VIEW) {
oxr_view_ref_relation(log, sess, space, time, out_relation);
//! @todo invert complete relation
math_pose_invert(&out_relation->pose, &out_relation->pose);
} else if (space->type == XR_REFERENCE_SPACE_TYPE_STAGE) {
oxr_stage_ref_relation(log, sess, baseSpc, time, out_relation);
} else if (space->type == XR_REFERENCE_SPACE_TYPE_LOCAL) {
oxr_locale_ref_relation(log, sess, baseSpc, time, out_relation);
} else { } else {
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE; out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS; return XR_SUCCESS;
@ -257,8 +295,8 @@ remove_angular_and_linear_stuff(struct xrt_space_relation *out_relation)
} }
/*! /*!
* This returns only the relation between two spaces without any of the app * This returns only the relation between two space without the app given offset pose for baseSpc applied,
* given relations applied, assumes that only one is a action space. * assumes that only one is a action space.
*/ */
static XrResult static XrResult
oxr_space_action_relation(struct oxr_logger *log, oxr_space_action_relation(struct oxr_logger *log,
@ -327,7 +365,7 @@ oxr_space_action_relation(struct oxr_logger *log,
/*! /*!
* This returns only the relation between two directly-associated spaces without * This returns only the relation between two directly-associated spaces without
* any of the app given relations applied. * the app given offset pose for baseSpc applied.
*/ */
static XrResult static XrResult
get_pure_space_relation(struct oxr_logger *log, get_pure_space_relation(struct oxr_logger *log,
@ -339,7 +377,7 @@ get_pure_space_relation(struct oxr_logger *log,
struct oxr_session *sess = spc->sess; struct oxr_session *sess = spc->sess;
if (spc->is_reference && baseSpc->is_reference) { if (spc->is_reference && baseSpc->is_reference) {
return oxr_space_ref_relation(log, sess, spc->type, baseSpc->type, time, out_relation); return oxr_space_ref_relation(log, sess, spc, baseSpc, time, out_relation);
} }
/// @todo Deal with action to action by keeping a true_space that we can always go via. (poor mans space graph) /// @todo Deal with action to action by keeping a true_space that we can always go via. (poor mans space graph)
if (!spc->is_reference && !baseSpc->is_reference) { if (!spc->is_reference && !baseSpc->is_reference) {