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
path: root/source
diff options
context:
space:
mode:
authorYimingWu <xp8110@outlook.com>2022-01-22 11:13:44 +0300
committerYimingWu <xp8110@outlook.com>2022-01-22 11:13:44 +0300
commit5ae76fae90da795891e7edccc14bccf36f93da54 (patch)
tree17b18e69bb7fcc46fd49151942fbb591e3b6e58b /source
parente88d966737c1e4c246f92d21fbe31c4eb702678c (diff)
LineArt: Noise tolerant chaining.
Instead of splitting it at each occlusion change, it tolerates short segments of "zig-zag" occlusion incoherence and doesn't split the chain at these points, thus creating a much smoother result. Reviewed By: Antonio Vazquez (antoniov), Aleš Jelovčan (frogstomp) Differential Revision: https://developer.blender.org/D13851
Diffstat (limited to 'source')
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h2
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c58
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c2
-rw-r--r--source/blender/makesdna/DNA_lineart_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c6
6 files changed, 70 insertions, 0 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
index 59937bb0757..1dc6816980c 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
@@ -607,6 +607,7 @@ static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(col, ptr, "use_fuzzy_all", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_loose_edge_chain", 0, IFACE_("Loose Edges"), ICON_NONE);
uiItemR(col, ptr, "use_loose_as_contour", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_detail_preserve", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_geometry_space_chain", 0, IFACE_("Geometry Space"), ICON_NONE);
uiItemR(layout,
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index 8c5820c9667..2691dcc8408 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -308,6 +308,8 @@ typedef struct LineartRenderBuffer {
bool force_crease;
bool sharp_as_crease;
+ bool chain_preserve_details;
+
/* Keep an copy of these data so when line art is running it's self-contained. */
bool cam_is_persp;
float cam_obmat[4][4];
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 0deb8b1c335..78ad895c93e 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -571,6 +571,57 @@ static void lineart_bounding_area_link_chain(LineartRenderBuffer *rb, LineartEdg
}
}
+static bool lineart_chain_fix_ambiguous_segments(LineartEdgeChain *ec,
+ LineartEdgeChainItem *last_matching_eci,
+ float distance_threshold,
+ bool preserve_details,
+ LineartEdgeChainItem **r_next_eci)
+{
+ float dist_accum = 0;
+
+ int fixed_occ = last_matching_eci->occlusion;
+ unsigned char fixed_mask = last_matching_eci->material_mask_bits;
+
+ LineartEdgeChainItem *can_skip_to = NULL;
+ LineartEdgeChainItem *last_eci = last_matching_eci;
+ for (LineartEdgeChainItem *eci = last_matching_eci->next; eci; eci = eci->next) {
+ dist_accum += len_v2v2(last_eci->pos, eci->pos);
+ if (dist_accum > distance_threshold) {
+ break;
+ }
+ last_eci = eci;
+ /* The reason for this is because we don't want visible segments to be "skipped" into
+ * connecting with invisible segments. */
+ if (eci->occlusion < fixed_occ) {
+ break;
+ }
+ if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ) {
+ can_skip_to = eci;
+ }
+ }
+ if (can_skip_to) {
+ /* Either mark all in-between segments with the same occlusion and mask or delete those
+ * different ones. */
+ LineartEdgeChainItem *next_eci;
+ for (LineartEdgeChainItem *eci = last_matching_eci->next; eci != can_skip_to; eci = next_eci) {
+ next_eci = eci->next;
+ if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ) {
+ continue;
+ }
+ if (preserve_details) {
+ eci->material_mask_bits = fixed_mask;
+ eci->occlusion = fixed_occ;
+ }
+ else {
+ BLI_remlink(&ec->chain, eci);
+ }
+ }
+ *r_next_eci = can_skip_to;
+ return true;
+ }
+ return false;
+}
+
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
{
LineartEdgeChain *ec, *new_ec;
@@ -597,6 +648,13 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
if (lineart_point_overlapping(next_eci, eci->pos[0], eci->pos[1], 1e-5)) {
continue;
}
+ if (lineart_chain_fix_ambiguous_segments(ec,
+ eci->prev,
+ rb->chaining_image_threshold,
+ rb->chain_preserve_details,
+ &next_eci)) {
+ continue;
+ }
}
else {
/* Set the same occlusion level for the end vertex, so when further connection is needed
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 5461b80cad1..923646a133a 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -3158,6 +3158,8 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->force_crease = (lmd->calculation_flags & LRT_USE_CREASE_ON_SMOOTH_SURFACES) != 0;
rb->sharp_as_crease = (lmd->calculation_flags & LRT_USE_CREASE_ON_SHARP_EDGES) != 0;
+ rb->chain_preserve_details = (lmd->calculation_flags & LRT_CHAIN_PRESERVE_DETAILS) != 0;
+
int16_t edge_types = lmd->edge_types_override;
rb->use_contour = (edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
diff --git a/source/blender/makesdna/DNA_lineart_types.h b/source/blender/makesdna/DNA_lineart_types.h
index d4440592a00..7ef03422c7f 100644
--- a/source/blender/makesdna/DNA_lineart_types.h
+++ b/source/blender/makesdna/DNA_lineart_types.h
@@ -51,6 +51,7 @@ typedef enum eLineartMainFlags {
LRT_USE_CREASE_ON_SHARP_EDGES = (1 << 16),
LRT_USE_CUSTOM_CAMERA = (1 << 17),
LRT_USE_IMAGE_BOUNDARY_TRIMMING = (1 << 20),
+ LRT_CHAIN_PRESERVE_DETAILS = (1 << 22),
} eLineartMainFlags;
typedef enum eLineartEdgeFlag {
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 086da4c31ba..02987bb0eab 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -3231,6 +3231,12 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
prop, "Use Geometry Space", "Use geometry distance for chaining instead of image space");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "use_detail_preserve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_CHAIN_PRESERVE_DETAILS);
+ RNA_def_property_ui_text(
+ prop, "Preserve Details", "Keep the zig-zag \"noise\" in initial chaining");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "use_overlap_edge_type_support", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_ALLOW_OVERLAP_EDGE_TYPES);
RNA_def_property_ui_text(prop,