Patch #32326: NDOF support of rotation and panning the view at the same time
Additional changes: - Option to the ndof menu letting you pick turntable/trackball independently of the mouse viewport navigation style - Option to change the rotation sensitivity separate from the panning Holding shift + moving the ndof does just as before locking it to panning Holding ctrl + moving will lock it to only rotation Patch by Fredrik Hansson, thanks! Reviewed by self and Mike Erwin.
This commit is contained in:
@@ -858,6 +858,7 @@ class USERPREF_MT_ndof_settings(Menu):
|
||||
|
||||
layout.separator()
|
||||
layout.prop(input_prefs, "ndof_sensitivity")
|
||||
layout.prop(input_prefs, "ndof_orbit_sensitivity")
|
||||
|
||||
if context.space_data.type == 'VIEW_3D':
|
||||
layout.separator()
|
||||
@@ -865,11 +866,10 @@ class USERPREF_MT_ndof_settings(Menu):
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Orbit options")
|
||||
if input_prefs.view_rotate_method == 'TRACKBALL':
|
||||
layout.prop(input_prefs, "ndof_roll_invert_axis")
|
||||
layout.prop(input_prefs, "ndof_turntable")
|
||||
layout.prop(input_prefs, "ndof_roll_invert_axis")
|
||||
layout.prop(input_prefs, "ndof_tilt_invert_axis")
|
||||
layout.prop(input_prefs, "ndof_rotate_invert_axis")
|
||||
layout.prop(input_prefs, "ndof_zoom_invert")
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Pan options")
|
||||
@@ -878,6 +878,7 @@ class USERPREF_MT_ndof_settings(Menu):
|
||||
layout.prop(input_prefs, "ndof_panz_invert_axis")
|
||||
|
||||
layout.label(text="Zoom options")
|
||||
layout.prop(input_prefs, "ndof_zoom_invert")
|
||||
layout.prop(input_prefs, "ndof_zoom_updown")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -1967,6 +1967,10 @@ void init_userdef_do_versions(void)
|
||||
U.ndof_flag = NDOF_LOCK_HORIZON |
|
||||
NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE;
|
||||
}
|
||||
|
||||
if (U.ndof_orbit_sensitivity == 0.0f) {
|
||||
U.ndof_orbit_sensitivity = 1.0f;
|
||||
}
|
||||
if (U.tweak_threshold == 0)
|
||||
U.tweak_threshold = 10;
|
||||
|
||||
|
||||
@@ -1036,20 +1036,6 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event
|
||||
ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
|
||||
#endif
|
||||
|
||||
if (ndof->tz) {
|
||||
/* Zoom!
|
||||
* velocity should be proportional to the linear velocity attained by rotational motion of same strength
|
||||
* [got that?]
|
||||
* proportional to arclength = radius * angle
|
||||
*/
|
||||
float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
|
||||
|
||||
if (U.ndof_flag & NDOF_ZOOM_INVERT)
|
||||
zoom_distance = -zoom_distance;
|
||||
|
||||
rv3d->dist += zoom_distance;
|
||||
}
|
||||
|
||||
if (rv3d->viewlock == RV3D_LOCKED) {
|
||||
/* rotation not allowed -- explore panning options instead */
|
||||
float pan_vec[3] = {ndof->tx, ndof->ty, 0.0f};
|
||||
@@ -1067,34 +1053,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event
|
||||
|
||||
rv3d->view = RV3D_VIEW_USER;
|
||||
|
||||
if (U.flag & USER_TRACKBALL) {
|
||||
float rot[4];
|
||||
float axis[3];
|
||||
float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
|
||||
|
||||
if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
|
||||
axis[2] = -axis[2];
|
||||
|
||||
if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
|
||||
axis[0] = -axis[0];
|
||||
|
||||
if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
|
||||
axis[1] = -axis[1];
|
||||
|
||||
/* transform rotation axis from view to world coordinates */
|
||||
mul_qt_v3(view_inv, axis);
|
||||
|
||||
/* update the onscreen doo-dad */
|
||||
rv3d->rot_angle = angle;
|
||||
copy_v3_v3(rv3d->rot_axis, axis);
|
||||
|
||||
axis_angle_to_quat(rot, axis, angle);
|
||||
|
||||
/* apply rotation */
|
||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||
|
||||
}
|
||||
else {
|
||||
if (U.ndof_flag & NDOF_TURNTABLE) {
|
||||
|
||||
/* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
|
||||
float angle, rot[4];
|
||||
@@ -1127,6 +1086,33 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event
|
||||
rot[3] = sin(angle);
|
||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||
}
|
||||
else {
|
||||
float rot[4];
|
||||
float axis[3];
|
||||
float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
|
||||
|
||||
if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
|
||||
axis[2] = -axis[2];
|
||||
|
||||
if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
|
||||
axis[0] = -axis[0];
|
||||
|
||||
if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
|
||||
axis[1] = -axis[1];
|
||||
|
||||
/* transform rotation axis from view to world coordinates */
|
||||
mul_qt_v3(view_inv, axis);
|
||||
|
||||
/* update the onscreen doo-dad */
|
||||
rv3d->rot_angle = angle;
|
||||
copy_v3_v3(rv3d->rot_axis, axis);
|
||||
|
||||
axis_angle_to_quat(rot, axis, angle);
|
||||
|
||||
/* apply rotation */
|
||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1247,6 +1233,159 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
|
||||
ot->flag = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* this is basically just the pan only code + the rotate only code crammed into one function that does both
|
||||
*/
|
||||
static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
if (event->type != NDOF_MOTION)
|
||||
return OPERATOR_CANCELLED;
|
||||
else {
|
||||
|
||||
ViewOpsData *vod;
|
||||
RegionView3D *rv3d;
|
||||
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
|
||||
|
||||
ED_view3d_camera_lock_init(v3d, rv3d);
|
||||
|
||||
viewops_data_create(C, op, event);
|
||||
vod = op->customdata;
|
||||
rv3d = vod->rv3d;
|
||||
|
||||
|
||||
if (ndof->progress != P_FINISHING) {
|
||||
|
||||
const float dt = ndof->dt;
|
||||
float view_inv[4];
|
||||
|
||||
float speed = 10.f; /* blender units per second */
|
||||
/* ^^ this is ok for default cube scene, but should scale with.. something */
|
||||
|
||||
/* tune these until everything feels right */
|
||||
const float forward_sensitivity = 1.f;
|
||||
const float vertical_sensitivity = 0.4f;
|
||||
const float lateral_sensitivity = 0.6f;
|
||||
|
||||
float pan_vec[3];
|
||||
const float rot_sensitivity = 1.f;
|
||||
const float zoom_sensitivity = 1.f;
|
||||
const float pan_sensitivity = 1.f;
|
||||
float rot[4];
|
||||
float axis[3];
|
||||
float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
|
||||
|
||||
if (U.ndof_flag & NDOF_PANX_INVERT_AXIS)
|
||||
pan_vec[0] = -lateral_sensitivity * ndof->tvec[0];
|
||||
else
|
||||
pan_vec[0] = lateral_sensitivity * ndof->tvec[0];
|
||||
|
||||
if (U.ndof_flag & NDOF_PANZ_INVERT_AXIS)
|
||||
pan_vec[1] = -vertical_sensitivity * ndof->tvec[1];
|
||||
else
|
||||
pan_vec[1] = vertical_sensitivity * ndof->tvec[1];
|
||||
|
||||
if (U.ndof_flag & NDOF_PANY_INVERT_AXIS)
|
||||
pan_vec[2] = -forward_sensitivity * ndof->tvec[2];
|
||||
else
|
||||
pan_vec[2] = forward_sensitivity * ndof->tvec[2];
|
||||
|
||||
mul_v3_fl(pan_vec, speed * dt);
|
||||
|
||||
/* transform motion from view to world coordinates */
|
||||
invert_qt_qt(view_inv, rv3d->viewquat);
|
||||
mul_qt_v3(view_inv, pan_vec);
|
||||
|
||||
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
|
||||
sub_v3_v3(rv3d->ofs, pan_vec);
|
||||
|
||||
if (U.ndof_flag & NDOF_TURNTABLE) {
|
||||
/* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
|
||||
float angle, rot[4];
|
||||
float xvec[3] = {1, 0, 0};
|
||||
|
||||
/* Determine the direction of the x vector (for rotating up and down) */
|
||||
mul_qt_v3(view_inv, xvec);
|
||||
|
||||
/* Perform the up/down rotation */
|
||||
angle = rot_sensitivity * dt * ndof->rx;
|
||||
if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
|
||||
angle = -angle;
|
||||
rot[0] = cos(angle);
|
||||
mul_v3_v3fl(rot + 1, xvec, sin(angle));
|
||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||
|
||||
/* Perform the orbital rotation */
|
||||
angle = rot_sensitivity * dt * ndof->ry;
|
||||
if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
|
||||
angle = -angle;
|
||||
|
||||
/* update the onscreen doo-dad */
|
||||
rv3d->rot_angle = angle;
|
||||
rv3d->rot_axis[0] = 0;
|
||||
rv3d->rot_axis[1] = 0;
|
||||
rv3d->rot_axis[2] = 1;
|
||||
|
||||
rot[0] = cos(angle);
|
||||
rot[1] = rot[2] = 0.0;
|
||||
rot[3] = sin(angle);
|
||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
float rot[4];
|
||||
float axis[3];
|
||||
float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
|
||||
|
||||
if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
|
||||
axis[2] = -axis[2];
|
||||
|
||||
if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
|
||||
axis[0] = -axis[0];
|
||||
|
||||
if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
|
||||
axis[1] = -axis[1];
|
||||
|
||||
/* transform rotation axis from view to world coordinates */
|
||||
mul_qt_v3(view_inv, axis);
|
||||
|
||||
/* update the onscreen doo-dad */
|
||||
rv3d->rot_angle = angle;
|
||||
copy_v3_v3(rv3d->rot_axis, axis);
|
||||
|
||||
axis_angle_to_quat(rot, axis, angle);
|
||||
|
||||
/* apply rotation */
|
||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||
|
||||
}
|
||||
}
|
||||
ED_view3d_camera_lock_sync(v3d, rv3d);
|
||||
|
||||
ED_region_tag_redraw(CTX_wm_region(C));
|
||||
viewops_data_free(C, op);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "NDOF move View";
|
||||
ot->description = "Position your viewpoint with the 3D mouse";
|
||||
ot->idname = "VIEW3D_OT_ndof_all";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = ndof_all_invoke;
|
||||
ot->poll = ED_operator_view3d_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
}
|
||||
|
||||
/* ************************ viewmove ******************************** */
|
||||
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ void VIEW3D_OT_move(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_rotate(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_view_selected(struct wmOperatorType *ot);
|
||||
|
||||
@@ -64,6 +64,7 @@ void view3d_operatortypes(void)
|
||||
WM_operatortype_append(VIEW3D_OT_dolly);
|
||||
WM_operatortype_append(VIEW3D_OT_ndof_orbit);
|
||||
WM_operatortype_append(VIEW3D_OT_ndof_pan);
|
||||
WM_operatortype_append(VIEW3D_OT_ndof_all);
|
||||
WM_operatortype_append(VIEW3D_OT_view_all);
|
||||
WM_operatortype_append(VIEW3D_OT_viewnumpad);
|
||||
WM_operatortype_append(VIEW3D_OT_view_orbit);
|
||||
@@ -221,8 +222,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
|
||||
RNA_boolean_set(kmi->ptr, "align_active", TRUE);
|
||||
|
||||
/* 3D mouse */
|
||||
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, 0, 0);
|
||||
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, 0, 0);
|
||||
WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
|
||||
|
||||
@@ -414,6 +414,8 @@ typedef struct UserDef {
|
||||
short use_16bit_textures, use_gpu_mipmap;
|
||||
|
||||
float ndof_sensitivity; /* overall sensitivity of 3D mouse */
|
||||
float ndof_orbit_sensitivity;
|
||||
float pad4;
|
||||
int ndof_flag; /* flags for 3D mouse */
|
||||
|
||||
float glalphaclip;
|
||||
@@ -649,6 +651,7 @@ extern UserDef U; /* from blenkernel blender.c */
|
||||
#define NDOF_PANX_INVERT_AXIS (1 << 12)
|
||||
#define NDOF_PANY_INVERT_AXIS (1 << 13)
|
||||
#define NDOF_PANZ_INVERT_AXIS (1 << 14)
|
||||
#define NDOF_TURNTABLE (1 << 15)
|
||||
|
||||
/* compute_device_type */
|
||||
#define USER_COMPUTE_DEVICE_NONE 0
|
||||
|
||||
@@ -3358,7 +3358,11 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
/* global options */
|
||||
prop = RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.25f, 4.0f);
|
||||
RNA_def_property_ui_text(prop, "Sensitivity", "Overall sensitivity of the 3D Mouse");
|
||||
RNA_def_property_ui_text(prop, "Sensitivity", "Overall sensitivity of the 3D Mouse for panning");
|
||||
|
||||
prop = RNA_def_property(srna, "ndof_orbit_sensitivity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.25f, 4.0f);
|
||||
RNA_def_property_ui_text(prop, "Orbit Sensitivity", "Overall sensitivity of the 3D Mouse for orbiting");
|
||||
|
||||
prop = RNA_def_property(srna, "ndof_zoom_updown", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ZOOM_UPDOWN);
|
||||
@@ -3375,6 +3379,11 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation");
|
||||
/* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/
|
||||
|
||||
/* 3D view */
|
||||
prop = RNA_def_property(srna, "ndof_turntable", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_TURNTABLE);
|
||||
RNA_def_property_ui_text(prop, "Turntable", "Turntable for ndof rotation");
|
||||
|
||||
/* 3D view: roll */
|
||||
prop = RNA_def_property(srna, "ndof_roll_invert_axis", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ROLL_INVERT_AXIS);
|
||||
|
||||
@@ -2617,12 +2617,13 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g
|
||||
wmNDOFMotionData *data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF");
|
||||
|
||||
const float s = U.ndof_sensitivity;
|
||||
const float rs = U.ndof_orbit_sensitivity;
|
||||
|
||||
data->tx = s * ghost->tx;
|
||||
|
||||
data->rx = s * ghost->rx;
|
||||
data->ry = s * ghost->ry;
|
||||
data->rz = s * ghost->rz;
|
||||
data->rx = rs * ghost->rx;
|
||||
data->ry = rs * ghost->ry;
|
||||
data->rz = rs * ghost->rz;
|
||||
|
||||
if (U.ndof_flag & NDOF_ZOOM_UPDOWN) {
|
||||
/* rotate so Y is where Z was */
|
||||
|
||||
Reference in New Issue
Block a user