Ejemplo n.º 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;
}
Ejemplo n.º 2
0
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
	wmWindow *win = CTX_wm_window(C);
	float upvec[3]; /* tmp */
	float mat[3][3];

	fly->rv3d = CTX_wm_region_view3d(C);
	fly->v3d = CTX_wm_view3d(C);
	fly->ar = CTX_wm_region(C);
	fly->scene = CTX_data_scene(C);

#ifdef NDOF_FLY_DEBUG
	puts("\n-- fly begin --");
#endif

	/* sanity check: for rare but possible case (if lib-linking the camera fails) */
	if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) {
		fly->rv3d->persp = RV3D_PERSP;
	}

	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 (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked");
		return false;
	}

	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;
	}

	fly->state = FLY_RUNNING;
	fly->speed = 0.0f;
	fly->axis = 2;
	fly->pan_view = false;
	fly->xlock = FLY_AXISLOCK_STATE_OFF;
	fly->zlock = FLY_AXISLOCK_STATE_OFF;
	fly->xlock_momentum = 0.0f;
	fly->zlock_momentum = 0.0f;
	fly->grid = 1.0f;
	fly->use_precision = false;
	fly->use_freelook = false;

#ifdef NDOF_FLY_DRAW_TOOMUCH
	fly->redraw = 1;
#endif
	zero_v3(fly->dvec_prev);

	fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);

	copy_v2_v2_int(fly->mval, event->mval);
	fly->ndof = NULL;

	fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer();

	fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);

	fly->rv3d->rflag |= RV3D_NAVIGATING; /* so we draw the corner margins */

	/* detect weather to start with Z locking */
	upvec[0] = 1.0f;
	upvec[1] = 0.0f;
	upvec[2] = 0.0f;
	copy_m3_m4(mat, fly->rv3d->viewinv);
	mul_m3_v3(mat, upvec);
	if (fabsf(upvec[2]) < 0.1f) {
		fly->zlock = FLY_AXISLOCK_STATE_IDLE;
	}
	upvec[0] = 0;
	upvec[1] = 0;
	upvec[2] = 0;

	fly->persp_backup = fly->rv3d->persp;
	fly->dist_backup = fly->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 ((fly->rv3d->persp == RV3D_CAMOB) &&
	    (fly->rv3d->is_persp == false))
	{
		((Camera *)fly->v3d->camera->data)->type = CAM_PERSP;
		fly->is_ortho_cam = true;
	}

	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)) {
			while (fly->root_parent->parent)
				fly->root_parent = fly->root_parent->parent;
			ob_back = fly->root_parent;
		}
		else {
			ob_back = fly->v3d->camera;
		}

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

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

		fly->rv3d->dist = 0.0;
	}
	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 */
		mul_m3_v3(mat, upvec);
		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(win, fly->ar->winrct.xmin + fly->ar->winx / 2, fly->ar->winrct.ymin + fly->ar->winy / 2);

	return 1;
}