[Bf-blender-cvs] [6a9b09a5e93] temp-lineart-contained: LineArt: Better handling of boundary cases.
YimingWu
noreply at git.blender.org
Sun Nov 7 15:41:34 CET 2021
Commit: 6a9b09a5e93626a102c6c391d452aaddafc45f48
Author: YimingWu
Date: Sun Nov 7 22:37:37 2021 +0800
Branches: temp-lineart-contained
https://developer.blender.org/rB6a9b09a5e93626a102c6c391d452aaddafc45f48
LineArt: Better handling of boundary cases.
For lineart_LineIntersectTest2d, it fixes the output to 0 or 1 when it's
close enough, gives correct range for point_on_triangle identification.
Then it gives more information through aAligned, which will be true if
two lines completely align, this helps later identification.
Finally: it handles complex cases where one point is on the edge of
a triangle while another point is on the outside.
===================================================================
M source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
M source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
M source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
===================================================================
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index a5860698cba..f8ecb4bdff5 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -492,11 +492,18 @@ typedef struct LineartBoundingArea {
#define LRT_MIN3_INDEX_ABC(x, y, z) (x < y ? (x < z ? a : (y < z ? b : c)) : (y < z ? b : c))
#define LRT_ABC(index) (index == 0 ? a : (index == 1 ? b : c))
+#define LRT_PABC(index) (index == 0 ? pa : (index == 1 ? pb : pc))
#define LRT_DOUBLE_CLOSE_ENOUGH(a, b) (((a) + DBL_EDGE_LIM) >= (b) && ((a)-DBL_EDGE_LIM) <= (b))
-
-BLI_INLINE int lineart_LineIntersectTest2d(
- const double *a1, const double *a2, const double *b1, const double *b2, double *aRatio)
+#define LRT_DOUBLE_CLOSE_ENOUGH_TRI(a, b) \
+ (((a) + DBL_TRIANGLE_LIM) >= (b) && ((a)-DBL_TRIANGLE_LIM) <= (b))
+
+BLI_INLINE int lineart_LineIntersectTest2d(const double *a1,
+ const double *a2,
+ const double *b1,
+ const double *b2,
+ double *aRatio,
+ bool *aAligned)
{
/* Legacy intersection math aligns better with occlusion function quirks. */
/* #define USE_VECTOR_LINE_INTERSECTION */
@@ -555,9 +562,20 @@ BLI_INLINE int lineart_LineIntersectTest2d(
double x_diff = (a2[0] - a1[0]);
double x_diff2 = (b2[0] - b1[0]);
+ *aAligned = false;
+
if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff, 0)) {
if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
- *aRatio = 0;
+ if ((LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b1[1])) ||
+ (LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b2[1]))) {
+ *aAligned = true;
+ *aRatio = 1;
+ }
+ else if ((LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b1[1])) ||
+ (LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b2[1]))) {
+ *aAligned = true;
+ *aRatio = 0;
+ }
return 0;
}
double r2 = ratiod(b1[0], b2[0], a1[0]);
@@ -575,8 +593,21 @@ BLI_INLINE int lineart_LineIntersectTest2d(
k1 = (a2[1] - a1[1]) / x_diff;
k2 = (b2[1] - b1[1]) / x_diff2;
- if (k1 == k2)
+ if (LRT_DOUBLE_CLOSE_ENOUGH(k2, k1)) {
+ if ((LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b1[1])) ||
+ (LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b2[1]))) {
+ *aAligned = true;
+ *aRatio = 1;
+ }
+ else if ((LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b1[0]) &&
+ LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b1[1])) ||
+ (LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b2[0]) &&
+ LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b2[1]))) {
+ *aAligned = true;
+ *aRatio = 0;
+ }
return 0;
+ }
x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
@@ -596,6 +627,13 @@ BLI_INLINE int lineart_LineIntersectTest2d(
(b2[0] < b1[0] && x < b2[0]))
return 0;
+ if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(*aRatio, 1)) {
+ *aRatio = 1;
+ }
+ else if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(*aRatio, 0)) {
+ *aRatio = 0;
+ }
+
return 1;
#endif
}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 6c66fcaabd0..20a50717485 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -640,6 +640,8 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
}
}
}
+ /* Get rid of those very short "zig-zag" lines that jumps around visibility. */
+ MOD_lineart_chain_discard_short(rb, DBL_EDGE_LIM);
LISTBASE_FOREACH (LineartEdgeChain *, iec, &rb->chains) {
lineart_bounding_area_link_chain(rb, iec);
}
@@ -920,6 +922,9 @@ float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
float last_point[2];
eci = ec->chain.first;
+ if (!eci) {
+ return 0;
+ }
copy_v2_v2(last_point, eci->pos);
for (eci = ec->chain.first; eci; eci = eci->next) {
dist = len_v2v2(eci->pos, last_point);
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 31310b46b1c..b2a8881a98b 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -2426,7 +2426,7 @@ static bool lineart_edge_from_triangle(const LineartTriangle *tri,
{ \
index = (num < is[order[0]] ? \
order[0] : \
- (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : order[2]))); \
+ (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : -1))); \
}
/* `ia ib ic` are ordered. */
@@ -2434,7 +2434,7 @@ static bool lineart_edge_from_triangle(const LineartTriangle *tri,
{ \
index = (num > is[order[2]] ? \
order[2] : \
- (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : order[0]))); \
+ (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : -1))); \
}
/**
@@ -2459,7 +2459,8 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
double is[3] = {0};
int order[3];
int LCross = -1, RCross = -1;
- int a, b, c;
+ int a, b, c; /* Crossing info. */
+ bool pa, pb, pc; /* Parallel info. */
int st_l = 0, st_r = 0;
double Lv[3];
@@ -2489,9 +2490,9 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
}
/* Check if the line visually crosses one of the edge in the triangle. */
- a = lineart_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0]);
- b = lineart_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1]);
- c = lineart_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2]);
+ a = lineart_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0], &pa);
+ b = lineart_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1], &pb);
+ c = lineart_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2], &pc);
/* Sort the intersection distance. */
INTERSECT_SORT_MIN_TO_MAX_3(is[0], is[1], is[2], order);
@@ -2576,6 +2577,11 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
cut = ratiod(e->v1->fbcoord[1], e->v2->fbcoord[1], trans[1]);
}
+#define LRT_GUARD_NOT_FOUND \
+ if (LCross < 0 || RCross < 0) { \
+ return false; \
+ }
+
/* Determine the pair of edges that the line has crossed. */
if (st_l == 2) {
@@ -2603,12 +2609,18 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
}
else if (st_r == 0) {
INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, RCross);
- if (LRT_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) {
+ if (RCross >= 0 && LRT_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) {
INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross);
}
else {
- INTERSECT_JUST_SMALLER(is, order, -DBL_TRIANGLE_LIM, LCross);
- INTERSECT_JUST_GREATER(is, order, -DBL_TRIANGLE_LIM, RCross);
+ INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, RCross);
+ if (RCross > 0) {
+ INTERSECT_JUST_SMALLER(is, order, is[RCross], LCross);
+ }
+ }
+ LRT_GUARD_NOT_FOUND
+ if ((LRT_PABC(LCross) && !LRT_ABC(LCross)) || (LRT_PABC(RCross) && !LRT_ABC(RCross))) {
+ return false;
}
}
}
@@ -2619,17 +2631,23 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
}
else if (st_r == 1) {
INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross);
- if (LRT_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) {
+ if (LCross >= 0 && LRT_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) {
INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
}
else {
- INTERSECT_JUST_SMALLER(is, order, 1 + DBL_TRIANGLE_LIM, LCross);
- INTERSECT_JUST_GREATER(is, order, 1 + DBL_TRIANGLE_LIM, RCross);
+ INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, LCross);
+ if (LCross > 0) {
+ INTERSECT_JUST_GREATER(is, order, is[LCross], RCross);
+ }
+ }
+ LRT_GUARD_NOT_FOUND
+ if ((LRT_PABC(LCross) && !LRT_ABC(LCross)) || (LRT_PABC(RCross) && !LRT_ABC(RCross))) {
+ return false;
}
}
else if (st_r == 0) {
- INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, LCross);
- if (LRT_ABC(LCross) && is[LCross] > DBL_TRIANGLE_LIM) {
+ INTERSECT_JUST_GREATER(is, order, -DBL_TRIANGLE_LIM, LCross);
+ if (LCross >= 0 && LRT_ABC(LCross)) {
INTERSECT_JUST_GREATER(is, order, is[LCross], RCross);
}
else {
@@ -2639,6 +2657,8 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
}
}
+ LRT_GUARD_NOT_FOUND
+
double LF = dot_l * dot_f, RF = dot_r * dot_f;
/* Determine the start and end point of image space cut on a line. */
@@ -4082,25 +4102,26 @@ static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer
double data[2] = {e->v1->fbcoord[0], e->v1->fbcoord[1]};
double LU[2] = {-1, 1}, RU[2] = {1, 1}, LB[2] = {-1, -1}, RB[2] = {1, -1};
double r = 1, sr = 1;
+ bool p_unused;
if (data[0] > -1 && data[0] < 1 && data[1] > -1 && data[1] < 1) {
return lineart_get_bounding_area(rb, data[0], data[1]);
}
- if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LU, RU, &sr) && sr < r &&
- sr > 0) {
+ if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LU, RU, &sr, &p_unused) &&
+ sr < r && sr > 0) {
r = sr;
}
- if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LB, RB, &sr) && sr < r &&
- sr > 0) {
+ if (linea
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list