XR: Add dedicated handling/API for VR trackers
Allows for easier testing/debugging of tracker functionality by separating trackers from session controller data. Also, this should make it possible to use controllers and trackers during a VR session simultaneously.
This commit is contained in:
parent
b0825be786
commit
62cabfca87
|
@ -115,6 +115,8 @@ typedef enum eXrPoseFlag {
|
|||
/* Pose represents controller grip/aim. */
|
||||
XR_POSE_GRIP = (1 << 0),
|
||||
XR_POSE_AIM = (1 << 1),
|
||||
/* Pose represents VR tracker. */
|
||||
XR_POSE_TRACKER = (1 << 2),
|
||||
} eXrPoseFlag;
|
||||
|
||||
typedef enum eXrMotionCaptureFlag {
|
||||
|
|
|
@ -523,6 +523,29 @@ static void rna_XrActionMapItem_pose_is_controller_aim_set(PointerRNA *ptr, bool
|
|||
# endif
|
||||
}
|
||||
|
||||
static bool rna_XrActionMapItem_pose_is_tracker_get(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapItem *ami = ptr->data;
|
||||
if ((ami->pose_flag & XR_POSE_TRACKER) != 0) {
|
||||
return true;
|
||||
}
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
# endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rna_XrActionMapItem_pose_is_tracker_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapItem *ami = ptr->data;
|
||||
SET_FLAG_FROM_TEST(ami->pose_flag, value, XR_POSE_TRACKER);
|
||||
# else
|
||||
UNUSED_VARS(ptr, value);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMapItem_bindings_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -1048,6 +1071,32 @@ bool rna_XrSessionState_controller_pose_actions_set(bContext *C,
|
|||
# endif
|
||||
}
|
||||
|
||||
bool rna_XrSessionState_tracker_pose_action_add(bContext *C,
|
||||
const char *action_set_name,
|
||||
const char *tracker_action_name)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
return WM_xr_tracker_pose_action_add(&wm->xr, action_set_name, tracker_action_name);
|
||||
# else
|
||||
UNUSED_VARS(C, action_set_name, tracker_action_name);
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
bool rna_XrSessionState_tracker_pose_action_remove(bContext *C,
|
||||
const char *action_set_name,
|
||||
const char *tracker_action_name)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
return WM_xr_tracker_pose_action_remove(&wm->xr, action_set_name, tracker_action_name);
|
||||
# else
|
||||
UNUSED_VARS(C, action_set_name, tracker_action_name);
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
void rna_XrSessionState_action_state_get(bContext *C,
|
||||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
|
@ -1171,6 +1220,32 @@ static void rna_XrSessionState_controller_aim_rotation_get(bContext *C,
|
|||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrSessionState_tracker_location_get(bContext *C,
|
||||
const char *user_path,
|
||||
float r_values[3])
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
WM_xr_session_state_tracker_location_get(&wm->xr, user_path, r_values);
|
||||
# else
|
||||
UNUSED_VARS(C, user_path);
|
||||
zero_v3(r_values);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrSessionState_tracker_rotation_get(bContext *C,
|
||||
const char *user_path,
|
||||
float r_values[4])
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
WM_xr_session_state_tracker_rotation_get(&wm->xr, user_path, r_values);
|
||||
# else
|
||||
UNUSED_VARS(C, user_path);
|
||||
unit_qt(r_values);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float *r_values)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -1827,6 +1902,11 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(
|
||||
prop, "Is Controller Aim", "The action poses will be used for the VR controller aims");
|
||||
|
||||
prop = RNA_def_property(srna, "pose_is_tracker", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, "rna_XrActionMapItem_pose_is_tracker_get", "rna_XrActionMapItem_pose_is_tracker_set");
|
||||
RNA_def_property_ui_text(prop, "Is Tracker", "The action poses represent a VR tracker");
|
||||
|
||||
prop = RNA_def_property(srna, "haptic_name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Haptic Name", "Name of the haptic action to apply when executing this action");
|
||||
|
@ -2359,6 +2439,42 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
parm = RNA_def_boolean(func, "result", 0, "Result", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(
|
||||
srna, "tracker_pose_action_add", "rna_XrSessionState_tracker_pose_action_add");
|
||||
RNA_def_function_ui_description(func, "Add a VR tracker pose to the session");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func,
|
||||
"tracker_action",
|
||||
NULL,
|
||||
MAX_NAME,
|
||||
"Tracker Action",
|
||||
"Name of the action representing the VR tracker");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_boolean(func, "result", 0, "Result", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(
|
||||
srna, "tracker_pose_action_remove", "rna_XrSessionState_tracker_pose_action_remove");
|
||||
RNA_def_function_ui_description(func, "Remove a VR tracker pose from the session");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func,
|
||||
"tracker_action",
|
||||
NULL,
|
||||
MAX_NAME,
|
||||
"Tracker Action",
|
||||
"Name of the action representing the VR tracker");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_boolean(func, "result", 0, "Result", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "action_state_get", "rna_XrSessionState_action_state_get");
|
||||
RNA_def_function_ui_description(func, "Get the current state of a VR action");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
|
@ -2541,6 +2657,49 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
RNA_def_property_ui_range(parm, -FLT_MAX, FLT_MAX, 1, 5);
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT);
|
||||
|
||||
func = RNA_def_function(srna, "tracker_location_get", "rna_XrSessionState_tracker_location_get");
|
||||
RNA_def_function_ui_description(func, "Get the last known tracker location in world space");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(
|
||||
func, "user_path", NULL, XR_MAX_USER_PATH_LENGTH, "User Path", "OpenXR user path");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_float_translation(func,
|
||||
"location",
|
||||
3,
|
||||
NULL,
|
||||
-FLT_MAX,
|
||||
FLT_MAX,
|
||||
"Location",
|
||||
"Tracker location",
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT);
|
||||
|
||||
func = RNA_def_function(srna, "tracker_rotation_get", "rna_XrSessionState_tracker_rotation_get");
|
||||
RNA_def_function_ui_description(
|
||||
func, "Get the last known tracker rotation (quaternion) in world space");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(
|
||||
func, "user_path", NULL, XR_MAX_USER_PATH_LENGTH, "User Path", "OpenXR user path");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_float_vector(func,
|
||||
"rotation",
|
||||
4,
|
||||
NULL,
|
||||
-FLT_MAX,
|
||||
FLT_MAX,
|
||||
"Rotation",
|
||||
"Tracker quaternion rotation",
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
parm->subtype = PROP_QUATERNION;
|
||||
RNA_def_property_ui_range(parm, -FLT_MAX, FLT_MAX, 1, 5);
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT);
|
||||
|
||||
prop = RNA_def_property(srna, "viewer_pose_location", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_location_get", NULL, NULL);
|
||||
|
|
|
@ -1592,6 +1592,12 @@ bool WM_xr_session_state_controller_aim_location_get(const wmXrData *xr,
|
|||
bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr,
|
||||
unsigned int subaction_idx,
|
||||
float r_rotation[4]);
|
||||
bool WM_xr_session_state_tracker_location_get(const wmXrData *xr,
|
||||
const char *subaction_path,
|
||||
float r_location[3]);
|
||||
bool WM_xr_session_state_tracker_rotation_get(const wmXrData *xr,
|
||||
const char *subaction_path,
|
||||
float r_rotation[4]);
|
||||
bool WM_xr_session_state_nav_location_get(const wmXrData *xr, float r_location[3]);
|
||||
void WM_xr_session_state_nav_location_set(wmXrData *xr, const float location[3]);
|
||||
bool WM_xr_session_state_nav_rotation_get(const wmXrData *xr, float r_rotation[4]);
|
||||
|
@ -1647,6 +1653,12 @@ bool WM_xr_controller_pose_actions_set(wmXrData *xr,
|
|||
const char *action_set_name,
|
||||
const char *grip_action_name,
|
||||
const char *aim_action_name);
|
||||
bool WM_xr_tracker_pose_action_add(wmXrData *xr,
|
||||
const char *action_set_name,
|
||||
const char *tracker_action_name);
|
||||
bool WM_xr_tracker_pose_action_remove(wmXrData *xr,
|
||||
const char *action_set_name,
|
||||
const char *tracker_action_name);
|
||||
|
||||
/**
|
||||
* XR action functions to be called post-XR session start.
|
||||
|
|
|
@ -43,6 +43,7 @@ static void action_set_destroy(void *val)
|
|||
|
||||
MEM_SAFE_FREE(action_set->name);
|
||||
|
||||
BLI_freelistN(&action_set->tracker_actions);
|
||||
BLI_freelistN(&action_set->active_modal_actions);
|
||||
BLI_freelistN(&action_set->active_haptic_actions);
|
||||
|
||||
|
@ -200,6 +201,11 @@ void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name)
|
|||
action_set->controller_grip_action = action_set->controller_aim_action = NULL;
|
||||
}
|
||||
|
||||
if (!BLI_listbase_is_empty(&action_set->tracker_actions)) {
|
||||
wm_xr_session_tracker_data_clear(session_state);
|
||||
BLI_freelistN(&action_set->tracker_actions);
|
||||
}
|
||||
|
||||
BLI_freelistN(&action_set->active_modal_actions);
|
||||
BLI_freelistN(&action_set->active_haptic_actions);
|
||||
|
||||
|
@ -309,6 +315,14 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char
|
|||
action_set->controller_grip_action = action_set->controller_aim_action = NULL;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (LinkData *, ld, &action_set->tracker_actions) {
|
||||
wmXrAction *tracker_action = ld->data;
|
||||
if (STREQ(tracker_action->name, action_name)) {
|
||||
WM_xr_tracker_pose_action_remove(xr, action_set_name, action_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (LinkData *, ld, &action_set->active_modal_actions) {
|
||||
wmXrAction *active_modal_action = ld->data;
|
||||
if (STREQ(active_modal_action->name, action_name)) {
|
||||
|
@ -409,6 +423,7 @@ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name)
|
|||
|
||||
xr->runtime->session_state.active_action_set = action_set;
|
||||
|
||||
/* Update controller/tracker data. */
|
||||
if (action_set->controller_grip_action && action_set->controller_aim_action) {
|
||||
wm_xr_session_controller_data_populate(
|
||||
action_set->controller_grip_action, action_set->controller_aim_action, xr);
|
||||
|
@ -417,6 +432,13 @@ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name)
|
|||
wm_xr_session_controller_data_clear(&xr->runtime->session_state);
|
||||
}
|
||||
|
||||
if (!BLI_listbase_is_empty(&action_set->tracker_actions)) {
|
||||
wm_xr_session_tracker_data_populate(&action_set->tracker_actions, xr);
|
||||
}
|
||||
else {
|
||||
wm_xr_session_tracker_data_clear(&xr->runtime->session_state);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -462,6 +484,66 @@ bool WM_xr_controller_pose_actions_set(wmXrData *xr,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_tracker_pose_action_add(wmXrData *xr,
|
||||
const char *action_set_name,
|
||||
const char *tracker_action_name)
|
||||
{
|
||||
wmXrActionSet *action_set = action_set_find(xr, action_set_name);
|
||||
if (!action_set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wmXrAction *tracker_action = action_find(xr, action_set_name, tracker_action_name);
|
||||
if (!tracker_action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LinkData *ld = MEM_callocN(sizeof(*ld), __func__);
|
||||
ld->data = tracker_action;
|
||||
BLI_addtail(&action_set->tracker_actions, ld);
|
||||
|
||||
if (action_set == xr->runtime->session_state.active_action_set) {
|
||||
wm_xr_session_tracker_data_populate(&action_set->tracker_actions, xr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_tracker_pose_action_remove(wmXrData *xr,
|
||||
const char *action_set_name,
|
||||
const char *tracker_action_name)
|
||||
{
|
||||
wmXrActionSet *action_set = action_set_find(xr, action_set_name);
|
||||
if (!action_set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wmXrAction *tracker_action = action_find(xr, action_set_name, tracker_action_name);
|
||||
if (!tracker_action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
LinkData *ld = BLI_findptr(
|
||||
&action_set->tracker_actions, tracker_action, offsetof(LinkData, data));
|
||||
if (!ld) {
|
||||
return false;
|
||||
}
|
||||
BLI_freelinkN(&action_set->tracker_actions, ld);
|
||||
}
|
||||
|
||||
if (action_set == xr->runtime->session_state.active_action_set) {
|
||||
if (BLI_listbase_is_empty(&action_set->tracker_actions)) {
|
||||
wm_xr_session_tracker_data_clear(&xr->runtime->session_state);
|
||||
}
|
||||
else {
|
||||
wm_xr_session_tracker_data_populate(&action_set->tracker_actions, xr);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_action_state_get(const wmXrData *xr,
|
||||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
|
|
|
@ -225,7 +225,7 @@ static GPUBatch *wm_xr_controller_model_batch_create(GHOST_XrContextHandle xr_co
|
|||
|
||||
static void wm_xr_controller_model_draw(const XrSessionSettings *settings,
|
||||
GHOST_XrContextHandle xr_context,
|
||||
wmXrSessionState *state)
|
||||
ListBase *controllers)
|
||||
{
|
||||
GHOST_XrControllerModelData model_data;
|
||||
|
||||
|
@ -244,7 +244,7 @@ static void wm_xr_controller_model_draw(const XrSessionSettings *settings,
|
|||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
LISTBASE_FOREACH (wmXrController *, controller, &state->controllers) {
|
||||
LISTBASE_FOREACH (wmXrController *, controller, controllers) {
|
||||
GPUBatch *model = controller->model;
|
||||
if (!model) {
|
||||
model = controller->model = wm_xr_controller_model_batch_create(xr_context,
|
||||
|
@ -287,7 +287,7 @@ static void wm_xr_controller_model_draw(const XrSessionSettings *settings,
|
|||
}
|
||||
}
|
||||
|
||||
static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSessionState *state)
|
||||
static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, ListBase *controllers)
|
||||
{
|
||||
bool draw_ray;
|
||||
switch (settings->controller_draw_style) {
|
||||
|
@ -320,9 +320,9 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
|
|||
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
immBegin(GPU_PRIM_LINES, (uint)BLI_listbase_count(&state->controllers) * 2);
|
||||
immBegin(GPU_PRIM_LINES, (uint)BLI_listbase_count(controllers) * 2);
|
||||
|
||||
LISTBASE_FOREACH (wmXrController *, controller, &state->controllers) {
|
||||
LISTBASE_FOREACH (wmXrController *, controller, controllers) {
|
||||
const float(*mat)[4] = controller->aim_mat;
|
||||
madd_v3_v3v3fl(ray, mat[3], mat[2], -scale);
|
||||
|
||||
|
@ -344,9 +344,9 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
|
|||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
|
||||
immBegin(GPU_PRIM_LINES, (uint)BLI_listbase_count(&state->controllers) * 6);
|
||||
immBegin(GPU_PRIM_LINES, (uint)BLI_listbase_count(controllers) * 6);
|
||||
|
||||
LISTBASE_FOREACH (wmXrController *, controller, &state->controllers) {
|
||||
LISTBASE_FOREACH (wmXrController *, controller, controllers) {
|
||||
const float(*mat)[4] = controller->aim_mat;
|
||||
madd_v3_v3v3fl(x_axis, mat[3], mat[0], scale);
|
||||
madd_v3_v3v3fl(y_axis, mat[3], mat[1], scale);
|
||||
|
@ -379,8 +379,19 @@ void wm_xr_draw_controllers(const bContext *UNUSED(C), ARegion *UNUSED(region),
|
|||
wmXrData *xr = customdata;
|
||||
const XrSessionSettings *settings = &xr->session_settings;
|
||||
GHOST_XrContextHandle xr_context = xr->runtime->context;
|
||||
wmXrSessionState *state = &xr->runtime->session_state;
|
||||
ListBase *controllers = &xr->runtime->session_state.controllers;
|
||||
|
||||
wm_xr_controller_model_draw(settings, xr_context, state);
|
||||
wm_xr_controller_aim_draw(settings, state);
|
||||
wm_xr_controller_model_draw(settings, xr_context, controllers);
|
||||
wm_xr_controller_aim_draw(settings, controllers);
|
||||
}
|
||||
|
||||
void wm_xr_draw_trackers(const bContext *UNUSED(C), ARegion *UNUSED(region), void *customdata)
|
||||
{
|
||||
wmXrData *xr = customdata;
|
||||
const XrSessionSettings *settings = &xr->session_settings;
|
||||
GHOST_XrContextHandle xr_context = xr->runtime->context;
|
||||
ListBase *trackers = &xr->runtime->session_state.trackers;
|
||||
|
||||
wm_xr_controller_model_draw(settings, xr_context, trackers);
|
||||
wm_xr_controller_aim_draw(settings, trackers);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ typedef struct wmXrSessionState {
|
|||
|
||||
/** Last known controller data. */
|
||||
ListBase controllers; /* #wmXrController */
|
||||
/** Last known tracker data. */
|
||||
ListBase trackers; /* #wmXrController */
|
||||
|
||||
/** The currently active action set that will be updated on calls to
|
||||
* wm_xr_session_actions_update(). If NULL, all action sets will be treated as active and
|
||||
|
@ -92,6 +94,8 @@ typedef struct {
|
|||
struct ARegionType *controller_art;
|
||||
/** Controller draw callback handle. */
|
||||
void *controller_draw_handle;
|
||||
/** Tracker draw callback handle. */
|
||||
void *tracker_draw_handle;
|
||||
} wmXrSurfaceData;
|
||||
|
||||
typedef struct wmXrDrawData {
|
||||
|
@ -176,11 +180,13 @@ typedef struct wmXrActionSet {
|
|||
/** XR pose actions that determine the controller grip/aim transforms. */
|
||||
wmXrAction *controller_grip_action;
|
||||
wmXrAction *controller_aim_action;
|
||||
/** XR pose actions that determine tracker transforms. */
|
||||
ListBase tracker_actions; /* #LinkData */
|
||||
|
||||
/** Currently active modal actions. */
|
||||
ListBase active_modal_actions;
|
||||
ListBase active_modal_actions; /* #LinkData */
|
||||
/** Currently active haptic actions. */
|
||||
ListBase active_haptic_actions;
|
||||
ListBase active_haptic_actions; /* wmXrHapticAction */
|
||||
} wmXrActionSet;
|
||||
|
||||
typedef struct wmXrMotionCapturePose {
|
||||
|
@ -223,6 +229,8 @@ void wm_xr_session_controller_data_populate(const wmXrAction *grip_action,
|
|||
const wmXrAction *aim_action,
|
||||
wmXrData *xr);
|
||||
void wm_xr_session_controller_data_clear(wmXrSessionState *state);
|
||||
void wm_xr_session_tracker_data_populate(const ListBase *tracker_actions, wmXrData *xr);
|
||||
void wm_xr_session_tracker_data_clear(wmXrSessionState *state);
|
||||
|
||||
/* wm_xr_draw.c */
|
||||
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]);
|
||||
|
@ -237,6 +245,7 @@ void wm_xr_pose_scale_to_imat(const GHOST_XrPose *pose, float scale, float r_ima
|
|||
*/
|
||||
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata);
|
||||
void wm_xr_draw_controllers(const struct bContext *C, struct ARegion *region, void *customdata);
|
||||
void wm_xr_draw_trackers(const struct bContext *C, struct ARegion *region, void *customdata);
|
||||
|
||||
/* wm_xr_mocap.c */
|
||||
void wm_xr_mocap_orig_poses_store(const XrSessionSettings *settings, wmXrSessionState *state);
|
||||
|
|
|
@ -75,22 +75,21 @@ static void wm_xr_session_create_cb(void)
|
|||
wm_xr_mocap_orig_poses_store(settings, state);
|
||||
}
|
||||
|
||||
static void wm_xr_session_controller_data_free(wmXrSessionState *state)
|
||||
static void wm_xr_session_controller_data_free(ListBase *controllers)
|
||||
{
|
||||
ListBase *lb = &state->controllers;
|
||||
wmXrController *c;
|
||||
|
||||
while ((c = BLI_pophead(lb))) {
|
||||
while ((c = BLI_pophead(controllers))) {
|
||||
if (c->model) {
|
||||
GPU_batch_discard(c->model);
|
||||
}
|
||||
BLI_freelinkN(lb, c);
|
||||
BLI_freelinkN(controllers, c);
|
||||
}
|
||||
}
|
||||
|
||||
void wm_xr_session_data_free(wmXrSessionState *state)
|
||||
{
|
||||
wm_xr_session_controller_data_free(state);
|
||||
wm_xr_session_controller_data_free(&state->controllers);
|
||||
wm_xr_session_controller_data_free(&state->trackers);
|
||||
BLI_freelistN(&state->mocap_orig_poses);
|
||||
}
|
||||
|
||||
|
@ -509,6 +508,48 @@ bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_session_state_tracker_location_get(const wmXrData *xr,
|
||||
const char *subaction_path,
|
||||
float r_location[3])
|
||||
{
|
||||
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
|
||||
zero_v3(r_location);
|
||||
return false;
|
||||
}
|
||||
|
||||
const wmXrController *tracker = BLI_findstring(&xr->runtime->session_state.trackers,
|
||||
subaction_path,
|
||||
offsetof(wmXrController, subaction_path));
|
||||
if (!tracker) {
|
||||
zero_v3(r_location);
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_v3_v3(r_location, tracker->grip_pose.position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_session_state_tracker_rotation_get(const wmXrData *xr,
|
||||
const char *subaction_path,
|
||||
float r_rotation[4])
|
||||
{
|
||||
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
|
||||
unit_qt(r_rotation);
|
||||
return false;
|
||||
}
|
||||
|
||||
const wmXrController *tracker = BLI_findstring(&xr->runtime->session_state.trackers,
|
||||
subaction_path,
|
||||
offsetof(wmXrController, subaction_path));
|
||||
if (!tracker) {
|
||||
unit_qt(r_rotation);
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_qt_qt(r_rotation, tracker->grip_pose.orientation_quat);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_session_state_nav_location_get(const wmXrData *xr, float r_location[3])
|
||||
{
|
||||
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
|
||||
|
@ -618,14 +659,70 @@ static void wm_xr_session_controller_pose_calc(const GHOST_XrPose *raw_pose,
|
|||
|
||||
static void wm_xr_session_controller_data_update(const wmXrAction *grip_action,
|
||||
const wmXrAction *aim_action,
|
||||
unsigned int subaction_idx,
|
||||
const float view_ofs[3],
|
||||
const float base_mat[4][4],
|
||||
const float nav_mat[4][4],
|
||||
bContext *C,
|
||||
XrSessionSettings *settings,
|
||||
GHOST_XrContextHandle xr_context,
|
||||
wmXrSessionState *state,
|
||||
wmWindow *win)
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
wmWindow *win,
|
||||
bScreen *screen_anim,
|
||||
bool *notify,
|
||||
wmXrController *controller)
|
||||
{
|
||||
wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx],
|
||||
view_ofs,
|
||||
base_mat,
|
||||
nav_mat,
|
||||
&controller->grip_pose,
|
||||
controller->grip_mat,
|
||||
controller->grip_mat_base);
|
||||
wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx],
|
||||
view_ofs,
|
||||
base_mat,
|
||||
nav_mat,
|
||||
&controller->aim_pose,
|
||||
controller->aim_mat,
|
||||
controller->aim_mat_base);
|
||||
|
||||
/* Update motion capture objects. */
|
||||
wm_xr_mocap_objects_update(controller->subaction_path,
|
||||
&controller->grip_pose,
|
||||
C,
|
||||
settings,
|
||||
scene,
|
||||
view_layer,
|
||||
win,
|
||||
screen_anim,
|
||||
notify);
|
||||
|
||||
/* Update controller model. */
|
||||
if (!controller->model) {
|
||||
/* Notify GHOST to load/continue loading the controller model data. This can be called more
|
||||
* than once since the model may not be available from the runtime yet. The batch itself will
|
||||
* be created in wm_xr_draw_controllers(). */
|
||||
GHOST_XrLoadControllerModel(xr_context, controller->subaction_path);
|
||||
}
|
||||
else {
|
||||
GHOST_XrUpdateControllerModelComponents(xr_context, controller->subaction_path);
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_xr_session_controller_and_tracker_data_update(const wmXrAction *grip_action,
|
||||
const wmXrAction *aim_action,
|
||||
const ListBase *tracker_actions,
|
||||
bContext *C,
|
||||
XrSessionSettings *settings,
|
||||
GHOST_XrContextHandle xr_context,
|
||||
wmXrSessionState *state,
|
||||
wmWindow *win)
|
||||
{
|
||||
BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths);
|
||||
BLI_assert(grip_action->count_subaction_paths == BLI_listbase_count(&state->controllers));
|
||||
BLI_assert(BLI_listbase_count(tracker_actions) <= BLI_listbase_count(&state->trackers));
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
@ -633,6 +730,7 @@ static void wm_xr_session_controller_data_update(const wmXrAction *grip_action,
|
|||
bScreen *screen_anim = ED_screen_animation_playing(wm);
|
||||
bool notify = true;
|
||||
unsigned int subaction_idx = 0;
|
||||
wmXrController *tracker = state->trackers.first;
|
||||
float view_ofs[3], base_mat[4][4], nav_mat[4][4];
|
||||
|
||||
if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) {
|
||||
|
@ -648,42 +746,47 @@ static void wm_xr_session_controller_data_update(const wmXrAction *grip_action,
|
|||
wm_xr_pose_scale_to_mat(&state->prev_base_pose, state->prev_base_scale, base_mat);
|
||||
wm_xr_pose_scale_to_mat(&state->nav_pose, state->nav_scale, nav_mat);
|
||||
|
||||
/* Update controllers. */
|
||||
LISTBASE_FOREACH_INDEX (wmXrController *, controller, &state->controllers, subaction_idx) {
|
||||
wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx],
|
||||
view_ofs,
|
||||
base_mat,
|
||||
nav_mat,
|
||||
&controller->grip_pose,
|
||||
controller->grip_mat,
|
||||
controller->grip_mat_base);
|
||||
wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx],
|
||||
view_ofs,
|
||||
base_mat,
|
||||
nav_mat,
|
||||
&controller->aim_pose,
|
||||
controller->aim_mat,
|
||||
controller->aim_mat_base);
|
||||
wm_xr_session_controller_data_update(grip_action,
|
||||
aim_action,
|
||||
subaction_idx,
|
||||
view_ofs,
|
||||
base_mat,
|
||||
nav_mat,
|
||||
C,
|
||||
settings,
|
||||
xr_context,
|
||||
scene,
|
||||
view_layer,
|
||||
win,
|
||||
screen_anim,
|
||||
¬ify,
|
||||
controller);
|
||||
}
|
||||
|
||||
/* Update motion capture objects. */
|
||||
wm_xr_mocap_objects_update(controller->subaction_path,
|
||||
&controller->grip_pose,
|
||||
C,
|
||||
settings,
|
||||
scene,
|
||||
view_layer,
|
||||
win,
|
||||
screen_anim,
|
||||
¬ify);
|
||||
/* Update trackers. */
|
||||
LISTBASE_FOREACH (LinkData *, ld, tracker_actions) {
|
||||
const wmXrAction *tracker_action = ld->data;
|
||||
|
||||
/* Update controller model. */
|
||||
if (!controller->model) {
|
||||
/* Notify GHOST to load/continue loading the controller model data. This can be called more
|
||||
* than once since the model may not be available from the runtime yet. The batch itself will
|
||||
* be created in wm_xr_draw_controllers(). */
|
||||
GHOST_XrLoadControllerModel(xr_context, controller->subaction_path);
|
||||
}
|
||||
else {
|
||||
GHOST_XrUpdateControllerModelComponents(xr_context, controller->subaction_path);
|
||||
for (subaction_idx = 0; subaction_idx < tracker_action->count_subaction_paths;
|
||||
++subaction_idx) {
|
||||
wm_xr_session_controller_data_update(tracker_action,
|
||||
tracker_action,
|
||||
subaction_idx,
|
||||
view_ofs,
|
||||
base_mat,
|
||||
nav_mat,
|
||||
C,
|
||||
settings,
|
||||
xr_context,
|
||||
scene,
|
||||
view_layer,
|
||||
win,
|
||||
screen_anim,
|
||||
¬ify,
|
||||
tracker);
|
||||
tracker = tracker->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1244,14 +1347,16 @@ void wm_xr_session_actions_update(const bContext *C)
|
|||
|
||||
/* Only update controller data and dispatch events for active action set. */
|
||||
if (active_action_set) {
|
||||
if (active_action_set->controller_grip_action && active_action_set->controller_aim_action) {
|
||||
wm_xr_session_controller_data_update(active_action_set->controller_grip_action,
|
||||
active_action_set->controller_aim_action,
|
||||
(bContext *)C,
|
||||
settings,
|
||||
xr_context,
|
||||
state,
|
||||
win);
|
||||
if ((active_action_set->controller_grip_action && active_action_set->controller_aim_action) ||
|
||||
!BLI_listbase_is_empty(&active_action_set->tracker_actions)) {
|
||||
wm_xr_session_controller_and_tracker_data_update(active_action_set->controller_grip_action,
|
||||
active_action_set->controller_aim_action,
|
||||
&active_action_set->tracker_actions,
|
||||
(bContext *)C,
|
||||
settings,
|
||||
xr_context,
|
||||
state,
|
||||
win);
|
||||
}
|
||||
|
||||
if (win) {
|
||||
|
@ -1273,15 +1378,13 @@ void wm_xr_session_controller_data_populate(const wmXrAction *grip_action,
|
|||
|
||||
wmXrSessionState *state = &xr->runtime->session_state;
|
||||
ListBase *controllers = &state->controllers;
|
||||
|
||||
BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths);
|
||||
const unsigned int count = grip_action->count_subaction_paths;
|
||||
|
||||
wm_xr_session_controller_data_free(state);
|
||||
wm_xr_session_controller_data_free(controllers);
|
||||
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
wmXrController *controller = MEM_callocN(sizeof(*controller), __func__);
|
||||
|
||||
BLI_assert(STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i]));
|
||||
strcpy(controller->subaction_path, grip_action->subaction_paths[i]);
|
||||
|
||||
|
@ -1302,7 +1405,7 @@ void wm_xr_session_controller_data_populate(const wmXrAction *grip_action,
|
|||
|
||||
void wm_xr_session_controller_data_clear(wmXrSessionState *state)
|
||||
{
|
||||
wm_xr_session_controller_data_free(state);
|
||||
wm_xr_session_controller_data_free(&state->controllers);
|
||||
|
||||
/* Deactivate draw callback. */
|
||||
if (g_xr_surface) {
|
||||
|
@ -1316,6 +1419,53 @@ void wm_xr_session_controller_data_clear(wmXrSessionState *state)
|
|||
}
|
||||
}
|
||||
|
||||
void wm_xr_session_tracker_data_populate(const ListBase *tracker_actions, wmXrData *xr)
|
||||
{
|
||||
wmXrSessionState *state = &xr->runtime->session_state;
|
||||
ListBase *trackers = &state->trackers;
|
||||
|
||||
wm_xr_session_controller_data_free(trackers);
|
||||
|
||||
LISTBASE_FOREACH (const LinkData *, ld, tracker_actions) {
|
||||
const wmXrAction *tracker_action = ld->data;
|
||||
|
||||
for (unsigned int subaction_idx = 0; subaction_idx < tracker_action->count_subaction_paths;
|
||||
++subaction_idx) {
|
||||
wmXrController *tracker = MEM_callocN(sizeof(*tracker), __func__);
|
||||
strcpy(tracker->subaction_path, tracker_action->subaction_paths[subaction_idx]);
|
||||
|
||||
BLI_addtail(trackers, tracker);
|
||||
}
|
||||
}
|
||||
|
||||
/* Activate draw callback. */
|
||||
if (g_xr_surface) {
|
||||
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
|
||||
if (surface_data && !surface_data->tracker_draw_handle) {
|
||||
if (surface_data->controller_art) {
|
||||
surface_data->tracker_draw_handle = ED_region_draw_cb_activate(
|
||||
surface_data->controller_art, wm_xr_draw_trackers, xr, REGION_DRAW_POST_VIEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wm_xr_session_tracker_data_clear(wmXrSessionState *state)
|
||||
{
|
||||
wm_xr_session_controller_data_free(&state->trackers);
|
||||
|
||||
/* Deactivate draw callback. */
|
||||
if (g_xr_surface) {
|
||||
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
|
||||
if (surface_data && surface_data->tracker_draw_handle) {
|
||||
if (surface_data->controller_art) {
|
||||
ED_region_draw_cb_exit(surface_data->controller_art, surface_data->tracker_draw_handle);
|
||||
}
|
||||
surface_data->tracker_draw_handle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */ /* XR-Session Actions */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
Loading…
Reference in New Issue