2019-03-18 05:52:32 +00:00
|
|
|
// Copyright 2019, Collabora, Ltd.
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
|
|
|
* @brief So much space!
|
|
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
|
|
|
* @ingroup oxr_main
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "math/m_api.h"
|
|
|
|
#include "util/u_debug.h"
|
2019-03-21 20:19:52 +00:00
|
|
|
#include "util/u_misc.h"
|
2019-03-18 05:52:32 +00:00
|
|
|
|
|
|
|
#include "oxr_objects.h"
|
|
|
|
#include "oxr_logger.h"
|
2019-04-05 19:18:03 +00:00
|
|
|
#include "oxr_handle.h"
|
2019-03-18 05:52:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
DEBUG_GET_ONCE_BOOL_OPTION(space, "OXR_DEBUG_SPACE", false)
|
|
|
|
|
|
|
|
const struct xrt_pose origin = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}};
|
|
|
|
|
|
|
|
static XrResult
|
|
|
|
check_reference_space_type(struct oxr_logger *log, XrReferenceSpaceType type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case XR_REFERENCE_SPACE_TYPE_VIEW: return XR_SUCCESS;
|
|
|
|
case XR_REFERENCE_SPACE_TYPE_LOCAL: return XR_SUCCESS;
|
|
|
|
case XR_REFERENCE_SPACE_TYPE_STAGE: return XR_SUCCESS;
|
|
|
|
#if 0
|
|
|
|
return oxr_error(log, XR_ERROR_REFERENCE_SPACE_UNSUPPORTED,
|
|
|
|
"(createInfo->referenceSpaceType = "
|
|
|
|
"XR_REFERENCE_SPACE_TYPE_STAGE)");
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
return oxr_error(log, XR_ERROR_REFERENCE_SPACE_UNSUPPORTED,
|
|
|
|
"(createInfo->referenceSpaceType = "
|
|
|
|
"<UNKNOWN>)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-05 19:18:03 +00:00
|
|
|
static XrResult
|
|
|
|
oxr_space_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
|
|
|
|
{
|
|
|
|
struct oxr_space *spc = (struct oxr_space *)hb;
|
|
|
|
free(spc);
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-04-05 22:28:36 +00:00
|
|
|
XrResult
|
|
|
|
oxr_space_action_create(struct oxr_logger *log,
|
2019-07-13 16:17:57 +00:00
|
|
|
struct oxr_session *sess,
|
|
|
|
uint64_t key,
|
2019-04-05 22:28:36 +00:00
|
|
|
const XrActionSpaceCreateInfo *createInfo,
|
|
|
|
struct oxr_space **out_space)
|
|
|
|
{
|
2019-05-07 12:47:18 +00:00
|
|
|
struct oxr_instance *inst = sess->sys->inst;
|
|
|
|
struct oxr_sub_paths sub_paths = {0};
|
|
|
|
|
2019-04-05 22:28:36 +00:00
|
|
|
struct oxr_space *spc = NULL;
|
|
|
|
OXR_ALLOCATE_HANDLE_OR_RETURN(log, spc, OXR_XR_DEBUG_SPACE,
|
2019-07-13 16:17:57 +00:00
|
|
|
oxr_space_destroy, &sess->handle);
|
2019-04-05 22:28:36 +00:00
|
|
|
|
|
|
|
//! @todo implement more fully
|
|
|
|
oxr_warn(log, " not fully implemented");
|
|
|
|
|
2019-05-07 12:47:18 +00:00
|
|
|
oxr_classify_sub_action_paths(log, inst, 1, &createInfo->subactionPath,
|
|
|
|
&sub_paths);
|
|
|
|
|
2019-07-13 16:17:57 +00:00
|
|
|
spc->sess = sess;
|
2019-04-05 22:28:36 +00:00
|
|
|
spc->is_reference = false;
|
2019-05-07 12:47:18 +00:00
|
|
|
spc->sub_paths = sub_paths;
|
2019-07-13 16:17:57 +00:00
|
|
|
spc->act_key = key;
|
2019-04-05 22:28:36 +00:00
|
|
|
memcpy(&spc->pose, &createInfo->poseInActionSpace, sizeof(spc->pose));
|
|
|
|
|
|
|
|
*out_space = spc;
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-03-18 05:52:32 +00:00
|
|
|
XrResult
|
|
|
|
oxr_space_reference_create(struct oxr_logger *log,
|
|
|
|
struct oxr_session *sess,
|
|
|
|
const XrReferenceSpaceCreateInfo *createInfo,
|
|
|
|
struct oxr_space **out_space)
|
|
|
|
{
|
|
|
|
XrResult ret;
|
|
|
|
|
|
|
|
ret = check_reference_space_type(log, createInfo->referenceSpaceType);
|
|
|
|
if (ret != XR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!math_pose_validate(
|
|
|
|
(struct xrt_pose *)&createInfo->poseInReferenceSpace)) {
|
|
|
|
return oxr_error(log, XR_ERROR_POSE_INVALID,
|
|
|
|
"(createInfo->poseInReferenceSpace)");
|
|
|
|
}
|
|
|
|
|
2019-04-05 19:18:03 +00:00
|
|
|
struct oxr_space *spc = NULL;
|
|
|
|
OXR_ALLOCATE_HANDLE_OR_RETURN(log, spc, OXR_XR_DEBUG_SPACE,
|
|
|
|
oxr_space_destroy, &sess->handle);
|
2019-03-18 05:52:32 +00:00
|
|
|
spc->sess = sess;
|
|
|
|
spc->is_reference = true;
|
|
|
|
spc->type = createInfo->referenceSpaceType;
|
|
|
|
memcpy(&spc->pose, &createInfo->poseInReferenceSpace,
|
|
|
|
sizeof(spc->pose));
|
|
|
|
|
|
|
|
*out_space = spc;
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
get_ref_space_type_short_str(struct oxr_space *spc)
|
|
|
|
{
|
|
|
|
if (!spc->is_reference) {
|
2019-05-07 12:47:18 +00:00
|
|
|
return "action";
|
2019-03-18 05:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (spc->type) {
|
|
|
|
case XR_REFERENCE_SPACE_TYPE_VIEW: return "view";
|
|
|
|
case XR_REFERENCE_SPACE_TYPE_LOCAL: return "local";
|
|
|
|
case XR_REFERENCE_SPACE_TYPE_STAGE: return "stage";
|
|
|
|
default: return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* 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,
|
|
|
|
XrReferenceSpaceType space,
|
|
|
|
XrReferenceSpaceType baseSpc,
|
|
|
|
XrTime time,
|
|
|
|
struct xrt_space_relation *out_relation)
|
|
|
|
{
|
|
|
|
// Treat stage space as the local space.
|
|
|
|
if (space == XR_REFERENCE_SPACE_TYPE_STAGE) {
|
|
|
|
space = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Treat stage space as the local space.
|
|
|
|
if (baseSpc == XR_REFERENCE_SPACE_TYPE_STAGE) {
|
|
|
|
baseSpc = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
math_relation_reset(out_relation);
|
|
|
|
|
|
|
|
if (space == XR_REFERENCE_SPACE_TYPE_VIEW &&
|
|
|
|
baseSpc == XR_REFERENCE_SPACE_TYPE_LOCAL) {
|
|
|
|
oxr_session_get_view_pose_at(log, sess, time,
|
|
|
|
&out_relation->pose);
|
|
|
|
|
|
|
|
out_relation->relation_flags = (enum xrt_space_relation_flags)(
|
|
|
|
XRT_SPACE_RELATION_POSITION_VALID_BIT |
|
|
|
|
XRT_SPACE_RELATION_POSITION_TRACKED_BIT |
|
|
|
|
XRT_SPACE_RELATION_ORIENTATION_VALID_BIT |
|
|
|
|
XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT);
|
|
|
|
|
|
|
|
} else if (space == XR_REFERENCE_SPACE_TYPE_LOCAL &&
|
|
|
|
baseSpc == XR_REFERENCE_SPACE_TYPE_VIEW) {
|
|
|
|
oxr_session_get_view_pose_at(log, sess, time,
|
|
|
|
&out_relation->pose);
|
|
|
|
math_pose_invert(&out_relation->pose, &out_relation->pose);
|
|
|
|
|
|
|
|
out_relation->relation_flags = (enum xrt_space_relation_flags)(
|
|
|
|
XRT_SPACE_RELATION_POSITION_VALID_BIT |
|
|
|
|
XRT_SPACE_RELATION_POSITION_TRACKED_BIT |
|
|
|
|
XRT_SPACE_RELATION_ORIENTATION_VALID_BIT |
|
|
|
|
XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT);
|
|
|
|
|
|
|
|
} else if (space == baseSpc) {
|
|
|
|
// math_relation_reset() sets to identity.
|
|
|
|
|
|
|
|
} else {
|
2019-03-21 20:53:50 +00:00
|
|
|
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
|
2019-03-18 05:52:32 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-05-07 12:47:18 +00:00
|
|
|
/*!
|
|
|
|
* This returns only the relation between two spaces without any of the app
|
|
|
|
* given relations applied, assumes that only one is a action space.
|
|
|
|
*/
|
|
|
|
XrResult
|
|
|
|
oxr_space_action_relation(struct oxr_logger *log,
|
|
|
|
struct oxr_session *sess,
|
|
|
|
struct oxr_space *spc,
|
|
|
|
struct oxr_space *baseSpc,
|
|
|
|
XrTime time,
|
|
|
|
struct xrt_space_relation *out_relation)
|
|
|
|
{
|
|
|
|
struct oxr_source_input *input = NULL;
|
|
|
|
struct oxr_space *act_spc, *ref_spc = NULL;
|
|
|
|
int64_t timestamp = 0;
|
|
|
|
bool invert = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find the action space
|
|
|
|
if (baseSpc->is_reference) {
|
|
|
|
// Note spc, is assumed to be the action space.
|
|
|
|
act_spc = spc;
|
|
|
|
ref_spc = baseSpc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the action space.
|
|
|
|
if (spc->is_reference) {
|
|
|
|
// Note baseSpc, is assumed to be the action space.
|
|
|
|
act_spc = baseSpc;
|
|
|
|
ref_spc = spc;
|
|
|
|
invert = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Internal error check.
|
|
|
|
if (act_spc == NULL || act_spc->is_reference || ref_spc == NULL ||
|
|
|
|
!ref_spc->is_reference) {
|
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, "this is bad!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset so no relation is returned.
|
|
|
|
math_relation_reset(out_relation);
|
|
|
|
|
|
|
|
// We treat state and local space as the same.
|
|
|
|
//! @todo Can not relate to the view space right now.
|
|
|
|
if (baseSpc->type == XR_REFERENCE_SPACE_TYPE_VIEW) {
|
|
|
|
//! @todo Error code?
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
oxr_source_get_pose_input(log, sess, act_spc->act_key,
|
|
|
|
&act_spc->sub_paths, &input);
|
|
|
|
|
|
|
|
// If the input isn't active.
|
|
|
|
if (input == NULL) {
|
|
|
|
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
oxr_xdev_get_pose_at(log, sess->sys->inst, input->xdev,
|
|
|
|
input->input->name, &out_relation->pose,
|
|
|
|
×tamp);
|
|
|
|
|
|
|
|
out_relation->relation_flags = (enum xrt_space_relation_flags)(
|
|
|
|
XRT_SPACE_RELATION_POSITION_VALID_BIT |
|
|
|
|
XRT_SPACE_RELATION_POSITION_TRACKED_BIT |
|
|
|
|
XRT_SPACE_RELATION_ORIENTATION_VALID_BIT |
|
|
|
|
XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT);
|
|
|
|
|
|
|
|
if (invert) {
|
|
|
|
math_pose_invert(&out_relation->pose, &out_relation->pose);
|
|
|
|
}
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-03-18 05:52:32 +00:00
|
|
|
/*!
|
|
|
|
* This returns only the relation between two directly-associated spaces without
|
|
|
|
* any of the app given relations applied.
|
|
|
|
*/
|
|
|
|
static XrResult
|
|
|
|
get_pure_space_relation(struct oxr_logger *log,
|
|
|
|
struct oxr_space *spc,
|
|
|
|
struct oxr_space *baseSpc,
|
|
|
|
XrTime time,
|
|
|
|
struct xrt_space_relation *out_relation)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
} else if (!spc->is_reference && !baseSpc->is_reference) {
|
|
|
|
// @todo Deal with action to action by keeping a true_space that
|
|
|
|
// we can always go via. Aka poor mans space graph.
|
|
|
|
// WARNING order not thought through here!
|
|
|
|
// struct xrt_pose pose1;
|
|
|
|
// struct xrt_pose pose2;
|
|
|
|
// get_pure_space_relation(log, session->true_space, baseSpc,
|
|
|
|
// time, &pose1);
|
|
|
|
// get_pure_space_relation(log, space, session->true_space,
|
|
|
|
// time, &pose2);
|
|
|
|
// math_pose_relate_2(&pose1, &pose2, out_pose);
|
2019-03-21 20:53:50 +00:00
|
|
|
out_relation->relation_flags = XRT_SPACE_RELATION_BITMASK_NONE;
|
2019-03-18 05:52:32 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
} else {
|
2019-05-07 12:47:18 +00:00
|
|
|
oxr_space_action_relation(log, sess, spc, baseSpc, time,
|
|
|
|
out_relation);
|
2019-03-18 05:52:32 +00:00
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
print_pose(const char *prefix, struct xrt_pose *pose)
|
|
|
|
{
|
|
|
|
if (!debug_get_bool_option_space()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct xrt_vec3 *p = &pose->position;
|
|
|
|
struct xrt_quat *q = &pose->orientation;
|
|
|
|
|
|
|
|
fprintf(stderr, "%s (%f, %f, %f) (%f, %f, %f, %f)\n", prefix, p->x,
|
|
|
|
p->y, p->z, q->x, q->y, q->z, q->w);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
print_space(const char *name, struct oxr_space *spc)
|
|
|
|
{
|
|
|
|
if (!debug_get_bool_option_space()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *type_str = get_ref_space_type_short_str(spc);
|
|
|
|
fprintf(stderr, "\t%s->type %s\n\t%s->pose", name, type_str, name);
|
|
|
|
print_pose("", &spc->pose);
|
|
|
|
}
|
|
|
|
|
|
|
|
XrResult
|
|
|
|
oxr_space_locate(struct oxr_logger *log,
|
|
|
|
struct oxr_space *spc,
|
|
|
|
struct oxr_space *baseSpc,
|
|
|
|
XrTime time,
|
2019-07-13 16:17:57 +00:00
|
|
|
XrSpaceLocation *location)
|
2019-03-18 05:52:32 +00:00
|
|
|
{
|
|
|
|
if (debug_get_bool_option_space()) {
|
|
|
|
fprintf(stderr, "%s\n", __func__);
|
|
|
|
}
|
|
|
|
print_space("space", spc);
|
|
|
|
print_space("baseSpace", baseSpc);
|
|
|
|
|
|
|
|
// Get the pure space relation.
|
|
|
|
//! @todo for longer paths in "space graph" than one edge, this will be
|
|
|
|
//! a loop.
|
|
|
|
struct xrt_space_relation pure;
|
|
|
|
XrResult ret = get_pure_space_relation(log, spc, baseSpc, time, &pure);
|
|
|
|
if (ret != XR_SUCCESS) {
|
2019-07-13 16:17:57 +00:00
|
|
|
location->locationFlags = 0;
|
2019-03-18 05:52:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Combine space and base space poses with pure relation
|
|
|
|
struct xrt_space_relation result;
|
|
|
|
math_relation_openxr_locate(&spc->pose, &pure, &baseSpc->pose, &result);
|
|
|
|
|
|
|
|
// Copy
|
2019-07-13 16:17:57 +00:00
|
|
|
location->pose = *(XrPosef *)&result.pose;
|
|
|
|
location->locationFlags = result.relation_flags;
|
|
|
|
#if 0
|
|
|
|
location->linearVelocity = *(XrVector3f *)&result.linear_velocity;
|
|
|
|
location->angularVelocity = *(XrVector3f *)&result.angular_velocity;
|
|
|
|
location->linearAcceleration =
|
2019-03-18 05:52:32 +00:00
|
|
|
*(XrVector3f *)&result.linear_acceleration;
|
2019-07-13 16:17:57 +00:00
|
|
|
location->angularAcceleration =
|
2019-03-18 05:52:32 +00:00
|
|
|
*(XrVector3f *)&result.angular_acceleration;
|
2019-07-13 16:17:57 +00:00
|
|
|
#endif
|
2019-03-18 05:52:32 +00:00
|
|
|
|
2019-07-13 16:17:57 +00:00
|
|
|
print_pose("\trelation->pose", (struct xrt_pose *)&location->pose);
|
2019-03-18 05:52:32 +00:00
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|