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:
authorYimingWu <xp8110@outlook.com>2021-10-26 19:10:25 +0300
committerYimingWu <xp8110@outlook.com>2021-10-26 19:10:49 +0300
commitec831ce5df86cbdbed8030d8a056f8a9b4eb0273 (patch)
tree8383daaf47fc9c59456f11b3e812109fe56d2cd5 /source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
parent3371a4c472eef06d1c9e15451b245cb4575d667f (diff)
LineArt: Trimming edges right at the image border
This option allows the edge to end right at the border instead of extending beyond. Useful when having multiple camera setup where you want the border to be clean. Also moved overscan option down inside "Composition" sub panel so it makes more sense. Reviewed By: Antonio Vazquez (antoniov) Differential Revision: https://developer.blender.org/D12126
Diffstat (limited to 'source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c')
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c127
1 files changed, 122 insertions, 5 deletions
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 8b7f53b8a36..85b801eece2 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,
@@ -952,6 +957,118 @@ 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;
+ }
+ else {
+ /* 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().