[Bf-blender-cvs] [8ccdd43fc13] xr-actions-D9124: XR: Implement XR grab operator

Peter Kim noreply at git.blender.org
Wed Nov 11 15:43:34 CET 2020


Commit: 8ccdd43fc13abac89aaa80868d3cf3b231c984ef
Author: Peter Kim
Date:   Wed Nov 11 23:30:24 2020 +0900
Branches: xr-actions-D9124
https://developer.blender.org/rB8ccdd43fc13abac89aaa80868d3cf3b231c984ef

XR: Implement XR grab operator

Transforms selected objects' location / rotation relative to a
controller's pose. Very basic compared to the existing transform
operators (which can also be used in VR via modal_3d), but provides
a more natural interaction in VR.

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

M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_operators.c
M	source/blender/windowmanager/xr/intern/wm_xr_session.c

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

diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index b1fc581a4fd..1ef2ac595de 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -176,6 +176,12 @@ void wm_xr_session_actions_uninit(wmXrData *xr);
 void wm_xr_session_controller_data_populate(const wmXrAction *controller_pose_action,
                                             wmXrSessionState *state);
 void wm_xr_session_controller_data_clear(wmXrSessionState *state);
+void wm_xr_session_object_autokey(struct bContext *C,
+                                  struct Scene *scene,
+                                  struct ViewLayer *view_layer,
+                                  wmWindow *win,
+                                  Object *ob,
+                                  bool notify);
 
 void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]);
 void wm_xr_controller_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
index 23859f4c417..5a644470a42 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
@@ -37,6 +37,7 @@
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_query.h"
 
+#include "ED_keyframing.h"
 #include "ED_mesh.h"
 #include "ED_object.h"
 #include "ED_screen.h"
@@ -611,6 +612,8 @@ static void WM_OT_xr_select_raycast(wmOperatorType *ot)
   ot->flag = OPTYPE_UNDO;
 
   /* properties */
+  static const float default_axis[3] = {0.0f, 0.0f, -1.0f};
+
   WM_operator_properties_mouse_select(ot);
 
   RNA_def_float(ot->srna,
@@ -622,8 +625,6 @@ static void WM_OT_xr_select_raycast(wmOperatorType *ot)
                 "Maximum distance",
                 0.0,
                 BVH_RAYCAST_DIST_MAX);
