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:
Peter Kim 2022-05-03 09:58:15 +09:00
parent b0825be786
commit 62cabfca87
7 changed files with 490 additions and 65 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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.

View File

@ -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,

View File

@ -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);
}

View File

@ -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);

View File

@ -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,
&notify,
controller);
}
/* 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 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,
&notify,
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 */
/* -------------------------------------------------------------------- */