FIX #109121: VR: Render controllers only if they are active

When turning on VR mode, if no controllers are available,
a fallback model (a sphere) is rendered in the middle of the VR area.

This change uses the OpenXR API to check if the controllers are
available, sets new properties in `GHOST_XrPose` and `wmXrController`
that store if each controller is active or not, and uses
those properties to render the controllers in the VR view only
when they are active.

NOTE: in `wmXrController`, two state properties have been included,
but only `grip_active` is currently used. `aim_active` has been
included for consistency, but it could be removed.

Pull Request: https://projects.blender.org/blender/blender/pulls/119989
This commit is contained in:
Fermin
2024-04-21 03:28:35 +02:00
committed by Peter Kim
parent 8392f69e10
commit 821b773d95
5 changed files with 26 additions and 8 deletions

View File

@@ -788,6 +788,7 @@ typedef void (*GHOST_XrDrawViewFn)(const struct GHOST_XrDrawViewInfo *draw_view,
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
typedef struct {
bool is_active;
float position[3];
/* Blender convention (w, x, y, z) */
float orientation_quat[4];

View File

@@ -339,6 +339,7 @@ void GHOST_XrAction::updateState(XrSession session,
CHECK_XR(xrGetActionStatePose(session, &state_info, &state),
(std::string("Failed to get state for pose action \"") + action_name + "\".")
.data());
((GHOST_XrPose *)m_states)[subaction_idx].is_active = state.isActive;
if (state.isActive) {
XrSpace pose_space = ((subaction != nullptr) && (subaction->space != nullptr)) ?
subaction->space->getSpace() :

View File

@@ -259,6 +259,10 @@ static void wm_xr_controller_model_draw(const XrSessionSettings *settings,
GPU_blend(GPU_BLEND_ALPHA);
LISTBASE_FOREACH (wmXrController *, controller, &state->controllers) {
if (!controller->grip_active) {
continue;
}
blender::gpu::Batch *model = controller->model;
if (!model) {
model = controller->model = wm_xr_controller_model_batch_create(xr_context,
@@ -334,9 +338,13 @@ 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);
LISTBASE_FOREACH (wmXrController *, controller, &state->controllers) {
if (!controller->grip_active) {
continue;
}
immBegin(GPU_PRIM_LINES, 2);
const float(*mat)[4] = controller->aim_mat;
madd_v3_v3v3fl(ray, mat[3], mat[2], -scale);
@@ -344,9 +352,9 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
immVertex3fv(pos, mat[3]);
immAttr4ubv(col, color);
immVertex3fv(pos, ray);
}
immEnd();
immEnd();
}
}
else {
const uchar r[4] = {255, 51, 82, 255};
@@ -358,9 +366,13 @@ 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);
LISTBASE_FOREACH (wmXrController *, controller, &state->controllers) {
if (!controller->grip_active) {
continue;
}
immBegin(GPU_PRIM_LINES, 6);
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);
@@ -380,9 +392,9 @@ static void wm_xr_controller_aim_draw(const XrSessionSettings *settings, wmXrSes
immVertex3fv(pos, mat[3]);
immAttr4ubv(col, b);
immVertex3fv(pos, z_axis);
}
immEnd();
immEnd();
}
}
immUnbindProgram();

View File

@@ -128,10 +128,12 @@ struct wmXrController {
char subaction_path[64]; /* #XR_MAX_USER_PATH_LENGTH. */
/** Pose (in world space) that represents the user's hand when holding the controller. */
bool grip_active;
GHOST_XrPose grip_pose;
float grip_mat[4][4];
float grip_mat_base[4][4];
/** Pose (in world space) that represents the controller's aiming source. */
bool aim_active;
GHOST_XrPose aim_pose;
float aim_mat[4][4];
float aim_mat_base[4][4];

View File

@@ -639,6 +639,7 @@ static void wm_xr_session_controller_data_update(const XrSessionSettings *settin
wm_xr_pose_scale_to_mat(&state->nav_pose, state->nav_scale, nav_mat);
LISTBASE_FOREACH_INDEX (wmXrController *, controller, &state->controllers, subaction_idx) {
controller->grip_active = ((GHOST_XrPose *)grip_action->states)[subaction_idx].is_active;
wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx],
view_ofs,
base_mat,
@@ -646,6 +647,7 @@ static void wm_xr_session_controller_data_update(const XrSessionSettings *settin
&controller->grip_pose,
controller->grip_mat,
controller->grip_mat_base);
controller->aim_active = ((GHOST_XrPose *)aim_action->states)[subaction_idx].is_active;
wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx],
view_ofs,
base_mat,