1
1

Compare commits

...

6 Commits

Author SHA1 Message Date
9976bd76d9 fixed device detection 2020-05-14 17:39:58 +02:00
4449f53786 Fix compile error on GCC 2020-05-14 15:07:22 +02:00
f700f6902a Merge remote-tracking branch 'blender/master' into xr-world-navigation 2020-05-14 09:18:03 +02:00
91323b6827 Fixed make update so that people get the right vr addon when doing 'make update'. 2020-05-14 09:14:53 +02:00
nfauvet
149d4167a9 synchronize with addons 2020-05-13 14:50:11 +02:00
nfauvet
8253dc47a6 Oculus Touch controllers support: all inputs exposed in python.
World transformation for navigation, exposed in python.
Fix: frustum culling for asymetric frustums.
2020-05-13 11:44:26 +02:00
14 changed files with 1598 additions and 39 deletions

View File

@@ -158,7 +158,7 @@ def submodules_update(args, release_version, branch):
branch = "master"
submodules = [
("release/scripts/addons", branch),
("release/scripts/addons", "xr-world-navigation"),
("release/scripts/addons_contrib", branch),
("release/datafiles/locale", branch),
("source/tools", branch),

View File

@@ -654,6 +654,33 @@ typedef struct {
void *exit_customdata;
} GHOST_XrSessionBeginInfo;
typedef struct GHOST_XrControllersDataInfo {
GHOST_XrPose left_pose;
GHOST_XrPose right_pose;
float left_trigger_value;
float right_trigger_value;
char left_trigger_touch;
char right_trigger_touch;
float left_grip_value;
float right_grip_value;
char left_primary_click;
char left_primary_touch;
char left_secondary_click;
char left_secondary_touch;
char right_primary_click;
char right_primary_touch;
char right_secondary_click;
char right_secondary_touch;
float left_thumbstick_x;
float left_thumbstick_y;
char left_thumbstick_click;
char left_thumbstick_touch;
float right_thumbstick_x;
float right_thumbstick_y;
char right_thumbstick_click;
char right_thumbstick_touch;
} GHOST_XrControllersDataInfo;
typedef struct GHOST_XrDrawViewInfo {
int ofsx, ofsy;
int width, height;
@@ -668,6 +695,13 @@ typedef struct GHOST_XrDrawViewInfo {
/** Set if the buffer should be submitted with a srgb transfer applied. */
char expects_srgb_buffer;
/** World transform */
GHOST_XrPose world_pose;
float world_scale;
/** Controllers poses and input states */
GHOST_XrControllersDataInfo controllers_data;
} GHOST_XrDrawViewInfo;
typedef struct GHOST_XrError {

View File

@@ -458,8 +458,15 @@ void GHOST_XrContext::startSession(const GHOST_XrSessionBeginInfo *begin_info)
m_custom_funcs.session_exit_customdata = begin_info->exit_customdata;
if (m_session == nullptr) {
if (isDebugMode()) printf("Create a new session object.\n");
m_session = std::unique_ptr<GHOST_XrSession>(new GHOST_XrSession(this));
}
else
{
if (isDebugMode()) printf("DONT Create a new session object, previous one is still != null.\n");
}
if (isDebugMode()) printf("Start the session.\n");
m_session->start(begin_info);
}
@@ -467,9 +474,13 @@ void GHOST_XrContext::endSession()
{
if (m_session) {
if (m_session->isRunning()) {
if (isDebugMode())
printf("Request Session End.\n");
m_session->requestEnd();
}
else {
if (isDebugMode())
printf("Session state is IDLE, destroying it.\n");
m_session = nullptr;
}
}
@@ -491,7 +502,7 @@ void GHOST_XrContext::drawSessionViews(void *draw_customdata)
void GHOST_XrContext::handleSessionStateChange(const XrEventDataSessionStateChanged *lifecycle)
{
if (m_session &&
m_session->handleStateChangeEvent(lifecycle) == GHOST_XrSession::SESSION_DESTROY) {
m_session->handleStateChangeEvent(lifecycle, isDebugMode()) == GHOST_XrSession::SESSION_DESTROY) {
m_session = nullptr;
}
}

View File

@@ -24,13 +24,37 @@
#include "GHOST_XrContext.h"
#include "GHOST_Xr_intern.h"
static bool GHOST_XrEventPollNext(XrInstance instance, XrEventDataBuffer &r_event_data)
static bool GHOST_XrEventPollNext(XrInstance instance, XrEventDataBuffer &r_event_data, bool debug)
{
/* (Re-)initialize as required by specification. */
r_event_data.type = XR_TYPE_EVENT_DATA_BUFFER;
r_event_data.next = nullptr;
return (xrPollEvent(instance, &r_event_data) == XR_SUCCESS);
XrResult result = xrPollEvent(instance, &r_event_data);
bool success = (result == XR_SUCCESS);
if (!success) {
switch (result) {
case XR_EVENT_UNAVAILABLE:
/* printf("FAIL Event received: XR_EVENT_UNAVAILABLE\n"); // spammy, no print here, we have this event every time nothing gets polled. */
break;
case XR_ERROR_INSTANCE_LOST:
if (debug) printf("POLL Fail Event received: XR_ERROR_INSTANCE_LOST\n");
break;
case XR_ERROR_RUNTIME_FAILURE:
if (debug) printf("POLL Fail Event received: XR_ERROR_RUNTIME_FAILURE\n");
break;
case XR_ERROR_HANDLE_INVALID:
if (debug) printf("POLL Fail Event received: XR_ERROR_HANDLE_INVALID\n");
break;
case XR_ERROR_VALIDATION_FAILURE:
if (debug) printf("POLL Fail Event received: XR_ERROR_VALIDATION_FAILURE\n");
break;
default:
if (debug) printf("POLL Fail Event received(should not happen): %i\n", result);
break;
}
}
return success;
}
GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_contexthandle)
@@ -42,21 +66,90 @@ GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_contexthandle)
return GHOST_kFailure;
}
while (GHOST_XrEventPollNext(xr_context->getInstance(), event_buffer)) {
while (GHOST_XrEventPollNext(xr_context->getInstance(), event_buffer, xr_context->isDebugMode())) {
XrEventDataBaseHeader *event = (XrEventDataBaseHeader *)&event_buffer;
switch (event->type) {
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
xr_context->handleSessionStateChange((XrEventDataSessionStateChanged *)event);
return GHOST_kSuccess;
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
GHOST_XrContextDestroy(xr_contexthandle);
return GHOST_kSuccess;
default:
if (xr_context->isDebugMode()) {
printf("Unhandled event: %i\n", event->type);
/*
XR_TYPE_EVENT_DATA_EVENTS_LOST (XrEventDataEventsLost *)event .lostEventCount = number of removed events because of overflow of events.
XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING (XrEventDataInstanceLossPending *)event .lossTime = application if about to loose the instance (occurs when software updates)
XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED (XrEventDataInteractionProfileChanged *)event .session = bla bla bla
XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING (XrEventDataReferenceSpaceChangePending *)event quand on recentre la vue. la struct contient la pose dans le precedent espace et le temps avant que l'api retourne des poses dans le nouvel espace.
XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED (XrEventDataSessionStateChanged *)event lifecycle change of an XrSession, with a new XrSessionState
XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT (...)
XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR (...)
XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX (...)
*/
case XR_TYPE_EVENT_DATA_EVENTS_LOST:
{
if (xr_context->isDebugMode())
{
XrEventDataEventsLost* e = (XrEventDataEventsLost*)event;
printf("Event XR_TYPE_EVENT_DATA_EVENTS_LOST received. LostEventCount = %d\n", e->lostEventCount);
}
return GHOST_kFailure;
}
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
{
if (xr_context->isDebugMode())
{
printf("Event XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED => ");
}
xr_context->handleSessionStateChange((XrEventDataSessionStateChanged *)event);
return GHOST_kSuccess;
}
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
{
if (xr_context->isDebugMode())
{
XrEventDataInteractionProfileChanged *e = (XrEventDataInteractionProfileChanged *)event;
printf("Event XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED received.\n");
}
return GHOST_kFailure;
}
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
{
if (xr_context->isDebugMode())
{
XrEventDataReferenceSpaceChangePending *e = (XrEventDataReferenceSpaceChangePending *)event;
printf("Event XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING received.\n");
}
return GHOST_kFailure;
}
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
{
if (xr_context->isDebugMode())
{
XrEventDataInstanceLossPending *e = (XrEventDataInstanceLossPending *)event;
printf("Event XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING received. LossTime: %d\n", e->lossTime);
}
GHOST_XrContextDestroy(xr_contexthandle);
return GHOST_kSuccess;
}
case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT:
{
if (xr_context->isDebugMode())
{
printf("Event XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT received.\n");
}
return GHOST_kFailure;
}
case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR:
{
if (xr_context->isDebugMode())
{
printf("Event XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR received.\n");
}
return GHOST_kFailure;
}
default:
{
if (xr_context->isDebugMode())
{
printf("Unhandled event: %i\n", event->type);
}
return GHOST_kFailure;
}
}
}

View File

@@ -22,6 +22,7 @@
#include <cassert>
#include <chrono>
#include <cstdio>
#include <cstring>
#include <list>
#include <sstream>
@@ -35,6 +36,46 @@
#include "GHOST_XrSession.h"
/** Oculus Touch OpenXR profile data */
struct OculusTouchProfile {
bool valid;
XrActionSet actionSet;
XrPath handPaths[2];
XrSpace handSpaces[2];
/* Common actions for each hands */
XrAction squeezeValueAction;
XrAction triggerValueAction;
XrAction triggerTouchAction;
XrAction thumbstickXAction;
XrAction thumbstickYAction;
XrAction thumbstickClickAction;
XrAction thumbstickTouchAction;
XrAction thumbrestTouchAction;
XrAction gripPoseAction;
XrAction aimPoseAction;
XrAction hapticAction;
/* Specific hand actions */
XrAction leftXClickAction;
XrAction leftXTouchAction;
XrAction leftYClickAction;
XrAction leftYTouchAction;
XrAction leftMenuClickAction;
XrAction rightAClickAction;
XrAction rightATouchAction;
XrAction rightBClickAction;
XrAction rightBTouchAction;
XrAction rightSystemClickAction;
};
enum class OpenXrProfile {
UNKNOWN,
OCULUS_TOUCH
};
struct OpenXRSessionData {
XrSystemId system_id = XR_NULL_SYSTEM_ID;
XrSession session = XR_NULL_HANDLE;
@@ -46,6 +87,9 @@ struct OpenXRSessionData {
XrSpace view_space;
std::vector<XrView> views;
std::vector<GHOST_XrSwapchain> swapchains;
OpenXrProfile detectedProfile = OpenXrProfile::UNKNOWN;
OculusTouchProfile oculusTouchProfile;
};
struct GHOST_XrDrawInfo {
@@ -57,6 +101,36 @@ struct GHOST_XrDrawInfo {
std::list<double> last_frame_times;
};
/* One structure for all devices */
struct GHOST_XrControllersData {
XrPosef left_pose;
float left_trigger_value;
bool left_trigger_touch;
float left_grip_value;
bool left_primary_click;
bool left_primary_touch;
bool left_secondary_click;
bool left_secondary_touch;
XrPosef right_pose;
float right_trigger_value;
bool right_trigger_touch;
float right_grip_value;
bool right_primary_click;
bool right_primary_touch;
bool right_secondary_click;
bool right_secondary_touch;
float left_thumbstick_x;
float left_thumbstick_y;
bool left_thumbstick_click;
bool left_thumbstick_touch;
float right_thumbstick_x;
float right_thumbstick_y;
bool right_thumbstick_click;
bool right_thumbstick_touch;
};
/* -------------------------------------------------------------------- */
/** \name Create, Initialize and Destruct
*
@@ -71,6 +145,13 @@ GHOST_XrSession::~GHOST_XrSession()
{
unbindGraphicsContext();
/* Destroy action set (which also destroy all handles of actions in that action set) */
switch (m_oxr->detectedProfile) {
case OpenXrProfile::OCULUS_TOUCH:
xrDestroyActionSet(m_oxr->oculusTouchProfile.actionSet);
break;
}
m_oxr->swapchains.clear();
if (m_oxr->reference_space != XR_NULL_HANDLE) {
@@ -104,6 +185,18 @@ void GHOST_XrSession::initSystem()
CHECK_XR(xrGetSystem(m_context->getInstance(), &system_info, &m_oxr->system_id),
"Failed to get device information. Is a device plugged in?");
/* Get detected device */
XrSystemProperties xrSystemProperties = {XR_TYPE_SYSTEM_PROPERTIES};
xrSystemProperties.next = NULL;
xrSystemProperties.graphicsProperties = {0};
xrSystemProperties.trackingProperties = {0};
CHECK_XR(xrGetSystemProperties(m_context->getInstance(), m_oxr->system_id, &xrSystemProperties),
"Failed to get system properties.");
if (strcmp(xrSystemProperties.systemName, "Quest") == 0 || strcmp(xrSystemProperties.systemName, "Oculus Rift S") == 0) {
m_oxr->detectedProfile = OpenXrProfile::OCULUS_TOUCH;
}
}
/** \} */ /* Create, Initialize and Destruct */
@@ -150,6 +243,458 @@ static void create_reference_spaces(OpenXRSessionData *oxr, const GHOST_XrPose *
"Failed to create view reference space.");
}
/* Helper function to create and bind an OpenXR action */
static void create_and_bind_xr_action(XrInstance xrInstance,
XrActionSet actionSet,
const XrActionCreateInfo *actionInfo,
XrAction *action,
std::vector<XrActionSuggestedBinding> &bindings,
const std::vector<std::string> &paths)
{
std::string error_msg = "failed to create \"";
error_msg += actionInfo->actionName;
error_msg += "\" action";
CHECK_XR(xrCreateAction(actionSet, actionInfo, action), error_msg.c_str());
for (int i = 0; i < paths.size(); ++i) {
XrPath xrPaths;
xrStringToPath(xrInstance, paths[i].c_str(), &xrPaths);
bindings.push_back(XrActionSuggestedBinding{*action, xrPaths});
}
}
static void init_xr_oculus_touch_profile(OpenXRSessionData *oxr, XrInstance xrInstance)
{
OculusTouchProfile *profile = &oxr->oculusTouchProfile;
/* Create action set */
XrActionSetCreateInfo actionSetInfo = {XR_TYPE_ACTION_SET_CREATE_INFO};
actionSetInfo.next = NULL;
actionSetInfo.priority = 0;
strcpy(actionSetInfo.actionSetName, "actionset");
strcpy(actionSetInfo.localizedActionSetName, "ActionSet");
CHECK_XR(xrCreateActionSet(xrInstance, &actionSetInfo, &profile->actionSet),
"Failed to create action set.");
/* Create common actions for each hand */
int const handsCount = 2;
xrStringToPath(xrInstance, "/user/hand/left", &profile->handPaths[0]);
xrStringToPath(xrInstance, "/user/hand/right", &profile->handPaths[1]);
std::vector<XrActionSuggestedBinding> bindings;
XrActionCreateInfo actionInfo = {XR_TYPE_ACTION_CREATE_INFO};
actionInfo.next = NULL;
actionInfo.countSubactionPaths = handsCount;
actionInfo.subactionPaths = profile->handPaths;
/* ...of type float */
actionInfo.actionType = XR_ACTION_TYPE_FLOAT_INPUT;
strcpy(actionInfo.actionName, "trigger");
strcpy(actionInfo.localizedActionName, "Trigger Value");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->triggerValueAction,
bindings,
{"/user/hand/left/input/trigger/value", "/user/hand/right/input/trigger/value"});
strcpy(actionInfo.actionName, "squeeze");
strcpy(actionInfo.localizedActionName, "Squeeze Value");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->squeezeValueAction,
bindings,
{"/user/hand/left/input/squeeze/value", "/user/hand/right/input/squeeze/value"});
strcpy(actionInfo.actionName, "thumbstick_x");
strcpy(actionInfo.localizedActionName, "Thumbstick X Value");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->thumbstickXAction,
bindings,
{"/user/hand/left/input/thumbstick/x", "/user/hand/right/input/thumbstick/x"});
strcpy(actionInfo.actionName, "thumbstick_y");
strcpy(actionInfo.localizedActionName, "Thumbstick Y Value");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->thumbstickYAction,
bindings,
{"/user/hand/left/input/thumbstick/y", "/user/hand/right/input/thumbstick/y"});
/* ...of type bool */
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
strcpy(actionInfo.actionName, "thumbstickclick");
strcpy(actionInfo.localizedActionName, "Thumbstick Click");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->thumbstickClickAction,
bindings,
{"/user/hand/left/input/thumbstick/click", "/user/hand/right/input/thumbstick/click"});
strcpy(actionInfo.actionName, "thumbsticktouch");
strcpy(actionInfo.localizedActionName, "Thumbstick Touch");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->thumbstickTouchAction,
bindings,
{"/user/hand/left/input/thumbstick/touch", "/user/hand/right/input/thumbstick/touch"});
strcpy(actionInfo.actionName, "triggertouch");
strcpy(actionInfo.localizedActionName, "Trigger Touch");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->triggerTouchAction,
bindings,
{"/user/hand/left/input/trigger/touch", "/user/hand/right/input/trigger/touch"});
/* ...of type haptic */
actionInfo.actionType = XR_ACTION_TYPE_VIBRATION_OUTPUT;
strcpy(actionInfo.actionName, "haptic");
strcpy(actionInfo.localizedActionName, "Haptic");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->hapticAction,
bindings,
{"/user/hand/left/output/haptic", "/user/hand/right/output/haptic"});
/* ...of type pose */
actionInfo.actionType = XR_ACTION_TYPE_POSE_INPUT;
strcpy(actionInfo.actionName, "handpose");
strcpy(actionInfo.localizedActionName, "Hand Pose");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->gripPoseAction,
bindings,
{"/user/hand/left/input/grip/pose", "/user/hand/right/input/grip/pose"});
/* Create spaces for poses */
XrActionSpaceCreateInfo actionSpaceInfo = {XR_TYPE_ACTION_SPACE_CREATE_INFO};
actionSpaceInfo.next = NULL;
actionSpaceInfo.action = profile->gripPoseAction;
actionSpaceInfo.poseInActionSpace.orientation.w = 1.f;
actionSpaceInfo.subactionPath = profile->handPaths[0];
CHECK_XR(xrCreateActionSpace(oxr->session, &actionSpaceInfo, &profile->handSpaces[0]),
"failed to create left hand pose space");
actionSpaceInfo.subactionPath = profile->handPaths[1];
CHECK_XR(xrCreateActionSpace(oxr->session, &actionSpaceInfo, &profile->handSpaces[1]),
"failed to create right hand pose space");
/* Create unique actions of each hand */
actionInfo.countSubactionPaths = 0;
actionInfo.subactionPaths = NULL;
actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
strcpy(actionInfo.actionName, "leftxclick");
strcpy(actionInfo.localizedActionName, "Left X Click");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->leftXClickAction,
bindings,
{"/user/hand/left/input/x/click"});
strcpy(actionInfo.actionName, "leftxtouch");
strcpy(actionInfo.localizedActionName, "Left X Touch");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->leftXTouchAction,
bindings,
{"/user/hand/left/input/x/touch"});
strcpy(actionInfo.actionName, "leftyclick");
strcpy(actionInfo.localizedActionName, "Left Y Click");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->leftYClickAction,
bindings,
{"/user/hand/left/input/y/click"});
strcpy(actionInfo.actionName, "leftytouch");
strcpy(actionInfo.localizedActionName, "Left Y Touch");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->leftYTouchAction,
bindings,
{"/user/hand/left/input/y/touch"});
strcpy(actionInfo.actionName, "rightaclick");
strcpy(actionInfo.localizedActionName, "Right A Click");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->rightAClickAction,
bindings,
{"/user/hand/right/input/a/click"});
strcpy(actionInfo.actionName, "rightatouch");
strcpy(actionInfo.localizedActionName, "Right A Touch");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->rightATouchAction,
bindings,
{"/user/hand/right/input/a/touch"});
strcpy(actionInfo.actionName, "rightbclick");
strcpy(actionInfo.localizedActionName, "Right B Click");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->rightBClickAction,
bindings,
{"/user/hand/right/input/b/click"});
strcpy(actionInfo.actionName, "rightbtouch");
strcpy(actionInfo.localizedActionName, "Right B Touch");
create_and_bind_xr_action(xrInstance,
profile->actionSet,
&actionInfo,
&profile->rightBTouchAction,
bindings,
{"/user/hand/right/input/b/touch"});
/* Create interaction profile */
XrPath oculusInteractionProfilePath;
CHECK_XR(xrStringToPath(xrInstance,
"/interaction_profiles/oculus/touch_controller",
&oculusInteractionProfilePath),
"failed to get oculus interaction profile");
/* Suggest bindings */
XrInteractionProfileSuggestedBinding suggestedBindings = {
XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING};
suggestedBindings.interactionProfile = oculusInteractionProfilePath;
suggestedBindings.countSuggestedBindings = bindings.size();
suggestedBindings.suggestedBindings = bindings.data();
CHECK_XR(xrSuggestInteractionProfileBindings(xrInstance, &suggestedBindings),
"failed to suggest bindings");
/* Attach action set to session */
XrSessionActionSetsAttachInfo attachInfo = {XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO};
attachInfo.next = NULL;
attachInfo.countActionSets = 1;
attachInfo.actionSets = &profile->actionSet;
CHECK_XR(xrAttachSessionActionSets(oxr->session, &attachInfo), "failed to attach action set");
profile->valid = true;
}
static void init_xr_controllers(OpenXRSessionData* oxr, XrInstance xrInstance)
{
switch (oxr->detectedProfile) {
case OpenXrProfile::OCULUS_TOUCH:
init_xr_oculus_touch_profile(oxr, xrInstance);
break;
}
}
static void fetch_oculus_touch_xr_data(OpenXRSessionData *oxr,
GHOST_XrDrawInfo *drawInfo,
GHOST_XrControllersData &controllers_data)
{
OculusTouchProfile profile = oxr->oculusTouchProfile;
if (!profile.valid) {
throw GHOST_XrException(
"Unable to fetch Oculus Touch controllers data: profile not initialized");
}
/* Retrieve active action set */
const XrActiveActionSet activeActionSet = {profile.actionSet, XR_NULL_PATH};
XrActionsSyncInfo syncInfo = {XR_TYPE_ACTIONS_SYNC_INFO};
syncInfo.countActiveActionSets = 1;
syncInfo.activeActionSets = &activeActionSet;
CHECK_XR(xrSyncActions(oxr->session, &syncInfo), "failed to sync actions");
XrActionStateFloat floatState = {XR_TYPE_ACTION_STATE_FLOAT};
floatState.next = NULL;
XrActionStateBoolean boolState = {XR_TYPE_ACTION_STATE_BOOLEAN};
boolState.next = NULL;
/* Retrieve hands common actions */
const int hands = 2;
for (int i = 0; i < hands; i++) {
XrActionStateGetInfo getInfo = {XR_TYPE_ACTION_STATE_GET_INFO};
getInfo.next = NULL;
getInfo.subactionPath = profile.handPaths[i];
/* Trigger values & touch */
getInfo.action = profile.triggerValueAction;
CHECK_XR(xrGetActionStateFloat(oxr->session, &getInfo, &floatState),
"failed to get trigger value!");
if (i == 0)
controllers_data.left_trigger_value = floatState.currentState;
else
controllers_data.right_trigger_value = floatState.currentState;
getInfo.action = profile.triggerTouchAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get trigger touch!");
if (i == 0)
controllers_data.left_trigger_touch = boolState.currentState;
else
controllers_data.right_trigger_touch = boolState.currentState;
/* Squeeze values */
getInfo.action = profile.squeezeValueAction;
CHECK_XR(xrGetActionStateFloat(oxr->session, &getInfo, &floatState),
"failed to get squeeze value!");
if (i == 0)
controllers_data.left_grip_value = floatState.currentState;
else
controllers_data.right_grip_value = floatState.currentState;
/* Thumbstick X values */
getInfo.action = profile.thumbstickXAction;
CHECK_XR(xrGetActionStateFloat(oxr->session, &getInfo, &floatState),
"failed to get thumb X value!");
if (i == 0)
controllers_data.left_thumbstick_x = floatState.currentState;
else
controllers_data.right_thumbstick_x = floatState.currentState;
/* Thumbstick Y values */
getInfo.action = profile.thumbstickYAction;
CHECK_XR(xrGetActionStateFloat(oxr->session, &getInfo, &floatState),
"failed to get thumb Y value!");
if (i == 0)
controllers_data.left_thumbstick_y = floatState.currentState;
else
controllers_data.right_thumbstick_y = floatState.currentState;
/* Thumbstick click values & touch */
getInfo.action = profile.thumbstickClickAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get thumb click value!");
if (i == 0)
controllers_data.left_thumbstick_click = boolState.currentState;
else
controllers_data.right_thumbstick_click = boolState.currentState;
getInfo.action = profile.thumbstickTouchAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get thumb touch value!");
if (i == 0)
controllers_data.left_thumbstick_touch = boolState.currentState;
else
controllers_data.right_thumbstick_touch = boolState.currentState;
/* Controller action poses */
getInfo.action = profile.gripPoseAction;
XrActionStatePose poseState = {XR_TYPE_ACTION_STATE_POSE};
poseState.next = NULL;
CHECK_XR(xrGetActionStatePose(oxr->session, &getInfo, &poseState),
"failed to get pose value!");
}
/* Left hand */
XrActionStateGetInfo getInfo = {XR_TYPE_ACTION_STATE_GET_INFO};
getInfo.next = NULL;
getInfo.subactionPath = profile.handPaths[0];
getInfo.action = profile.leftXClickAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get left X click value!");
controllers_data.left_primary_click = boolState.currentState;
/*controllers_data.left_primary_onpress = boolState.changedSinceLastSync &&
boolState.currentState;
controllers_data.left_primary_onrelease = boolState.changedSinceLastSync &&
!boolState.currentState;*/
getInfo.action = profile.leftXTouchAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get left X touch value!");
controllers_data.left_primary_touch = boolState.currentState;
getInfo.action = profile.leftYClickAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get left X click value!");
controllers_data.left_secondary_click = boolState.currentState;
getInfo.action = profile.leftYTouchAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get left Y touch value!");
controllers_data.left_secondary_touch = boolState.currentState;
/* Right hand */
getInfo.subactionPath = profile.handPaths[1];
getInfo.action = profile.rightAClickAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get right A click value!");
controllers_data.right_primary_click = boolState.currentState;
getInfo.action = profile.rightATouchAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get right A touch value!");
controllers_data.right_primary_touch = boolState.currentState;
getInfo.action = profile.rightBClickAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get right B click value!");
controllers_data.right_secondary_click = boolState.currentState;
getInfo.action = profile.rightBTouchAction;
CHECK_XR(xrGetActionStateBoolean(oxr->session, &getInfo, &boolState),
"failed to get right B touch value!");
controllers_data.right_secondary_touch = boolState.currentState;
/* Retrieve controller spaces */
XrSpaceLocation spaceLocation[hands];
bool spaceLocationValid[hands];
for (int i = 0; i < hands; i++) {
spaceLocation[i].type = XR_TYPE_SPACE_LOCATION;
spaceLocation[i].next = NULL;
CHECK_XR(xrLocateSpace(profile.handSpaces[i],
oxr->reference_space,
drawInfo->frame_state.predictedDisplayTime,
&spaceLocation[i]),
"failed to locate space!");
spaceLocationValid[i] =
//(spaceLocation[i].locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 &&
(spaceLocation[i].locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0;
if (spaceLocationValid[i]) {
if (i == 0) {
memcpy(&controllers_data.left_pose, &spaceLocation[i].pose, sizeof(XrPosef));
}
else {
memcpy(&controllers_data.right_pose, &spaceLocation[i].pose, sizeof(XrPosef));
}
}
}
}
static void set_xr_controllers_data(OpenXRSessionData *oxr,
GHOST_XrDrawInfo *drawInfo,
GHOST_XrControllersData& controllers_data)
{
switch (oxr->detectedProfile) {
case OpenXrProfile::OCULUS_TOUCH:
fetch_oculus_touch_xr_data(oxr, drawInfo, controllers_data);
break;
}
}
void GHOST_XrSession::start(const GHOST_XrSessionBeginInfo *begin_info)
{
assert(m_context->getInstance() != XR_NULL_HANDLE);
@@ -195,12 +740,15 @@ void GHOST_XrSession::start(const GHOST_XrSessionBeginInfo *begin_info)
"detailed error information to the command line.");
prepareDrawing();
create_reference_spaces(m_oxr.get(), &begin_info->base_pose);
init_xr_controllers(m_oxr.get(), m_context->getInstance());
}
void GHOST_XrSession::requestEnd()
{
xrRequestExitSession(m_oxr->session);
CHECK_XR(xrRequestExitSession(m_oxr->session), "Failed to request the end of the session.");
}
void GHOST_XrSession::beginSession()
@@ -217,7 +765,8 @@ void GHOST_XrSession::endSession()
}
GHOST_XrSession::LifeExpectancy GHOST_XrSession::handleStateChangeEvent(
const XrEventDataSessionStateChanged *lifecycle)
const XrEventDataSessionStateChanged *lifecycle,
bool debug)
{
m_oxr->session_state = lifecycle->state;
@@ -225,16 +774,47 @@ GHOST_XrSession::LifeExpectancy GHOST_XrSession::handleStateChangeEvent(
assert((m_oxr->session == XR_NULL_HANDLE) || (m_oxr->session == lifecycle->session));
switch (lifecycle->state) {
case XR_SESSION_STATE_IDLE:
{
if (debug) printf("XR_SESSION_STATE_IDLE.\n");
break;
}
case XR_SESSION_STATE_READY: {
if (debug) printf("XR_SESSION_STATE_READY.\n");
beginSession();
break;
}
case XR_SESSION_STATE_STOPPING:
endSession();
break;
case XR_SESSION_STATE_SYNCHRONIZED:
{
if (debug) printf("XR_SESSION_STATE_SYNCHRONIZED.\n");
break;
}
case XR_SESSION_STATE_VISIBLE:
{
if (debug) printf("XR_SESSION_STATE_VISIBLE.\n");
break;
}
case XR_SESSION_STATE_FOCUSED:
{
if (debug) printf("XR_SESSION_STATE_FOCUSED.\n");
break;
}
case XR_SESSION_STATE_STOPPING:
{
if (debug) printf("XR_SESSION_STATE_STOPPING.\n");
endSession();
break;
}
case XR_SESSION_STATE_EXITING:
{
if (debug) printf("XR_SESSION_STATE_EXITING.\n");
return SESSION_DESTROY;
}
case XR_SESSION_STATE_LOSS_PENDING:
return SESSION_DESTROY;
{
if (debug) printf("XR_SESSION_STATE_LOSS_PENDING.\n");
return SESSION_DESTROY;
}
default:
break;
}
@@ -352,7 +932,7 @@ void GHOST_XrSession::draw(void *draw_customdata)
endFrameDrawing(&layers);
}
static void copy_openxr_pose_to_ghost_pose(const XrPosef &oxr_pose, GHOST_XrPose &r_ghost_pose)
static void copy_openxr_pose_to_ghost_pose(GHOST_XrPose &r_ghost_pose, const XrPosef &oxr_pose)
{
/* Set and convert to Blender coodinate space. */
r_ghost_pose.position[0] = oxr_pose.position.x;
@@ -367,7 +947,7 @@ static void copy_openxr_pose_to_ghost_pose(const XrPosef &oxr_pose, GHOST_XrPose
static void ghost_xr_draw_view_info_from_view(const XrView &view, GHOST_XrDrawViewInfo &r_info)
{
/* Set and convert to Blender coodinate space. */
copy_openxr_pose_to_ghost_pose(view.pose, r_info.eye_pose);
copy_openxr_pose_to_ghost_pose(r_info.eye_pose, view.pose);
r_info.fov.angle_left = view.fov.angleLeft;
r_info.fov.angle_right = view.fov.angleRight;
@@ -383,14 +963,49 @@ static bool ghost_xr_draw_view_expects_srgb_buffer(const GHOST_XrContext *contex
return (context->getOpenXRRuntimeID() == OPENXR_RUNTIME_MONADO);
}
static void copy_controllers_data_to_draw_view_info(GHOST_XrDrawViewInfo *draw_view_info, GHOST_XrControllersData const &controllers_data)
{
copy_openxr_pose_to_ghost_pose(draw_view_info->controllers_data.left_pose, controllers_data.left_pose);
copy_openxr_pose_to_ghost_pose(draw_view_info->controllers_data.right_pose, controllers_data.right_pose);
draw_view_info->controllers_data.left_grip_value = controllers_data.left_grip_value;
draw_view_info->controllers_data.right_grip_value = controllers_data.right_grip_value;
draw_view_info->controllers_data.left_trigger_value = controllers_data.left_trigger_value;
draw_view_info->controllers_data.left_trigger_touch = controllers_data.left_trigger_touch;
draw_view_info->controllers_data.right_trigger_value = controllers_data.right_trigger_value;
draw_view_info->controllers_data.right_trigger_touch = controllers_data.right_trigger_touch;
draw_view_info->controllers_data.left_thumbstick_x = controllers_data.left_thumbstick_x;
draw_view_info->controllers_data.left_thumbstick_y = controllers_data.left_thumbstick_y;
draw_view_info->controllers_data.left_thumbstick_click = controllers_data.left_thumbstick_click;
draw_view_info->controllers_data.left_thumbstick_touch = controllers_data.left_thumbstick_touch;
draw_view_info->controllers_data.right_thumbstick_x = controllers_data.right_thumbstick_x;
draw_view_info->controllers_data.right_thumbstick_y = controllers_data.right_thumbstick_y;
draw_view_info->controllers_data.right_thumbstick_click = controllers_data.right_thumbstick_click;
draw_view_info->controllers_data.right_thumbstick_touch = controllers_data.right_thumbstick_touch;
draw_view_info->controllers_data.left_primary_click = controllers_data.left_primary_click;
draw_view_info->controllers_data.left_primary_touch = controllers_data.left_primary_touch;
draw_view_info->controllers_data.left_secondary_click = controllers_data.left_secondary_click;
draw_view_info->controllers_data.left_secondary_touch = controllers_data.left_secondary_touch;
draw_view_info->controllers_data.right_primary_click = controllers_data.right_primary_click;
draw_view_info->controllers_data.right_primary_touch = controllers_data.right_primary_touch;
draw_view_info->controllers_data.right_secondary_click = controllers_data.right_secondary_click;
draw_view_info->controllers_data.right_secondary_touch = controllers_data.right_secondary_touch;
}
void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
XrCompositionLayerProjectionView &r_proj_layer_view,
XrSpaceLocation &view_location,
XrView &view,
GHOST_XrControllersData const& controllers_data,
void *draw_customdata)
{
XrSwapchainImageBaseHeader *swapchain_image = swapchain.acquireDrawableSwapchainImage();
GHOST_XrDrawViewInfo draw_view_info = {};
copy_controllers_data_to_draw_view_info(&draw_view_info, controllers_data);
r_proj_layer_view.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
r_proj_layer_view.pose = view.pose;
@@ -402,7 +1017,8 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
draw_view_info.ofsy = r_proj_layer_view.subImage.imageRect.offset.y;
draw_view_info.width = r_proj_layer_view.subImage.imageRect.extent.width;
draw_view_info.height = r_proj_layer_view.subImage.imageRect.extent.height;
copy_openxr_pose_to_ghost_pose(view_location.pose, draw_view_info.local_pose);
copy_openxr_pose_to_ghost_pose(draw_view_info.local_pose, view_location.pose);
ghost_xr_draw_view_info_from_view(view, draw_view_info);
/* Draw! */
@@ -415,6 +1031,9 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
XrCompositionLayerProjection GHOST_XrSession::drawLayer(
std::vector<XrCompositionLayerProjectionView> &r_proj_layer_views, void *draw_customdata)
{
GHOST_XrControllersData controllersData = {};
set_xr_controllers_data(m_oxr.get(), m_draw_info.get(), controllersData);
XrViewLocateInfo viewloc_info = {XR_TYPE_VIEW_LOCATE_INFO};
XrViewState view_state = {XR_TYPE_VIEW_STATE};
XrCompositionLayerProjection layer = {XR_TYPE_COMPOSITION_LAYER_PROJECTION};
@@ -446,6 +1065,7 @@ XrCompositionLayerProjection GHOST_XrSession::drawLayer(
r_proj_layer_views[view_idx],
view_location,
m_oxr->views[view_idx],
controllersData,
draw_customdata);
}
@@ -500,6 +1120,7 @@ void GHOST_XrSession::bindGraphicsContext()
{
const GHOST_XrCustomFuncs &custom_funcs = m_context->getCustomFuncs();
assert(custom_funcs.gpu_ctx_bind_fn);
m_gpu_ctx = static_cast<GHOST_Context *>(custom_funcs.gpu_ctx_bind_fn());
}

View File

@@ -30,6 +30,7 @@ class GHOST_XrContext;
class GHOST_XrSwapchain;
struct GHOST_XrDrawInfo;
struct OpenXRSessionData;
struct GHOST_XrControllersData;
class GHOST_XrSession {
public:
@@ -44,7 +45,7 @@ class GHOST_XrSession {
void start(const GHOST_XrSessionBeginInfo *begin_info);
void requestEnd();
LifeExpectancy handleStateChangeEvent(const XrEventDataSessionStateChanged *lifecycle);
LifeExpectancy handleStateChangeEvent(const XrEventDataSessionStateChanged *lifecycle, bool debug = false);
bool isRunning() const;
bool needsUpsideDownDrawing() const;
@@ -80,6 +81,7 @@ class GHOST_XrSession {
XrCompositionLayerProjectionView &r_proj_layer_view,
XrSpaceLocation &view_location,
XrView &view,
GHOST_XrControllersData const& controllers_data,
void *draw_customdata);
void beginFrameDrawing();
void endFrameDrawing(std::vector<XrCompositionLayerBaseHeader *> *layers);

View File

@@ -1634,10 +1634,14 @@ static void draw_frustum_bound_sphere_calc(const BoundBox *bbox,
bsphere->center[0] = farcenter[0] * z / e;
bsphere->center[1] = farcenter[1] * z / e;
bsphere->center[2] = z;
bsphere->radius = len_v3v3(bsphere->center, farpoint);
/* Transform to world space. */
mul_m4_v3(viewinv, bsphere->center);
/* In order to compute sphere radius, the farpoint need to be transformed as well */
/* (if viewinv contains scaling) */
mul_m4_v3(viewinv, farpoint);
bsphere->radius = len_v3v3(bsphere->center, farpoint);
}
}

View File

@@ -92,6 +92,172 @@ static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float *
# endif
}
static void rna_XrSessionState_world_location_get(PointerRNA *ptr, float *r_values)
{
# ifdef WITH_XR_OPENXR
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
WM_xr_session_state_world_location_get(xr, r_values);
# else
UNUSED_VARS(ptr);
zero_v3(r_values);
# endif
}
static void rna_XrSessionState_world_location_set(PointerRNA *ptr, float* values)
{
# ifdef WITH_XR_OPENXR
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
WM_xr_session_state_world_location_set(xr, values);
# else
UNUSED_VARS(ptr);
UNUSED_VARS(values);
# endif
}
static void rna_XrSessionState_world_rotation_get(PointerRNA *ptr, float *r_values)
{
# ifdef WITH_XR_OPENXR
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
WM_xr_session_state_world_rotation_get(xr, r_values);
# else
UNUSED_VARS(ptr);
unit_qt(r_values);
# endif
}
static void rna_XrSessionState_world_rotation_set(PointerRNA *ptr, float *values)
{
# ifdef WITH_XR_OPENXR
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
WM_xr_session_state_world_rotation_set(xr, values);
#else
UNUSED_VARS(ptr);
UNUSED_VARS(values);
# endif
}
static float rna_XrSessionState_world_scale_get(PointerRNA *ptr)
{
# ifdef WITH_XR_OPENXR
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
return WM_xr_session_state_world_scale_get(xr);
# else
return 1.f;
# endif
}
static void rna_XrSessionState_world_scale_set(PointerRNA *ptr, float value)
{
# ifdef WITH_XR_OPENXR
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
WM_xr_session_state_world_scale_set(xr, value);
# else
UNUSED_VARS(ptr);
UNUSED_VARS(value);
# endif
}
# ifdef WITH_XR_OPENXR
# define rna_XrSessionState(side, attribute, type, clearFn) \
static void rna_XrSessionState_##side##_controller_##attribute##_get(PointerRNA * ptr, \
type *r_values) \
{ \
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr); \
WM_xr_session_state_##side##_controller_##attribute##_get(xr, r_values); \
}
# else
# define rna_XrSessionState(name, type, clearFn) \
{ \
static void rna_XrSessionState_##side##_controller_##attribute##_get(PointerRNA *ptr, \
type *r_values) \
{ \
UNUSED_VARS(ptr); \
clearFn(r_values); \
}
# endif
/* rna_XrSessionState_left_controller_location_get */
rna_XrSessionState(left, location, float, zero_v3)
/* rna_XrSessionState_left_controller_rotation_get */
rna_XrSessionState(left, rotation, float, unit_qt)
/* rna_XrSessionState_right_controller_location_get */
rna_XrSessionState(right, location, float, zero_v3)
/* rna_XrSessionState_right_controller_rotation_get */
rna_XrSessionState(right, rotation, float, unit_qt)
# ifdef WITH_XR_OPENXR
# define rna_XrSessionControllerValue(side, attribute, type)\
static type rna_XrSessionState_##side##_controller_##attribute##_get(PointerRNA *ptr) \
{ \
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr); \
return WM_xr_session_state_##side##_##attribute##_get(xr); \
}
# else
# define rna_XrSessionControllerButton(side, attribute, type) \
static type rna_XrSessionState_##side##_controller_##attribute##_get(PointerRNA *ptr) \
{ \
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr); \
return (type)0; \
}
#endif
/* rna_XrSessionState_left_controller_trigger_value_get */
rna_XrSessionControllerValue(left, trigger_value, float)
/* rna_XrSessionState_Right_controller_trigger_value_get */
rna_XrSessionControllerValue(right, trigger_value, float)
/* rna_XrSessionState_left_controller_trigger_touch_get */
rna_XrSessionControllerValue(left, trigger_touch, bool)
/* rna_XrSessionState_Right_controller_trigger_touch_get */
rna_XrSessionControllerValue(right, trigger_touch, bool)
/* rna_XrSessionState_left_controller_grip_value_get */
rna_XrSessionControllerValue(left, grip_value, float)
/* rna_XrSessionState_Right_controller_grip_value_get */
rna_XrSessionControllerValue(right, grip_value, float)
/* rna_XrSessionState_left_controller_primary_click_get */
rna_XrSessionControllerValue(left, primary_click, bool)
/* rna_XrSessionState_left_controller_primary_touch_get */
rna_XrSessionControllerValue(left, primary_touch, bool)
/* rna_XrSessionState_left_controller_secondary_click_get */
rna_XrSessionControllerValue(left, secondary_click, bool)
/* rna_XrSessionState_left_controller_secondary_touch_get */
rna_XrSessionControllerValue(left, secondary_touch, bool)
/* rna_XrSessionState_right_controller_primary_click_get */
rna_XrSessionControllerValue(right, primary_click, bool)
/* rna_XrSessionState_right_controller_primary_touch_get */
rna_XrSessionControllerValue(right, primary_touch, bool)
/* rna_XrSessionState_right_controller_secondary_click_get */
rna_XrSessionControllerValue(right, secondary_click, bool)
/* rna_XrSessionState_right_controller_secondary_touch_get */
rna_XrSessionControllerValue(right, secondary_touch, bool)
/* rna_XrSessionState_left_controller_thumbstick_x_get */
rna_XrSessionControllerValue(left, thumbstick_x, float)
/* rna_XrSessionState_right_controller_thumbstick_x_get */
rna_XrSessionControllerValue(right, thumbstick_x, float)
/* rna_XrSessionState_left_controller_thumbstick_y_get */
rna_XrSessionControllerValue(left, thumbstick_y, float)
/* rna_XrSessionState_right_controller_thumbstick_y_get */
rna_XrSessionControllerValue(right, thumbstick_y, float)
/* rna_XrSessionState_left_controller_thumbstick_click_get */
rna_XrSessionControllerValue(left, thumbstick_click, bool)
/* rna_XrSessionState_right_controller_thumbstick_click_get */
rna_XrSessionControllerValue(right, thumbstick_click, bool)
/* rna_XrSessionState_left_controller_thumbstick_touch_get */
rna_XrSessionControllerValue(left, thumbstick_touch, bool)
/* rna_XrSessionState_right_controller_thumbstick_touch_get */
rna_XrSessionControllerValue(right, thumbstick_touch, bool)
#else /* RNA_RUNTIME */
static void rna_def_xr_session_settings(BlenderRNA *brna)
@@ -189,6 +355,22 @@ static void rna_def_xr_session_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
}
static void rna_def_xr_define_sized_property(StructRNA *srna,
char *name,
char *description,
char *function_name,
PropertySubType sub_type,
PropertyType type,
int array_size)
{
PropertyRNA *prop = RNA_def_property(srna, name, type, sub_type);
RNA_def_property_array(prop, array_size);
RNA_def_property_float_funcs(prop, function_name, NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, name, description);
}
static void rna_def_xr_session_state(BlenderRNA *brna)
{
StructRNA *srna;
@@ -230,6 +412,175 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
prop,
"Viewer Pose Rotation",
"Last known rotation of the viewer pose (center between the eyes) in world space");
prop = RNA_def_property(srna, "world_location", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop,
"rna_XrSessionState_world_location_get",
"rna_XrSessionState_world_location_set",
NULL);
RNA_def_property_ui_text(
prop,
"World Location",
"Last known location of the world in world space");
prop = RNA_def_property(srna, "world_rotation", PROP_FLOAT, PROP_QUATERNION);
RNA_def_property_array(prop, 4);
RNA_def_property_float_funcs(prop,
"rna_XrSessionState_world_rotation_get",
"rna_XrSessionState_world_rotation_set",
NULL);
RNA_def_property_ui_text(
prop,
"World Rotation",
"Last known rotation of the world in world space");
prop = RNA_def_property(srna, "world_scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(
prop, "rna_XrSessionState_world_scale_get", "rna_XrSessionState_world_scale_set", NULL);
RNA_def_property_ui_text(prop, "World Scale", "Get World Scale Value");
rna_def_xr_define_sized_property(srna,
"left_controller_location",
"Last known location of the left controller in world space",
"rna_XrSessionState_left_controller_location_get",
PROP_TRANSLATION,
PROP_FLOAT,
3);
rna_def_xr_define_sized_property(srna,
"left_controller_rotation",
"Last known rotation of the left controller in world space",
"rna_XrSessionState_left_controller_rotation_get",
PROP_QUATERNION,
PROP_FLOAT,
4);
rna_def_xr_define_sized_property(srna,
"right_controller_location",
"Last known location of the right controller in world space",
"rna_XrSessionState_right_controller_location_get",
PROP_TRANSLATION,
PROP_FLOAT,
3);
rna_def_xr_define_sized_property(srna,
"right_controller_rotation",
"Last known rotation of the right controller in world space",
"rna_XrSessionState_right_controller_rotation_get",
PROP_QUATERNION,
PROP_FLOAT,
4);
prop = RNA_def_property(srna, "left_trigger_value", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_left_controller_trigger_value_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Trigger", "Get Left Trigger Value");
prop = RNA_def_property(srna, "left_trigger_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_trigger_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Trigger Touch", "Get Left Trigger Touch");
prop = RNA_def_property(srna, "right_trigger_value", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_right_controller_trigger_value_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Trigger", "Get Right Trigger Value");
prop = RNA_def_property(srna, "right_trigger_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_trigger_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Trigger Touch", "Get Right Trigger Touch");
prop = RNA_def_property(srna, "left_grip_value", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_left_controller_grip_value_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Grip", "Get Left Grip Value");
prop = RNA_def_property(srna, "right_grip_value", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_right_controller_grip_value_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Grip", "Get Right Grip Value");
prop = RNA_def_property(srna, "left_primary_click", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_primary_click_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Primary Click", "Get Left Primary Click");
prop = RNA_def_property(srna, "left_primary_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_primary_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Primary Touch", "Get Left Primary Touch");
prop = RNA_def_property(srna, "left_secondary_click", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_secondary_click_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Secondary Click", "Get Left Secondary Click");
prop = RNA_def_property(srna, "left_secondary_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_secondary_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Secondary Touch", "Get Left Secondary Touch");
prop = RNA_def_property(srna, "right_primary_click", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_primary_click_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Primary Click", "Get Right Primary Click");
prop = RNA_def_property(srna, "right_primary_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_primary_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Primary Touch", "Get Right Primary Touch");
prop = RNA_def_property(srna, "right_secondary_click", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_secondary_click_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Secondary Click", "Get Right Secondary Click");
prop = RNA_def_property(srna, "right_secondary_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_secondary_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Secondary Touch", "Get Right Secondary Touch");
prop = RNA_def_property(srna, "left_thumbstick_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_left_controller_thumbstick_x_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Thumbstick X", "Get Left Thumbstick X Value");
prop = RNA_def_property(srna, "left_thumbstick_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_left_controller_thumbstick_y_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Thumbstick Y", "Get Left Thumbstick Y Value");
prop = RNA_def_property(srna, "left_thumbstick_click", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_thumbstick_click_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Thumbstick Click", "Get Left Thumbstick Click Value");
prop = RNA_def_property(srna, "left_thumbstick_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_left_controller_thumbstick_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Left Thumbstick Touch", "Get Left Thumbstick Touch Value");
prop = RNA_def_property(srna, "right_thumbstick_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_right_controller_thumbstick_x_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Thumbstick X", "Get Right Thumbstick X Value");
prop = RNA_def_property(srna, "right_thumbstick_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_XrSessionState_right_controller_thumbstick_y_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Thumbstick Y", "Get Right Thumbstick Y Value");
prop = RNA_def_property(srna, "right_thumbstick_click", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_thumbstick_click_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Thumbstick Click", "Get Right Thumbstick Click Value");
prop = RNA_def_property(srna, "right_thumbstick_touch", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_XrSessionState_right_controller_thumbstick_touch_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Right Thumbstick Touch", "Get Right Thumbstick Touch Value");
}
void RNA_def_xr(BlenderRNA *brna)

View File

@@ -881,6 +881,48 @@ bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_ro
bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr,
float r_viewmat[4][4],
float *r_focal_len);
/* world */
bool WM_xr_session_state_world_location_get(const wmXrData* xr, float r_location[3]);
bool WM_xr_session_state_world_location_set(const wmXrData* xr, const float r_location[3]);
bool WM_xr_session_state_world_rotation_get(const wmXrData* xr, float r_rotation[4]);
bool WM_xr_session_state_world_rotation_set(const wmXrData* xr, const float r_rotation[4]);
float WM_xr_session_state_world_scale_get(const wmXrData* xr);
bool WM_xr_session_state_world_scale_set(const wmXrData* xr, const float scale);
bool WM_xr_session_state_world_matrix_get(const wmXrData* xr, float world_matrix[4][4]);
/* controllers */
bool WM_xr_session_state_left_controller_location_get(const wmXrData* xr, float r_location[3]);
bool WM_xr_session_state_left_controller_rotation_get(const wmXrData* xr, float r_rotation[4]);
bool WM_xr_session_state_right_controller_location_get(const wmXrData* xr, float r_location[3]);
bool WM_xr_session_state_right_controller_rotation_get(const wmXrData* xr, float r_rotation[4]);
float WM_xr_session_state_left_trigger_value_get(const wmXrData* xr);
bool WM_xr_session_state_left_trigger_touch_get(const wmXrData* xr);
float WM_xr_session_state_right_trigger_value_get(const wmXrData* xr);
bool WM_xr_session_state_right_trigger_touch_get(const wmXrData* xr);
float WM_xr_session_state_left_grip_value_get(const wmXrData* xr);
float WM_xr_session_state_right_grip_value_get(const wmXrData* xr);
bool WM_xr_session_state_left_primary_click_get(const wmXrData* xr);
bool WM_xr_session_state_left_primary_touch_get(const wmXrData* xr);
bool WM_xr_session_state_left_secondary_click_get(const wmXrData* xr);
bool WM_xr_session_state_left_secondary_touch_get(const wmXrData* xr);
bool WM_xr_session_state_right_primary_click_get(const wmXrData* xr);
bool WM_xr_session_state_right_primary_touch_get(const wmXrData* xr);
bool WM_xr_session_state_right_secondary_click_get(const wmXrData* xr);
bool WM_xr_session_state_right_secondary_touch_get(const wmXrData* xr);
float WM_xr_session_state_left_thumbstick_x_get(const wmXrData* xr);
float WM_xr_session_state_left_thumbstick_y_get(const wmXrData* xr);
float WM_xr_session_state_right_thumbstick_x_get(const wmXrData* xr);
float WM_xr_session_state_right_thumbstick_y_get(const wmXrData* xr);
bool WM_xr_session_state_left_thumbstick_click_get(const wmXrData* xr);
bool WM_xr_session_state_right_thumbstick_click_get(const wmXrData* xr);
bool WM_xr_session_state_left_thumbstick_touch_get(const wmXrData* xr);
bool WM_xr_session_state_right_thumbstick_touch_get(const wmXrData* xr);
#endif
#ifdef __cplusplus

View File

@@ -40,6 +40,8 @@
#include "wm_surface.h"
#include "wm_xr_intern.h"
#include "BLI_math_rotation.h"
typedef struct {
wmWindowManager *wm;
} wmXrErrorHandlerData;
@@ -105,6 +107,13 @@ bool wm_xr_init(wmWindowManager *wm)
if (!wm->xr.runtime) {
wm->xr.runtime = wm_xr_runtime_data_create();
wm->xr.runtime->context = context;
/* Initialize the "world navigation" matrix */
unit_qt(wm->xr.runtime->session_state.world_pose.orientation_quat);
wm->xr.runtime->session_state.world_pose.position[0] = 0.f;
wm->xr.runtime->session_state.world_pose.position[1] = 0.f;
wm->xr.runtime->session_state.world_pose.position[2] = 0.f;
wm->xr.runtime->session_state.world_scale = 1.f;
}
}
BLI_assert(wm->xr.runtime && wm->xr.runtime->context);

View File

@@ -37,7 +37,7 @@
#include "wm_surface.h"
#include "wm_xr_intern.h"
void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4])
void wm_xr_pose_to_viewmat(float r_viewmat[4][4], const GHOST_XrPose* pose)
{
float iquat[4];
invert_qt_qt_normalized(iquat, pose->orientation_quat);
@@ -48,6 +48,7 @@ void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4])
static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data,
const GHOST_XrDrawViewInfo *draw_view,
const XrSessionSettings *session_settings,
float scale,
float r_view_mat[4][4],
float r_proj_mat[4][4])
{
@@ -65,15 +66,15 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data,
draw_view->fov.angle_right,
draw_view->fov.angle_up,
draw_view->fov.angle_down,
session_settings->clip_start,
session_settings->clip_end);
session_settings->clip_start * scale,
session_settings->clip_end * scale);
float eye_mat[4][4];
float base_mat[4][4];
wm_xr_pose_to_viewmat(&eye_pose, eye_mat);
wm_xr_pose_to_viewmat(eye_mat, &eye_pose);
/* Calculate the base pose matrix (in world space!). */
wm_xr_pose_to_viewmat(&draw_data->base_pose, base_mat);
wm_xr_pose_to_viewmat(base_mat, &draw_data->base_pose);
mul_m4_m4m4(r_view_mat, eye_mat, base_mat);
}
@@ -95,6 +96,16 @@ static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
GPU_viewport_draw_to_screen_ex(surface_data->viewport, 0, &rect, draw_view->expects_srgb_buffer);
}
void apply_world_transform(float viewmat[4][4], GHOST_XrPose world_pose, float scale)
{
float world[4][4];
float scalev[3] = {scale, scale, scale};
loc_quat_size_to_mat4(world, world_pose.position, world_pose.orientation_quat, scalev);
mul_m4_m4m4(viewmat, viewmat, world);
}
/**
* \brief Draw a viewport for a single eye.
*
@@ -116,13 +127,19 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
BLI_assert(WM_xr_session_is_ready(xr_data));
wm_xr_session_draw_data_update(session_state, settings, draw_view, draw_data);
wm_xr_draw_matrices_create(draw_data, draw_view, settings, viewmat, winmat);
wm_xr_session_state_update(settings, draw_data, draw_view, session_state);
wm_xr_draw_matrices_create(
draw_data, draw_view, settings, session_state->world_scale, viewmat, winmat);
apply_world_transform(viewmat, session_state->world_pose, session_state->world_scale);
wm_xr_session_state_update(settings, draw_data, draw_view, session_state, viewmat);
if (!wm_xr_session_surface_offscreen_ensure(surface_data, draw_view)) {
return;
}
/* In case a framebuffer is still bound from drawing the last eye. */
GPU_framebuffer_restore();
/* Some systems have drawing glitches without this. */
@@ -138,8 +155,8 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
display_flags,
viewmat,
winmat,
settings->clip_start,
settings->clip_end,
settings->clip_start * session_state->world_scale,
settings->clip_end * session_state->world_scale,
false,
true,
true,

View File

@@ -25,6 +25,33 @@
#include "wm_xr.h"
typedef struct wmXrControllersData {
GHOST_XrPose left_pose;
GHOST_XrPose right_pose;
float left_trigger_value;
float right_trigger_value;
bool left_trigger_touch;
bool right_trigger_touch;
float left_grip_value;
float right_grip_value;
bool left_primary_click;
bool left_primary_touch;
bool left_secondary_click;
bool left_secondary_touch;
bool right_primary_click;
bool right_primary_touch;
bool right_secondary_click;
bool right_secondary_touch;
float left_thumbstick_x;
float left_thumbstick_y;
bool left_thumbstick_click;
bool left_thumbstick_touch;
float right_thumbstick_x;
float right_thumbstick_y;
bool right_thumbstick_click;
bool right_thumbstick_touch;
} wmXrControllersData;
typedef struct wmXrSessionState {
bool is_started;
@@ -38,6 +65,7 @@ typedef struct wmXrSessionState {
* resetting to base pose. */
char prev_base_pose_type; /* eXRSessionBasePoseType */
Object *prev_base_pose_object;
/** Copy of XrSessionSettings.flag created on the last draw call, stored to detect changes. */
int prev_settings_flag;
/** Copy of wmXrDrawData.eye_position_ofs. */
@@ -45,6 +73,13 @@ typedef struct wmXrSessionState {
bool force_reset_to_base_pose;
bool is_view_data_set;
/** World */
GHOST_XrPose world_pose;
float world_scale;
/** Controllers */
wmXrControllersData controllers_data;
} wmXrSessionState;
typedef struct wmXrRuntimeData {
@@ -84,13 +119,14 @@ void wm_xr_session_draw_data_update(const wmXrSessionState *state,
void wm_xr_session_state_update(const XrSessionSettings *settings,
const wmXrDrawData *draw_data,
const GHOST_XrDrawViewInfo *draw_view,
wmXrSessionState *state);
wmXrSessionState *state,
float viewmat[4][4]);
bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data,
const GHOST_XrDrawViewInfo *draw_view);
void *wm_xr_session_gpu_binding_context_create(void);
void wm_xr_session_gpu_binding_context_destroy(GHOST_ContextHandle context);
void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]);
void wm_xr_pose_to_viewmat(float r_viewmat[4][4], const GHOST_XrPose* pose);
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata);
#endif

