コード例 #1
0
/**
 * Creates a #View3DControl handle and sets up
 * the view for first-person style navigation.
 */
struct View3DCameraControl *ED_view3d_cameracontrol_aquire(
    Scene *scene, View3D *v3d, RegionView3D *rv3d,
    const bool use_parent_root)
{
    View3DCameraControl *vctrl;

    vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);

    /* Store context */
    vctrl->ctx_scene = scene;
    vctrl->ctx_v3d = v3d;
    vctrl->ctx_rv3d = rv3d;

    vctrl->use_parent_root = use_parent_root;

    vctrl->persp_backup = rv3d->persp;
    vctrl->dist_backup = rv3d->dist;

    /* check for flying ortho camera - which we cant support well
     * we _could_ also check for an ortho camera but this is easier */
    if ((rv3d->persp == RV3D_CAMOB) &&
            (rv3d->is_persp == false))
    {
        ((Camera *)v3d->camera->data)->type = CAM_PERSP;
        vctrl->is_ortho_cam = true;
    }

    if (rv3d->persp == RV3D_CAMOB) {
        Object *ob_back;
        if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) {
            while (vctrl->root_parent->parent)
                vctrl->root_parent = vctrl->root_parent->parent;
            ob_back = vctrl->root_parent;
        }
        else {
            ob_back = v3d->camera;
        }

        /* store the original camera loc and rot */
        vctrl->obtfm = BKE_object_tfm_backup(ob_back);

        BKE_object_where_is_calc(scene, v3d->camera);
        negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);

        rv3d->dist = 0.0;
    }
    else {
        float tvec[3];
        /* perspective or ortho */
        if (rv3d->persp == RV3D_ORTHO)
            rv3d->persp = RV3D_PERSP;  /* if ortho projection, make perspective */

        copy_qt_qt(vctrl->rot_backup, rv3d->viewquat);
        copy_v3_v3(vctrl->ofs_backup, 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. */

        rv3d->dist = 0.0f;

        copy_v3_fl3(tvec, 0.0f, 0.0f, vctrl->dist_backup);
        mul_mat3_m4_v3(rv3d->viewinv, tvec);
        sub_v3_v3(rv3d->ofs, tvec);
        /* Done with correcting for the dist */
    }

    ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist);

    return vctrl;
}
コード例 #2
0
/**
 * Updates cameras from the ``rv3d`` values, optionally auto-keyframing.
 */
void ED_view3d_cameracontrol_update(
    View3DCameraControl *vctrl,
    /* args for keyframing */
    const bool use_autokey,
    struct bContext *C, const bool do_rotate, const bool do_translate)
{
    /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */

    Scene *scene       = vctrl->ctx_scene;
    View3D *v3d        = vctrl->ctx_v3d;
    RegionView3D *rv3d = vctrl->ctx_rv3d;

    ID *id_key;

    /* transform the parent or the camera? */
    if (vctrl->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, vctrl->view_mat_prev);
        ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
        mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
        mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat);

        BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false);

        ob_update = v3d->camera->parent;
        while (ob_update) {
            DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
            ob_update = ob_update->parent;
        }

        copy_m4_m4(vctrl->view_mat_prev, view_mat);

        id_key = &vctrl->root_parent->id;
    }
    else {
        float view_mat[4][4];
        float size_mat[4][4];
        float size_back[3];

        /* even though we handle the size matrix, this still changes over time */
        copy_v3_v3(size_back, v3d->camera->size);

        ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
        size_to_mat4(size_mat, v3d->camera->size);
        mul_m4_m4m4(view_mat, view_mat, size_mat);

        BKE_object_apply_mat4(v3d->camera, view_mat, true, true);

        copy_v3_v3(v3d->camera->size, size_back);

        id_key = &v3d->camera->id;
    }

    /* record the motion */
    if (use_autokey && autokeyframe_cfra_can_key(scene, id_key)) {
        ListBase dsources = {NULL, NULL};

        /* add data-source 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 (do_rotate) {
            struct KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
            ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
        }
        if (do_translate) {
            struct KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
            ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
        }

        /* free temp data */
        BLI_freelistN(&dsources);
    }
}
コード例 #3
0
static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly,
                            const bool do_rotate, const bool do_translate)
{
	/* 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];
		float size_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);
		mult_m4_m4m4(diff_mat, view_mat, prev_view_imat);
		mult_m4_m4m4(parent_mat, diff_mat, fly->root_parent->obmat);

		size_to_mat4(size_mat, fly->root_parent->size);
		mult_m4_m4m4(parent_mat, parent_mat, size_mat);

		BKE_object_apply_mat4(fly->root_parent, parent_mat, true, false);

		// BKE_object_where_is_calc(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];
		float size_mat[4][4];

		ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
		size_to_mat4(size_mat, v3d->camera->size);
		mult_m4_m4m4(view_mat, view_mat, size_mat);

		BKE_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 (do_rotate) {
			KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
			ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
		}
		if (do_translate) {
			KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
			ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
		}

		/* free temp data */
		BLI_freelistN(&dsources);
	}
}