Code cleanup: de-duplicate ndof controls for walk/fly mode

This commit is contained in:
Campbell Barton
2014-02-19 21:19:13 +11:00
parent 7929970bf9
commit d56ed8dcd9
4 changed files with 139 additions and 231 deletions

View File

@@ -1148,7 +1148,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
* (should these functions live in this file?)
*/
#define NDOF_HAS_TRANSLATE ((!view3d_operator_offset_lock_check(C, op)) && !is_zero_v3(ndof->tvec))
#define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec))
#define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec))
/**
@@ -1302,6 +1302,117 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, RegionView3D
}
}
/**
* Called from both fly mode and walk mode,
*/
void view3d_ndof_fly(
const wmNDOFMotionData *ndof,
View3D *v3d, RegionView3D *rv3d,
const bool use_precision, const short protectflag,
bool *r_has_translate, bool *r_has_rotate)
{
/* shorthand for oft-used variables */
const float dt = ndof->dt;
bool has_translate = NDOF_HAS_TRANSLATE;
bool has_rotate = NDOF_HAS_ROTATE;
float view_inv[4];
invert_qt_qt(view_inv, rv3d->viewquat);
rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
if (has_translate) {
float speed = 10.0f; /* blender units per second */
float trans[3], trans_orig_y;
/* ^^ this is ok for default cube scene, but should scale with.. something */
if (use_precision)
speed *= 0.2f;
WM_event_ndof_pan_get(ndof, trans, false);
mul_v3_fl(trans, speed * dt);
trans_orig_y = trans[1];
/* transform motion from view to world coordinates */
mul_qt_v3(view_inv, trans);
if (U.ndof_flag & NDOF_FLY_HELICOPTER) {
/* replace world z component with device y (yes it makes sense) */
trans[2] = trans_orig_y;
}
if (rv3d->persp == RV3D_CAMOB) {
/* respect camera position locks */
if (protectflag & OB_LOCK_LOCX) trans[0] = 0.0f;
if (protectflag & OB_LOCK_LOCY) trans[1] = 0.0f;
if (protectflag & OB_LOCK_LOCZ) trans[2] = 0.0f;
}
if (!is_zero_v3(trans)) {
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
sub_v3_v3(rv3d->ofs, trans);
has_translate = true;
}
else {
has_translate = false;
}
}
if (has_rotate) {
const float turn_sensitivity = 1.0f;
float rotation[4];
float axis[3];
float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
if (fabsf(angle) > 0.0001f) {
has_rotate = true;
if (use_precision)
angle *= 0.2f;
/* transform rotation axis from view to world coordinates */
mul_qt_v3(view_inv, axis);
/* apply rotation to view */
axis_angle_to_quat(rotation, axis, angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
if (U.ndof_flag & NDOF_LOCK_HORIZON) {
/* force an upright viewpoint
* TODO: make this less... sudden */
float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
/* find new inverse since viewquat has changed */
invert_qt_qt(view_inv, rv3d->viewquat);
/* could apply reverse rotation to existing view_inv to save a few cycles */
/* transform view vectors to world coordinates */
mul_qt_v3(view_inv, view_horizon);
mul_qt_v3(view_inv, view_direction);
/* find difference between view & world horizons
* true horizon lives in world xy plane, so look only at difference in z */
angle = -asinf(view_horizon[2]);
/* rotate view so view horizon = world horizon */
axis_angle_to_quat(rotation, view_direction, angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
}
rv3d->view = RV3D_VIEW_USER;
}
else {
has_rotate = false;
}
}
*r_has_translate = has_translate;
*r_has_rotate = has_rotate;
}
/* -- "orbit" navigation (trackball/turntable)
* -- zooming
* -- panning in rotationally-locked views
@@ -1440,7 +1551,7 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
/* -- "pan" navigation
* -- zoom or dolly?
*/
static int ndof_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;

View File

@@ -944,127 +944,23 @@ static int flyApply(bContext *C, FlyInfo *fly)
return OPERATOR_FINISHED;
}
static int flyApply_ndof(bContext *C, FlyInfo *fly)
static void flyApply_ndof(bContext *C, FlyInfo *fly)
{
/* shorthand for oft-used variables */
wmNDOFMotionData *ndof = fly->ndof;
const float dt = ndof->dt;
RegionView3D *rv3d = fly->rv3d;
const int flag = U.ndof_flag;
Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
bool has_translate, has_rotate;
#if 0
bool do_rotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == false);
bool do_translate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)) != 0;
#endif
view3d_ndof_fly(fly->ndof,
fly->v3d, fly->rv3d,
fly->use_precision, lock_ob ? lock_ob->protectflag : 0,
&has_translate, &has_rotate);
bool do_rotate = (fly->pan_view == false);
bool do_translate = true;
float view_inv[4];
invert_qt_qt(view_inv, rv3d->viewquat);
rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
if (do_translate) {
float speed = 10.0f; /* blender units per second */
float trans[3], trans_orig_y;
/* ^^ this is ok for default cube scene, but should scale with.. something */
if (fly->use_precision)
speed *= 0.2f;
WM_event_ndof_pan_get(ndof, trans, false);
mul_v3_fl(trans, speed * dt);
trans_orig_y = trans[1];
/* transform motion from view to world coordinates */
mul_qt_v3(view_inv, trans);
if (flag & NDOF_FLY_HELICOPTER) {
/* replace world z component with device y (yes it makes sense) */
trans[2] = trans_orig_y;
}
if (rv3d->persp == RV3D_CAMOB) {
/* respect camera position locks */
Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0f;
if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0f;
if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0f;
}
if (!is_zero_v3(trans)) {
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
sub_v3_v3(rv3d->ofs, trans);
do_translate = true;
}
else {
do_translate = false;
}
}
if (do_rotate) {
const float turn_sensitivity = 1.0f;
float rotation[4];
float axis[3];
float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
if (fabsf(angle) > 0.0001f) {
do_rotate = true;
if (fly->use_precision)
angle *= 0.2f;
/* transform rotation axis from view to world coordinates */
mul_qt_v3(view_inv, axis);
/* apply rotation to view */
axis_angle_to_quat(rotation, axis, angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
if (flag & NDOF_LOCK_HORIZON) {
/* force an upright viewpoint
* TODO: make this less... sudden */
float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
/* find new inverse since viewquat has changed */
invert_qt_qt(view_inv, rv3d->viewquat);
/* could apply reverse rotation to existing view_inv to save a few cycles */
/* transform view vectors to world coordinates */
mul_qt_v3(view_inv, view_horizon);
mul_qt_v3(view_inv, view_direction);
/* find difference between view & world horizons
* true horizon lives in world xy plane, so look only at difference in z */
angle = -asinf(view_horizon[2]);
#ifdef NDOF_FLY_DEBUG
printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle));
#endif
/* rotate view so view horizon = world horizon */
axis_angle_to_quat(rotation, view_direction, angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
}
rv3d->view = RV3D_VIEW_USER;
}
else {
do_rotate = false;
}
}
if (do_translate || do_rotate) {
if (has_translate || has_rotate) {
fly->redraw = true;
if (rv3d->persp == RV3D_CAMOB) {
flyMoveCamera(C, fly, do_rotate, do_translate);
if (fly->rv3d->persp == RV3D_CAMOB) {
flyMoveCamera(C, fly, has_rotate, has_translate);
}
}
return OPERATOR_FINISHED;
}
static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)

