diff options
author | YimingWu <xp8110@outlook.com> | 2021-07-28 14:55:29 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2021-07-28 14:55:29 +0300 |
commit | 8e9d06f5a0425255ce526e9c1aa7f852165749f0 (patch) | |
tree | 63810f0ac5e66ef5a1cb1be53035a6333a982b89 | |
parent | 544ddcdaac20bab7707a49edbd31b8ae38446603 (diff) |
LineArt: Camera Overscan
Expand camera effective region to a portion beyond image frame so strokes won't end right at the border.
Reviewed By: Antonio Vazquez (antoniov)
Differential Revision: https://developer.blender.org/D12049
6 files changed, 41 insertions, 10 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c index 8228915c6a8..ac458041ca3 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c @@ -380,6 +380,8 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel) return; } + uiItemR(layout, ptr, "overscan", 0, NULL, ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, true); uiItemR(col, ptr, "use_remove_doubles", 0, NULL, ICON_NONE); diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h index 3730dba8e70..8eed2e705e8 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h @@ -228,6 +228,8 @@ typedef struct LineartRenderBuffer { double view_projection[4][4]; double view[4][4]; + float overscan; + struct LineartBoundingArea *initial_bounding_areas; unsigned int bounding_area_count; diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index a97d79a886e..3a6d6a8f32f 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -2013,7 +2013,10 @@ static void lineart_geometry_load_assign_thread(LineartObjectLoadTaskInfo *olti_ use_olti->pending = obi; } -static bool lineart_geometry_check_visible(double (*model_view_proj)[4], Object *use_ob) +static bool lineart_geometry_check_visible(double (*model_view_proj)[4], + double shift_x, + double shift_y, + Object *use_ob) { BoundBox *bb = BKE_object_boundbox_get(use_ob); if (!bb) { @@ -2027,6 +2030,8 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4], Object copy_v3db_v3fl(co[i], bb->vec[i]); copy_v3_v3_db(tmp, co[i]); mul_v4_m4v3_db(co[i], model_view_proj, tmp); + co[i][0] -= shift_x * 2 * co[i][3]; + co[i][1] -= shift_y * 2 * co[i][3]; } bool cond[6] = {true, true, true, true, true, true}; @@ -2062,11 +2067,6 @@ static void lineart_main_load_geometries( int fit = BKE_camera_sensor_fit(cam->sensor_fit, rb->w, rb->h); double asp = ((double)rb->w / (double)rb->h); - double t_start; - - if (G.debug_value == 4000) { - t_start = PIL_check_seconds_timer(); - } int bound_box_discard_count = 0; if (cam->type == CAM_PERSP) { @@ -2076,14 +2076,20 @@ static void lineart_main_load_geometries( if (fit == CAMERA_SENSOR_FIT_HOR && asp < 1) { sensor /= asp; } - double fov = focallength_to_fov(cam->lens, sensor); + const double fov = focallength_to_fov(cam->lens / (1 + rb->overscan), sensor); lineart_matrix_perspective_44d(proj, fov, asp, cam->clip_start, cam->clip_end); } else if (cam->type == CAM_ORTHO) { - double w = cam->ortho_scale / 2; + const double w = cam->ortho_scale / 2; lineart_matrix_ortho_44d(proj, -w, w, -w / asp, w / asp, cam->clip_start, cam->clip_end); } + double t_start; + + if (G.debug_value == 4000) { + t_start = PIL_check_seconds_timer(); + } + invert_m4_m4(inv, rb->cam_obmat); mul_m4db_m4db_m4fl_uniq(result, proj, inv); copy_m4_m4_db(proj, result); @@ -2130,7 +2136,7 @@ static void lineart_main_load_geometries( continue; } - if (!lineart_geometry_check_visible(obi->model_view_proj, use_ob)) { + if (!lineart_geometry_check_visible(obi->model_view_proj, rb->shift_x, rb->shift_y, use_ob)) { if (G.debug_value == 4000) { bound_box_discard_count++; } @@ -3023,6 +3029,11 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene, rb->shift_x = fit == CAMERA_SENSOR_FIT_HOR ? c->shiftx : c->shiftx / asp; rb->shift_y = fit == CAMERA_SENSOR_FIT_VERT ? c->shifty : c->shifty * asp; + rb->overscan = lmd->overscan; + + rb->shift_x /= (1 + rb->overscan); + rb->shift_y /= (1 + rb->overscan); + rb->crease_threshold = cos(M_PI - lmd->crease_threshold); rb->angle_splitting_threshold = lmd->angle_splitting_threshold; rb->chaining_image_threshold = lmd->chaining_image_threshold; diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index b9697beeea9..81e9abc4916 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -307,6 +307,7 @@ .calculation_flags = LRT_ALLOW_DUPLI_OBJECTS | LRT_ALLOW_CLIPPING_BOUNDARIES, \ .angle_splitting_threshold = DEG2RAD(60.0f), \ .chaining_image_threshold = 0.001f, \ + .overscan = 0.1f,\ } #define _DNA_DEFAULT_LengthGpencilModifierData \ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index fac5bd3d4f4..6ffaf457d63 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -963,6 +963,12 @@ typedef struct LineartGpencilModifierData { char source_vertex_group[64]; char vgname[64]; + /* Camera focal length is divided by (1 + overscan), before caluclation, which give a wider FOV, + * this doesn't change coordinates range internally (-1, 1), but makes the caluclated frame + * bigger than actual output. This is for the easier shifting calculation. A value of 0.5 means + * the "internal" focal length become 2/3 of the actual camera. */ + float overscan; + float opacity; short thickness; @@ -970,7 +976,7 @@ typedef struct LineartGpencilModifierData { unsigned char material_mask_bits; unsigned char intersection_mask; - char _pad[7]; + char _pad[3]; /** `0..1` range for cosine angle */ float crease_threshold; diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index a6d4d05b438..4e95174e42b 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -3137,6 +3137,15 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna) "Certain settings will be unavailable"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "overscan", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text( + prop, + "Overscan", + "A margin to prevent strokes from ending abruptly at the edge of the image"); + RNA_def_property_ui_range(prop, 0.0f, 0.5f, 0.01f, 3); + RNA_def_property_range(prop, 0.0f, 0.5f); + RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "thickness", PROP_INT, PROP_NONE); RNA_def_property_ui_text(prop, "Thickness", "The thickness for the generated strokes"); RNA_def_property_ui_range(prop, 1, 100, 1, 1); |