From 1649521abe637b5af74174eda0d8ca0b5f1c6ceb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 11 Nov 2011 05:34:07 +0000 Subject: fix [#29203] Camera can still move even when transforms locked added object_tfm_protected_backup, object_tfm_protected_restore so its easier to transform the object and respect protected channels (otherwise you need checks everywhere for each channel which is verbose). --- source/blender/blenkernel/BKE_object.h | 16 ++++++ source/blender/blenkernel/intern/object.c | 65 +++++++++++++++++++++++ source/blender/editors/space_view3d/view3d_edit.c | 31 +++++++---- source/blender/editors/space_view3d/view3d_view.c | 6 +++ 4 files changed, 109 insertions(+), 9 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 2ef942a2e09..ecc00901dd5 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -116,6 +116,22 @@ int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3 void *object_tfm_backup(struct Object *ob); void object_tfm_restore(struct Object *ob, void *obtfm_pt); +typedef struct ObjectTfmProtectedChannels { + float loc[3], dloc[3]; + float size[3], dsize[3]; + float rot[3], drot[3]; + float quat[4], dquat[4]; + float rotAxis[3], drotAxis[3]; + float rotAngle, drotAngle; +} ObjectTfmProtectedChannels; + +void object_tfm_protected_backup(const struct Object *ob, + ObjectTfmProtectedChannels *obtfm); + +void object_tfm_protected_restore(struct Object *ob, + const ObjectTfmProtectedChannels *obtfm, + const short protectflag); + void object_handle_update(struct Scene *scene, struct Object *ob); void object_sculpt_modifiers_changed(struct Object *ob); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 45bd8f095a4..4e6bc4eee89 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1498,6 +1498,71 @@ void object_mat3_to_rot(Object *ob, float mat[][3], short use_compat) } } +void object_tfm_protected_backup(const Object *ob, + ObjectTfmProtectedChannels *obtfm) +{ + +#define TFMCPY( _v) (obtfm->_v = ob->_v) +#define TFMCPY3D( _v) copy_v3_v3(obtfm->_v, ob->_v) +#define TFMCPY4D( _v) copy_v4_v4(obtfm->_v, ob->_v) + + TFMCPY3D(loc); + TFMCPY3D(dloc); + TFMCPY3D(size); + TFMCPY3D(dsize); + TFMCPY3D(rot); + TFMCPY3D(drot); + TFMCPY4D(quat); + TFMCPY4D(dquat); + TFMCPY3D(rotAxis); + TFMCPY3D(drotAxis); + TFMCPY(rotAngle); + TFMCPY(drotAngle); + +#undef TFMCPY +#undef TFMCPY3D +#undef TFMCPY4D + +} + +void object_tfm_protected_restore(Object *ob, + const ObjectTfmProtectedChannels *obtfm, + const short protectflag) +{ + unsigned int i; + + for (i= 0; i < 3; i++) { + if (protectflag & (OB_LOCK_LOCX<loc[i]= obtfm->loc[i]; + ob->dloc[i]= obtfm->dloc[i]; + } + + if (protectflag & (OB_LOCK_SCALEX<size[i]= obtfm->size[i]; + ob->dsize[i]= obtfm->dsize[i]; + } + + if (protectflag & (OB_LOCK_ROTX<rot[i]= obtfm->rot[i]; + ob->drot[i]= obtfm->drot[i]; + + ob->quat[i + 1]= obtfm->quat[i + 1]; + ob->dquat[i + 1]= obtfm->dquat[i + 1]; + + ob->rotAxis[i]= obtfm->rotAxis[i]; + ob->drotAxis[i]= obtfm->drotAxis[i]; + } + } + + if ((protectflag & OB_LOCK_ROT4D) && (protectflag & OB_LOCK_ROTW)) { + ob->quat[0]= obtfm->quat[0]; + ob->dquat[0]= obtfm->dquat[0]; + + ob->rotAngle= obtfm->rotAngle; + ob->drotAngle= obtfm->drotAngle; + } +} + /* see pchan_apply_mat4() for the equivalent 'pchan' function */ void object_apply_mat4(Object *ob, float mat[][4], const short use_compat, const short use_parent) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 7331959ef51..0329b6c3739 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -99,6 +99,7 @@ void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) { if(ED_view3d_camera_lock_check(v3d, rv3d)) { + ObjectTfmProtectedChannels obtfm; Object *root_parent; if((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (root_parent= v3d->camera->parent)) { @@ -117,7 +118,10 @@ int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) mul_m4_m4m4(diff_mat, v3d->camera->imat, view_mat); mul_m4_m4m4(parent_mat, root_parent->obmat, diff_mat); + + object_tfm_protected_backup(root_parent, &obtfm); object_apply_mat4(root_parent, parent_mat, TRUE, FALSE); + object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag); ob_update= v3d->camera; while(ob_update) { @@ -127,7 +131,10 @@ int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) } } else { + object_tfm_protected_backup(v3d->camera, &obtfm); ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); + object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag); + DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, v3d->camera); } @@ -346,6 +353,7 @@ typedef struct ViewOpsData { double timer_lastdraw; float oldquat[4]; + float viewquat[4]; /* working copy of rv3d->viewquat */ float trackvec[3]; float mousevec[3]; /* dolly only */ float reverse, dist0; @@ -408,6 +416,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) ED_view3d_camera_lock_init(vod->v3d, vod->rv3d); vod->dist0= rv3d->dist; + copy_qt_qt(vod->viewquat, rv3d->viewquat); copy_qt_qt(vod->oldquat, rv3d->viewquat); vod->origx= vod->oldx= event->x; vod->origy= vod->oldy= event->y; @@ -643,13 +652,13 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) q1[0]= cos(phi); mul_v3_fl(q1+1, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, q1, vod->oldquat); + mul_qt_qtqt(vod->viewquat, q1, vod->oldquat); if (vod->use_dyn_ofs) { /* compute the post multiplication quat, to rotate the offset correctly */ copy_qt_qt(q1, vod->oldquat); conjugate_qt(q1); - mul_qt_qtqt(q1, q1, rv3d->viewquat); + mul_qt_qtqt(q1, q1, vod->viewquat); conjugate_qt(q1); /* conj == inv for unit quat */ copy_v3_v3(rv3d->ofs, vod->ofs); @@ -671,7 +680,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) const float sensitivity = 0.0035f; /* Get the 3x3 matrix and its inverse from the quaternion */ - quat_to_mat3( m,rv3d->viewquat); + quat_to_mat3( m,vod->viewquat); invert_m3_m3(m_inv,m); /* Determine the direction of the x vector (for rotating up and down) */ @@ -682,7 +691,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) phi = sensitivity * -(y - vod->oldy); q1[0] = cos(phi); mul_v3_v3fl(q1+1, xvec, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + mul_qt_qtqt(vod->viewquat, vod->viewquat, q1); if (vod->use_dyn_ofs) { conjugate_qt(q1); /* conj == inv for unit quat */ @@ -696,7 +705,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) q1[0] = cos(phi); q1[1] = q1[2] = 0.0; q1[3] = sin(phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + mul_qt_qtqt(vod->viewquat, vod->viewquat, q1); if (vod->use_dyn_ofs) { conjugate_qt(q1); @@ -711,7 +720,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) int i; float viewquat_inv[4]; float zaxis[3]={0,0,1}; - invert_qt_qt(viewquat_inv, rv3d->viewquat); + invert_qt_qt(viewquat_inv, vod->viewquat); mul_qt_v3(viewquat_inv, zaxis); @@ -736,7 +745,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) * for testing roll */ rotation_between_vecs_to_quat(viewquat_align, zaxis_test, zaxis); normalize_qt(viewquat_align); - mul_qt_qtqt(viewquat_align, rv3d->viewquat, viewquat_align); + mul_qt_qtqt(viewquat_align, vod->viewquat, viewquat_align); normalize_qt(viewquat_align); invert_qt_qt(viewquat_align_inv, viewquat_align); @@ -766,7 +775,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) } } - copy_qt_qt(rv3d->viewquat, quat_best); + copy_qt_qt(vod->viewquat, quat_best); rv3d->view= view; /* if we snap to a rolled camera the grid is invalid */ break; @@ -777,7 +786,11 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) vod->oldy= y; /* avoid precision loss over time */ - normalize_qt(rv3d->viewquat); + normalize_qt(vod->viewquat); + + /* use a working copy so view rotation locking doesnt overwrite the locked + * rotation back into the view we calculate with */ + copy_qt_qt(rv3d->viewquat, vod->viewquat); ED_view3d_camera_lock_sync(vod->v3d, rv3d); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 7de1f2a85bb..a5849864d86 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -370,6 +370,7 @@ static int view3d_setcameratoview_exec(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); + ObjectTfmProtectedChannels obtfm; copy_qt_qt(rv3d->lviewquat, rv3d->viewquat); rv3d->lview= rv3d->view; @@ -377,7 +378,12 @@ static int view3d_setcameratoview_exec(bContext *C, wmOperator *UNUSED(op)) rv3d->lpersp= rv3d->persp; } + object_tfm_protected_backup(v3d->camera, &obtfm); + ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); + + object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag); + DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); rv3d->persp = RV3D_CAMOB; -- cgit v1.2.3