[Bf-blender-cvs] [9dda65455b5] master: XR Controller Support Step 4: Controller Drawing
Peter Kim
noreply at git.blender.org
Tue Oct 12 09:18:56 CEST 2021
Commit: 9dda65455b54336fe3efef91eba9e41866dac1c1
Author: Peter Kim
Date: Tue Oct 12 16:18:05 2021 +0900
Branches: master
https://developer.blender.org/rB9dda65455b54336fe3efef91eba9e41866dac1c1
XR Controller Support Step 4: Controller Drawing
Addresses T77127 (Controller Drawing).
Adds VR controller visualization and custom drawing via draw
handlers. Add-ons can draw to the XR surface (headset display) and
mirror window by adding a View3D draw handler of region type 'XR' and
draw type 'POST_VIEW'. Controller drawing and custom overlays can be
toggled individually as XR session options, which will be added in a
future update to the VR Scene Inspection add-on.
For the actual drawing, the OpenXR XR_MSFT_controller_model extension
is used to load a glTF model provided by the XR runtime. The model's
vertex data is then used to create a GPUBatch in the XR session
state. Finally, this batch is drawn via the XR surface draw handler
mentioned above.
For runtimes that do not support the controller model extension, a
a simple fallback shape (sphere) is drawn instead.
Reviewed By: Severin, fclem
Differential Revision: https://developer.blender.org/D10948
===================================================================
M intern/ghost/CMakeLists.txt
M intern/ghost/GHOST_C-api.h
M intern/ghost/GHOST_Types.h
M intern/ghost/intern/GHOST_C-api.cpp
M intern/ghost/intern/GHOST_XrContext.cpp
A intern/ghost/intern/GHOST_XrControllerModel.cpp
A intern/ghost/intern/GHOST_XrControllerModel.h
M intern/ghost/intern/GHOST_XrSession.cpp
M intern/ghost/intern/GHOST_XrSession.h
M source/blender/draw/intern/draw_manager.c
M source/blender/editors/include/ED_space_api.h
M source/blender/editors/include/ED_view3d_offscreen.h
M source/blender/editors/space_api/spacetypes.c
M source/blender/editors/space_view3d/space_view3d.c
M source/blender/editors/space_view3d/view3d_draw.c
M source/blender/makesdna/DNA_screen_types.h
M source/blender/makesdna/DNA_view3d_enums.h
M source/blender/makesdna/DNA_view3d_types.h
M source/blender/makesdna/DNA_xr_types.h
M source/blender/makesrna/intern/rna_screen.c
M source/blender/makesrna/intern/rna_xr.c
M source/blender/windowmanager/WM_api.h
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 76cac1049fb..05423209c71 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -473,6 +473,7 @@ if(WITH_XR_OPENXR)
intern/GHOST_Xr.cpp
intern/GHOST_XrAction.cpp
intern/GHOST_XrContext.cpp
+ intern/GHOST_XrControllerModel.cpp
intern/GHOST_XrEvent.cpp
intern/GHOST_XrGraphicsBinding.cpp
intern/GHOST_XrSession.cpp
@@ -482,13 +483,19 @@ if(WITH_XR_OPENXR)
intern/GHOST_IXrGraphicsBinding.h
intern/GHOST_XrAction.h
intern/GHOST_XrContext.h
+ intern/GHOST_XrControllerModel.h
intern/GHOST_XrException.h
intern/GHOST_XrSession.h
intern/GHOST_XrSwapchain.h
intern/GHOST_Xr_intern.h
intern/GHOST_Xr_openxr_includes.h
)
+ list(APPEND INC
+ ../../extern/json/include
+ ../../extern/tinygltf
+ )
list(APPEND INC_SYS
+ ${EIGEN3_INCLUDE_DIRS}
${XR_OPENXR_SDK_INCLUDE_DIR}
)
list(APPEND LIB
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index b78aac6f5eb..784febe8581 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -1140,6 +1140,30 @@ void GHOST_XrGetActionCustomdataArray(GHOST_XrContextHandle xr_context,
const char *action_set_name,
void **r_customdata_array);
+/* controller model */
+/**
+ * Load the OpenXR controller model.
+ */
+int GHOST_XrLoadControllerModel(GHOST_XrContextHandle xr_context, const char *subaction_path);
+
+/**
+ * Unload the OpenXR controller model.
+ */
+void GHOST_XrUnloadControllerModel(GHOST_XrContextHandle xr_context, const char *subaction_path);
+
+/**
+ * Update component transforms for the OpenXR controller model.
+ */
+int GHOST_XrUpdateControllerModelComponents(GHOST_XrContextHandle xr_context,
+ const char *subaction_path);
+
+/**
+ * Get vertex data for the OpenXR controller model.
+ */
+int GHOST_XrGetControllerModelData(GHOST_XrContextHandle xr_context,
+ const char *subaction_path,
+ GHOST_XrControllerModelData *r_data);
+
#endif /* WITH_XR_OPENXR */
#ifdef __cplusplus
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 898ee451baf..2c8014a08cc 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -754,8 +754,31 @@ typedef struct GHOST_XrActionProfileInfo {
const char *profile_path;
uint32_t count_subaction_paths;
const char **subaction_paths;
- /* Bindings for each subaction path. */
+ /** Bindings for each subaction path. */
const GHOST_XrActionBindingInfo *bindings;
} GHOST_XrActionProfileInfo;
+typedef struct GHOST_XrControllerModelVertex {
+ float position[3];
+ float normal[3];
+} GHOST_XrControllerModelVertex;
+
+typedef struct GHOST_XrControllerModelComponent {
+ /** World space transform. */
+ float transform[4][4];
+ uint32_t vertex_offset;
+ uint32_t vertex_count;
+ uint32_t index_offset;
+ uint32_t index_count;
+} GHOST_XrControllerModelComponent;
+
+typedef struct GHOST_XrControllerModelData {
+ uint32_t count_vertices;
+ const GHOST_XrControllerModelVertex *vertices;
+ uint32_t count_indices;
+ const uint32_t *indices;
+ uint32_t count_components;
+ const GHOST_XrControllerModelComponent *components;
+} GHOST_XrControllerModelData;
+
#endif /* WITH_XR_OPENXR */
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index a2871b46222..a21c3a90c06 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -1069,4 +1069,39 @@ void GHOST_XrGetActionCustomdataArray(GHOST_XrContextHandle xr_contexthandle,
xr_context);
}
+int GHOST_XrLoadControllerModel(GHOST_XrContextHandle xr_contexthandle, const char *subaction_path)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XrSession *xr_session = xr_context->getSession();
+ GHOST_XR_CAPI_CALL_RET(xr_session->loadControllerModel(subaction_path), xr_context);
+ return 0;
+}
+
+void GHOST_XrUnloadControllerModel(GHOST_XrContextHandle xr_contexthandle,
+ const char *subaction_path)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XrSession *xr_session = xr_context->getSession();
+ GHOST_XR_CAPI_CALL(xr_session->unloadControllerModel(subaction_path), xr_context);
+}
+
+int GHOST_XrUpdateControllerModelComponents(GHOST_XrContextHandle xr_contexthandle,
+ const char *subaction_path)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XrSession *xr_session = xr_context->getSession();
+ GHOST_XR_CAPI_CALL_RET(xr_session->updateControllerModelComponents(subaction_path), xr_context);
+ return 0;
+}
+
+int GHOST_XrGetControllerModelData(GHOST_XrContextHandle xr_contexthandle,
+ const char *subaction_path,
+ GHOST_XrControllerModelData *r_data)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XrSession *xr_session = xr_context->getSession();
+ GHOST_XR_CAPI_CALL_RET(xr_session->getControllerModelData(subaction_path, *r_data), xr_context);
+ return 0;
+}
+
#endif /* WITH_XR_OPENXR */
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index fe8fec052fe..15b40690d83 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -412,11 +412,14 @@ void GHOST_XrContext::getExtensionsToEnable(
try_ext.push_back(XR_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
- /* Try enabling interaction profile extensions. */
+ /* Interaction profile extensions. */
try_ext.push_back(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME);
try_ext.push_back(XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME);
try_ext.push_back(XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME);
+ /* Controller model extension. */
+ try_ext.push_back(XR_MSFT_CONTROLLER_MODEL_EXTENSION_NAME);
+
/* Varjo quad view extension. */
try_ext.push_back(XR_VARJO_QUAD_VIEWS_EXTENSION_NAME);
diff --git a/intern/ghost/intern/GHOST_XrControllerModel.cpp b/intern/ghost/intern/GHOST_XrControllerModel.cpp
new file mode 100644
index 00000000000..ae15bf11aa0
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrControllerModel.cpp
@@ -0,0 +1,629 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include <cassert>
+
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+#include "GHOST_Types.h"
+#include "GHOST_XrException.h"
+#include "GHOST_Xr_intern.h"
+
+#include "GHOST_XrControllerModel.h"
+
+#define TINYGLTF_IMPLEMENTATION
+#define TINYGLTF_NO_STB_IMAGE
+#define TINYGLTF_NO_STB_IMAGE_WRITE
+#define STBIWDEF static inline
+#include "tiny_gltf.h"
+
+struct GHOST_XrControllerModelNode {
+ int32_t parent_idx = -1;
+ int32_t component_idx = -1;
+ float local_transform[4][4];
+};
+
+/* -------------------------------------------------------------------- */
+/** \name glTF Utilities
+ *
+ * Adapted from Microsoft OpenXR-Mixed Reality Samples (MIT License):
+ * https://github.com/microsoft/OpenXR-MixedReality
+ * \{ */
+
+struct GHOST_XrPrimitive {
+ std::vector<GHOST_XrControllerModelVertex> vertices;
+ std::vector<uint32_t> indices;
+};
+
+/**
+ * Validate that an accessor does not go out of bounds of the buffer view that it references and
+ * that the buffer view does not exceed the bounds of the buffer that it references
+ */
+static void validate_accessor(const tinygltf::Accessor &accessor,
+ const tinygltf::BufferView &buffer_view,
+ const tinygltf::Buffer &buffer,
+ size_t byte_stride,
+ size_t element_size)
+{
+ /* Make sure the accessor does not go out of range of the buffer view. */
+ if (accessor.byteOffset + (accessor.count - 1) * byte_stride + element_size >
+ buffer_view.byteLength) {
+ throw GHOST_XrException("glTF: Accessor goes out of range of bufferview.");
+ }
+
+ /* Make sure the buffer view does not go out of range of the buffer. */
+ if (buffer_view.byteOffset + buffer_view.byteLength > buffer.data.size()) {
+ throw GHOST_XrException("glTF: BufferView goes out of range of buffer.");
+ }
+}
+
+template<float (GHOST_XrControllerModelVertex::*field)[3]>
+static void read_vertices(const tinygltf::Accessor &accessor,
+ const tinygltf::BufferView &buffer_view,
+ const tinygltf::Buffer &buffer,
+ GHOST_XrPrimitive &primitive)
+{
+ if (accessor.type != TINYGLTF_TYPE_VEC3) {
+ throw GHOST_XrException(
+ "glTF: Accessor for primitive attribute has incorrect type (VEC3 expected).");
+ }
+
+ if (accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) {
+ throw GHOST_XrException(
+ "glTF: Accessor for primitive attribute has incorrect component type (FLOAT expected).");
+ }
+
+ /* If stride is not specified, it is tightly packed. */
+ constexpr size_t packed_size = sizeof(float) * 3;
+ const size_t stride = buffer_view.byteStride == 0 ? packed_size : buffer_view.byteStride;
+ validate_accessor(accessor, buffer_view, buffer, stride, packed_size);
+
+ /* Resize the vertices vector, if necessary, to includ
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list