Add VR locomotion: move/turn with thumbsticks while the menu is open
build / build (push) Successful in 2m25s
build / build (push) Successful in 2m25s
- Left thumbstick snap-turns, right thumbstick smooth-moves, letting the
player line themselves up with the fixed game quad ("virtual screen")
without needing physical room-scale space to do it in. Implemented via
a second OpenXR reference space (a "play space") derived from the real
LOCAL space by the inverse of the player's transform, so every existing
quad/hit-testing/rendering call site just needed g_local_space swapped
for it - no manual coordinate-transform math required elsewhere
- Generalized the ray/quad hit-testing in xr_input.c to a proper
oriented-plane intersection (needed once quads can rotate); verified it
degenerates to the old axis-aligned formula when unrotated, so the
keyboard and non-recentered menu are unaffected
- The menu launcher now re-centers in front of the player, correctly
oriented to face them, each time it's freshly reopened
- "Reset Position" (Main Menu tab) recenters using the player's current
real head pose - not a plain reset-to-origin, which only undid
thumbstick movement and ignored physical drift since the session
started. The same recenter runs once automatically at startup too, as a
fallback for when there's no complete saved position to use instead
- Position/orientation persists in questshock.config.json's new
player_position group (independent of savegames), including new
numeric-value support in the config file's hand-rolled JSON parser
(previously string-enums only)
This commit is contained in:
@@ -62,14 +62,14 @@ bool xr_frame_begin(void);
|
||||
// launcher and keyboard overlay quads via xr_overlay_render_and_build_layer()
|
||||
// for whichever of them is currently visible, and submits whichever of the
|
||||
// three quads actually rendered this frame as composition layers
|
||||
// positioned in front of the local reference space's origin, then ends the
|
||||
// XR frame.
|
||||
// positioned in front of the play space's origin (see
|
||||
// xr_session_set_player_transform() above), then ends the XR frame.
|
||||
void xr_frame_end(void);
|
||||
|
||||
void xr_shutdown(void);
|
||||
|
||||
// Local-space geometry of the single game quad xr_frame_end() submits
|
||||
// (distance in front of the local space origin, half-width/half-height,
|
||||
// Play-space geometry of the single game quad xr_frame_end() submits
|
||||
// (distance in front of the play space origin, half-width/half-height,
|
||||
// all in meters) - shared with xr_input.c's ray/quad hit-testing so the
|
||||
// laser pointer always matches whatever's actually visible.
|
||||
void xr_get_game_quad_extent(float *distance_m, float *half_width_m, float *half_height_m);
|
||||
@@ -98,6 +98,49 @@ float xr_session_get_frame_ms(void);
|
||||
float xr_session_get_cpu_utilization(void);
|
||||
float xr_session_get_gpu_utilization(void);
|
||||
|
||||
// The player's virtual position/orientation - horizontal-plane only (x/z
|
||||
// plus a yaw rotation about the vertical axis); height always comes from
|
||||
// the real tracked HMD pose, never from this. Everything the app submits
|
||||
// (game/menu/keyboard/beam quads) and every hand/head pose it locates is
|
||||
// expressed relative to a second reference space, derived from the real
|
||||
// LOCAL space by this transform's inverse (see xr_session.c's own
|
||||
// xr_session_rebuild_play_space()) - so changing it moves/turns the player
|
||||
// relative to those otherwise-fixed quads, letting them walk up to and
|
||||
// square up with the game quad ("virtual screen") without needing any
|
||||
// physical room-scale space to do it in.
|
||||
//
|
||||
// xr_session_set_player_transform() only stores the three floats (no XR
|
||||
// calls) - safe to call before xr_init() has even run, which is how
|
||||
// qs_config_load_startup() seeds the saved position before the OpenXR
|
||||
// session/spaces exist yet (xr_init() picks it up when it creates its own
|
||||
// spaces); also used live by xr_input.c's thumbstick locomotion and
|
||||
// "Reset Position" recenter (xr_input_recenter_player_to_screen()) and
|
||||
// qs_config.c's "Load Configuration", and read back by "Save Configuration"
|
||||
// via the getter.
|
||||
void xr_session_set_player_transform(float x, float z, float yaw_deg);
|
||||
void xr_session_get_player_transform(float *x, float *z, float *yaw_deg);
|
||||
|
||||
// The real, physical tracking-origin reference space - used only by
|
||||
// xr_input_recenter_player_to_screen() (xr_input.c), which needs the
|
||||
// player's CURRENT real head pose (not one already bent through the
|
||||
// existing play-space transform - see xr_session_set_player_transform()'s
|
||||
// own comment above) to compute a brand new one. Every other consumer in
|
||||
// this app (rendering, hit-testing) uses the play space instead - see
|
||||
// xr_session_rebuild_play_space()'s own comment for why this one stays a
|
||||
// separate, never-swapped-out space.
|
||||
XrSpace xr_session_get_local_space(void);
|
||||
|
||||
// The most recent xrWaitFrame-predicted display time (xr_frame_begin()'s
|
||||
// own g_predicted_display_time) - for the same reason as
|
||||
// xr_session_get_local_space() above, xr_input_recenter_player_to_screen()
|
||||
// needs a valid XrTime to locate a space with but isn't itself called from
|
||||
// the normal per-frame xr_frame_end()/xr_input_sync_and_draw() call chain
|
||||
// that already threads one through (it's triggered by a button press,
|
||||
// dispatched via qs_config.c's cross-thread event queue instead). A frame
|
||||
// or so of staleness doesn't matter for a one-shot recenter. 0 before the
|
||||
// first frame has ever begun.
|
||||
XrTime xr_session_get_predicted_display_time(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user