View File

@@ -107,6 +107,12 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
void view3d_ndof_fly(
const struct wmNDOFMotionData *ndof,
struct View3D *v3d, struct RegionView3D *rv3d,
const bool use_precision, const short protectflag,
bool *r_has_translate, bool *r_has_rotate);
/* view3d_fly.c */
void view3d_keymap(struct wmKeyConfig *keyconf);
void VIEW3D_OT_fly(struct wmOperatorType *ot);

View File

@@ -1217,128 +1217,23 @@ static int walkApply(bContext *C, WalkInfo *walk)
#undef WALK_BOOST_FACTOR
}
static int walkApply_ndof(bContext *C, WalkInfo *walk)
static void walkApply_ndof(bContext *C, WalkInfo *walk)
{
/* shorthand for oft-used variables */
wmNDOFMotionData *ndof = walk->ndof;
const float dt = ndof->dt;
RegionView3D *rv3d = walk->rv3d;
const int flag = U.ndof_flag;
Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
bool has_translate, has_rotate;
#if 0
bool do_rotate = (flag & NDOF_SHOULD_ROTATE) && (walk->pan_view == false);
bool do_translate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)) != 0;
#endif
view3d_ndof_fly(walk->ndof,
walk->v3d, walk->rv3d,
walk->is_slow, lock_ob ? lock_ob->protectflag : 0,
&has_translate, &has_rotate);
bool do_rotate = true;
bool do_translate = true;
float view_inv[4];
invert_qt_qt(view_inv, rv3d->viewquat);
rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
if (do_translate) {
float speed = 10.0f; /* blender units per second */
float trans[3], trans_orig_y;
/* ^^ this is ok for default cube scene, but should scale with.. something */
if (walk->is_slow)
speed *= 0.2f;
WM_event_ndof_pan_get(ndof, trans, false);
mul_v3_fl(trans, speed * dt);
trans_orig_y = trans[1];
/* transform motion from view to world coordinates */
mul_qt_v3(view_inv, trans);
if (flag & NDOF_FLY_HELICOPTER) {
/* replace world z component with device y (yes it makes sense) */
trans[2] = trans_orig_y;
}
if (rv3d->persp == RV3D_CAMOB) {
/* respect camera position locks */
Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0f;
if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0f;
if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0f;
}
if (!is_zero_v3(trans)) {
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
sub_v3_v3(rv3d->ofs, trans);
do_translate = true;
}
else {
do_translate = false;
}
}
if (do_rotate) {
const float turn_sensitivity = 1.0f;
float rotation[4];
float axis[3];
float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis);
if (fabsf(angle) > 0.0001f) {
do_rotate = true;
if (walk->is_slow)
angle *= 0.2f;
/* transform rotation axis from view to world coordinates */
mul_qt_v3(view_inv, axis);
/* apply rotation to view */
axis_angle_to_quat(rotation, axis, angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
if (flag & NDOF_LOCK_HORIZON) {
/* force an upright viewpoint
* TODO: make this less... sudden */
float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
/* find new inverse since viewquat has changed */
invert_qt_qt(view_inv, rv3d->viewquat);
/* could apply reverse rotation to existing view_inv to save a few cycles */
/* transform view vectors to world coordinates */
mul_qt_v3(view_inv, view_horizon);
mul_qt_v3(view_inv, view_direction);
/* find difference between view & world horizons
* true horizon lives in world xy plane, so look only at difference in z */
angle = -asinf(view_horizon[2]);
#ifdef NDOF_WALK_DEBUG
printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle));
#endif
/* rotate view so view horizon = world horizon */
axis_angle_to_quat(rotation, view_direction, angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
}
rv3d->view = RV3D_VIEW_USER;
}
else {
do_rotate = false;
}
}
if (do_translate || do_rotate) {
if (has_translate || has_rotate) {
walk->redraw = true;
if (rv3d->persp == RV3D_CAMOB) {
walkMoveCamera(C, walk, do_rotate, do_translate);
if (walk->rv3d->persp == RV3D_CAMOB) {
walkMoveCamera(C, walk, has_rotate, has_translate);
}
}
return OPERATOR_FINISHED;
}
/****** walk operator ******/