Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpencil_modifiers/intern')
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencildash.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c75
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h15
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c173
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c48
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c4
9 files changed, 287 insertions, 40 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 595a0c1cc5e..9ea146c77f2 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -156,7 +156,7 @@ float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
weight = dw ? dw->weight : -1.0f;
if ((weight >= 0.0f) && (inverse)) {
- return -1.0f;
+ return 1.0f - weight;
}
if ((weight < 0.0f) && (!inverse)) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c b/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
index ba33edd6a94..33cc3094a36 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
@@ -255,7 +255,7 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec
BKE_gpencil_frame_active_set(depsgraph, gpd);
bGPDframe *gpf = gpl->actframe;
if (gpf == NULL) {
- return;
+ continue;
}
apply_dash_for_frame(ob, gpl, gpd, gpf, (DashGpencilModifierData *)md);
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
index c5ccf1d8229..fa31aec2b5b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
@@ -160,12 +160,14 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec
LineartCache *local_lc = gpd->runtime.lineart_cache;
if (!gpd->runtime.lineart_cache) {
- MOD_lineart_compute_feature_lines(depsgraph, lmd, &gpd->runtime.lineart_cache);
+ MOD_lineart_compute_feature_lines(
+ depsgraph, lmd, &gpd->runtime.lineart_cache, (!(ob->dtx & OB_DRAW_IN_FRONT)));
MOD_lineart_destroy_render_data(lmd);
}
else {
if (!(lmd->flags & LRT_GPENCIL_USE_CACHE)) {
- MOD_lineart_compute_feature_lines(depsgraph, lmd, &local_lc);
+ MOD_lineart_compute_feature_lines(
+ depsgraph, lmd, &local_lc, (!(ob->dtx & OB_DRAW_IN_FRONT)));
MOD_lineart_destroy_render_data(lmd);
}
MOD_lineart_chain_clear_picked_flag(local_lc);
@@ -210,7 +212,8 @@ static void bakeModifier(Main *UNUSED(bmain),
lmd->edge_types_override = lmd->edge_types;
lmd->level_end_override = lmd->level_end;
- MOD_lineart_compute_feature_lines(depsgraph, lmd, &gpd->runtime.lineart_cache);
+ MOD_lineart_compute_feature_lines(
+ depsgraph, lmd, &gpd->runtime.lineart_cache, (!(ob->dtx & OB_DRAW_IN_FRONT)));
MOD_lineart_destroy_render_data(lmd);
}
@@ -261,7 +264,13 @@ static void updateDepsgraph(GpencilModifierData *md,
else {
add_this_collection(ctx->scene->master_collection, ctx, mode);
}
- if (ctx->scene->camera) {
+ if (lmd->calculation_flags & LRT_USE_CUSTOM_CAMERA && lmd->source_camera) {
+ DEG_add_object_relation(
+ ctx->node, lmd->source_camera, DEG_OB_COMP_TRANSFORM, "Line Art Modifier");
+ DEG_add_object_relation(
+ ctx->node, lmd->source_camera, DEG_OB_COMP_PARAMETERS, "Line Art Modifier");
+ }
+ else if (ctx->scene->camera) {
DEG_add_object_relation(
ctx->node, ctx->scene->camera, DEG_OB_COMP_TRANSFORM, "Line Art Modifier");
DEG_add_object_relation(
@@ -277,6 +286,7 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
walk(userData, ob, (ID **)&lmd->source_collection, IDWALK_CB_NOP);
walk(userData, ob, (ID **)&lmd->source_object, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&lmd->source_camera, IDWALK_CB_NOP);
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -382,7 +392,12 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
return;
}
- uiItemR(layout, ptr, "overscan", 0, NULL, ICON_NONE);
+ uiLayout *row = uiLayoutRowWithHeading(layout, false, IFACE_("Custom Camera"));
+ uiItemR(row, ptr, "use_custom_camera", 0, "", 0);
+ uiLayout *subrow = uiLayoutRow(row, true);
+ uiLayoutSetActive(subrow, RNA_boolean_get(ptr, "use_custom_camera"));
+ uiLayoutSetPropSep(subrow, true);
+ uiItemR(subrow, ptr, "source_camera", 0, "", ICON_OBJECT_DATA);
uiLayout *col = uiLayoutColumn(layout, true);
@@ -391,7 +406,7 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(col, ptr, "use_object_instances", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_clip_plane_boundaries", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_crease_on_smooth", 0, IFACE_("Crease On Smooth"), ICON_NONE);
- uiItemR(layout, ptr, "use_crease_on_sharp", 0, IFACE_("Crease On Sharp"), ICON_NONE);
+ uiItemR(col, ptr, "use_crease_on_sharp", 0, IFACE_("Crease On Sharp"), ICON_NONE);
}
static void style_panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -412,14 +427,23 @@ static void style_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void occlusion_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
- PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
+ const bool use_multiple_levels = RNA_boolean_get(ptr, "use_multiple_levels");
+ const bool show_in_front = RNA_boolean_get(&ob_ptr, "show_in_front");
+
uiLayoutSetPropSep(layout, true);
uiLayoutSetEnabled(layout, !is_baked);
- const bool use_multiple_levels = RNA_boolean_get(ptr, "use_multiple_levels");
+ if (!show_in_front) {
+ uiItemL(layout, IFACE_("Object is not in front"), ICON_INFO);
+ }
+
+ layout = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(layout, show_in_front);
uiItemR(layout, ptr, "use_multiple_levels", 0, IFACE_("Range"), ICON_NONE);
@@ -447,11 +471,14 @@ static bool anything_showing_through(PointerRNA *ptr)
static void material_mask_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
- PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
+ const bool show_in_front = RNA_boolean_get(&ob_ptr, "show_in_front");
+
uiLayoutSetEnabled(layout, !is_baked);
- uiLayoutSetActive(layout, anything_showing_through(ptr));
+ uiLayoutSetActive(layout, show_in_front && anything_showing_through(ptr));
uiItemR(layout, ptr, "use_material_mask", 0, IFACE_("Material Mask"), ICON_NONE);
}
@@ -654,6 +681,32 @@ static void bake_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemO(col, NULL, ICON_NONE, "OBJECT_OT_lineart_clear_all");
}
+static void composition_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ uiLayout *layout = panel->layout;
+
+ const bool show_in_front = RNA_boolean_get(&ob_ptr, "show_in_front");
+
+ uiLayoutSetPropSep(layout, true);
+
+ uiItemR(layout, ptr, "overscan", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_image_boundary_trimming", 0, NULL, ICON_NONE);
+
+ if (show_in_front) {
+ uiItemL(layout, IFACE_("Object is shown in front"), ICON_ERROR);
+ }
+
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(col, !show_in_front);
+
+ uiItemR(col, ptr, "stroke_depth_offset", UI_ITEM_R_SLIDER, IFACE_("Depth Offset"), ICON_NONE);
+ uiItemR(
+ col, ptr, "use_offset_towards_custom_camera", 0, IFACE_("Towards Custom Camera"), ICON_NONE);
+}
+
static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
@@ -682,6 +735,8 @@ static void panelRegister(ARegionType *region_type)
gpencil_modifier_subpanel_register(
region_type, "vgroup", "Vertex Weight Transfer", NULL, vgroup_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
+ region_type, "composition", "Composition", NULL, composition_panel_draw, panel_type);
+ gpencil_modifier_subpanel_register(
region_type, "bake", "Bake", NULL, bake_panel_draw, panel_type);
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index fb75b1e99ac..2e55369ea97 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -240,10 +240,10 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(layout, ptr, "hardness", 0, NULL, ICON_NONE);
}
else {
- const bool is_normalized = RNA_boolean_get(ptr, "normalize_opacity");
+ const bool is_normalized = RNA_boolean_get(ptr, "use_normalized_opacity");
const bool is_weighted = RNA_boolean_get(ptr, "use_weight_factor");
- uiItemR(layout, ptr, "normalize_opacity", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_normalized_opacity", 0, NULL, ICON_NONE);
const char *text = (is_normalized) ? IFACE_("Strength") : IFACE_("Opacity Factor");
uiLayout *row = uiLayoutRow(layout, true);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index cac700e15f4..233992bbd31 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -191,8 +191,8 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
- uiItemR(layout, ptr, "normalize_thickness", 0, NULL, ICON_NONE);
- if (RNA_boolean_get(ptr, "normalize_thickness")) {
+ uiItemR(layout, ptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
+ if (RNA_boolean_get(ptr, "use_normalized_thickness")) {
uiItemR(layout, ptr, "thickness", 0, NULL, ICON_NONE);
}
else {
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index c00f34185dd..d8926a63307 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -182,9 +182,9 @@ typedef struct LineartEdgeChain {
typedef struct LineartEdgeChainItem {
struct LineartEdgeChainItem *next, *prev;
- /** Need z value for fading */
- float pos[3];
- /** For restoring position to 3d space */
+ /** Need z value for fading, w value for image frame clipping. */
+ float pos[4];
+ /** For restoring position to 3d space. */
float gpos[3];
float normal[3];
unsigned char line_type;
@@ -299,6 +299,7 @@ typedef struct LineartRenderBuffer {
bool use_loose_as_contour;
bool use_loose_edge_chain;
bool use_geometry_space_chain;
+ bool use_image_boundary_trimming;
bool filter_face_mark;
bool filter_face_mark_invert;
@@ -311,6 +312,7 @@ typedef struct LineartRenderBuffer {
bool cam_is_persp;
float cam_obmat[4][4];
double camera_pos[3];
+ double active_camera_pos[3]; /* Stroke offset calculation may use active or selected camera. */
double near_clip, far_clip;
float shift_x, shift_y;
float crease_threshold;
@@ -593,15 +595,20 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb);
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb);
void MOD_lineart_chain_connect(LineartRenderBuffer *rb);
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold);
+void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb);
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad);
void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance);
+void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
+ float dist,
+ bool use_custom_camera);
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc);
bool MOD_lineart_compute_feature_lines(struct Depsgraph *depsgraph,
struct LineartGpencilModifierData *lmd,
- LineartCache **cached_result);
+ struct LineartCache **cached_result,
+ bool enable_stroke_offset);
struct Scene;
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 8935bdd1870..f3110cf87b6 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -126,7 +126,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
- copy_v2_v2(eci->pos, fbcoord);
+ copy_v4_v4(eci->pos, fbcoord);
copy_v3_v3(eci->gpos, gpos);
eci->index = index;
copy_v3_v3(eci->normal, normal);
@@ -156,7 +156,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
- copy_v2_v2(eci->pos, fbcoord);
+ copy_v4_v4(eci->pos, fbcoord);
copy_v3_v3(eci->gpos, gpos);
eci->index = index;
copy_v3_v3(eci->normal, normal);
@@ -177,15 +177,15 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
int last_occlusion;
unsigned char last_transparency;
/* Used when converting from double. */
- float use_fbcoord[2];
+ float use_fbcoord[4];
float use_gpos[3];
#define VERT_COORD_TO_FLOAT(a) \
- copy_v2fl_v2db(use_fbcoord, (a)->fbcoord); \
+ copy_v4fl_v4db(use_fbcoord, (a)->fbcoord); \
copy_v3fl_v3db(use_gpos, (a)->gloc);
#define POS_TO_FLOAT(lpos, gpos) \
- copy_v2fl_v2db(use_fbcoord, lpos); \
+ copy_v3fl_v3db(use_fbcoord, lpos); \
copy_v3fl_v3db(use_gpos, gpos);
LRT_ITER_ALL_LINES_BEGIN
@@ -262,6 +262,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]);
interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at);
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
+ use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
POS_TO_FLOAT(lpos, gpos)
lineart_chain_prepend_point(rb,
ec,
@@ -287,6 +288,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]);
interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at);
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
+ use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
POS_TO_FLOAT(lpos, gpos)
lineart_chain_prepend_point(rb,
ec,
@@ -340,6 +342,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]);
interp_v3_v3v3_db(lpos, e->v1->fbcoord, e->v2->fbcoord, es->at);
interp_v3_v3v3_db(gpos, e->v1->gloc, e->v2->gloc, global_at);
+ use_fbcoord[3] = interpf(e->v2->fbcoord[3], e->v1->fbcoord[3], global_at);
POS_TO_FLOAT(lpos, gpos)
lineart_chain_append_point(rb,
ec,
@@ -403,6 +406,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]);
interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at);
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
+ use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
last_occlusion = es->prev ? es->prev->occlusion : last_occlusion;
last_transparency = es->prev ? es->prev->material_mask_bits : last_transparency;
POS_TO_FLOAT(lpos, gpos)
@@ -430,6 +434,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
double global_at = lfb[3] * es->at / (es->at * lfb[3] + (1 - es->at) * rfb[3]);
interp_v3_v3v3_db(lpos, new_e->v1->fbcoord, new_e->v2->fbcoord, es->at);
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
+ use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
POS_TO_FLOAT(lpos, gpos)
lineart_chain_append_point(rb,
ec,
@@ -926,9 +931,9 @@ void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance)
{
- LISTBASE_FOREACH (LineartEdgeChain *, rlc, &rb->chains) {
+ LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
LineartEdgeChainItem *next_eci;
- for (LineartEdgeChainItem *eci = rlc->chain.first; eci; eci = next_eci) {
+ for (LineartEdgeChainItem *eci = ec->chain.first; eci; eci = next_eci) {
next_eci = eci->next;
LineartEdgeChainItem *eci2, *eci3, *eci4;
@@ -944,7 +949,7 @@ void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance)
if (dist_to_line_segment_v2(eci3->pos, eci->pos, eci2->pos) < tolerance) {
/* And if p4 is on the extension of p1-p2 , we remove p3. */
if ((eci4 = eci3->next) && (dist_to_line_v2(eci4->pos, eci->pos, eci2->pos) < tolerance)) {
- BLI_remlink(&rlc->chain, eci3);
+ BLI_remlink(&ec->chain, eci3);
next_eci = eci;
}
}
@@ -952,6 +957,116 @@ void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance)
}
}
+static LineartEdgeChainItem *lineart_chain_create_crossing_point(LineartRenderBuffer *rb,
+ LineartEdgeChainItem *eci_inside,
+ LineartEdgeChainItem *eci_outside)
+{
+ float isec[2];
+ float LU[2] = {-1.0f, 1.0f}, LB[2] = {-1.0f, -1.0f}, RU[2] = {1.0f, 1.0f}, RB[2] = {1.0f, -1.0f};
+ bool found = false;
+ LineartEdgeChainItem *eci2 = eci_outside, *eci1 = eci_inside;
+ if (eci2->pos[0] < -1.0f) {
+ found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, LU, LB, isec) > 0);
+ }
+ if (!found && eci2->pos[0] > 1.0f) {
+ found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, RU, RB, isec) > 0);
+ }
+ if (!found && eci2->pos[1] < -1.0f) {
+ found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, LB, RB, isec) > 0);
+ }
+ if (!found && eci2->pos[1] > 1.0f) {
+ found = (isect_seg_seg_v2_point(eci1->pos, eci2->pos, LU, RU, isec) > 0);
+ }
+
+ if (UNLIKELY(!found)) {
+ return NULL;
+ }
+
+ float ratio = (fabs(eci2->pos[0] - eci1->pos[0]) > fabs(eci2->pos[1] - eci1->pos[1])) ?
+ ratiof(eci1->pos[0], eci2->pos[0], isec[0]) :
+ ratiof(eci1->pos[1], eci2->pos[1], isec[1]);
+ float gratio = eci1->pos[3] * ratio / (ratio * eci1->pos[3] + (1 - ratio) * eci2->pos[3]);
+
+ LineartEdgeChainItem *eci = lineart_mem_acquire(rb->chain_data_pool,
+ sizeof(LineartEdgeChainItem));
+ memcpy(eci, eci1, sizeof(LineartEdgeChainItem));
+ interp_v3_v3v3(eci->gpos, eci1->gpos, eci2->gpos, gratio);
+ interp_v3_v3v3(eci->pos, eci1->pos, eci2->pos, ratio);
+ eci->pos[3] = interpf(eci2->pos[3], eci1->pos[3], gratio);
+ eci->next = eci->prev = NULL;
+ return eci;
+}
+
+#define LRT_ECI_INSIDE(eci) \
+ ((eci)->pos[0] >= -1.0f && (eci)->pos[0] <= 1.0f && (eci)->pos[1] >= -1.0f && \
+ (eci)->pos[1] <= 1.0f)
+
+void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
+{
+ LineartEdgeChain *ec;
+ LineartEdgeChainItem *eci, *next_eci, *prev_eci, *new_eci;
+ bool is_inside, new_inside;
+ ListBase swap = {0};
+ swap.first = rb->chains.first;
+ swap.last = rb->chains.last;
+
+ rb->chains.last = rb->chains.first = NULL;
+ while ((ec = BLI_pophead(&swap)) != NULL) {
+ bool ec_added = false;
+ LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first;
+ is_inside = LRT_ECI_INSIDE(first_eci) ? true : false;
+ if (!is_inside) {
+ ec->picked = true;
+ }
+ for (eci = first_eci->next; eci; eci = next_eci) {
+ next_eci = eci->next;
+ prev_eci = eci->prev;
+
+ /* We only need to do something if the edge crossed from outside to the inside or from inside
+ * to the outside. */
+ if ((new_inside = LRT_ECI_INSIDE(eci)) != is_inside) {
+ if (new_inside == false) {
+ /* Stroke goes out. */
+ new_eci = lineart_chain_create_crossing_point(rb, prev_eci, eci);
+
+ LineartEdgeChain *new_ec = lineart_mem_acquire(rb->chain_data_pool,
+ sizeof(LineartEdgeChain));
+ memcpy(new_ec, ec, sizeof(LineartEdgeChain));
+ new_ec->chain.first = next_eci;
+ eci->prev = NULL;
+ prev_eci->next = NULL;
+ ec->chain.last = prev_eci;
+ BLI_addtail(&ec->chain, new_eci);
+ BLI_addtail(&rb->chains, ec);
+ ec_added = true;
+ ec = new_ec;
+
+ next_eci = eci->next;
+ is_inside = new_inside;
+ continue;
+ }
+ /* Stroke comes in. */
+ new_eci = lineart_chain_create_crossing_point(rb, eci, prev_eci);
+
+ ec->chain.first = eci;
+ eci->prev = NULL;
+
+ BLI_addhead(&ec->chain, new_eci);
+
+ ec_added = false;
+
+ next_eci = eci->next;
+ is_inside = new_inside;
+ continue;
+ }
+ }
+
+ if ((!ec_added) && is_inside) {
+ BLI_addtail(&rb->chains, ec);
+ }
+ }
+}
+
/**
* This should always be the last stage!, see the end of
* #MOD_lineart_chain_split_for_fixed_occlusion().
@@ -1008,3 +1123,45 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
}
}
}
+
+void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
+ float dist,
+ bool use_custom_camera)
+{
+ float dir[3];
+ float cam[3];
+ float view[3];
+ float view_clamp[3];
+ copy_v3fl_v3db(cam, rb->camera_pos);
+ copy_v3fl_v3db(view, rb->view_vector);
+
+ if (use_custom_camera) {
+ copy_v3fl_v3db(cam, rb->camera_pos);
+ }
+ else {
+ copy_v3fl_v3db(cam, rb->active_camera_pos);
+ }
+
+ if (rb->cam_is_persp) {
+ LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
+ LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) {
+ sub_v3_v3v3(dir, cam, eci->gpos);
+ float orig_len = len_v3(dir);
+ normalize_v3(dir);
+ mul_v3_fl(dir, MIN2(dist, orig_len - rb->near_clip));
+ add_v3_v3(eci->gpos, dir);
+ }
+ }
+ }
+ else {
+ LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
+ LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) {
+ sub_v3_v3v3(dir, cam, eci->gpos);
+ float len_lim = dot_v3v3(view, dir) - rb->near_clip;
+ normalize_v3_v3(view_clamp, view);
+ mul_v3_fl(view_clamp, MIN2(dist, len_lim));
+ add_v3_v3(eci->gpos, view_clamp);
+ }
+ }
+ }
+}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 6660da79b40..93e9062e910 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -2998,7 +2998,7 @@ void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
}
}
-static LineartCache *lineart_init_cache()
+static LineartCache *lineart_init_cache(void)
{
LineartCache *lc = MEM_callocN(sizeof(LineartCache), "Lineart Cache");
return lc;
@@ -3016,6 +3016,8 @@ void MOD_lineart_clear_cache(struct LineartCache **lc)
static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
LineartGpencilModifierData *lmd,
+ Object *camera,
+ Object *active_camera,
LineartCache *lc)
{
LineartRenderBuffer *rb = MEM_callocN(sizeof(LineartRenderBuffer), "Line Art render buffer");
@@ -3024,10 +3026,10 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
lmd->render_buffer_ptr = rb;
lc->rb_edge_types = lmd->edge_types_override;
- if (!scene || !scene->camera || !lc) {
+ if (!scene || !camera || !lc) {
return NULL;
}
- Camera *c = scene->camera->data;
+ Camera *c = camera->data;
double clipping_offset = 0;
if (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) {
@@ -3035,8 +3037,11 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
clipping_offset = 0.0001;
}
- copy_v3db_v3fl(rb->camera_pos, scene->camera->obmat[3]);
- copy_m4_m4(rb->cam_obmat, scene->camera->obmat);
+ copy_v3db_v3fl(rb->camera_pos, camera->obmat[3]);
+ if (active_camera) {
+ copy_v3db_v3fl(rb->active_camera_pos, active_camera->obmat[3]);
+ }
+ copy_m4_m4(rb->cam_obmat, camera->obmat);
rb->cam_is_persp = (c->type == CAM_PERSP);
rb->near_clip = c->clip_start + clipping_offset;
rb->far_clip = c->clip_end - clipping_offset;
@@ -3072,6 +3077,8 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->use_loose_as_contour = (lmd->calculation_flags & LRT_LOOSE_AS_CONTOUR) != 0;
rb->use_loose_edge_chain = (lmd->calculation_flags & LRT_CHAIN_LOOSE_EDGES) != 0;
rb->use_geometry_space_chain = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 0;
+ rb->use_image_boundary_trimming = (lmd->calculation_flags & LRT_USE_IMAGE_BOUNDARY_TRIMMING) !=
+ 0;
/* See lineart_edge_from_triangle() for how this option may impact performance. */
rb->allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0;
@@ -4076,11 +4083,13 @@ static LineartBoundingArea *lineart_bounding_area_next(LineartBoundingArea *this
*/
bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
LineartGpencilModifierData *lmd,
- LineartCache **cached_result)
+ LineartCache **cached_result,
+ bool enable_stroke_depth_offset)
{
LineartRenderBuffer *rb;
Scene *scene = DEG_get_evaluated_scene(depsgraph);
int intersections_only = 0; /* Not used right now, but preserve for future. */
+ Object *use_camera;
double t_start;
@@ -4090,14 +4099,24 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
BKE_scene_camera_switch_update(scene);
- if (!scene->camera) {
- return false;
+ if (lmd->calculation_flags & LRT_USE_CUSTOM_CAMERA) {
+ if (!lmd->source_camera ||
+ (use_camera = DEG_get_evaluated_object(depsgraph, lmd->source_camera))->type !=
+ OB_CAMERA) {
+ return false;
+ }
+ }
+ else {
+ if (!scene->camera) {
+ return false;
+ }
+ use_camera = scene->camera;
}
LineartCache *lc = lineart_init_cache();
*cached_result = lc;
- rb = lineart_create_render_buffer(scene, lmd, lc);
+ rb = lineart_create_render_buffer(scene, lmd, use_camera, scene->camera, lc);
/* Triangle thread testing data size varies depending on the thread count.
* See definition of LineartTriangleThread for details. */
@@ -4117,7 +4136,7 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
/* Get view vector before loading geometries, because we detect feature lines there. */
lineart_main_get_view_vector(rb);
lineart_main_load_geometries(
- depsgraph, scene, scene->camera, rb, lmd->calculation_flags & LRT_ALLOW_DUPLI_OBJECTS);
+ depsgraph, scene, use_camera, rb, lmd->calculation_flags & LRT_ALLOW_DUPLI_OBJECTS);
if (!rb->vertex_buffer_pointers.first) {
/* No geometry loaded, return early. */
@@ -4185,10 +4204,19 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
MOD_lineart_smooth_chains(rb, rb->chain_smooth_tolerance / 50);
}
+ if (rb->use_image_boundary_trimming) {
+ MOD_lineart_chain_clip_at_border(rb);
+ }
+
if (rb->angle_splitting_threshold > FLT_EPSILON) {
MOD_lineart_chain_split_angle(rb, rb->angle_splitting_threshold);
}
+ if (enable_stroke_depth_offset && lmd->stroke_depth_offset > FLT_EPSILON) {
+ MOD_lineart_chain_offset_towards_camera(
+ rb, lmd->stroke_depth_offset, lmd->flags & LRT_GPENCIL_OFFSET_TOWARDS_CUSTOM_CAMERA);
+ }
+
/* Finally transfer the result list into cache. */
memcpy(&lc->chains, &rb->chains, sizeof(ListBase));
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c
index 988c90483a6..b74499daf6b 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c
@@ -118,12 +118,12 @@ static bool bake_strokes(Object *ob,
}
LineartCache *local_lc = *lc;
if (!(*lc)) {
- MOD_lineart_compute_feature_lines(dg, lmd, lc);
+ MOD_lineart_compute_feature_lines(dg, lmd, lc, (!(ob->dtx & OB_DRAW_IN_FRONT)));
MOD_lineart_destroy_render_data(lmd);
}
else {
if (is_first || (!(lmd->flags & LRT_GPENCIL_USE_CACHE))) {
- MOD_lineart_compute_feature_lines(dg, lmd, &local_lc);
+ MOD_lineart_compute_feature_lines(dg, lmd, &local_lc, (!(ob->dtx & OB_DRAW_IN_FRONT)));
MOD_lineart_destroy_render_data(lmd);
}
MOD_lineart_chain_clear_picked_flag(local_lc);