forked from bartvdbraak/blender
fixed crash when NDOF operators were called without an NDOF_MOTION event
This commit is contained in:
parent
79e359f92a
commit
5dd2b3e06f
@ -447,34 +447,41 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
|
|||||||
|
|
||||||
static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
|
static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
|
||||||
{
|
{
|
||||||
SpaceImage *sima= CTX_wm_space_image(C);
|
if (event->type != NDOF_MOTION)
|
||||||
ARegion *ar= CTX_wm_region(C);
|
return OPERATOR_CANCELLED;
|
||||||
|
else {
|
||||||
|
SpaceImage *sima= CTX_wm_space_image(C);
|
||||||
|
ARegion *ar= CTX_wm_region(C);
|
||||||
|
|
||||||
wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
|
wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
|
||||||
|
|
||||||
float dt = ndof->dt;
|
float dt = ndof->dt;
|
||||||
/* tune these until it feels right */
|
/* tune these until it feels right */
|
||||||
const float zoom_sensitivity = 0.5f; // 50% per second (I think)
|
const float zoom_sensitivity = 0.5f; // 50% per second (I think)
|
||||||
const float pan_sensitivity = 300.f; // screen pixels per second
|
const float pan_sensitivity = 300.f; // screen pixels per second
|
||||||
|
|
||||||
float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom;
|
float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom;
|
||||||
float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom;
|
float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom;
|
||||||
|
|
||||||
/* "mouse zoom" factor = 1 + (dx + dy) / 300
|
/* "mouse zoom" factor = 1 + (dx + dy) / 300
|
||||||
* what about "ndof zoom" factor? should behave like this:
|
* what about "ndof zoom" factor? should behave like this:
|
||||||
* at rest -> factor = 1
|
* at rest -> factor = 1
|
||||||
* move forward -> factor > 1
|
* move forward -> factor > 1
|
||||||
* move backward -> factor < 1
|
* move backward -> factor < 1
|
||||||
*/
|
*/
|
||||||
float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2];
|
float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2];
|
||||||
|
|
||||||
sima_zoom_set_factor(sima, ar, zoom_factor);
|
if (U.ndof_flag & NDOF_ZOOM_INVERT)
|
||||||
sima->xof += pan_x;
|
zoom_factor = -zoom_factor;
|
||||||
sima->yof += pan_y;
|
|
||||||
|
|
||||||
ED_region_tag_redraw(ar);
|
sima_zoom_set_factor(sima, ar, zoom_factor);
|
||||||
|
sima->xof += pan_x;
|
||||||
|
sima->yof += pan_y;
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
ED_region_tag_redraw(ar);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMAGE_OT_view_ndof(wmOperatorType *ot)
|
void IMAGE_OT_view_ndof(wmOperatorType *ot)
|
||||||
|
@ -949,134 +949,125 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event
|
|||||||
// -- zooming
|
// -- zooming
|
||||||
// -- panning in rotationally-locked views
|
// -- panning in rotationally-locked views
|
||||||
{
|
{
|
||||||
RegionView3D* rv3d = CTX_wm_region_view3d(C);
|
if (event->type != NDOF_MOTION)
|
||||||
wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
|
return OPERATOR_CANCELLED;
|
||||||
|
else {
|
||||||
|
RegionView3D* rv3d = CTX_wm_region_view3d(C);
|
||||||
|
wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
|
||||||
|
|
||||||
rv3d->rot_angle = 0.f; // off by default, until changed later this function
|
rv3d->rot_angle = 0.f; // off by default, until changed later this function
|
||||||
|
|
||||||
if (ndof->progress != P_FINISHING) {
|
if (ndof->progress != P_FINISHING) {
|
||||||
const float dt = ndof->dt;
|
const float dt = ndof->dt;
|
||||||
|
|
||||||
// tune these until everything feels right
|
// tune these until everything feels right
|
||||||
const float rot_sensitivity = 1.f;
|
const float rot_sensitivity = 1.f;
|
||||||
const float zoom_sensitivity = 1.f;
|
const float zoom_sensitivity = 1.f;
|
||||||
const float pan_sensitivity = 1.f;
|
const float pan_sensitivity = 1.f;
|
||||||
|
|
||||||
// rather have bool, but...
|
// rather have bool, but...
|
||||||
int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec);
|
int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec);
|
||||||
|
|
||||||
float view_inv[4];
|
float view_inv[4];
|
||||||
invert_qt_qt(view_inv, rv3d->viewquat);
|
|
||||||
|
|
||||||
//#define DEBUG_NDOF_MOTION
|
|
||||||
#ifdef DEBUG_NDOF_MOTION
|
|
||||||
printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
|
|
||||||
ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ndof->tvec[2]) {
|
|
||||||
// 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->tvec[2];
|
|
||||||
rv3d->dist += zoom_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rv3d->viewlock == RV3D_LOCKED) {
|
|
||||||
/* rotation not allowed -- explore panning options instead */
|
|
||||||
float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f};
|
|
||||||
mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
|
|
||||||
|
|
||||||
/* transform motion from view to world coordinates */
|
|
||||||
invert_qt_qt(view_inv, rv3d->viewquat);
|
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) */
|
//#define DEBUG_NDOF_MOTION
|
||||||
sub_v3_v3(rv3d->ofs, pan_vec);
|
#ifdef DEBUG_NDOF_MOTION
|
||||||
}
|
printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
|
||||||
|
ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (has_rotation) {
|
if (ndof->tvec[2]) {
|
||||||
|
// Zoom!
|
||||||
|
// velocity should be proportional to the linear velocity attained by rotational motion of same strength
|
||||||
|
// [got that?]
|
||||||
|
// proportional to arclength = radius * angle
|
||||||
|
|
||||||
const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES;
|
float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tvec[2];
|
||||||
|
|
||||||
rv3d->view = RV3D_VIEW_USER;
|
if (U.ndof_flag & NDOF_ZOOM_INVERT)
|
||||||
|
zoom_distance = -zoom_distance;
|
||||||
|
|
||||||
if (U.flag & USER_TRACKBALL) {
|
rv3d->dist += zoom_distance;
|
||||||
float rot[4];
|
}
|
||||||
#if 0 // -------------------------- Mike's nifty original version
|
|
||||||
float view_inv_conj[4];
|
|
||||||
|
|
||||||
ndof_to_quat(ndof, rot);
|
if (rv3d->viewlock == RV3D_LOCKED) {
|
||||||
// mul_qt_fl(rot, rot_sensitivity);
|
/* rotation not allowed -- explore panning options instead */
|
||||||
// ^^ no apparent effect
|
float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f};
|
||||||
|
mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
|
||||||
|
|
||||||
if (invert)
|
/* transform motion from view to world coordinates */
|
||||||
invert_qt(rot);
|
invert_qt_qt(view_inv, rv3d->viewquat);
|
||||||
|
mul_qt_v3(view_inv, pan_vec);
|
||||||
|
|
||||||
copy_qt_qt(view_inv_conj, view_inv);
|
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
|
||||||
conjugate_qt(view_inv_conj);
|
sub_v3_v3(rv3d->ofs, pan_vec);
|
||||||
|
}
|
||||||
|
|
||||||
// transform rotation from view to world coordinates
|
if (has_rotation) {
|
||||||
mul_qt_qtqt(rot, view_inv, rot);
|
|
||||||
mul_qt_qtqt(rot, rot, view_inv_conj);
|
|
||||||
#else // ---------------------------------------- Mike's revised version
|
|
||||||
float axis[3];
|
|
||||||
float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
|
|
||||||
|
|
||||||
if (invert)
|
const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES;
|
||||||
angle = -angle;
|
|
||||||
|
|
||||||
// transform rotation axis from view to world coordinates
|
rv3d->view = RV3D_VIEW_USER;
|
||||||
mul_qt_v3(view_inv, axis);
|
|
||||||
|
|
||||||
// update the onscreen doo-dad
|
if (U.flag & USER_TRACKBALL) {
|
||||||
rv3d->rot_angle = angle;
|
float rot[4];
|
||||||
copy_v3_v3(rv3d->rot_axis, axis);
|
float axis[3];
|
||||||
|
float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
|
||||||
|
|
||||||
axis_angle_to_quat(rot, axis, angle);
|
if (invert)
|
||||||
#endif // --------------------------------------------
|
angle = -angle;
|
||||||
// apply rotation
|
|
||||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
|
||||||
} else {
|
|
||||||
/* 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) */
|
// transform rotation axis from view to world coordinates
|
||||||
mul_qt_v3(view_inv, xvec);
|
mul_qt_v3(view_inv, axis);
|
||||||
|
|
||||||
/* Perform the up/down rotation */
|
// update the onscreen doo-dad
|
||||||
angle = rot_sensitivity * dt * ndof->rvec[0];
|
rv3d->rot_angle = angle;
|
||||||
if (invert)
|
copy_v3_v3(rv3d->rot_axis, 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 */
|
axis_angle_to_quat(rot, axis, angle);
|
||||||
angle = rot_sensitivity * dt * ndof->rvec[1];
|
|
||||||
if (invert)
|
|
||||||
angle = -angle;
|
|
||||||
|
|
||||||
// update the onscreen doo-dad
|
// apply rotation
|
||||||
rv3d->rot_angle = angle;
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
||||||
rv3d->rot_axis[0] = 0;
|
} else {
|
||||||
rv3d->rot_axis[1] = 0;
|
/* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
|
||||||
rv3d->rot_axis[2] = 1;
|
float angle, rot[4];
|
||||||
|
float xvec[3] = {1,0,0};
|
||||||
|
|
||||||
rot[0] = cos(angle);
|
/* Determine the direction of the x vector (for rotating up and down) */
|
||||||
rot[1] = rot[2] = 0.0;
|
mul_qt_v3(view_inv, xvec);
|
||||||
rot[3] = sin(angle);
|
|
||||||
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
|
/* Perform the up/down rotation */
|
||||||
|
angle = rot_sensitivity * dt * ndof->rvec[0];
|
||||||
|
if (invert)
|
||||||
|
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->rvec[1];
|
||||||
|
if (invert)
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ED_region_tag_redraw(CTX_wm_region(C));
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ED_region_tag_redraw(CTX_wm_region(C));
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
|
void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
|
||||||
@ -1098,57 +1089,62 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
|
|||||||
// -- "pan" navigation
|
// -- "pan" navigation
|
||||||
// -- zoom or dolly?
|
// -- zoom or dolly?
|
||||||
{
|
{
|
||||||
RegionView3D* rv3d = CTX_wm_region_view3d(C);
|
if (event->type != NDOF_MOTION)
|
||||||
wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
|
return OPERATOR_CANCELLED;
|
||||||
|
else {
|
||||||
|
RegionView3D* rv3d = CTX_wm_region_view3d(C);
|
||||||
|
wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
|
||||||
|
|
||||||
rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators
|
|
||||||
|
|
||||||
if (ndof->progress != P_FINISHING) {
|
rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators
|
||||||
const float dt = ndof->dt;
|
|
||||||
float view_inv[4];
|
if (ndof->progress != P_FINISHING) {
|
||||||
|
const float dt = ndof->dt;
|
||||||
|
float view_inv[4];
|
||||||
#if 0 // ------------------------------------------- zoom with Z
|
#if 0 // ------------------------------------------- zoom with Z
|
||||||
// tune these until everything feels right
|
// tune these until everything feels right
|
||||||
const float zoom_sensitivity = 1.f;
|
const float zoom_sensitivity = 1.f;
|
||||||
const float pan_sensitivity = 1.f;
|
const float pan_sensitivity = 1.f;
|
||||||
|
|
||||||
float pan_vec[3] = {
|
float pan_vec[3] = {
|
||||||
ndof->tx, ndof->ty, 0
|
ndof->tx, ndof->ty, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// "zoom in" or "translate"? depends on zoom mode in user settings?
|
// "zoom in" or "translate"? depends on zoom mode in user settings?
|
||||||
if (ndof->tz) {
|
if (ndof->tz) {
|
||||||
float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
|
float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
|
||||||
rv3d->dist += zoom_distance;
|
rv3d->dist += zoom_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
|
||||||
|
#else // ------------------------------------------------------- dolly with Z
|
||||||
|
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] = {lateral_sensitivity * ndof->tvec[0],
|
||||||
|
vertical_sensitivity * ndof->tvec[1],
|
||||||
|
forward_sensitivity * ndof->tvec[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
mul_v3_fl(pan_vec, speed * dt);
|
||||||
|
#endif
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
|
ED_region_tag_redraw(CTX_wm_region(C));
|
||||||
#else // ------------------------------------------------------- dolly with Z
|
|
||||||
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
|
return OPERATOR_FINISHED;
|
||||||
const float forward_sensitivity = 1.f;
|
|
||||||
const float vertical_sensitivity = 0.4f;
|
|
||||||
const float lateral_sensitivity = 0.6f;
|
|
||||||
|
|
||||||
float pan_vec[3] = {lateral_sensitivity * ndof->tvec[0],
|
|
||||||
vertical_sensitivity * ndof->tvec[1],
|
|
||||||
forward_sensitivity * ndof->tvec[2]
|
|
||||||
};
|
|
||||||
|
|
||||||
mul_v3_fl(pan_vec, speed * dt);
|
|
||||||
#endif
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ED_region_tag_redraw(CTX_wm_region(C));
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
|
void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
|
||||||
|
Loading…
Reference in New Issue
Block a user