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 *,
struct oxr_session *sess,
XrTime at_time,
struct xrt_space_relation *out_relation);
struct xrt_space_relation *out_relation,
struct xrt_device **out_xdev);
XrResult
oxr_session_locate_views(struct oxr_logger *log,
@ -710,11 +711,20 @@ oxr_space_locate(
XrResult
oxr_space_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
XrReferenceSpaceType space,
XrReferenceSpaceType baseSpc,
struct oxr_space *space,
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,
struct xrt_space_relation *out_relation);
bool
initial_head_relation_valid(struct oxr_session *sess);

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
oxr_session_get_view_relation_at(struct oxr_logger *log,
struct oxr_session *sess,
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
// 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);
m_relation_chain_resolve(&xrc, out_relation);
*out_xdev = xdev;
return oxr_session_success_result(sess);
}
@ -378,7 +385,7 @@ oxr_session_locate_views(struct oxr_logger *log,
const uint64_t xdisplay_time =
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_fov fovs[2] = {0};
struct xrt_pose poses[2] = {0};
@ -392,26 +399,16 @@ oxr_session_locate_views(struct oxr_logger *log,
fovs, //
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);
/*
* Get the pure_relation if needed.
*/
// 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); //
// transform head_relation into base_space
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);
// @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
@ -432,8 +429,8 @@ oxr_session_locate_views(struct oxr_logger *log,
struct xrt_space_relation result = {0};
struct xrt_relation_chain xrc = {0};
m_relation_chain_push_pose_if_not_identity(&xrc, &view_pose);
m_relation_chain_push_relation(&xrc, &pure_relation);
m_relation_chain_push_pose_if_not_identity(&xrc, &baseSpc->pose);
m_relation_chain_push_relation(&xrc, &base_spc_head_relation);
m_relation_chain_push_inverted_pose_if_not_identity(&xrc, &baseSpc->pose);
m_relation_chain_resolve(&xrc, &result);
union {
struct xrt_pose xrt;
@ -908,17 +905,17 @@ oxr_session_hand_joints(struct oxr_logger *log,
/*! @todo: testing, relating to view space unsupported
* 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;
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_pose_if_not_identity(&chain, tracking_origin_offset);
m_relation_chain_push_inverted_relation(&chain, &view_relation);
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) {
// action space

View file

@ -165,6 +165,90 @@ global_to_local_space(struct oxr_session *sess, struct xrt_space_relation *rel)
return true;
}
/*!
* Transform @view_relation given in global space into baseSpc without the app given offset pose for baseSpc
* applied.
*/
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,
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);
} else {
OXR_WARN_ONCE(log, "unsupported base reference space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
return XR_SUCCESS;
}
static XrResult
oxr_view_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
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);
}
static XrResult
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);
} else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
return XR_SUCCESS;
}
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;
} else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
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.
@ -172,71 +256,25 @@ global_to_local_space(struct oxr_session *sess, struct xrt_space_relation *rel)
XrResult
oxr_space_ref_relation(struct oxr_logger *log,
struct oxr_session *sess,
XrReferenceSpaceType space,
XrReferenceSpaceType baseSpc,
struct oxr_space *space,
struct oxr_space *baseSpc,
XrTime time,
struct xrt_space_relation *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 {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
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;
}
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 {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
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 == XR_REFERENCE_SPACE_TYPE_STAGE) {
if (baseSpc == XR_REFERENCE_SPACE_TYPE_LOCAL) {
math_pose_invert(&sess->initial_head_relation.pose, &out_relation->pose);
} else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
} else if (space == XR_REFERENCE_SPACE_TYPE_LOCAL) {
if (baseSpc == XR_REFERENCE_SPACE_TYPE_STAGE) {
out_relation->pose = sess->initial_head_relation.pose;
} else {
OXR_WARN_ONCE(log, "unsupported base space in space_ref_relation");
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
return XR_SUCCESS;
}
} 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 {
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
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
* given relations applied, assumes that only one is a action space.
* This returns only the relation between two space without the app given offset pose for baseSpc applied,
* assumes that only one is a action space.
*/
static XrResult
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
* any of the app given relations applied.
* the app given offset pose for baseSpc applied.
*/
static XrResult
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;
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)
if (!spc->is_reference && !baseSpc->is_reference) {