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>2021-06-25 08:15:25 +0300
committerYimingWu <xp8110@outlook.com>2021-06-25 08:15:25 +0300
commit841df831e89dfc4011c323203c2efb8265dc1878 (patch)
tree6e669d413cbd7de6510a5903102ad9a37e4cdc71 /source
parent3d7021b4ec23d79fef361364c35965d9af0f4e5b (diff)
LineArt: More type & related chaining improvements
This patch includes: Floating edge type support, Special chaining option for floating edge, Chaining option for reducing jagged edges when floating edges are involved. Reviewed By: Sebastian Parborg (zeddb) Differential Revision: https://developer.blender.org/D11306
Diffstat (limited to 'source')
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c19
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h13
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c7
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c170
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h6
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h7
-rw-r--r--source/blender/makesdna/DNA_lineart_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c31
8 files changed, 203 insertions, 59 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
index f0aae7e4498..1f70ecb4595 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c
@@ -305,6 +305,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayout *col = uiLayoutColumnWithHeading(layout, true, IFACE_("Edge Types"));
uiItemR(col, ptr, "use_contour", 0, IFACE_("Contour"), ICON_NONE);
+ uiItemR(col, ptr, "use_floating", 0, IFACE_("Floating"), ICON_NONE);
uiItemR(col, ptr, "use_material", 0, IFACE_("Material Borders"), ICON_NONE);
uiItemR(col, ptr, "use_edge_mark", 0, IFACE_("Edge Marks"), ICON_NONE);
uiItemR(col, ptr, "use_intersection", 0, IFACE_("Intersections"), ICON_NONE);
@@ -312,7 +313,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayout *sub = uiLayoutRowWithHeading(col, false, IFACE_("Crease"));
uiItemR(sub, ptr, "use_crease", 0, "", ICON_NONE);
uiLayout *entry = uiLayoutRow(sub, false);
- uiLayoutSetActive(entry, RNA_boolean_get(ptr, "use_crease") || is_first);
+ uiLayoutSetEnabled(entry, RNA_boolean_get(ptr, "use_crease") || is_first);
if (use_cache && !is_first) {
uiItemL(entry, IFACE_("Angle Cached"), ICON_INFO);
}
@@ -368,6 +369,7 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(col, ptr, "use_edge_overlap", 0, IFACE_("Overlapping Edges As Contour"), ICON_NONE);
uiItemR(col, ptr, "use_object_instances", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_clip_plane_boundaries", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "allow_overlap_edge_types", 0, NULL, ICON_NONE);
}
static void style_panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -430,7 +432,7 @@ static void transparency_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
- uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_transparency"));
+ uiLayoutSetEnabled(layout, RNA_boolean_get(ptr, "use_transparency"));
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetPropDecorate(row, false);
@@ -457,6 +459,7 @@ static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
const bool use_cache = RNA_boolean_get(ptr, "use_cache");
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
+ const bool is_geom = RNA_boolean_get(ptr, "chain_geometry_space");
uiLayoutSetPropSep(layout, true);
uiLayoutSetEnabled(layout, !is_baked);
@@ -469,8 +472,16 @@ static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayout *col = uiLayoutColumnWithHeading(layout, true, IFACE_("Chain"));
uiItemR(col, ptr, "use_fuzzy_intersections", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "use_fuzzy_all", 0, NULL, ICON_NONE);
-
- uiItemR(layout, ptr, "chaining_image_threshold", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "chain_floating_edges", 0, IFACE_("Floating Edges"), ICON_NONE);
+ uiItemR(col, ptr, "floating_as_contour", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "chain_geometry_space", 0, NULL, ICON_NONE);
+
+ uiItemR(layout,
+ ptr,
+ "chaining_image_threshold",
+ 0,
+ is_geom ? IFACE_("Geometry Threshold") : NULL,
+ ICON_NONE);
uiItemR(layout, ptr, "split_angle", UI_ITEM_R_SLIDER, 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 72b73b4d174..a7f4231e4aa 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -189,7 +189,7 @@ typedef struct LineartEdgeChainItem {
/** For restoring position to 3d space */
float gpos[3];
float normal[3];
- char line_type;
+ unsigned char line_type;
char occlusion;
unsigned char transparency_mask;
size_t index;
@@ -267,6 +267,7 @@ typedef struct LineartRenderBuffer {
ListBase crease;
ListBase material;
ListBase edge_mark;
+ ListBase floating;
ListBase chains;
@@ -287,11 +288,16 @@ typedef struct LineartRenderBuffer {
bool use_material;
bool use_edge_marks;
bool use_intersections;
+ bool use_floating;
bool fuzzy_intersections;
bool fuzzy_everything;
bool allow_boundaries;
bool allow_overlapping_edges;
+ bool allow_duplicated_types;
bool remove_doubles;
+ bool floating_as_contour;
+ bool chain_floating_edges;
+ bool chain_geometry_space;
/* Keep an copy of these data so when line art is running it's self-contained. */
bool cam_is_persp;
@@ -358,11 +364,10 @@ typedef struct LineartRenderTaskInfo {
ListBase crease;
ListBase material;
ListBase edge_mark;
+ ListBase floating;
} LineartRenderTaskInfo;
-struct BMesh;
-
typedef struct LineartObjectInfo {
struct LineartObjectInfo *next;
struct Object *original_ob;
@@ -370,7 +375,7 @@ typedef struct LineartObjectInfo {
double model_view_proj[4][4];
double model_view[4][4];
double normal[4][4];
- LineartElementLinkNode *v_reln;
+ LineartElementLinkNode *v_eln;
int usage;
int global_i_offset;
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 85a1dbb4df0..408e0081990 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -729,7 +729,8 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
}
}
- float new_len = len_v2v2(cre->eci->pos, eci->pos);
+ float new_len = rb->chain_geometry_space ? len_v3v3(cre->eci->gpos, eci->gpos) :
+ len_v2v2(cre->eci->pos, eci->pos);
if (new_len < dist) {
closest_cre = cre;
dist = new_len;
@@ -800,6 +801,10 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
}
BLI_addtail(&rb->chains, ec);
+ if (ec->type == LRT_EDGE_FLAG_FLOATING && (!rb->chain_floating_edges)) {
+ continue;
+ }
+
occlusion = ec->level;
transparency_mask = ec->transparency_mask;
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index dffa6fce395..f2d1f6776ab 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -430,6 +430,7 @@ static int lineart_occlusion_make_task_info(LineartRenderBuffer *rb, LineartRend
LRT_ASSIGN_OCCLUSION_TASK(crease);
LRT_ASSIGN_OCCLUSION_TASK(material);
LRT_ASSIGN_OCCLUSION_TASK(edge_mark);
+ LRT_ASSIGN_OCCLUSION_TASK(floating);
#undef LRT_ASSIGN_OCCLUSION_TASK
@@ -464,6 +465,10 @@ static void lineart_occlusion_worker(TaskPool *__restrict UNUSED(pool), LineartR
for (eip = rti->edge_mark.first; eip && eip != rti->edge_mark.last; eip = eip->next) {
lineart_occlusion_single_line(rb, eip, rti->thread_id);
}
+
+ for (eip = rti->floating.first; eip && eip != rti->floating.last; eip = eip->next) {
+ lineart_occlusion_single_line(rb, eip, rti->thread_id);
+ }
}
}
@@ -486,6 +491,7 @@ static void lineart_main_occlusion_begin(LineartRenderBuffer *rb)
rb->intersection.last = rb->intersection.first;
rb->material.last = rb->material.first;
rb->edge_mark.last = rb->edge_mark.first;
+ rb->floating.last = rb->floating.first;
TaskPool *tp = BLI_task_pool_create(NULL, TASK_PRIORITY_HIGH);
@@ -720,6 +726,7 @@ static void lineart_triangle_post(LineartTriangle *tri, LineartTriangle *orig)
/* Just re-assign normal and set cull flag. */
copy_v3_v3_db(tri->gn, orig->gn);
tri->flags = LRT_CULL_GENERATED;
+ tri->transparency_mask = orig->transparency_mask;
}
static void lineart_triangle_set_cull_flag(LineartTriangle *tri, uchar flag)
@@ -735,6 +742,16 @@ static bool lineart_edge_match(LineartTriangle *tri, LineartEdge *e, int v1, int
(tri->v[v2] == e->v1 && tri->v[v1] == e->v2));
}
+static void lineart_discard_duplicated_edges(LineartEdge *old_e, int v1id, int v2id)
+{
+ LineartEdge *e = old_e;
+ e++;
+ while (e->v1_obindex == v1id && e->v2_obindex == v2id) {
+ e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED;
+ e++;
+ }
+}
+
/**
* Does near-plane cut on 1 triangle only. When cutting with far-plane, the camera vectors gets
* reversed by the caller so don't need to implement one in a different direction.
@@ -800,6 +817,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
old_e = ta->e[e_num]; \
new_flag = old_e->flags; \
old_e->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
+ lineart_discard_duplicated_edges(old_e, old_e->v1_obindex, old_e->v2_obindex); \
INCREASE_EDGE \
e->v1 = (v1_link); \
e->v2 = (v2_link); \
@@ -820,12 +838,15 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
#define REMOVE_TRIANGLE_EDGE \
if (ta->e[0]) { \
ta->e[0]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
+ lineart_discard_duplicated_edges(ta->e[0], ta->e[0]->v1_obindex, ta->e[0]->v2_obindex); \
} \
if (ta->e[1]) { \
ta->e[1]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
+ lineart_discard_duplicated_edges(ta->e[1], ta->e[1]->v1_obindex, ta->e[1]->v2_obindex); \
} \
if (ta->e[2]) { \
ta->e[2]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
+ lineart_discard_duplicated_edges(ta->e[2], ta->e[2]->v1_obindex, ta->e[2]->v2_obindex); \
}
switch (in0 + in1 + in2) {
@@ -1432,8 +1453,25 @@ static char lineart_identify_feature_line(LineartRenderBuffer *rb,
lr = e->l->radial_next;
}
- if (ll == lr || !lr) {
- return LRT_EDGE_FLAG_CONTOUR;
+ if (!ll && !lr) {
+ if (!rb->floating_as_contour) {
+ return LRT_EDGE_FLAG_FLOATING;
+ }
+ }
+
+ uint16_t edge_flag_result = 0;
+
+ if (count_freestyle && rb->use_edge_marks) {
+ FreestyleEdge *fe;
+ fe = CustomData_bmesh_get(&bm_if_freestyle->edata, e->head.data, CD_FREESTYLE_EDGE);
+ if (fe->flag & FREESTYLE_EDGE_MARK) {
+ edge_flag_result |= LRT_EDGE_FLAG_EDGE_MARK;
+ }
+ }
+
+ /* Mesh boundary */
+ if (!lr || ll == lr) {
+ return (edge_flag_result | LRT_EDGE_FLAG_CONTOUR);
}
LineartTriangle *tri1, *tri2;
@@ -1449,7 +1487,6 @@ static char lineart_identify_feature_line(LineartRenderBuffer *rb,
double *view_vector = vv;
double dot_1 = 0, dot_2 = 0;
double result;
- FreestyleEdge *fe;
if (rb->cam_is_persp) {
sub_v3_v3v3_db(view_vector, l->gloc, rb->camera_pos);
@@ -1462,24 +1499,20 @@ static char lineart_identify_feature_line(LineartRenderBuffer *rb,
dot_2 = dot_v3v3_db(view_vector, tri2->gn);
if ((result = dot_1 * dot_2) <= 0 && (dot_1 + dot_2)) {
- return LRT_EDGE_FLAG_CONTOUR;
+ edge_flag_result |= LRT_EDGE_FLAG_CONTOUR;
}
if (rb->use_crease && (dot_v3v3_db(tri1->gn, tri2->gn) < crease_threshold)) {
if (!no_crease) {
- return LRT_EDGE_FLAG_CREASE;
+ edge_flag_result |= LRT_EDGE_FLAG_CREASE;
}
}
- else if (rb->use_material && (ll->f->mat_nr != lr->f->mat_nr)) {
- return LRT_EDGE_FLAG_MATERIAL;
- }
- else if (count_freestyle && rb->use_edge_marks) {
- fe = CustomData_bmesh_get(&bm_if_freestyle->edata, e->head.data, CD_FREESTYLE_EDGE);
- if (fe->flag & FREESTYLE_EDGE_MARK) {
- return LRT_EDGE_FLAG_EDGE_MARK;
- }
+
+ if (rb->use_material && (ll->f->mat_nr != lr->f->mat_nr)) {
+ edge_flag_result |= LRT_EDGE_FLAG_MATERIAL;
}
- return 0;
+
+ return edge_flag_result;
}
static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e)
@@ -1527,6 +1560,9 @@ static void lineart_add_edge_to_list_thread(LineartObjectInfo *obi, LineartEdge
case LRT_EDGE_FLAG_INTERSECTION:
LRT_ASSIGN_EDGE(intersection);
break;
+ case LRT_EDGE_FLAG_FLOATING:
+ LRT_ASSIGN_EDGE(floating);
+ break;
}
#undef LRT_ASSIGN_EDGE
}
@@ -1543,6 +1579,7 @@ static void lineart_finalize_object_edge_list(LineartRenderBuffer *rb, LineartOb
LRT_OBI_TO_RB(material);
LRT_OBI_TO_RB(edge_mark);
LRT_OBI_TO_RB(intersection);
+ LRT_OBI_TO_RB(floating);
#undef LRT_OBI_TO_RB
}
@@ -1561,6 +1598,17 @@ static void lineart_triangle_adjacent_assign(LineartTriangle *tri,
}
}
+static int lineart_edge_type_duplication_count(char eflag)
+{
+ int count = 0;
+ /* See eLineartEdgeFlag for details. */
+ for (int i = 0; i < LRT_EDGE_FLAG_FLOATING; i++) {
+ if (eflag & (1 << i)) {
+ count++;
+ }
+ }
+ return count;
+}
static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBuffer *rb)
{
BMesh *bm;
@@ -1639,8 +1687,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
CanFindFreestyle = 1;
}
- /* Only allocate memory for verts and tris as we don't know how many lines we will generate
- * yet. */
+ /* If we allow duplicated edges, one edge should get added multiple times if is has been
+ * classified as more than one edge type. This is so we can create multiple different line type
+ * chains containing the same edge. */
orv = lineart_mem_acquire_thread(&rb->render_data_pool, sizeof(LineartVert) * bm->totvert);
ort = lineart_mem_acquire_thread(&rb->render_data_pool, bm->totface * rb->triangle_size);
@@ -1653,7 +1702,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
eln->element_count = bm->totvert;
eln->object_ref = orig_ob;
- obi->v_reln = eln;
+ obi->v_eln = eln;
if (orig_ob->lineart.flags & OBJECT_LRT_OWN_CREASE) {
use_crease = cosf(M_PI - orig_ob->lineart.crease_threshold);
@@ -1741,8 +1790,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
char eflag = lineart_identify_feature_line(
rb, e, ort, orv, use_crease, orig_ob->type == OB_FONT, CanFindFreestyle, bm);
if (eflag) {
- /* Only allocate for feature lines (instead of all lines) to save memory. */
- allocate_la_e++;
+ /* Only allocate for feature lines (instead of all lines) to save memory.
+ * If allow duplicated edges, one edge gets added multiple times if it has multiple types. */
+ allocate_la_e += rb->allow_duplicated_types ? lineart_edge_type_duplication_count(eflag) : 1;
}
/* Here we just use bm's flag for when loading actual lines, then we don't need to call
* lineart_identify_feature_line() again, e->head.hflag deleted after loading anyway. Always
@@ -1770,30 +1820,50 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
continue;
}
- la_e->v1 = &orv[BM_elem_index_get(e->v1)];
- la_e->v2 = &orv[BM_elem_index_get(e->v2)];
- la_e->v1_obindex = la_e->v1->index;
- la_e->v2_obindex = la_e->v2->index;
- if (e->l) {
- int findex = BM_elem_index_get(e->l->f);
- la_e->t1 = lineart_triangle_from_index(rb, ort, findex);
- lineart_triangle_adjacent_assign(la_e->t1, &orta[findex], la_e);
- if (e->l->radial_next && e->l->radial_next != e->l) {
- findex = BM_elem_index_get(e->l->radial_next->f);
- la_e->t2 = lineart_triangle_from_index(rb, ort, findex);
- lineart_triangle_adjacent_assign(la_e->t2, &orta[findex], la_e);
+ bool edge_added = false;
+
+ /* See eLineartEdgeFlag for details. */
+ for (int flag_bit = 0; flag_bit < LRT_EDGE_FLAG_FLOATING; flag_bit++) {
+ char use_type = 1 << flag_bit;
+ if (!(use_type & e->head.hflag)) {
+ continue;
}
- }
- la_e->flags = e->head.hflag;
- la_e->object_ref = orig_ob;
- BLI_addtail(&la_e->segments, la_s);
- if (usage == OBJECT_LRT_INHERIT || usage == OBJECT_LRT_INCLUDE ||
- usage == OBJECT_LRT_NO_INTERSECTION) {
- lineart_add_edge_to_list_thread(obi, la_e);
- }
- la_e++;
- la_s++;
+ la_e->v1 = &orv[BM_elem_index_get(e->v1)];
+ la_e->v2 = &orv[BM_elem_index_get(e->v2)];
+ la_e->v1_obindex = la_e->v1->index;
+ la_e->v2_obindex = la_e->v2->index;
+ if (e->l) {
+ int findex = BM_elem_index_get(e->l->f);
+ la_e->t1 = lineart_triangle_from_index(rb, ort, findex);
+ if (!edge_added) {
+ lineart_triangle_adjacent_assign(la_e->t1, &orta[findex], la_e);
+ }
+ if (e->l->radial_next && e->l->radial_next != e->l) {
+ findex = BM_elem_index_get(e->l->radial_next->f);
+ la_e->t2 = lineart_triangle_from_index(rb, ort, findex);
+ if (!edge_added) {
+ lineart_triangle_adjacent_assign(la_e->t2, &orta[findex], la_e);
+ }
+ }
+ }
+ la_e->flags = use_type;
+ la_e->object_ref = orig_ob;
+ BLI_addtail(&la_e->segments, la_s);
+ if (usage == OBJECT_LRT_INHERIT || usage == OBJECT_LRT_INCLUDE ||
+ usage == OBJECT_LRT_NO_INTERSECTION) {
+ lineart_add_edge_to_list_thread(obi, la_e);
+ }
+
+ edge_added = true;
+
+ la_e++;
+ la_s++;
+
+ if (!rb->allow_duplicated_types) {
+ break;
+ }
+ }
}
/* always free bm as it's a copy from before threading */
@@ -1803,9 +1873,8 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
static void lineart_object_load_worker(TaskPool *__restrict UNUSED(pool),
LineartObjectLoadTaskInfo *olti)
{
- LineartRenderBuffer *rb = olti->rb;
for (LineartObjectInfo *obi = olti->pending; obi; obi = obi->next) {
- lineart_geometry_object_load(obi, rb);
+ lineart_geometry_object_load(obi, olti->rb);
}
}
@@ -1948,7 +2017,6 @@ static void lineart_main_load_geometries(
{
double proj[4][4], view[4][4], result[4][4];
float inv[4][4];
-
Camera *cam = camera->data;
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
int fit = BKE_camera_sensor_fit(cam->sensor_fit, rb->w, rb->h);
@@ -2071,11 +2139,11 @@ static void lineart_main_load_geometries(
for (int i = 0; i < thread_count; i++) {
for (LineartObjectInfo *obi = olti[i].pending; obi; obi = obi->next) {
- if (!obi->v_reln) {
+ if (!obi->v_eln) {
continue;
}
- LineartVert *v = (LineartVert *)obi->v_reln->pointer;
- int v_count = obi->v_reln->element_count;
+ LineartVert *v = (LineartVert *)obi->v_eln->pointer;
+ int v_count = obi->v_eln->element_count;
for (int vi = 0; vi < v_count; vi++) {
v[vi].index += global_i;
}
@@ -2823,6 +2891,7 @@ static void lineart_destroy_render_data(LineartRenderBuffer *rb)
memset(&rb->intersection, 0, sizeof(ListBase));
memset(&rb->edge_mark, 0, sizeof(ListBase));
memset(&rb->material, 0, sizeof(ListBase));
+ memset(&rb->floating, 0, sizeof(ListBase));
BLI_listbase_clear(&rb->chains);
BLI_listbase_clear(&rb->wasted_cuts);
@@ -2919,10 +2988,15 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->fuzzy_everything = (lmd->calculation_flags & LRT_EVERYTHING_AS_CONTOUR) != 0;
rb->allow_boundaries = (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) != 0;
rb->remove_doubles = (lmd->calculation_flags & LRT_REMOVE_DOUBLES) != 0;
+ rb->floating_as_contour = (lmd->calculation_flags & LRT_FLOATING_AS_CONTOUR) != 0;
+ rb->chain_floating_edges = (lmd->calculation_flags & LRT_CHAIN_FLOATING_EDGES) != 0;
+ rb->chain_geometry_space = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 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;
+ rb->allow_duplicated_types = (lmd->calculation_flags & LRT_ALLOW_OVERLAP_EDGE_TYPES) != 0;
+
int16_t edge_types = lmd->edge_types_override;
rb->use_contour = (edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
@@ -2930,6 +3004,7 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
rb->use_material = (edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
rb->use_edge_marks = (edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0;
rb->use_intersections = (edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0;
+ rb->use_floating = (edge_types & LRT_EDGE_FLAG_FLOATING) != 0;
rb->chain_data_pool = &lc->chain_data_pool;
@@ -4043,6 +4118,7 @@ static int UNUSED_FUNCTION(lineart_rb_edge_types)(LineartRenderBuffer *rb)
types |= rb->use_material ? LRT_EDGE_FLAG_MATERIAL : 0;
types |= rb->use_edge_marks ? LRT_EDGE_FLAG_EDGE_MARK : 0;
types |= rb->use_intersections ? LRT_EDGE_FLAG_INTERSECTION : 0;
+ types |= rb->use_floating ? LRT_EDGE_FLAG_FLOATING : 0;
return types;
}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h
index e457d4a83a0..9d109320f09 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h
@@ -98,6 +98,9 @@ void lineart_count_and_print_render_buffer_memory(struct LineartRenderBuffer *rb
if (!e) { \
e = rb->intersection.first; \
} \
+ if (!e) { \
+ e = rb->floating.first; \
+ } \
for (current_head = &rb->contour.first; e; e = next_e) { \
next_e = e->next;
@@ -115,6 +118,9 @@ void lineart_count_and_print_render_buffer_memory(struct LineartRenderBuffer *rb
else if (current_head == &rb->edge_mark.first) { \
current_head = &rb->intersection.first; \
} \
+ else if (current_head == &rb->intersection.first) { \
+ current_head = &rb->floating.first; \
+ } \
else { \
break; \
} \
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 3977ad326da..c0768c9a077 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -874,8 +874,9 @@ typedef enum eLineartGpencilModifierSource {
} eLineartGpencilModifierSource;
typedef enum eLineArtGPencilModifierFlags {
- LRT_GPENCIL_INVERT_SOURCE_VGROUP = (1 << 0),
- LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 1),
+ /* These two moved to eLineartMainFlags to keep consistent with flag variable purpose. */
+ /* LRT_GPENCIL_INVERT_SOURCE_VGROUP = (1 << 0), */
+ /* LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 1), */
LRT_GPENCIL_BINARY_WEIGHTS = (1 << 2) /* Deprecated, this is removed for lack of use case. */,
LRT_GPENCIL_IS_BAKED = (1 << 3),
LRT_GPENCIL_USE_CACHE = (1 << 4),
@@ -925,7 +926,7 @@ typedef struct LineartGpencilModifierData {
/** `0..PI` angle, for splitting strokes at sharp points. */
float angle_splitting_threshold;
- /* CPU mode */
+ /* Doubles as geometry threshold when geometry space chaining is enabled */
float chaining_image_threshold;
/* Ported from SceneLineArt flags. */
diff --git a/source/blender/makesdna/DNA_lineart_types.h b/source/blender/makesdna/DNA_lineart_types.h
index 860a6579bf7..bbb3bd29197 100644
--- a/source/blender/makesdna/DNA_lineart_types.h
+++ b/source/blender/makesdna/DNA_lineart_types.h
@@ -46,6 +46,15 @@ typedef enum eLineartMainFlags {
LRT_ALLOW_OVERLAPPING_EDGES = (1 << 3),
LRT_ALLOW_CLIPPING_BOUNDARIES = (1 << 4),
LRT_REMOVE_DOUBLES = (1 << 5),
+ LRT_FLOATING_AS_CONTOUR = (1 << 6),
+ LRT_GPENCIL_INVERT_SOURCE_VGROUP = (1 << 7),
+ LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 8),
+ LRT_FILTER_FACE_MARK = (1 << 9),
+ LRT_FILTER_FACE_MARK_INVERT = (1 << 10),
+ LRT_FILTER_FACE_MARK_BOUNDARIES = (1 << 11),
+ LRT_CHAIN_FLOATING_EDGES = (1 << 11),
+ LRT_CHAIN_GEOMETRY_SPACE = (1 << 12),
+ LRT_ALLOW_OVERLAP_EDGE_TYPES = (1 << 13),
} 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 5d83286d3ec..4c890895446 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -2812,6 +2812,12 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
prop, "Remove Doubles", "Remove doubles from the source geometry before generating stokes");
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "floating_as_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_FLOATING_AS_CONTOUR);
+ RNA_def_property_ui_text(
+ prop, "Floating As Contour", "Floating edges will be classified as contour lines");
+ RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "chaining_image_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_ui_text(
prop,
@@ -2821,6 +2827,26 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 0.3f);
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "chain_floating_edges", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_CHAIN_FLOATING_EDGES);
+ RNA_def_property_ui_text(
+ prop, "Chain Floating Edges", "Allow floating edges to be chained together");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "chain_geometry_space", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_CHAIN_GEOMETRY_SPACE);
+ RNA_def_property_ui_text(
+ 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, "allow_overlap_edge_types", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_ALLOW_OVERLAP_EDGE_TYPES);
+ RNA_def_property_ui_text(prop,
+ "Overlapping Edge Types",
+ "Allow an edge to have multiple overlapping types. This will create an "
+ "individual stroke for each overlapping type");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "source_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, modifier_lineart_source_type);
RNA_def_property_ui_text(prop, "Source Type", "Line art stroke source type");
@@ -2846,6 +2872,11 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Contour", "Generate strokes from contours lines");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "use_floating", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", LRT_EDGE_FLAG_FLOATING);
+ RNA_def_property_ui_text(prop, "Use Floating", "Generate strokes from floating edges");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "use_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", LRT_EDGE_FLAG_CREASE);
RNA_def_property_ui_text(prop, "Use Crease", "Generate strokes from creased edges");