[Bf-blender-cvs] [cb12fb78cad] master: XR Controller Support Step 1: Internal Abstractions for OpenXR Actions

Peter Kim noreply at git.blender.org
Sat May 15 20:37:21 CEST 2021


Commit: cb12fb78cad4be5fa18edf0de1f8891cd97a9bed
Author: Peter Kim
Date:   Sun May 16 03:33:10 2021 +0900
Branches: master
https://developer.blender.org/rBcb12fb78cad4be5fa18edf0de1f8891cd97a9bed

XR Controller Support Step 1: Internal Abstractions for OpenXR Actions

Adds internal API for creating and managing OpenXR actions at the
GHOST and WM layers. Does not bring about any changes for users since
XR action functionality is not yet exposed in the Python API (will be
added in a subsequent patch).

OpenXR actions are a means to communicate with XR input devices and
can be used to retrieve button/pose states or apply haptic feedback.
Actions are bound to device inputs via a semantic path binding
(https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#semantic-path-interaction-profiles),
which serves as an XR version of keymaps.

Main features:

- Abstraction of OpenXR action management functions to GHOST-XR,
  WM-XR APIs.
- New "xr_session_start_pre" callback for creating actions at
  appropriate point in the XR session.
- Creation of name-identifiable action sets/actions.
- Binding of actions to controller inputs.
- Acquisition of controller button states.
- Acquisition of controller poses.
- Application of controller haptic feedback.
- Carefully designed error handling and useful error reporting
  (e.g. action set/action name included in error message).

Reviewed By: Julian Eisel

Differential Revision: http://developer.blender.org/D10942

===================================================================

M	intern/ghost/CMakeLists.txt
M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_IXrContext.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_C-api.cpp
A	intern/ghost/intern/GHOST_Util.h
A	intern/ghost/intern/GHOST_XrAction.cpp
A	intern/ghost/intern/GHOST_XrAction.h
M	intern/ghost/intern/GHOST_XrContext.cpp
M	intern/ghost/intern/GHOST_XrContext.h
M	intern/ghost/intern/GHOST_XrException.h
M	intern/ghost/intern/GHOST_XrSession.cpp
M	intern/ghost/intern/GHOST_XrSession.h
M	intern/ghost/intern/GHOST_Xr_intern.h
M	source/blender/blenkernel/BKE_callbacks.h
M	source/blender/makesdna/DNA_xr_types.h
M	source/blender/python/intern/bpy_app_handlers.c
M	source/blender/windowmanager/CMakeLists.txt
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/WM_types.h
M	source/blender/windowmanager/xr/intern/wm_xr.c
A	source/blender/windowmanager/xr/intern/wm_xr_actions.c
M	source/blender/windowmanager/xr/intern/wm_xr_draw.c
M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c

===================================================================

diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 1739659ab88..f90e8a973bf 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -79,6 +79,7 @@ set(SRC
   intern/GHOST_SystemPaths.h
   intern/GHOST_TimerManager.h
   intern/GHOST_TimerTask.h
+  intern/GHOST_Util.h
   intern/GHOST_Window.h
   intern/GHOST_WindowManager.h
 )
@@ -438,6 +439,7 @@ endif()
 if(WITH_XR_OPENXR)
   list(APPEND SRC
     intern/GHOST_Xr.cpp
+    intern/GHOST_XrAction.cpp
     intern/GHOST_XrContext.cpp
     intern/GHOST_XrEvent.cpp
     intern/GHOST_XrGraphicsBinding.cpp
@@ -446,6 +448,7 @@ if(WITH_XR_OPENXR)
 
     GHOST_IXrContext.h
     intern/GHOST_IXrGraphicsBinding.h
+    intern/GHOST_XrAction.h
     intern/GHOST_XrContext.h
     intern/GHOST_XrException.h
     intern/GHOST_XrSession.h
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index c776eb6b44c..2bd9af6df5c 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -1059,7 +1059,110 @@ int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context
  * \returns GHOST_kSuccess if any event was handled, otherwise GHOST_kFailure.
  */
 GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
-#endif
+
+/* actions */
+/**
+ * Create an OpenXR action set for input/output.
+ */
+int GHOST_XrCreateActionSet(GHOST_XrContextHandle xr_context, const GHOST_XrActionSetInfo *info);
+
+/**
+ * Destroy a previously created OpenXR action set.
+ */
+void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_context, const char *action_set_name);
+
+/**
+ * Create OpenXR input/output actions.
+ */
+int GHOST_XrCreateActions(GHOST_XrContextHandle xr_context,
+                          const char *action_set_name,
+                          GHOST_TUns32 count,
+                          const GHOST_XrActionInfo *infos);
+
+/**
+ * Destroy previously created OpenXR actions.
+ */
+void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context,
+                            const char *action_set_name,
+                            GHOST_TUns32 count,
+                            const char *const *action_names);
+
+/**
+ * Create spaces for pose-based OpenXR actions.
+ */
+int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context,
+                               const char *action_set_name,
+                               GHOST_TUns32 count,
+                               const GHOST_XrActionSpaceInfo *infos);
+
+/**
+ * Destroy previously created spaces for OpenXR actions.
+ */
+void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context,
+                                 const char *action_set_name,
+                                 GHOST_TUns32 count,
+                                 const GHOST_XrActionSpaceInfo *infos);
+
+/**
+ * Create input/output path bindings for OpenXR actions.
+ */
+int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context,
+                                 const char *action_set_name,
+                                 GHOST_TUns32 count,
+                                 const GHOST_XrActionProfileInfo *infos);
+
+/**
+ * Destroy previously created bindings for OpenXR actions.
+ */
+void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context,
+                                   const char *action_set_name,
+                                   GHOST_TUns32 count,
+                                   const GHOST_XrActionProfileInfo *infos);
+
+/**
+ * Attach all created action sets to the current OpenXR session.
+ */
+int GHOST_XrAttachActionSets(GHOST_XrContextHandle xr_context);
+
+/**
+ * Update button/tracking states for OpenXR actions.
+ *
+ * \param action_set_name: The name of the action set to sync. If NULL, all action sets
+ * attached to the session will be synced.
+ */
+int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set_name);
+
+/**
+ * Apply an OpenXR haptic output action.
+ */
+int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context,
+                              const char *action_set_name,
+                              const char *action_name,
+                              const GHOST_TInt64 *duration,
+                              const float *frequency,
+                              const float *amplitude);
+
+/**
+ * Stop a previously applied OpenXR haptic output action.
+ */
+void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_context,
+                              const char *action_set_name,
+                              const char *action_name);
+
+/**
+ * Get action set custom data (owned by Blender, not GHOST).
+ */
+void *GHOST_XrGetActionSetCustomdata(GHOST_XrContextHandle xr_context,
+                                     const char *action_set_name);
+
+/**
+ * Get action custom data (owned by Blender, not GHOST).
+ */
+void *GHOST_XrGetActionCustomdata(GHOST_XrContextHandle xr_context,
+                                  const char *action_set_name,
+                                  const char *action_name);
+
+#endif /* WITH_XR_OPENXR */
 
 #ifdef __cplusplus
 }
diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h
index dd266a3b6ae..86fe78814a7 100644
--- a/intern/ghost/GHOST_IXrContext.h
+++ b/intern/ghost/GHOST_IXrContext.h
@@ -22,6 +22,8 @@
 
 #include "GHOST_Types.h"
 
+class GHOST_XrSession;
+
 class GHOST_IXrContext {
  public:
   virtual ~GHOST_IXrContext() = default;
@@ -31,6 +33,10 @@ class GHOST_IXrContext {
   virtual bool isSessionRunning() const = 0;
   virtual void drawSessionViews(void *draw_customdata) = 0;
 
+  /* Needed for the GHOST C api. */
+  virtual GHOST_XrSession *getSession() = 0;
+  virtual const GHOST_XrSession *getSession() const = 0;
+
   virtual void dispatchErrorMessage(const class GHOST_XrException *) const = 0;
 
   virtual void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 7d819913efc..3a8d0fbfecf 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -634,7 +634,9 @@ typedef enum GHOST_TXrGraphicsBinding {
 
 typedef void (*GHOST_XrErrorHandlerFn)(const struct GHOST_XrError *);
 
+typedef void (*GHOST_XrSessionCreateFn)(void);
 typedef void (*GHOST_XrSessionExitFn)(void *customdata);
+typedef void (*GHOST_XrCustomdataFreeFn)(void *customdata);
 
 typedef void *(*GHOST_XrGraphicsContextBindFn)(void);
 typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_ContextHandle graphics_context);
@@ -665,6 +667,7 @@ typedef struct {
 typedef struct {
   GHOST_XrPose base_pose;
 
+  GHOST_XrSessionCreateFn create_fn;
   GHOST_XrSessionExitFn exit_fn;
   void *exit_customdata;
 } GHOST_XrSessionBeginInfo;
@@ -691,4 +694,54 @@ typedef struct GHOST_XrError {
   void *customdata;
 } GHOST_XrError;
 
-#endif
+typedef struct GHOST_XrActionSetInfo {
+  const char *name;
+
+  GHOST_XrCustomdataFreeFn customdata_free_fn;
+  void *customdata; /* wmXrActionSet */
+} GHOST_XrActionSetInfo;
+
+/** XR action type. Enum values match those in OpenXR's
+ * XrActionType enum for consistency. */
+typedef enum GHOST_XrActionType {
+  GHOST_kXrActionTypeBooleanInput = 1,
+  GHOST_kXrActionTypeFloatInput = 2,
+  GHOST_kXrActionTypeVector2fInput = 3,
+  GHOST_kXrActionTypePoseInput = 4,
+  GHOST_kXrActionTypeVibrationOutput = 100,
+} GHOST_XrActionType;
+
+typedef struct GHOST_XrActionInfo {
+  const char *name;
+  GHOST_XrActionType type;
+  GHOST_TUns32 count_subaction_paths;
+  const char **subaction_paths;
+  /** States for each subaction path. */
+  void *states;
+
+  GHOST_XrCustomdataFreeFn customdata_free_fn;
+  void *customdata; /* wmXrAction */
+} GHOST_XrActionInfo;
+
+typedef struct GHOST_XrActionSpaceInfo {
+  const char *action_name;
+  GHOST_TUns32 count_subaction_paths;
+  const char **subaction_paths;
+  /** Poses for each subaction path. */
+  const GHOST_XrPose *poses;
+} GHOST_XrActionSpaceInfo;
+
+typedef struct GHOST_XrActionBindingInfo {
+  const char *action_name;
+  GHOST_TUns32 count_interaction_paths;
+  /** Interaction path: User (subaction) path + component path. */
+  const char **interaction_paths;
+} GHOST_XrActionBindingInfo;
+
+typedef struct GHOST_XrActionProfileInfo {
+  const char *profile_path;
+  GHOST_TUns32 count_bindings;
+  const GHOST_XrActionBindingInfo *bindings;
+} GHOST_XrActionProfileInfo;
+
+#endif /* WITH_XR_OPENXR */
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 1d96354c504..955f35274ea 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -33,6 +33,7 @@
 #include "intern/GHOST_Debug.h"
 #ifdef WITH_XR_OPENXR
 #  include "GHOST_IXrContext.h"
+#  include "intern/GHOST_XrSession.h"
 #endif
 #include "intern/GHOST_CallbackEventConsumer.h"
 #include "intern/GHOST_XrException.h"
@@ -953,4 +954,145 @@ int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context
   return 0; /* Only reached if exception is thrown. */
 }
 
-#endif
+int GHOST_XrCreateActionSet(GHOST_XrContextHandle xr_contexthandle,
+                            const GHOST_XrActionSetInfo *info)
+{
+  GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+  GHOST_XrSession *xr_session = xr_context->getSession();
+  GHOST_XR_CAPI_CALL_RET(xr_session->createActionSet(*info), xr_context);
+  return 0;
+}
+
+void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name)
+{
+  GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+  GHOST_XrSession *xr_session = xr_context->getSession();
+  GHOST_XR_CAPI_CALL(xr_session->destroyActionSet(action_set_name), xr_context);
+}
+
+int GHOST_XrCreateActions(GHOST_XrContextHandle xr_contexthandle,
+                          const char *action_set_name,
+                          GHOST_TUns32 count,
+                          const GHOST_XrActionInfo *infos)
+{
+  GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+  GHOST_XrSession *xr_session = xr_context->getSession();
+  GHOST_XR_CAPI_CALL_RET(xr_session->createActions(action_set_name, count, infos), xr_context);
+  return 0;
+}
+
+void GHOST_XrDestroyActions(GHOST_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list