View File

@@ -132,10 +132,20 @@ static void wm_xr_session_base_pose_calc(const Scene *scene,
mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->obmat);
/* Only use rotation around Z-axis to align view with floor. */
/*
quat_to_eul(tmp_eul, tmp_quat);
tmp_eul[0] = M_PI_2;
tmp_eul[1] = 0;
eul_to_quat(r_base_pose->orientation_quat, tmp_eul);
*/
/* TODO: find out why we did it */
/* override quat */
tmp_eul[0] = M_PI_2;
tmp_eul[1] = 0;
tmp_eul[2] = 0;
eul_to_quat(r_base_pose->orientation_quat, tmp_eul);
}
else {
copy_v3_fl(r_base_pose->position, 0.0f);
@@ -203,6 +213,24 @@ void wm_xr_session_draw_data_update(const wmXrSessionState *state,
}
}
void wm_xr_session_controller_transform_update(GHOST_XrPose *dst_pose,
const GHOST_XrPose *base_pose,
const GHOST_XrPose *pose)
{
copy_v3_v3(dst_pose->position, base_pose->position);
dst_pose->position[0] = base_pose->position[0] + pose->position[0];
dst_pose->position[1] = base_pose->position[1] - pose->position[2];
dst_pose->position[2] = base_pose->position[2] + pose->position[1];
mul_qt_qtqt(dst_pose->orientation_quat, base_pose->orientation_quat, pose->orientation_quat);
float invBaseRotation[4];
copy_qt_qt(invBaseRotation, base_pose->orientation_quat);
invert_qt(invBaseRotation);
mul_qt_qtqt(dst_pose->orientation_quat, dst_pose->orientation_quat, invBaseRotation);
}
/**
* Update information that is only stored for external state queries. E.g. for Python API to
* request the current (as in, last known) viewer pose.
@@ -210,7 +238,8 @@ void wm_xr_session_draw_data_update(const wmXrSessionState *state,
void wm_xr_session_state_update(const XrSessionSettings *settings,
const wmXrDrawData *draw_data,
const GHOST_XrDrawViewInfo *draw_view,
wmXrSessionState *state)
wmXrSessionState *state,
float viewmat[4][4])
{
GHOST_XrPose viewer_pose;
const bool use_position_tracking = settings->flag & XR_SESSION_USE_POSITION_TRACKING;
@@ -221,6 +250,7 @@ void wm_xr_session_state_update(const XrSessionSettings *settings,
copy_v3_v3(viewer_pose.position, draw_data->base_pose.position);
/* The local pose and the eye pose (which is copied from an earlier local pose) both are view
* space, so Y-up. In this case we need them in regular Z-up. */
viewer_pose.position[0] += draw_data->eye_position_ofs[0];
viewer_pose.position[1] -= draw_data->eye_position_ofs[2];
viewer_pose.position[2] += draw_data->eye_position_ofs[1];
@@ -232,7 +262,14 @@ void wm_xr_session_state_update(const XrSessionSettings *settings,
copy_v3_v3(state->viewer_pose.position, viewer_pose.position);
copy_qt_qt(state->viewer_pose.orientation_quat, viewer_pose.orientation_quat);
wm_xr_pose_to_viewmat(&viewer_pose, state->viewer_viewmat);
/*
wm_xr_pose_to_viewmat(state->viewer_viewmat, &viewer_pose);
do not re-compute viewmat use the one that includes "world" transform
*/
memcpy(state->viewer_viewmat, viewmat, 16 * sizeof(float));
/* No idea why, but multiplying by two seems to make it match the VR view more. */
state->focal_len = 2.0f *
fov_to_focallength(draw_view->fov.angle_right - draw_view->fov.angle_left,
@@ -243,6 +280,42 @@ void wm_xr_session_state_update(const XrSessionSettings *settings,
state->prev_base_pose_type = settings->base_pose_type;
state->prev_base_pose_object = settings->base_pose_object;
state->is_view_data_set = true;
/* Controllers states */
wm_xr_session_controller_transform_update(&state->controllers_data.left_pose,
&draw_data->base_pose,
&draw_view->controllers_data.left_pose);
wm_xr_session_controller_transform_update(&state->controllers_data.right_pose,
&draw_data->base_pose,
&draw_view->controllers_data.right_pose);
state->controllers_data.left_trigger_value = draw_view->controllers_data.left_trigger_value;
state->controllers_data.left_trigger_touch = draw_view->controllers_data.left_trigger_touch;
state->controllers_data.right_trigger_value = draw_view->controllers_data.right_trigger_value;
state->controllers_data.right_trigger_touch = draw_view->controllers_data.right_trigger_touch;
state->controllers_data.left_grip_value = draw_view->controllers_data.left_grip_value;
state->controllers_data.right_grip_value = draw_view->controllers_data.right_grip_value;
state->controllers_data.left_primary_click = draw_view->controllers_data.left_primary_click;
state->controllers_data.left_primary_touch = draw_view->controllers_data.left_primary_touch;
state->controllers_data.left_secondary_click = draw_view->controllers_data.left_secondary_click;
state->controllers_data.left_secondary_touch = draw_view->controllers_data.left_secondary_touch;
state->controllers_data.right_primary_click = draw_view->controllers_data.right_primary_click;
state->controllers_data.right_primary_touch = draw_view->controllers_data.right_primary_touch;
state->controllers_data.right_secondary_click = draw_view->controllers_data.right_secondary_click;
state->controllers_data.right_secondary_touch = draw_view->controllers_data.right_secondary_touch;
state->controllers_data.left_thumbstick_x = draw_view->controllers_data.left_thumbstick_x;
state->controllers_data.left_thumbstick_y = draw_view->controllers_data.left_thumbstick_y;
state->controllers_data.left_thumbstick_click = draw_view->controllers_data.left_thumbstick_click;
state->controllers_data.left_thumbstick_touch = draw_view->controllers_data.left_thumbstick_touch;
state->controllers_data.right_thumbstick_x = draw_view->controllers_data.right_thumbstick_x;
state->controllers_data.right_thumbstick_y = draw_view->controllers_data.right_thumbstick_y;
state->controllers_data.right_thumbstick_click = draw_view->controllers_data.right_thumbstick_click;
state->controllers_data.right_thumbstick_touch = draw_view->controllers_data.right_thumbstick_touch;
}
wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr)
@@ -272,6 +345,252 @@ bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_ro
return true;
}
bool WM_xr_session_state_world_location_get(const wmXrData *xr, float r_location[3])
{
if (!WM_xr_session_is_ready(xr)) {
zero_v3(r_location);
return false;
}
copy_v3_v3(r_location, xr->runtime->session_state.world_pose.position);
return true;
}
bool WM_xr_session_state_world_location_set(const wmXrData *xr, const float location[3])
{
if (!WM_xr_session_is_ready(xr)) {
return false;
}
copy_v3_v3(xr->runtime->session_state.world_pose.position, location);
return true;
}
float WM_xr_session_state_get_float(const wmXrData *xr, float value, float defaultValue)
{
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
return defaultValue;
}
return value;
}
bool WM_xr_session_state_get_bool(const wmXrData *xr, bool value, bool defaultValue)
{
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
return defaultValue;
}
return value;
}
/* World matrix */
bool WM_xr_session_state_world_rotation_get(const wmXrData *xr, float r_rotation[4])
{
if (!WM_xr_session_is_ready(xr)) {
unit_qt(r_rotation);
return false;
}
copy_v4_v4(r_rotation, xr->runtime->session_state.world_pose.orientation_quat);
return true;
}
bool WM_xr_session_state_world_rotation_set(const wmXrData *xr, const float rotation[4])
{
if (!WM_xr_session_is_ready(xr)) {
return false;
}
copy_v4_v4(xr->runtime->session_state.world_pose.orientation_quat, rotation);
return true;
}
float WM_xr_session_state_world_scale_get(const wmXrData *xr)
{
return WM_xr_session_state_get_float(xr, xr->runtime->session_state.world_scale, 1.f);
}
bool WM_xr_session_state_world_scale_set(const wmXrData *xr, const float scale)
{
if (!WM_xr_session_is_ready(xr)) {
return false;
}
xr->runtime->session_state.world_scale = scale;
return true;
}
/* Thumbsticks */
float WM_xr_session_state_left_thumbstick_x_get(const wmXrData *xr)
{
return WM_xr_session_state_get_float(xr, xr->runtime->session_state.controllers_data.left_thumbstick_x, 0.f);
}
float WM_xr_session_state_left_thumbstick_y_get(const wmXrData *xr)
{
return WM_xr_session_state_get_float(
xr, xr->runtime->session_state.controllers_data.left_thumbstick_y, 0.f);
}
float WM_xr_session_state_right_thumbstick_x_get(const wmXrData *xr)
{
return WM_xr_session_state_get_float(
xr, xr->runtime->session_state.controllers_data.right_thumbstick_x, 0.f);
}
float WM_xr_session_state_right_thumbstick_y_get(const wmXrData *xr)
{
return WM_xr_session_state_get_float(
xr, xr->runtime->session_state.controllers_data.right_thumbstick_y, 0.f);
}
bool WM_xr_session_state_left_thumbstick_click_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.left_thumbstick_click, false);
}
bool WM_xr_session_state_right_thumbstick_click_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.right_thumbstick_click, false);
}
bool WM_xr_session_state_left_thumbstick_touch_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.left_thumbstick_touch, false);
}
bool WM_xr_session_state_right_thumbstick_touch_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.right_thumbstick_touch, false);
}
/* Buttons */
bool WM_xr_session_state_left_primary_click_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.left_primary_click, false);
}
bool WM_xr_session_state_left_primary_touch_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.left_primary_touch, false);
}
bool WM_xr_session_state_left_secondary_click_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.left_secondary_click, false);
}
bool WM_xr_session_state_left_secondary_touch_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.left_secondary_touch, false);
}
bool WM_xr_session_state_right_primary_click_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.right_primary_click, false);
}
bool WM_xr_session_state_right_primary_touch_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.right_primary_touch, false);
}
bool WM_xr_session_state_right_secondary_click_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.right_secondary_click, false);
}
bool WM_xr_session_state_right_secondary_touch_get(const wmXrData *xr)
{
return WM_xr_session_state_get_bool(
xr, xr->runtime->session_state.controllers_data.right_secondary_touch, false);
}
bool WM_xr_session_state_get_vector3(float dst[3], const wmXrData *xr, float *src)
{
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
zero_v3(dst);
return false;
}
copy_v3_v3(dst, src);
return true;
}
bool WM_xr_session_state_get_quaternion(float dst[4], const wmXrData *xr, float *src)
{
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
unit_qt(dst);
return false;
}
copy_v4_v4(dst, src);
return true;
}
/* Poses */
bool WM_xr_session_state_left_controller_location_get(const wmXrData *xr, float r_location[3])
{
return WM_xr_session_state_get_vector3(r_location, xr, xr->runtime->session_state.controllers_data.left_pose.position);
}
bool WM_xr_session_state_left_controller_rotation_get(const wmXrData *xr, float r_rotation[4])
{
return WM_xr_session_state_get_quaternion(r_rotation, xr, xr->runtime->session_state.controllers_data.left_pose.orientation_quat);
}
bool WM_xr_session_state_right_controller_location_get(const wmXrData *xr, float r_location[3])
{
return WM_xr_session_state_get_vector3(r_location, xr, xr->runtime->session_state.controllers_data.right_pose.position);
}
bool WM_xr_session_state_right_controller_rotation_get(const wmXrData *xr, float r_rotation[4])
{
return WM_xr_session_state_get_quaternion(r_rotation, xr, xr->runtime->session_state.controllers_data.right_pose.orientation_quat);
}
/* Triggers */
float WM_xr_session_state_left_trigger_value_get(const wmXrData *xr)
{
return xr->runtime->session_state.controllers_data.left_trigger_value;
}
bool WM_xr_session_state_left_trigger_touch_get(const wmXrData *xr)
{
return xr->runtime->session_state.controllers_data.left_trigger_touch;
}
float WM_xr_session_state_right_trigger_value_get(const wmXrData *xr)
{
return xr->runtime->session_state.controllers_data.right_trigger_value;
}
bool WM_xr_session_state_right_trigger_touch_get(const wmXrData *xr)
{
return xr->runtime->session_state.controllers_data.right_trigger_touch;
}
/* Grips */
float WM_xr_session_state_left_grip_value_get(const wmXrData *xr)
{
return xr->runtime->session_state.controllers_data.left_grip_value;
}
float WM_xr_session_state_right_grip_value_get(const wmXrData *xr)
{
return xr->runtime->session_state.controllers_data.right_grip_value;
}
bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr,
float r_viewmat[4][4],
float *r_focal_len)
@@ -288,6 +607,26 @@ bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr,
return true;
}
bool WM_xr_session_state_world_matrix_get(const wmXrData *xr,
float world_matrix[4][4])
{
if (!WM_xr_session_is_ready(xr)) {
unit_m4(world_matrix);
return false;
}
float scale[3] = {xr->runtime->session_state.world_scale,
xr->runtime->session_state.world_scale,
xr->runtime->session_state.world_scale};
loc_quat_size_to_mat4(world_matrix,
xr->runtime->session_state.world_pose.position,
xr->runtime->session_state.world_pose.orientation_quat,
scale);
return true;
}
/* -------------------------------------------------------------------- */
/** \name XR-Session Surface
*