Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_fly.c')
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c480
1 files changed, 348 insertions, 132 deletions
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index ed1ed5b3881..30d1a508888 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -29,6 +29,9 @@
/* defines VIEW3D_OT_fly modal operator */
+//#define NDOF_FLY_DEBUG
+//#define NDOF_FLY_DRAW_TOOMUCH // is this needed for ndof? - commented so redraw doesnt thrash - campbell
+
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -106,7 +109,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Fly Modal");
/* this function is called for each spacetype, only needs to add map once */
- if(keymap) return;
+ if (keymap) return;
keymap= WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items);
@@ -143,7 +146,6 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
-
}
typedef struct FlyInfo {
@@ -158,7 +160,9 @@ typedef struct FlyInfo {
short state;
short use_precision;
short redraw;
- int mval[2];
+
+ int mval[2]; /* latest 2D mouse values */
+ wmNDOFMotionData* ndof; /* latest 3D mouse values */
/* fly state state */
float speed; /* the speed the view is moving per redraw */
@@ -257,17 +261,21 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
fly->ar = CTX_wm_region(C);
fly->scene= CTX_data_scene(C);
- if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) {
+#ifdef NDOF_FLY_DEBUG
+ puts("\n-- fly begin --");
+#endif
+
+ if (fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
return FALSE;
}
- if(fly->v3d->ob_centre) {
+ if (fly->v3d->ob_centre) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view is locked to an object");
return FALSE;
}
- if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) {
+ if (fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
return FALSE;
}
@@ -283,11 +291,15 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
fly->grid= 1.0f;
fly->use_precision= 0;
+#ifdef NDOF_FLY_DRAW_TOOMUCH
+ fly->redraw= 1;
+#endif
fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f;
fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
VECCOPY2D(fly->mval, event->mval)
+ fly->ndof = NULL;
fly->time_lastdraw= fly->time_lastwheel= PIL_check_seconds_timer();
@@ -307,7 +319,7 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
fly->dist_backup= fly->rv3d->dist;
if (fly->rv3d->persp==RV3D_CAMOB) {
Object *ob_back;
- if((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (fly->root_parent=fly->v3d->camera->parent)) {
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (fly->root_parent=fly->v3d->camera->parent)) {
while(fly->root_parent->parent)
fly->root_parent= fly->root_parent->parent;
ob_back= fly->root_parent;
@@ -325,12 +337,22 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]);
fly->rv3d->dist=0.0;
- } else {
+ }
+ else {
/* perspective or ortho */
if (fly->rv3d->persp==RV3D_ORTHO)
fly->rv3d->persp= RV3D_PERSP; /*if ortho projection, make perspective */
+
copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat);
copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs);
+
+ /* the dist defines a vector that is infront of the offset
+ to rotate the view about.
+ this is no good for fly mode because we
+ want to rotate about the viewers center.
+ but to correct the dist removal we must
+ alter offset so the view doesn't jump. */
+
fly->rv3d->dist= 0.0f;
upvec[2]= fly->dist_backup; /*x and y are 0*/
@@ -338,7 +360,6 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
sub_v3_v3(fly->rv3d->ofs, upvec);
/*Done with correcting for the dist*/
}
-
/* center the mouse, probably the UI mafia are against this but without its quite annoying */
WM_cursor_warp(CTX_wm_window(C), fly->ar->winrct.xmin + fly->ar->winx/2, fly->ar->winrct.ymin + fly->ar->winy/2);
@@ -353,9 +374,13 @@ static int flyEnd(bContext *C, FlyInfo *fly)
float upvec[3];
- if(fly->state == FLY_RUNNING)
+ if (fly->state == FLY_RUNNING)
return OPERATOR_RUNNING_MODAL;
+#ifdef NDOF_FLY_DEBUG
+ puts("\n-- fly end --");
+#endif
+
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer);
ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel);
@@ -366,14 +391,14 @@ static int flyEnd(bContext *C, FlyInfo *fly)
/* Revert to original view? */
if (fly->persp_backup==RV3D_CAMOB) { /* a camera view */
Object *ob_back;
- if(fly->root_parent)ob_back= fly->root_parent;
- else ob_back= fly->v3d->camera;
+ ob_back= (fly->root_parent) ? fly->root_parent : fly->v3d->camera;
/* store the original camera loc and rot */
object_tfm_restore(ob_back, fly->obtfm);
DAG_id_tag_update(&ob_back->id, OB_RECALC_OB);
- } else {
+ }
+ else {
/* Non Camera we need to reset the view back to the original location bacause the user canceled*/
copy_qt_qt(rv3d->viewquat, fly->rot_backup);
copy_v3_v3(rv3d->ofs, fly->ofs_backup);
@@ -398,10 +423,13 @@ static int flyEnd(bContext *C, FlyInfo *fly)
rv3d->rflag &= ~RV3D_NAVIGATING;
//XXX2.5 BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */
- if(fly->obtfm)
+ if (fly->obtfm)
MEM_freeN(fly->obtfm);
- if(fly->state == FLY_CONFIRM) {
+ if (fly->ndof)
+ MEM_freeN(fly->ndof);
+
+ if (fly->state == FLY_CONFIRM) {
MEM_freeN(fly);
return OPERATOR_FINISHED;
}
@@ -417,7 +445,52 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
}
else if (event->type == MOUSEMOVE) {
VECCOPY2D(fly->mval, event->mval);
- } /* handle modal keymap first */
+ }
+ else if (event->type == NDOF_MOTION) {
+ // do these automagically get delivered? yes.
+ // puts("ndof motion detected in fly mode!");
+ // static const char* tag_name = "3D mouse position";
+
+ wmNDOFMotionData* incoming_ndof = (wmNDOFMotionData*) event->customdata;
+ switch (incoming_ndof->progress) {
+ case P_STARTING:
+ // start keeping track of 3D mouse position
+#ifdef NDOF_FLY_DEBUG
+ puts("start keeping track of 3D mouse position");
+#endif
+ // fall through...
+ case P_IN_PROGRESS:
+ // update 3D mouse position
+#ifdef NDOF_FLY_DEBUG
+ putchar('.'); fflush(stdout);
+#endif
+ if (fly->ndof == NULL) {
+ // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
+ fly->ndof = MEM_dupallocN(incoming_ndof);
+ // fly->ndof = malloc(sizeof(wmNDOFMotionData));
+ }
+ else {
+ memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
+ }
+ break;
+ case P_FINISHING:
+ // stop keeping track of 3D mouse position
+#ifdef NDOF_FLY_DEBUG
+ puts("stop keeping track of 3D mouse position");
+#endif
+ if (fly->ndof) {
+ MEM_freeN(fly->ndof);
+ // free(fly->ndof);
+ fly->ndof = NULL;
+ }
+ /* update the time else the view will jump when 2D mouse/timer resume */
+ fly->time_lastdraw= PIL_check_seconds_timer();
+ break;
+ default:
+ ; // should always be one of the above 3
+ }
+ }
+ /* handle modal keymap first */
else if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case FLY_MODAL_CANCEL:
@@ -439,7 +512,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
/*Mouse wheel delays range from 0.5==slow to 0.01==fast*/
time_wheel = 1.0f + (10.0f - (20.0f * MIN2(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */
- if (fly->speed<0.0f) fly->speed= 0.0f;
+ if (fly->speed < 0.0f) {
+ fly->speed= 0.0f;
+ }
else {
if (event->shift)
fly->speed += fly->grid*time_wheel * 0.1f;
@@ -458,7 +533,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
fly->time_lastwheel = time_currwheel;
time_wheel = 1.0f + (10.0f - (20.0f * MIN2(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */
- if (fly->speed>0) fly->speed=0;
+ if (fly->speed > 0.0f) {
+ fly->speed=0;
+ }
else {
if (event->shift)
fly->speed-= fly->grid*time_wheel * 0.1f;
@@ -528,14 +605,81 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
case FLY_MODAL_PRECISION_DISABLE:
fly->use_precision= FALSE;
break;
+ }
+ }
+}
+
+static void move_camera(bContext* C, RegionView3D* rv3d, FlyInfo* fly, int orientationChanged, int positionChanged)
+{
+ /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */
+
+ View3D* v3d = fly->v3d;
+ Scene *scene= fly->scene;
+ ID *id_key;
+
+ /* transform the parent or the camera? */
+ if (fly->root_parent) {
+ Object *ob_update;
+
+ float view_mat[4][4];
+ float prev_view_mat[4][4];
+ float prev_view_imat[4][4];
+ float diff_mat[4][4];
+ float parent_mat[4][4];
+
+ ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist);
+ invert_m4_m4(prev_view_imat, prev_view_mat);
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ mul_m4_m4m4(diff_mat, prev_view_imat, view_mat);
+ mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat);
+ object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE);
+
+ // where_is_object(scene, fly->root_parent);
+
+ ob_update= v3d->camera->parent;
+ while(ob_update) {
+ DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
+ ob_update= ob_update->parent;
}
+
+ id_key= &fly->root_parent->id;
+ }
+ else {
+ float view_mat[4][4];
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE);
+ id_key= &v3d->camera->id;
+ }
+
+ /* record the motion */
+ if (autokeyframe_cfra_can_key(scene, id_key)) {
+ ListBase dsources = {NULL, NULL};
+
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
+
+ /* insert keyframes
+ * 1) on the first frame
+ * 2) on each subsequent frame
+ * TODO: need to check in future that frame changed before doing this
+ */
+ if (orientationChanged) {
+ KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ }
+ if (positionChanged) {
+ KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&dsources);
}
}
static int flyApply(bContext *C, FlyInfo *fly)
{
-
#define FLY_ROTATE_FAC 2.5f /* more is faster */
#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
@@ -545,11 +689,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
a fly loop where the user can move move the view as if they are flying
*/
RegionView3D *rv3d= fly->rv3d;
- View3D *v3d = fly->v3d;
ARegion *ar = fly->ar;
- Scene *scene= fly->scene;
-
- float prev_view_mat[4][4];
float mat[3][3], /* 3x3 copy of the view matrix so we can move allong the view axis */
dvec[3]={0,0,0}, /* this is the direction thast added to the view offset per redraw */
@@ -567,15 +707,11 @@ static int flyApply(bContext *C, FlyInfo *fly)
unsigned char
apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/
- if(fly->root_parent)
- ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist);
+#ifdef NDOF_FLY_DEBUG
+ static unsigned int iteration = 1;
+ printf("fly timer %d\n", iteration++);
+#endif
- /* the dist defines a vector that is infront of the offset
- to rotate the view about.
- this is no good for fly mode because we
- want to rotate about the viewers center.
- but to correct the dist removal we must
- alter offset so the view doesn't jump. */
xmargin= ar->winx/20.0f;
ymargin= ar->winy/20.0f;
@@ -605,23 +741,25 @@ static int flyApply(bContext *C, FlyInfo *fly)
*
* the mouse moves isnt linear */
- if(moffset[0]) {
+ if (moffset[0]) {
moffset[0] /= ar->winx - (xmargin*2);
moffset[0] *= fabsf(moffset[0]);
}
- if(moffset[1]) {
+ if (moffset[1]) {
moffset[1] /= ar->winy - (ymargin*2);
moffset[1] *= fabsf(moffset[1]);
}
/* Should we redraw? */
- if(fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) {
+ if (fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) {
float dvec_tmp[3];
double time_current; /*time how fast it takes for us to redraw, this is so simple scenes dont fly too fast */
float time_redraw;
float time_redraw_clamped;
-
+#ifdef NDOF_FLY_DRAW_TOOMUCH
+ fly->redraw= 1;
+#endif
time_current= PIL_check_seconds_timer();
time_redraw= (float)(time_current - fly->time_lastdraw);
time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */
@@ -648,8 +786,8 @@ static int flyApply(bContext *C, FlyInfo *fly)
mul_m3_v3(mat, dvec_tmp);
mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid);
-
- } else {
+ }
+ else {
float roll; /* similar to the angle between the camera's up and the Z-up, but its very rough so just roll*/
/* rotate about the X axis- look up/down */
@@ -670,27 +808,28 @@ static int flyApply(bContext *C, FlyInfo *fly)
if (moffset[0]) {
/* if we're upside down invert the moffset */
- upvec[0]=0;
- upvec[1]=1;
- upvec[2]=0;
+ upvec[0]= 0.0f;
+ upvec[1]= 1.0f;
+ upvec[2]= 0.0f;
mul_m3_v3(mat, upvec);
- if(upvec[2] < 0.0f)
+ if (upvec[2] < 0.0f)
moffset[0]= -moffset[0];
/* make the lock vectors */
if (fly->zlock) {
- upvec[0]=0;
- upvec[1]=0;
- upvec[2]=1;
- } else {
- upvec[0]=0;
- upvec[1]=1;
- upvec[2]=0;
+ upvec[0]= 0.0f;
+ upvec[1]= 0.0f;
+ upvec[2]= 1.0f;
+ }
+ else {
+ upvec[0]= 0.0f;
+ upvec[1]= 1.0f;
+ upvec[2]= 0.0f;
mul_m3_v3(mat, upvec);
}
- axis_angle_to_quat( tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); /* Rotate about the relative up vec */
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
if (fly->xlock) fly->xlock = 2;/*check for rotation*/
@@ -698,25 +837,26 @@ static int flyApply(bContext *C, FlyInfo *fly)
}
if (fly->zlock==2) {
- upvec[0]=1;
- upvec[1]=0;
- upvec[2]=0;
+ upvec[0]= 1.0f;
+ upvec[1]= 0.0f;
+ upvec[2]= 0.0f;
mul_m3_v3(mat, upvec);
/*make sure we have some z rolling*/
if (fabsf(upvec[2]) > 0.00001f) {
- roll= upvec[2]*5;
- upvec[0]=0; /*rotate the view about this axis*/
- upvec[1]=0;
- upvec[2]=1;
+ roll= upvec[2] * 5.0f;
+ upvec[0]= 0.0f; /*rotate the view about this axis*/
+ upvec[1]= 0.0f;
+ upvec[2]= 1.0f;
mul_m3_v3(mat, upvec);
axis_angle_to_quat( tmp_quat, upvec, roll*time_redraw_clamped*fly->zlock_momentum * FLY_ZUP_CORRECT_FAC); /* Rotate about the relative up vec */
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
- } else {
- fly->zlock=1; /* dont check until the view rotates again */
+ }
+ else {
+ fly->zlock= 1; /* dont check until the view rotates again */
fly->zlock_momentum= 0.0f;
}
}
@@ -727,8 +867,8 @@ static int flyApply(bContext *C, FlyInfo *fly)
upvec[2]=1;
mul_m3_v3(mat, upvec);
/*make sure we have some z rolling*/
- if (fabs(upvec[2]) > 0.00001) {
- roll= upvec[2] * -5;
+ if (fabsf(upvec[2]) > 0.00001f) {
+ roll= upvec[2] * -5.0f;
upvec[0]= 1.0f; /*rotate the view about this axis*/
upvec[1]= 0.0f;
@@ -740,7 +880,8 @@ static int flyApply(bContext *C, FlyInfo *fly)
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
fly->xlock_momentum += 0.05f;
- } else {
+ }
+ else {
fly->xlock=1; /* see above */
fly->xlock_momentum= 0.0f;
}
@@ -784,96 +925,164 @@ static int flyApply(bContext *C, FlyInfo *fly)
ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB");
#endif
- /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */
- if (rv3d->persp==RV3D_CAMOB) {
- ID *id_key;
- /* transform the parent or the camera? */
- if(fly->root_parent) {
- Object *ob_update;
-
- float view_mat[4][4];
- float prev_view_imat[4][4];
- float diff_mat[4][4];
- float parent_mat[4][4];
-
- invert_m4_m4(prev_view_imat, prev_view_mat);
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- mul_m4_m4m4(diff_mat, prev_view_imat, view_mat);
- mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat);
- object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE);
-
- // where_is_object(scene, fly->root_parent);
-
- ob_update= v3d->camera->parent;
- while(ob_update) {
- DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
- ob_update= ob_update->parent;
- }
+ if (rv3d->persp==RV3D_CAMOB)
+ move_camera(C, rv3d, fly, (fly->xlock || fly->zlock || moffset[0] || moffset[1]), fly->speed);
- copy_m4_m4(prev_view_mat, view_mat);
+ }
+ else {
+ /* we're not redrawing but we need to update the time else the view will jump */
+ fly->time_lastdraw= PIL_check_seconds_timer();
+ }
+ /* end drawing */
+ copy_v3_v3(fly->dvec_prev, dvec);
+ }
- id_key= &fly->root_parent->id;
+ return OPERATOR_FINISHED;
+}
- }
- else {
- float view_mat[4][4];
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE);
- id_key= &v3d->camera->id;
- }
+static int 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;
- /* record the motion */
- if (autokeyframe_cfra_can_key(scene, id_key)) {
- ListBase dsources = {NULL, NULL};
-
- /* add datasource override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
-
- /* insert keyframes
- * 1) on the first frame
- * 2) on each subsequent frame
- * TODO: need to check in future that frame changed before doing this
- */
- if (fly->xlock || fly->zlock || moffset[0] || moffset[1]) {
- KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- }
- if (fly->speed) {
- KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- }
-
- /* free temp data */
- BLI_freelistN(&dsources);
- }
+/* int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE),
+ shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); */
+
+ int shouldRotate = (fly->pan_view == FALSE),
+ shouldTranslate = TRUE;
+
+ float view_inv[4];
+ invert_qt_qt(view_inv, rv3d->viewquat);
+
+ rv3d->rot_angle = 0.f; // disable onscreen rotation doo-dad
+
+ if (shouldTranslate) {
+ const float forward_sensitivity = 1.f;
+ const float vertical_sensitivity = 0.4f;
+ const float lateral_sensitivity = 0.6f;
+
+ float speed = 10.f; /* blender units per second */
+ /* ^^ this is ok for default cube scene, but should scale with.. something */
+
+ float trans[3] = {
+ lateral_sensitivity * ndof->tvec[0],
+ vertical_sensitivity * ndof->tvec[1],
+ forward_sensitivity * ndof->tvec[2]
+ };
+
+ if (fly->use_precision)
+ speed *= 0.2f;
+
+ mul_v3_fl(trans, speed * dt);
+
+ // 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] = speed * dt * vertical_sensitivity * ndof->tvec[1];
+ }
+
+ if (rv3d->persp==RV3D_CAMOB) {
+ // respect camera position locks
+ Object *lock_ob= fly->root_parent ? fly->root_parent : fly->v3d->camera;
+ if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.f;
+ if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.f;
+ if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.f;
+ }
+
+ 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);
+ shouldTranslate = TRUE;
+ }
+ else {
+ shouldTranslate = FALSE;
+ }
+ }
+
+ if (shouldRotate) {
+ const float turn_sensitivity = 1.f;
+
+ float rotation[4];
+ float axis[3];
+ float angle = turn_sensitivity * ndof_to_axis_angle(ndof, axis);
+
+ if (fabsf(angle) > 0.0001f) {
+ shouldRotate = 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.f, 0.f, 0.f}; /* view +x */
+ float view_direction[3] = {0.f, 0.f, -1.f}; /* 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);
}
- } else
- /*were not redrawing but we need to update the time else the view will jump */
- fly->time_lastdraw= PIL_check_seconds_timer();
- /* end drawing */
- copy_v3_v3(fly->dvec_prev, dvec);
+
+ rv3d->view = RV3D_VIEW_USER;
+ }
+ else {
+ shouldRotate = FALSE;
+ }
}
-/* moved to flyEnd() */
+ if (shouldTranslate || shouldRotate) {
+ fly->redraw = TRUE;
+
+ if (rv3d->persp==RV3D_CAMOB) {
+ move_camera(C, rv3d, fly, shouldRotate, shouldTranslate);
+ }
+ }
return OPERATOR_FINISHED;
}
-
static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
RegionView3D *rv3d= CTX_wm_region_view3d(C);
FlyInfo *fly;
- if(rv3d->viewlock)
+ if (rv3d->viewlock)
return OPERATOR_CANCELLED;
fly= MEM_callocN(sizeof(FlyInfo), "FlyOperation");
op->customdata= fly;
- if(initFlyInfo(C, fly, op, event)==FALSE) {
+ if (initFlyInfo(C, fly, op, event)==FALSE) {
MEM_freeN(op->customdata);
return OPERATOR_CANCELLED;
}
@@ -908,21 +1117,28 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
flyEvent(fly, event);
- if(event->type==TIMER && event->customdata == fly->timer)
+ if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */
+ if (event->type==NDOF_MOTION) {
+ flyApply_ndof(C, fly);
+ }
+ }
+ else if (event->type==TIMER && event->customdata == fly->timer) {
flyApply(C, fly);
+ }
do_draw |= fly->redraw;
exit_code = flyEnd(C, fly);
- if(exit_code!=OPERATOR_RUNNING_MODAL)
+ if (exit_code!=OPERATOR_RUNNING_MODAL)
do_draw= TRUE;
- if(do_draw) {
- if(rv3d->persp==RV3D_CAMOB) {
+ if (do_draw) {
+ if (rv3d->persp==RV3D_CAMOB) {
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, fly_object);
}
+ // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now
ED_region_tag_redraw(CTX_wm_region(C));
}