[Bf-blender-cvs] [2585d7f1b81] xr-controller-support: XR: Add grab navigation operator
Peter Kim
noreply at git.blender.org
Fri Jun 18 14:37:18 CEST 2021
Commit: 2585d7f1b812c54043648c128b9aec7a5e24106d
Author: Peter Kim
Date: Fri Jun 18 21:32:18 2021 +0900
Branches: xr-controller-support
https://developer.blender.org/rB2585d7f1b812c54043648c128b9aec7a5e24106d
XR: Add grab navigation operator
Similar to the XR grab transform operator but applies deltas to the
navigation matrix instead of objects. Supports bimanual interaction
for viewer/navigation scaling and locks for rotation and scale.
===================================================================
M source/blender/windowmanager/xr/intern/wm_xr_operators.c
===================================================================
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
index 1ef4bdc01c3..d0915b87f13 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
@@ -74,6 +74,8 @@ static bool wm_xr_operator_sessionactive(bContext *C)
return false;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name XR Session Toggle
*
@@ -160,8 +162,355 @@ static void WM_OT_xr_session_toggle(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name XR Raycast Utilities
+/** \name XR Grab Utilities
+ * \{ */
+
+typedef struct XrGrabData {
+ float mat_prev[4][4];
+ float mat_other_prev[4][4];
+ bool bimanual_prev;
+} 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)
+{
+ MEM_SAFE_FREE(op->customdata);
+}
+
+static void wm_xr_grab_update(wmOperator *op, const wmXrActionData *actiondata)
+{
+ XrGrabData *data = op->customdata;
+
+ quat_to_mat4(data->mat_prev, actiondata->controller_rot);
+ copy_v3_v3(data->mat_prev[3], actiondata->controller_loc);
+
+ if (actiondata->bimanual) {
+ quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
+ copy_v3_v3(data->mat_other_prev[3], actiondata->controller_loc_other);
+ data->bimanual_prev = true;
+ }
+ else {
+ data->bimanual_prev = false;
+ }
+}
+
+static void wm_xr_grab_compute(const wmXrActionData *actiondata,
+ const XrGrabData *data,
+ const Object *obedit,
+ bool reverse,
+ bool loc_lock,
+ bool rot_lock,
+ float r_delta[4][4])
+{
+ float m0[4][4], m1[4][4];
+
+ if (obedit) {
+ float m2[4][4];
+
+ if (rot_lock) {
+ unit_m4(m0);
+ copy_v3_v3(m0[3], reverse ? actiondata->controller_loc : data->mat_prev[3]);
+ mul_m4_m4m4(m1, obedit->imat, m0);
+ invert_m4(m1);
+
+ copy_v3_v3(m0[3], reverse ? data->mat_prev[3] : actiondata->controller_loc);
+ mul_m4_m4m4(m2, obedit->imat, m0);
+
+ mul_m4_m4m4(r_delta, m2, m1);
+ }
+ else {
+ if (reverse) {
+ quat_to_mat4(m0, actiondata->controller_rot);
+ copy_v3_v3(m0[3], actiondata->controller_loc);
+ mul_m4_m4m4(m1, obedit->imat, m0);
+ invert_m4(m1);
+
+ mul_m4_m4m4(m2, obedit->imat, data->mat_prev);
+
+ mul_m4_m4m4(r_delta, m2, m1);
+ }
+ else {
+ mul_m4_m4m4(m1, obedit->imat, data->mat_prev);
+ invert_m4(m1);
+
+ quat_to_mat4(m0, actiondata->controller_rot);
+ copy_v3_v3(m0[3], actiondata->controller_loc);
+ mul_m4_m4m4(m2, obedit->imat, m0);
+
+ mul_m4_m4m4(r_delta, m2, m1);
+ }
+
+ if (loc_lock) {
+ zero_v3(r_delta[3]);
+ }
+ }
+ }
+ else {
+ if (rot_lock) {
+ unit_m4(m0);
+ copy_v3_v3(m0[3], reverse ? actiondata->controller_loc : data->mat_prev[3]);
+ invert_m4_m4(m1, m0);
+
+ copy_v3_v3(m0[3], reverse ? data->mat_prev[3] : actiondata->controller_loc);
+
+ mul_m4_m4m4(r_delta, m0, m1);
+ }
+ else {
+ if (reverse) {
+ quat_to_mat4(m1, actiondata->controller_rot);
+ copy_v3_v3(m1[3], actiondata->controller_loc);
+ invert_m4(m1);
+
+ mul_m4_m4m4(r_delta, data->mat_prev, m1);
+ }
+ else {
+ invert_m4_m4(m1, data->mat_prev);
+
+ quat_to_mat4(m0, actiondata->controller_rot);
+ copy_v3_v3(m0[3], actiondata->controller_loc);
+
+ mul_m4_m4m4(r_delta, m0, m1);
+ }
+
+ if (loc_lock) {
+ zero_v3(r_delta[3]);
+ }
+ }
+ }
+}
+
+static void wm_xr_grab_compute_bimanual(const wmXrActionData *actiondata,
+ const XrGrabData *data,
+ const Object *obedit,
+ bool reverse,
+ bool loc_lock,
+ bool rot_lock,
+ bool scale_lock,
+ float r_delta[4][4])
+{
+ float prev[4][4], curr[4][4];
+ unit_m4(prev);
+ unit_m4(curr);
+
+ if (!rot_lock) {
+ /* Rotation. */
+ float x_axis_prev[3], x_axis_curr[3], y_axis_prev[3], y_axis_curr[3], z_axis_prev[3],
+ z_axis_curr[3];
+ float m0[3][3], m1[3][3];
+ quat_to_mat3(m0, actiondata->controller_rot);
+ quat_to_mat3(m1, actiondata->controller_rot_other);
+
+ /* x-axis is the base line between the two controllers. */
+ sub_v3_v3v3(x_axis_prev, data->mat_prev[3], data->mat_other_prev[3]);
+ sub_v3_v3v3(x_axis_curr, actiondata->controller_loc, actiondata->controller_loc_other);
+ /* y-axis is the average of the controllers' y-axes. */
+ add_v3_v3v3(y_axis_prev, data->mat_prev[1], data->mat_other_prev[1]);
+ mul_v3_fl(y_axis_prev, 0.5f);
+ add_v3_v3v3(y_axis_curr, m0[1], m1[1]);
+ mul_v3_fl(y_axis_curr, 0.5f);
+ /* z-axis is the cross product of the two. */
+ cross_v3_v3v3(z_axis_prev, x_axis_prev, y_axis_prev);
+ cross_v3_v3v3(z_axis_curr, x_axis_curr, y_axis_curr);
+ /* Fix the y-axis to be orthogonal. */
+ cross_v3_v3v3(y_axis_prev, z_axis_prev, x_axis_prev);
+ cross_v3_v3v3(y_axis_curr, z_axis_curr, x_axis_curr);
+ /* Normalize. */
+ normalize_v3_v3(prev[0], x_axis_prev);
+ normalize_v3_v3(prev[1], y_axis_prev);
+ normalize_v3_v3(prev[2], z_axis_prev);
+ normalize_v3_v3(curr[0], x_axis_curr);
+ normalize_v3_v3(curr[1], y_axis_curr);
+ normalize_v3_v3(curr[2], z_axis_curr);
+ }
+
+ if (!loc_lock) {
+ /* Translation: translation of the averaged controller locations. */
+ add_v3_v3v3(prev[3], data->mat_prev[3], data->mat_other_prev[3]);
+ mul_v3_fl(prev[3], 0.5f);
+ add_v3_v3v3(curr[3], actiondata->controller_loc, actiondata->controller_loc_other);
+ mul_v3_fl(curr[3], 0.5f);
+ }
+
+ if (!scale_lock) {
+ /* Scaling: distance between controllers. */
+ float scale, v[3];
+
+ sub_v3_v3v3(v, data->mat_prev[3], data->mat_other_prev[3]);
+ scale = len_v3(v);
+ mul_v3_fl(prev[0], scale);
+ mul_v3_fl(prev[1], scale);
+ mul_v3_fl(prev[2], scale);
+
+ sub_v3_v3v3(v, actiondata->controller_loc, actiondata->controller_loc_other);
+ scale = len_v3(v);
+ mul_v3_fl(curr[0], scale);
+ mul_v3_fl(curr[1], scale);
+ mul_v3_fl(curr[2], scale);
+ }
+
+ if (obedit) {
+ mul_m4_m4m4(prev, obedit->imat, prev);
+ mul_m4_m4m4(curr, obedit->imat, curr);
+ }
+
+ if (reverse) {
+ invert_m4(curr);
+ mul_m4_m4m4(r_delta, prev, curr);
+ }
+ else {
+ invert_m4(prev);
+ mul_m4_m4m4(r_delta, curr, prev);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name XR Navigation Grab
*
+ * Navigates the scene by grabbing with XR controllers.
+ * \{ */
+
+static int wm_xr_navigation_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);
+
+ const wmXrActionData *actiondata = event->customdata;
+
+ wm_xr_grab_init(op);
+ wm_xr_grab_update(op, actiondata);
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int wm_xr_navigation_grab_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+ return OPERATOR_CANCELLED;
+}
+
+static int wm_xr_navigation_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;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmXrData *xr = &wm->xr;
+ bool loc_lock, rot_lock, scale_lock;
+ GHOST_XrPose nav_pose;
+ float nav_scale, nav_mat[4][4], delta[4][4], m[4][4];
+
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "lock_location");
+ loc_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+ prop = RNA_struct_find_property(op->ptr, "lock_rotation");
+ rot_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+ prop = RNA_struct_find_property(op->ptr, "lock_scale");
+ scale_lock = prop ? RNA_property_boolean_get(op->ptr, prop) : false;
+
+ const bool do_bimanual = (actiondata->bimanual && data->bimanual_prev);
+ const bool apply_navigation = (do_bimanual ? !(loc_lock && rot_lock && scale_lock) :
+ !(loc_lock && rot_lock)) &&
+ (actiondata->bimanual || !data->bimanual_prev);
+
+ if (apply_navigation) {
+ WM_xr_session_state_nav_location_get(xr, nav_pose.position);
+ WM_xr_session_state_nav_rotation_get(xr, nav_pose.orientation_quat);
+ WM_xr_session_state_nav_scale_get(xr, &nav_scale);
+
+ wm_xr_pose_scale_to_mat(&nav_pose, nav_scale, nav_mat);
+
+ if (do_bimanual) {
+ wm_xr_grab_compute_bimanual(
+ actiondata, data, NULL, true, loc_lock, rot_lock, scale_lock, delta);
+ }
+ else {
+ wm_xr_grab_compute(actiondata, data, NULL, true, loc_lock, rot_lock, delta);
+ }
+
+ mul_m4_m4m4(m, delta, nav_mat);
+
+ if (!loc_lock) {
+ WM_xr_session_state_nav_location_set(xr, m[3]);
+ }
+ if (!rot_lock) {
+ mat4_to_quat(nav_pose.orientation_quat, m);
+ normalize_qt(nav_pose.orientation_quat);
+ WM_xr_session_state_nav_rotation_set(xr, nav_pose.orientation_quat);
+ }
+ if (!scale_lock && do_bimanual) {
+ nav_scale = len_v3(m[0]);
+ WM_xr_session_state_nav_scale_set(xr, nav_scale);
+ }
+ }
+
+ if (actiondata->bimanual) {
+ if (!data->bimanual_prev) {
+ quat_to_mat4(data->mat_other_prev, actiondata->controller_rot_other);
+ copy_v3_v3(data->mat_other_prev[3], actiondata->controll
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list