diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2012-03-24 02:12:24 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-04-17 17:11:34 +0400 |
commit | 02e5bdf864bdf001af5ef751f296e90c02edad5b (patch) | |
tree | 98aef831e7ef5e854c5542219e74d0be4bdf13d2 | |
parent | e0e05ae85eee83dfc5c07f3dba0664a3ade62d7a (diff) |
Initial implementation of overscan renderingoverscan
For now only affects blender internal renderer and viewport.
Currently it's possible to define overscan (in %%) manually
or make it so distortion matches the motrack displacement
model.
Still need to do loads of things in compositor, but it's
not such a bad starting point.
We can even start a branch for this.
Reviewers: dfelinto
Differential Revision: https://developer.blender.org/D462
30 files changed, 341 insertions, 103 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index ce375eca894..c8c3ae3c389 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -172,6 +172,12 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel): subrow.prop(rd, "frame_map_old", text="Old") subrow.prop(rd, "frame_map_new", text="New") + col = layout.column() + col.prop(rd, "use_detect_overscan") + sub = col.row() + sub.active = not rd.use_detect_overscan + sub.prop(rd, "overscan") + class RENDER_PT_antialiasing(RenderButtonsPanel, Panel): bl_label = "Anti-Aliasing" diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 01b401c6bcc..ac5915168c7 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -97,7 +97,12 @@ typedef struct CameraParams { float ycor; float viewdx; float viewdy; - rctf viewplane; + rctf viewplane; /* viewplane used for displaying/rendering which might include overscan correction */ + rctf underscan_viewplane; /* viewplane which isn't affected by overscan */ + + /* overscan */ + float overscan; + bool apply_overscan; /* computed matrix */ float winmat[4][4]; diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 5fe890461e0..a02b192e316 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -138,6 +138,10 @@ int BKE_scene_num_threads(const struct Scene *scene); int BKE_render_num_threads(const struct RenderData *r); int BKE_scene_num_omp_threads(const struct Scene *scene); + +/* overscan */ +void BKE_scene_update_overscan(struct Scene *scene); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 6d155ba37de..3a0d7f489a1 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -188,6 +188,8 @@ void BKE_tracking_distortion_free(struct MovieDistortion *distortion); void BKE_tracking_distort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); void BKE_tracking_undistort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); +float BKE_tracking_overscan_detect(struct MovieClip *clip); + struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, int calibration_width, int calibration_height, float overscan); struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index b20ba40c0dd..ded7db71960 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -202,6 +202,9 @@ void BKE_camera_params_init(CameraParams *params) /* fallback for non camera objects */ params->clipsta = 0.1f; params->clipsta = 100.0f; + + params->overscan = 0.0f; + params->apply_overscan = false; } void BKE_camera_params_from_object(CameraParams *params, Object *ob) @@ -227,6 +230,8 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob) params->clipsta = cam->clipsta; params->clipend = cam->clipend; + + params->apply_overscan = true; } else if (ob->type == OB_LAMP) { /* lamp object */ @@ -286,9 +291,11 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float xasp, float yasp) { - rctf viewplane; + rctf viewplane, underscan_viewplane; float pixsize, viewfac, sensor_size, dx, dy; int sensor_fit; + float overscan = params->overscan / 100.0f; + float viewx, viewy; /* fields rendering */ params->ycor = yasp / xasp; @@ -335,15 +342,32 @@ void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int win viewplane.xmax += dx; viewplane.ymax += dy; + underscan_viewplane = viewplane; + + /* apply overscan */ + if (params->apply_overscan) { + viewx = viewplane.xmax - viewplane.xmin; + viewy = viewplane.ymax - viewplane.ymin; + + viewplane.xmin -= 0.5f*overscan*viewx; + viewplane.xmax += 0.5f*overscan*viewx; + viewplane.ymin -= 0.5f*overscan*viewy; + viewplane.ymax += 0.5f*overscan*viewy; + } + /* fields offset */ if (params->field_second) { if (params->field_odd) { viewplane.ymin -= 0.5f * params->ycor; viewplane.ymax -= 0.5f * params->ycor; + underscan_viewplane.ymin -= 0.5f * params->ycor; + underscan_viewplane.ymax -= 0.5f * params->ycor; } else { viewplane.ymin += 0.5f * params->ycor; viewplane.ymax += 0.5f * params->ycor; + underscan_viewplane.ymin += 0.5f * params->ycor; + underscan_viewplane.ymax += 0.5f * params->ycor; } } @@ -354,9 +378,15 @@ void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int win viewplane.ymin *= pixsize; viewplane.ymax *= pixsize; + underscan_viewplane.xmin *= pixsize; + underscan_viewplane.xmax *= pixsize; + underscan_viewplane.ymin *= pixsize; + underscan_viewplane.ymax *= pixsize; + params->viewdx = pixsize; params->viewdy = params->ycor * pixsize; params->viewplane = viewplane; + params->underscan_viewplane = underscan_viewplane; } /* viewplane is assumed to be already computed */ @@ -380,6 +410,7 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons { float facx, facy; float depth; + float overscan_factor= 1.0f; /* aspect correcton */ if (scene) { @@ -387,6 +418,8 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons float aspy = (float) scene->r.ysch * scene->r.yasp; int sensor_fit = BKE_camera_sensor_fit(camera->sensor_fit, aspx, aspy); + overscan_factor = 1.0f + scene->r.overscan / 100.0f; + if (sensor_fit == CAMERA_SENSOR_FIT_HOR) { r_asp[0] = 1.0; r_asp[1] = aspy / aspx; @@ -401,12 +434,12 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons r_asp[1] = 1.0f; } - if (camera->type == CAM_ORTHO) { - facx = 0.5f * camera->ortho_scale * r_asp[0] * scale[0]; - facy = 0.5f * camera->ortho_scale * r_asp[1] * scale[1]; - r_shift[0] = camera->shiftx * camera->ortho_scale * scale[0]; - r_shift[1] = camera->shifty * camera->ortho_scale * scale[1]; - depth = do_clip ? -((camera->clipsta * scale[2]) + 0.1f) : -drawsize * camera->ortho_scale * scale[2]; + if (camera->type==CAM_ORTHO) { + facx = 0.5f * camera->ortho_scale * r_asp[0] * scale[0] * overscan_factor; + facy = 0.5f * camera->ortho_scale * r_asp[1] * scale[1] * overscan_factor; + r_shift[0] = camera->shiftx * camera->ortho_scale * scale[0] * overscan_factor; + r_shift[1] = camera->shifty * camera->ortho_scale * scale[1] * overscan_factor; + depth = do_clip ? -((camera->clipsta * scale[2]) + 0.1f) : - drawsize * camera->ortho_scale * scale[2]; *r_drawsize = 0.5f * camera->ortho_scale; } @@ -435,10 +468,10 @@ void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, cons scale_y = scale[1]; } - facx = fac * r_asp[0] * scale_x; - facy = fac * r_asp[1] * scale_y; - r_shift[0] = camera->shiftx * fac * 2.0f * scale_x; - r_shift[1] = camera->shifty * fac * 2.0f * scale_y; + facx = fac * r_asp[0] * scale_x * overscan_factor; + facy = fac * r_asp[1] * scale_y * overscan_factor; + r_shift[0] = camera->shiftx * fac * 2.0f * scale_x * overscan_factor; + r_shift[1] = camera->shifty * fac * 2.0f * scale_y * overscan_factor; } r_vec[0][0] = r_shift[0] + facx; r_vec[0][1] = r_shift[1] + facy; r_vec[0][2] = depth; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index df1695daf5b..f051582d9f4 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2475,9 +2475,15 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) if (idtype == ID_MC) { MovieClip *clip = (MovieClip *) id; + Scene *scene; BKE_tracking_dopesheet_tag_update(&clip->tracking); + for (scene = bmain->scene.first; scene; scene = scene->id.next) { + if (scene->clip == (MovieClip*)id) + BKE_scene_update_overscan(scene); + } + for (obt = bmain->object.first; obt; obt = obt->id.next) { bConstraint *con; for (con = obt->constraints.first; con; con = con->next) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 608b0495454..01eb2457ed5 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -52,6 +52,7 @@ #include "DNA_screen_types.h" #include "DNA_sequence_types.h" #include "DNA_space_types.h" +#include "DNA_movieclip_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -86,6 +87,8 @@ #include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_world.h" +#include "BKE_movieclip.h" +#include "BKE_tracking.h" #include "RE_engine.h" @@ -1891,3 +1894,14 @@ int BKE_scene_num_omp_threads(const struct Scene *scene) else return scene->omp_threads; } + +/* overscan */ +void BKE_scene_update_overscan(Scene *scene) +{ + float overscan = scene->r.overscan; + + if (scene->r.detect_overscan && scene->clip) + overscan = BKE_tracking_overscan_detect(scene->clip); + + scene->r.overscan = overscan; +} diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index ca0b52bd7c2..80db404fbe5 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -49,6 +49,7 @@ #include "BLI_listbase.h" #include "BLI_ghash.h" #include "BLI_path_util.h" +#include "BLI_rect.h" #include "BLI_string.h" #include "BLI_threads.h" @@ -1954,6 +1955,34 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r } } +float BKE_tracking_overscan_detect(MovieClip *clip) +{ + float overscan = 0.0f; + float scalex = 1.0f, scaley = 1.0f; + int width, height; + float delta[2]; + rcti rect; + MovieClipUser user= {0}; + + BKE_movieclip_user_set_frame(&user, 1); + + BKE_movieclip_get_size(clip, &user, &width, &height); + BLI_rcti_init(&rect, 0, width, 0, height); + BKE_tracking_max_undistortion_delta_across_bound(&clip->tracking, &rect, delta); + + if (delta[0] > 0.0f) { + scalex = 1.0f + delta[0] / width; + } + + if (delta[1] > 0.0f) { + scaley = 1.0f + delta[1] / height; + } + + overscan = (MAX2(scalex, scaley) - 1.0f) * 100.0f; + + return overscan; +} + /*********************** Image sampling *************************/ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, bool grayscale) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index a4597b6bf6c..6f134aef5a3 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -782,7 +782,7 @@ void draw_gpencil_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d) * deal with the camera border, otherwise map the coords to the camera border. */ if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) { rctf rectf; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */ + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, NULL, true); /* no shift */ offsx = iroundf(rectf.xmin); offsy = iroundf(rectf.ymin); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 4c4926f5ae7..8593aa68a2e 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1389,7 +1389,7 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { Scene *scene = CTX_data_scene(C); - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, subrect, true); /* no shift */ + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, subrect, NULL, true); /* no shift */ return 1; } } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 6bbaca73eb5..253a34eae3a 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1278,7 +1278,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(p->scene, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */ + ED_view3d_calc_camera_border(p->scene, p->ar, v3d, rv3d, &p->subrect_data, NULL, true); /* no shift */ p->subrect = &p->subrect_data; } } diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 377bb7cebb1..992b9eeb3ac 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -221,13 +221,14 @@ void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, cons bool ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *r_clipsta, float *r_clipend, const bool use_ortho_factor); bool ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, - struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize); + float overscan, struct rctf *r_viewplane, float *r_clipsta, + float *r_clipend, float *r_pixsize); void ED_view3d_polygon_offset(const struct RegionView3D *rv3d, const float dist); void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, - struct rctf *r_viewborder, const bool no_shift); + struct rctf *r_viewborder, struct rctf *r_underscan_viewborder, const bool no_shift); void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, float r_size[2]); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 3078b16ceeb..fd896665e65 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1035,7 +1035,7 @@ static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, Region if (draw_border) { if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, NULL, false); disprect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); disprect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); @@ -1063,7 +1063,7 @@ static bool render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d if (ar->winx < 4 || ar->winy < 4) return false; - *r_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, viewplane, r_clipsta, r_clipend, r_pixsize); + *r_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, 0.0f, viewplane, r_clipsta, r_clipend, r_pixsize); engine->resolution_x = ar->winx; engine->resolution_y = ar->winy; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index e095485f68b..892c69c9005 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -194,9 +194,9 @@ static void screen_opengl_render_apply(OGLRender *oglrender) rctf viewplane; float clipsta, clipend; - bool is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL); + bool is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, 0.0f, &viewplane, &clipsta, &clipend, NULL); if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); - else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index eb5c23a60f7..d97c0aa82d6 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1897,6 +1897,18 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po return; uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "use_detect_overscan", 0, NULL, 0); + + if ((node->custom2 & CMP_NODE_MOVIEDISTORTION_DETECTOVERSCAN) == 0) { + uiItemR(layout, ptr, "overscan", 0, NULL, 0); + } + else { + char buf[64]; + BLI_snprintf(buf, sizeof(buf), "Overscan: %.1f%%", node->custom3); + uiItemL(layout, buf, 0); + } + + uiItemR(layout, ptr, "use_crop_overscan", 0, NULL, 0); } static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d9bc40b6555..50db6282e4e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1723,6 +1723,7 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base float drawsize; const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera); MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false); + float overscan_factor = 1.0f + scene->r.overscan / 100.0f; /* draw data for movie clip set as active for scene */ if (clip) { @@ -1795,15 +1796,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES); else break; - tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]); - tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); + tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]) * overscan_factor; + tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]) * overscan_factor; glVertex3fv(tvec); /* left */ - tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]); + tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]) * overscan_factor; glVertex3fv(tvec); /* right */ tvec[0] = shift[0]; - tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); + tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]) * overscan_factor; glVertex3fv(tvec); /* top */ glEnd(); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d22dca4ad88..fbd5c3f4e1f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -934,17 +934,27 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } +static void view3d_camera_border_within_viewport(ARegion *ar, rctf *rect_view, rctf *rect_camera, rctf *viewborder_r) +{ + viewborder_r->xmin = ((rect_camera->xmin - rect_view->xmin)/BLI_rctf_size_x(rect_view))*ar->winx; + viewborder_r->xmax = ((rect_camera->xmax - rect_view->xmin)/BLI_rctf_size_x(rect_view))*ar->winx; + viewborder_r->ymin = ((rect_camera->ymin - rect_view->ymin)/BLI_rctf_size_y(rect_view))*ar->winy; + viewborder_r->ymax = ((rect_camera->ymax - rect_view->ymin)/BLI_rctf_size_y(rect_view))*ar->winy; +} + static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift, const bool no_zoom) + rctf *r_viewborder, rctf *r_underscan_viewborder, + const bool no_shift, const bool no_zoom) { CameraParams params; - rctf rect_view, rect_camera; + rctf rect_view, rect_camera, rect_camera_underscan; /* get viewport viewplane */ BKE_camera_params_init(¶ms); BKE_camera_params_from_view3d(¶ms, v3d, rv3d); if (no_zoom) params.zoom = 1.0f; + params.overscan = scene->r.overscan; BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); rect_view = params.viewplane; @@ -958,29 +968,33 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV params.shiftx = 0.0f; params.shifty = 0.0f; } + params.overscan = scene->r.overscan; BKE_camera_params_compute_viewplane(¶ms, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp); rect_camera = params.viewplane; + rect_camera_underscan = params.underscan_viewplane; /* get camera border within viewport */ - r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; - r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; - r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; - r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; + if (r_viewborder) + view3d_camera_border_within_viewport(ar, &rect_view, &rect_camera, r_viewborder); + + if (r_underscan_viewborder) + view3d_camera_border_within_viewport(ar, &rect_view, &rect_camera_underscan, r_underscan_viewborder); } void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2]) { rctf viewborder; - view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, true, true); + view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, NULL, true, true); r_size[0] = BLI_rctf_size_x(&viewborder); r_size[1] = BLI_rctf_size_y(&viewborder); } void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift) + rctf *r_viewborder, rctf *r_underscan_viewborder, + const bool no_shift) { - view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false); + view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, r_underscan_viewborder, no_shift, false); } static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac) @@ -1058,24 +1072,31 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) { float hmargin, vmargin; float x1, x2, y1, y2; - float x1i, x2i, y1i, y2i; + float x1i, x2i, y1i, y2i, x5i, x6i, y5i, y6i; + float x5, y5, x6, y6; - rctf viewborder; + rctf viewborder, underscan_viewborder; Camera *ca = NULL; RegionView3D *rv3d = ar->regiondata; + int draw_passepart; if (v3d->camera == NULL) return; if (v3d->camera->type == OB_CAMERA) ca = v3d->camera->data; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, &underscan_viewborder, false); /* the offsets */ x1 = viewborder.xmin; y1 = viewborder.ymin; x2 = viewborder.xmax; y2 = viewborder.ymax; - + + x5 = underscan_viewborder.xmin; + y5 = underscan_viewborder.ymin; + x6 = underscan_viewborder.xmax; + y6 = underscan_viewborder.ymax; + /* apply offsets so the real 3D camera shows through */ /* note: quite un-scientific but without this bit extra @@ -1085,11 +1106,18 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) * but keep it here in case we need to remove the workaround */ x1i = (int)(x1 - 1.0001f); y1i = (int)(y1 - 1.0001f); - x2i = (int)(x2 + (1.0f - 0.0001f)); - y2i = (int)(y2 + (1.0f - 0.0001f)); + x2i = (int)(x2 + (1.0f-0.0001f)); + y2i = (int)(y2 + (1.0f-0.0001f)); + + /* same goes to underscan border */ + x5i = (int)(x5 - 1.0001f); + y5i = (int)(y5 - 1.0001f); + x6i = (int)(x6 + (1.0f-0.0001f)); + y6i = (int)(y6 + (1.0f-0.0001f)); /* passepartout, specified in camera edit buttons */ - if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { + draw_passepart= (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f; + if (draw_passepart) { if (ca->passepartalpha == 1.0f) { glColor3f(0, 0, 0); } @@ -1138,6 +1166,32 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) UI_ThemeColor(TH_VIEW_OVERLAY); glRectf(x1i, y1i, x2i, y2i); + if (scene->r.overscan > 0.0f) { + UI_ThemeColorShade(TH_WIRE, 100); + uiDrawBox(GL_LINE_LOOP, x5i, y5i, x6i, y6i, 2.0); + + if (draw_passepart) { + setlinestyle(0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glColor4f(0, 0, 0, ca->passepartalpha*0.5f); + + if (x5i > x1i) + glRectf(x1i, y1i, x5i, y2i); + if (x6i < x2i) + glRectf(x6i, y1i, x2i, y2i); + if (y6i < y2i) + glRectf(x5i, y6i, x6i, y2i); + if (y5i > y1i) + glRectf(x5i, y5i, x6i, y1i); + setlinestyle(3); + } + + glDisable(GL_BLEND); + } + /* border */ if (scene->r.mode & R_BORDER) { float x3, y3, x4, y4; @@ -1148,7 +1202,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) y4 = y1 + scene->r.border.ymax * (y2 - y1); cpack(0x4040FF); - glRecti(x3, y3, x4, y4); + glRectf(x3, y3, x4, y4); } /* safety border */ @@ -1158,15 +1212,15 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - x3 = x1 + 0.5f * (x2 - x1); - y3 = y1 + 0.5f * (y2 - y1); + x3 = x5+ 0.5f*(x6-x5); + y3 = y5+ 0.5f*(y6-y5); glBegin(GL_LINES); - glVertex2f(x1, y3); - glVertex2f(x2, y3); + glVertex2f(x5, y3); + glVertex2f(x6, y3); - glVertex2f(x3, y1); - glVertex2f(x3, y2); + glVertex2f(x3, y5); + glVertex2f(x3, y6); glEnd(); } @@ -1174,54 +1228,54 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); glBegin(GL_LINES); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + glVertex2f(x5, y5); + glVertex2f(x6, y6); - glVertex2f(x1, y2); - glVertex2f(x2, y1); + glVertex2f(x5, y6); + glVertex2f(x6, y5); glEnd(); } if (ca->dtx & CAM_DTX_THIRDS) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_grid3(x1, x2, y1, y2, 1.0f / 3.0f); + drawviewborder_grid3(x5, x6, y5, y6, 1.0f / 3.0f); } if (ca->dtx & CAM_DTX_GOLDEN) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_grid3(x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); + drawviewborder_grid3(x5, x6, y5, y6, 1.0f - (1.0f / 1.61803399f)); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 0, 'A'); + drawviewborder_triangle(x5, x6, y5, y6, 0, 'A'); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 0, 'B'); + drawviewborder_triangle(x5, x6, y5, y6, 0, 'B'); } if (ca->dtx & CAM_DTX_HARMONY_TRI_A) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 1, 'A'); + drawviewborder_triangle(x5, x6, y5, y6, 1, 'A'); } if (ca->dtx & CAM_DTX_HARMONY_TRI_B) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 1, 'B'); + drawviewborder_triangle(x5, x6, y5, y6, 1, 'B'); } if (ca->flag & CAM_SHOWTITLESAFE) { UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - hmargin = 0.1f * (x2 - x1); - vmargin = 0.05f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + hmargin = 0.1f * (x6 - x5); + vmargin = 0.05f * (y6 - y5); + uiDrawBox(GL_LINE_LOOP, x5 + hmargin, y5 + vmargin, x6 - hmargin, y6 - vmargin, 2.0f); - hmargin = 0.035f * (x2 - x1); - vmargin = 0.035f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + hmargin = 0.035f * (x6 - x5); + vmargin = 0.035f * (y6 - y5); + uiDrawBox(GL_LINE_LOOP, x5 + hmargin, y5 + vmargin, x6 - hmargin, y6 - vmargin, 2.0f); } if (ca->flag & CAM_SHOWSENSOR) { /* determine sensor fit, and get sensor x/y, for auto fit we @@ -1236,22 +1290,22 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) rctf rect; if (sensor_fit == CAMERA_SENSOR_FIT_HOR) { - float sensor_scale = (x2i - x1i) / sensor_x; + float sensor_scale = (x6i-x5i) / sensor_x; float sensor_height = sensor_scale * sensor_y; - rect.xmin = x1i; - rect.xmax = x2i; - rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f; + rect.xmin = x5i; + rect.xmax = x6i; + rect.ymin = (y5i + y6i) * 0.5f - sensor_height * 0.5f; rect.ymax = rect.ymin + sensor_height; } else { - float sensor_scale = (y2i - y1i) / sensor_y; + float sensor_scale = (y6i-y5i) / sensor_y; float sensor_width = sensor_scale * sensor_x; - rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f; + rect.xmin = (x5i + x6i) * 0.5f - sensor_width * 0.5f; rect.xmax = rect.xmin + sensor_width; - rect.ymin = y1i; - rect.ymax = y2i; + rect.ymin = y5i; + rect.ymax = y6i; } /* draw */ @@ -1669,7 +1723,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if (do_camera_frame) { rctf vb; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, NULL, &vb, false); x1 = vb.xmin; y1 = vb.ymin; x2 = vb.xmax; @@ -2221,9 +2275,10 @@ float view3d_depth_near(ViewDepths *d) void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) { short zbuf = v3d->zbuf; + float overscan = scene->r.overscan; RegionView3D *rv3d = ar->regiondata; - setwinmatrixview3d(ar, v3d, NULL); + setwinmatrixview3d(ar, v3d, NULL, overscan); setviewmatrixview3d(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); @@ -2253,6 +2308,7 @@ void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *), boo short flag = v3d->flag; float glalphaclip = U.glalphaclip; int obcenter_dia = U.obcenter_dia; + float overscan = scene->r.overscan; /* temp set drawtype to solid */ /* Setting these temporarily is not nice */ @@ -2260,7 +2316,7 @@ void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *), boo U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ U.obcenter_dia = 0; - setwinmatrixview3d(ar, v3d, NULL); + setwinmatrixview3d(ar, v3d, NULL, overscan); setviewmatrixview3d(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); @@ -2514,12 +2570,13 @@ CustomDataMask ED_view3d_screen_datamask(bScreen *screen) void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]) { RegionView3D *rv3d = ar->regiondata; + float overscan= scene->r.overscan; /* setup window matrices */ if (winmat) copy_m4_m4(rv3d->winmat, winmat); else - setwinmatrixview3d(ar, v3d, NULL); + setwinmatrixview3d(ar, v3d, NULL, overscan); /* setup view matrix */ if (viewmat) @@ -3027,7 +3084,7 @@ bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti * /* compute border */ if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, NULL, false); rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 6b08ae98677..d91aa92bbc7 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -3082,7 +3082,7 @@ static int render_border_exec(bContext *C, wmOperator *op) /* calculate range */ if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, NULL, false); } else { vb.xmin = 0; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 6afe0ef896f..ae61931e4d5 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -234,7 +234,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), float x1, x2, y1, y2; if (fly->scene->camera) { - ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); + ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, NULL, false); xoff = viewborder.xmin; yoff = viewborder.ymin; } @@ -391,7 +391,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent /* calculate center */ if (fly->scene->camera) { - ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); + ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, NULL, false); fly->width = BLI_rctf_size_x(&viewborder); fly->height = BLI_rctf_size_y(&viewborder); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 3e7c97abaa9..0a9e0ab85aa 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -208,7 +208,7 @@ void ED_view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegio float *ofs, float *quat, float *dist, float *lens, const int smooth_viewtx); -void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); +void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect, float overscan); void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d); void fly_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index fdfce062adc..169bd584c94 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -728,12 +728,13 @@ bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, } /* also exposed in previewrender.c */ -bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, +bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, float overscan, rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize) { CameraParams params; BKE_camera_params_init(¶ms); + params.overscan = overscan; BKE_camera_params_from_view3d(¶ms, v3d, rv3d); BKE_camera_params_compute_viewplane(¶ms, winx, winy, 1.0f, 1.0f); @@ -767,14 +768,14 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) /*! * \param rect for picking, NULL not to use. */ -void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) +void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect, float overscan) { RegionView3D *rv3d = ar->regiondata; rctf viewplane; float clipsta, clipend, x1, y1, x2, y2; bool is_ortho; - is_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL); + is_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, overscan, &viewplane, &clipsta, &clipend, NULL); rv3d->is_persp = !is_ortho; #if 0 @@ -963,6 +964,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b char dt; short dtx; const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL); + float overscan = scene->r.overscan; G.f |= G_PICKSEL; @@ -977,7 +979,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b BLI_rctf_rcti_copy(&rect, input); } - setwinmatrixview3d(ar, v3d, &rect); + setwinmatrixview3d(ar, v3d, &rect, overscan); mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); if (v3d->drawtype > OB_WIRE) { @@ -1061,7 +1063,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b hits = glRenderMode(GL_RENDER); G.f &= ~G_PICKSEL; - setwinmatrixview3d(ar, v3d, NULL); + setwinmatrixview3d(ar, v3d, NULL, overscan); mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); if (v3d->drawtype > OB_WIRE) { @@ -1550,7 +1552,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) { /* Letterbox */ rctf cam_framef; - ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, false); + ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, NULL, false); cam_frame.xmin = cam_framef.xmin + ar->winrct.xmin; cam_frame.xmax = cam_framef.xmax + ar->winrct.xmin; cam_frame.ymin = cam_framef.ymin + ar->winrct.ymin; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index fa395c9af31..96d3286eb1c 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -308,7 +308,7 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a rctf viewborder; if (walk->scene->camera) { - ED_view3d_calc_camera_border(walk->scene, ar, walk->v3d, walk->rv3d, &viewborder, false); + ED_view3d_calc_camera_border(walk->scene, ar, walk->v3d, walk->rv3d, &viewborder, NULL, false); xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f; yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f; } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 0f4e9fa16f2..25ff62aefcd 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -1692,7 +1692,7 @@ void BIF_draw_manipulator(const bContext *C) } } -static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], float hotspot) +static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const int mval[2], float hotspot) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; @@ -1701,19 +1701,24 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl short hits; const bool is_picksel = true; - extern void setwinmatrixview3d(ARegion *, View3D *, rctf *); // XXX check a bit later on this... (ton) + extern void setwinmatrixview3d(ARegion *, View3D *, rctf *, float /*overscan*/); // XXX check a bit later on this... (ton) + float overscan = 0.0f; /* when looking through a selected camera, the manipulator can be at the * exact same position as the view, skip so we don't break selection */ if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) return 0; + if (rv3d->persp == RV3D_CAMOB) { + overscan = scene->r.overscan; + } + rect.xmin = mval[0] - hotspot; rect.xmax = mval[0] + hotspot; rect.ymin = mval[1] - hotspot; rect.ymax = mval[1] + hotspot; - setwinmatrixview3d(ar, v3d, &rect); + setwinmatrixview3d(ar, v3d, &rect, overscan); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); glSelectBuffer(64, buffer); @@ -1734,7 +1739,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl glPopName(); hits = glRenderMode(GL_RENDER); - setwinmatrixview3d(ar, v3d, NULL); + setwinmatrixview3d(ar, v3d, NULL, overscan); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); if (hits == 1) return buffer[3]; @@ -1786,6 +1791,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); int constraint_axis[3] = {0, 0, 0}; int val; int shift = event->shift; @@ -1797,11 +1803,11 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode); // find the hotspots first test narrow hotspot - val = manipulator_selectbuf(sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); + val = manipulator_selectbuf(scene, sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); if (val) { // drawflags still global, for drawing call above - drawflags = manipulator_selectbuf(sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); + drawflags = manipulator_selectbuf(scene, sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); if (drawflags == 0) drawflags = val; if (drawflags & MAN_TRANS_C) { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index e13d53934cb..5e885b82c36 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1041,4 +1041,8 @@ enum { /* viewer and cmposite output */ #define CMP_NODE_OUTPUT_IGNORE_ALPHA 1 +/* movie distoriton */ +#define CMP_NODE_MOVIEDISTORTION_DETECTOVERSCAN (1<<0) +#define CMP_NODE_MOVIEDISTORTION_CROPOVERSCAN (1<<1) + #endif diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e36ce7d9657..4b93de39a3a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -533,7 +533,10 @@ typedef struct RenderData { char seq_prev_type; char seq_rend_type; char seq_flag; /* flag use for sequence render/draw */ - char pad5[5]; + + /* overscan */ + char detect_overscan; + float overscan; /* render simplify */ int simplify_flag; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 0f2380cbad4..cd68393c4c1 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -5486,6 +5486,24 @@ static void def_cmp_moviedistortion(StructRNA *srna) RNA_def_property_enum_items(prop, distortion_type_items); RNA_def_property_ui_text(prop, "Distortion", "Distortion to use to filter image"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "overscan", PROP_FLOAT, PROP_PERCENTAGE); + RNA_def_property_float_sdna(prop, NULL, "custom3"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_range(prop, 0, 100, 10, 1); + RNA_def_property_ui_text(prop, "Overscan", "Factor of overscan meaning percentage from original resolution to be added in both directions"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "use_detect_overscan", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom2", CMP_NODE_MOVIEDISTORTION_DETECTOVERSCAN); + RNA_def_property_ui_text(prop, "Detect Overscan", "Automatically detect overscan value from input image buffer"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "use_crop_overscan", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom2", CMP_NODE_MOVIEDISTORTION_CROPOVERSCAN); + RNA_def_property_ui_text(prop, "Crop Overscan", "Crop overscan pixels from output image"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } static void def_cmp_mask(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 1d83206f17f..deab69dbcbe 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -511,6 +511,19 @@ static void rna_Scene_volume_set(PointerRNA *ptr, float value) sound_set_scene_volume(scene, value); } +static void rna_Scene_overscan_set(PointerRNA *ptr, float value) +{ + Scene *scene = (Scene*)(ptr->id.data); + + if (!scene->r.detect_overscan) + scene->r.overscan = value; +} + +static void rna_Scene_detect_overscan_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + BKE_scene_update_overscan(scene); +} + static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { scene->r.framelen = (float)scene->r.framapto / (float)scene->r.images; @@ -4240,6 +4253,20 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "FPS Base", "Framerate base"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update"); + prop = RNA_def_property(srna, "overscan", PROP_FLOAT, PROP_PERCENTAGE); + RNA_def_property_float_sdna(prop, NULL, "overscan"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_float_funcs(prop, NULL, "rna_Scene_overscan_set", NULL); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_range(prop, 0, 100, 10, 1); + RNA_def_property_ui_text(prop, "Overscan", "Amount of overscan meaning percentage from original resolution to be added in both directions"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_detect_overscan", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "detect_overscan", 1); + RNA_def_property_ui_text(prop, "Detect Overscan", "Automatically detect overscan from distortion mode of active scene clip"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_detect_overscan_update"); + /* frame mapping */ prop = RNA_def_property(srna, "frame_map_old", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "framapto"); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 6d994b36f26..e1131ca2be4 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -200,6 +200,8 @@ void RE_SetWindow(struct Render *re, rctf *viewplane, float clipsta, float clipe void RE_SetOrtho(struct Render *re, rctf *viewplane, float clipsta, float clipend); void RE_SetPixelSize(struct Render *re, float pixsize); +void RE_SceneRenderSize(struct Scene *scene, int *width, int *height); + /* option to set viewmatrix before making dbase */ void RE_SetView(struct Render *re, float mat[4][4]); diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 2c431bf869c..25dedf57ca1 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -493,9 +493,11 @@ void RE_SetEnvmapCamera(Render *re, Object *cam_ob, float viewscale, float clips void RE_SetCamera(Render *re, Object *cam_ob) { CameraParams params; + float overscan = re->scene->r.overscan; /* setup parameters */ BKE_camera_params_init(¶ms); + params.overscan = overscan; BKE_camera_params_from_object(¶ms, cam_ob); params.use_fields = (re->r.mode & R_FIELDS); @@ -523,6 +525,14 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo copy_m4_m4(mat, re->winmat); } +void RE_SceneRenderSize(Scene *scene, int *width, int *height) +{ + float overscan_factor = 1.0f + scene->r.overscan / 100.0f; + + *width = (scene->r.size*scene->r.xsch*overscan_factor) / 100; + *height = (scene->r.size*scene->r.ysch*overscan_factor) / 100; +} + /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 1a3d07f9aeb..401d561a09d 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1568,8 +1568,7 @@ static void render_scene(Render *re, Scene *sce, int cfra) /* exception: scene uses own size (unfinished code) */ if (0) { - winx = (sce->r.size * sce->r.xsch) / 100; - winy = (sce->r.size * sce->r.ysch) / 100; + RE_SceneRenderSize(sce, &winx, &winy); } /* initial setup */ @@ -2559,8 +2558,7 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc * r.border is the clipping rect */ /* calculate actual render result and display size */ - winx = (scene->r.size * scene->r.xsch) / 100; - winy = (scene->r.size * scene->r.ysch) / 100; + RE_SceneRenderSize(scene, &winx, &winy); /* we always render smaller part, inserting it in larger image is compositor bizz, it uses disprect for it */ if (scene->r.mode & R_BORDER) { @@ -2953,8 +2951,7 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) Object *camera; int winx, winy; - winx = (sce->r.size * sce->r.xsch) / 100; - winy = (sce->r.size * sce->r.ysch) / 100; + RE_SceneRenderSize(sce, &winx, &winy); RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL); @@ -2985,8 +2982,7 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode) rcti disprect; /* calculate actual render result and display size */ - winx = (scene->r.size * scene->r.xsch) / 100; - winy = (scene->r.size * scene->r.ysch) / 100; + RE_SceneRenderSize(scene, &winx, &winy); /* only in movie case we render smaller part */ if (scene->r.mode & R_BORDER) { |