-
-  static const float default_axis[3] = {0.0f, 0.0f, -1.0f};
   RNA_def_float_vector(ot->srna,
                        "axis",
                        3,
@@ -638,6 +639,285 @@ static void WM_OT_xr_select_raycast(wmOperatorType *ot)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name XR Grab
+ *
+ * Transforms location and rotation of selected objects relative to an XR controller's pose.
+ * \{ */
+
+typedef struct XrGrabData {
+  float mat_prev[4][4];
+} XrGrabData;
+
+static void wm_xr_grab_init(wmOperator *op)
+{
+  BLI_assert(op->customdata == NULL);
+
+  op->customdata = MEM_callocN(sizeof(XrGrabData), __func__);
+}
+
+static void wm_xr_grab_uninit(wmOperator *op)
+{
+  if (op->customdata) {
+    MEM_freeN(op->customdata);
+  }
+}
+
+static int wm_xr_grab_invoke_3d(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  BLI_assert(event->type == EVT_XR_ACTION);
+  BLI_assert(event->custom == EVT_DATA_XR);
+  BLI_assert(event->customdata);
+
+  bool loc_lock, rot_lock;
+  float loc_t, rot_t;
+  float loc_ofs[3], rot_ofs[4];
+  bool loc_ofs_set = false;
+  bool rot_ofs_set = false;
+
+  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "location_lock");
+  loc_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+  if (!loc_lock) {
+    prop = RNA_struct_find_property(op->ptr, "location_interpolation");
+    loc_t = prop ? RNA_property_float_get(op->ptr, prop) : 1.0f;
+    prop = RNA_struct_find_property(op->ptr, "location_offset");
+    if (prop && RNA_property_is_set(op->ptr, prop)) {
+      RNA_property_float_get_array(op->ptr, prop, loc_ofs);
+      loc_ofs_set = true;
+    }
+  }
+
+  prop = RNA_struct_find_property(op->ptr, "rotation_lock");
+  rot_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+  if (!rot_lock) {
+    prop = RNA_struct_find_property(op->ptr, "rotation_interpolation");
+    rot_t = prop ? RNA_property_float_get(op->ptr, prop) : 1.0f;
+    prop = RNA_struct_find_property(op->ptr, "rotation_offset");
+    if (prop && RNA_property_is_set(op->ptr, prop)) {
+      float tmp[3];
+      RNA_property_float_get_array(op->ptr, prop, tmp);
+      eul_to_quat(rot_ofs, tmp);
+      normalize_qt(rot_ofs);
+      rot_ofs_set = true;
+    }
+  }
+
+  if (loc_lock && rot_lock) {
+    return OPERATOR_CANCELLED;
+  }
+
+  const wmXrActionData *actiondata = event->customdata;
+  float tmp0[4], tmp1[4], tmp2[4];
+  bool selected = false;
+
+  if (loc_ofs_set) {
+    /* Convert to controller space. */
+    float tmp[3][3];
+    quat_to_mat3(tmp, actiondata->controller_rot);
+    mul_m3_v3(tmp, loc_ofs);
+  }
+  if (rot_ofs_set) {
+    /* Convert to controller space. */
+    invert_qt_qt_normalized(tmp0, rot_ofs);
+    mul_qt_qtqt(rot_ofs, actiondata->controller_rot, tmp0);
+    normalize_qt(rot_ofs);
+  }
+
+  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+    if (!loc_lock) {
+      if (loc_t > 0.0f) {
+        ob->loc[0] += loc_t * (actiondata->controller_loc[0] - ob->loc[0]);
+        ob->loc[1] += loc_t * (actiondata->controller_loc[1] - ob->loc[1]);
+        ob->loc[2] += loc_t * (actiondata->controller_loc[2] - ob->loc[2]);
+      }
+      if (loc_ofs_set) {
+        add_v3_v3(ob->loc, loc_ofs);
+      }
+    }
+
+    if (!rot_lock) {
+      if (rot_t > 0.0f) {
+        eul_to_quat(tmp1, ob->rot);
+        interp_qt_qtqt(tmp0, tmp1, actiondata->controller_rot, rot_t);
+        if (!rot_ofs_set) {
+          quat_to_eul(ob->rot, tmp0);
+        }
+      }
+      else if (rot_ofs_set) {
+        eul_to_quat(tmp0, ob->rot);
+      }
+      if (rot_ofs_set) {
+        rotation_between_quats_to_quat(tmp1, rot_ofs, tmp0);
+        mul_qt_qtqt(tmp0, rot_ofs, tmp1);
+        normalize_qt(tmp0);
+        mul_qt_qtqt(tmp2, actiondata->controller_rot, tmp1);
+        normalize_qt(tmp2);
+        rotation_between_quats_to_quat(tmp1, tmp0, tmp2);
+
+        mul_qt_qtqt(tmp2, tmp0, tmp1);
+        normalize_qt(tmp2);
+        quat_to_eul(ob->rot, tmp2);
+      }
+    }
+
+    DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+    selected = true;
+  }
+  CTX_DATA_END;
+
+  if (!selected) {
+    wm_xr_grab_uninit(op);
+    return OPERATOR_CANCELLED;
+  }
+
+  wm_xr_grab_init(op);
+
+  XrGrabData *data = op->customdata;
+  quat_to_mat4(data->mat_prev, actiondata->controller_rot);
+  copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
+
+  WM_event_add_modal_handler(C, op);
+
+  return OPERATOR_RUNNING_MODAL;
+}
+
+static int wm_xr_grab_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+  return OPERATOR_CANCELLED;
+}
+
+static int wm_xr_grab_modal_3d(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  BLI_assert(event->type == EVT_XR_ACTION);
+  BLI_assert(event->custom == EVT_DATA_XR);
+  BLI_assert(event->customdata);
+
+  const wmXrActionData *actiondata = event->customdata;
+  XrGrabData *data = op->customdata;
+  Scene *scene = CTX_data_scene(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  wmWindowManager *wm = CTX_wm_manager(C);
+  bScreen *screen_anim = ED_screen_animation_playing(wm);
+  bool loc_lock, rot_lock;
+  bool selected = false;
+  float delta[4][4], tmp[4][4];
+
+  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "location_lock");
+  loc_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+  prop = RNA_struct_find_property(op->ptr, "rotation_lock");
+  rot_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+
+  invert_m4_m4(tmp, data->mat_prev);
+  quat_to_mat4(data->mat_prev, actiondata->controller_rot);
+  copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
+  mul_m4_m4m4(delta, data->mat_prev, tmp);
+
+  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+    if (!loc_lock || !rot_lock) {
+      copy_m4_m4(tmp, ob->obmat);
+      mul_m4_m4m4(ob->obmat, delta, tmp);
+
+      if (!loc_lock) {
+        copy_v3_v3(ob->loc, ob->obmat[3]);
+      }
+      if (!rot_lock) {
+        mat4_to_eul(ob->rot, ob->obmat);
+      }
+
+      DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+    }
+
+    if (screen_anim && autokeyframe_cfra_can_key(scene, &ob->id)) {
+      wm_xr_session_object_autokey(C, scene, view_layer, NULL, ob, true);
+    }
+
+    selected = true;
+  }
+  CTX_DATA_END;
+
+  if (!selected || (event->val == KM_RELEASE)) {
+    wm_xr_grab_uninit(op);
+    WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, scene);
+    return OPERATOR_FINISHED;
+  }
+  else if (event->val == KM_PRESS) {
+    return OPERATOR_RUNNING_MODAL;
+  }
+
+  /* XR events currently only support press and release. */
+  BLI_assert(false);
+  wm_xr_grab_uninit(op);
+  WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, scene);
+  return OPERATOR_FINISHED;
+}
+
+static void WM_OT_xr_grab(wmOperatorType *ot)
+{
+  /* identifiers */
+  ot->name = "XR Grab";
+  ot->idname = "WM_OT_xr_grab";
+  ot->description =
+      "Transform location and rotation of selected objects relative to a VR controller's pose";
+
+  /* callbacks */
+  ot->invoke_3d = wm_xr_grab_invoke_3d;
+  ot->exec = wm_xr_grab_exec;
+  ot->modal_3d = wm_xr_grab_modal_3d;
+  ot->poll = wm_xr_operator_sessionactive;
+
+  /* flags */
+  ot->flag = OPTYPE_UNDO;
+
+  /* properties */
+  static const float default_offset[3] = {0};
+
+  RNA_def_boolean(
+      ot->srna, "location_lock", false, "Lock Location", "Preserve objects' original location");
+  RNA_def_float(ot->srna,
+                "location_interpolation",
+                0.0f,
+                0.0f,
+                1.0f,
+                "Location Interpolation",
+                "Interpolation factor between object and controller locations",
+                0.0f,
+                1.0f);
+  RNA_def_float_translation(ot->srna,
+                            "location_offset",
+                            3,
+                            default_offset,
+                            -FLT_MAX,
+                            FLT_MAX,
+                            "Location Offset",
+                            "Additional location offset in controller space",
+                            -FLT_MAX,
+                            FLT_MAX);
+  RNA_def_boolean(
+      ot->srna, "rotation_lock", false, "Lock Rotation", "Preserve objects' original rotation");
+  RNA_def

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list