fixed crash when NDOF operators were called without an NDOF_MOTION event

This commit is contained in:
Mike Erwin 2011-08-06 22:31:16 +00:00
parent 79e359f92a
commit 5dd2b3e06f
2 changed files with 185 additions and 182 deletions

@ -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)