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/lineart/MOD_lineart.h')
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h561
1 files changed, 383 insertions, 178 deletions
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index ad3e1b5d7f2..5dd833fb12b 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -36,10 +36,16 @@ typedef struct LineartTriangle {
/* first culled in line list to use adjacent triangle info, then go through triangle list. */
double gn[3];
- unsigned char material_mask_bits;
- unsigned char intersection_mask;
- unsigned char mat_occlusion;
- unsigned char flags; /* #eLineartTriangleFlags */
+ uint8_t material_mask_bits;
+ uint8_t intersection_mask;
+ uint8_t mat_occlusion;
+ uint8_t flags; /* #eLineartTriangleFlags */
+
+ /* target_reference = (obi->obindex | triangle_index) */
+ /* higher 12 bits-------^ ^-----index in object, lower 20 bits */
+ uint32_t target_reference;
+
+ uint8_t intersection_priority;
/**
* Only use single link list, because we don't need to go back in order.
@@ -66,6 +72,7 @@ typedef enum eLineArtElementNodeFlag {
LRT_ELEMENT_IS_ADDITIONAL = (1 << 0),
LRT_ELEMENT_BORDER_ONLY = (1 << 1),
LRT_ELEMENT_NO_INTERSECTION = (1 << 2),
+ LRT_ELEMENT_INTERSECTION_DATA = (1 << 3),
} eLineArtElementNodeFlag;
typedef struct LineartElementLinkNode {
@@ -75,61 +82,99 @@ typedef struct LineartElementLinkNode {
void *object_ref;
eLineArtElementNodeFlag flags;
+ /* For edge element link nodes, used for shadow edge matching. */
+ int obindex;
+
/** Per object value, always set, if not enabled by #ObjectLineArt, then it's set to global. */
float crease_threshold;
} LineartElementLinkNode;
typedef struct LineartEdgeSegment {
struct LineartEdgeSegment *next, *prev;
- /** at==0: left at==1: right (this is in 2D projected space) */
- double at;
- /** Occlusion level after "at" point */
- unsigned char occlusion;
+ /** The point after which a property of the segment is changed, e.g. occlusion/material mask etc.
+ * ratio==0: v1 ratio==1: v2 (this is in 2D projected space), */
+ double ratio;
+ /** Occlusion level after "ratio" point */
+ uint8_t occlusion;
/* Used to filter line art occlusion edges */
- unsigned char material_mask_bits;
+ uint8_t material_mask_bits;
+
+ /* Lit/shaded flag for shadow is stored here.
+ * TODO(Yiming): Transfer material masks from shadow results
+ * onto here so then we can even filter transparent shadows. */
+ uint32_t shadow_mask_bits;
} LineartEdgeSegment;
+typedef struct LineartShadowEdge {
+ struct LineartShadowEdge *next, *prev;
+ /* Two end points in frame-buffer coordinates viewed from the light source. */
+ double fbc1[4], fbc2[4];
+ double g1[3], g2[3];
+ bool orig1, orig2;
+ struct LineartEdge *e_ref;
+ struct LineartEdge *e_ref_light_contour;
+ struct LineartEdgeSegment *es_ref; /* Only for 3rd stage casting. */
+ ListBase shadow_segments;
+} LineartShadowEdge;
+
+enum eLineartShadowSegmentFlag {
+ LRT_SHADOW_CASTED = 1,
+ LRT_SHADOW_FACING_LIGHT = 2,
+};
+
+/* Represents a cutting point on a #LineartShadowEdge */
+typedef struct LineartShadowSegment {
+ struct LineartShadowSegment *next, *prev;
+ /* eLineartShadowSegmentFlag */
+ int flag;
+ /* The point after which a property of the segment is changed. e.g. shadow mask/target_ref etc.
+ * Coordinates in NDC during shadow calculation but transformed to global linear before cutting
+ * onto edges during the loading stage of the "actual" rendering. */
+ double ratio;
+ /* Left and right pos, because when casting shadows at some point there will be
+ * non-continuous cuts, see #lineart_shadow_edge_cut for detailed explanation. */
+ double fbc1[4], fbc2[4];
+ /* Global position. */
+ double g1[4], g2[4];
+ uint32_t target_reference;
+ uint32_t shadow_mask_bits;
+} LineartShadowSegment;
+
typedef struct LineartVert {
double gloc[3];
double fbcoord[4];
/* Scene global index. */
int index;
-
- /**
- * Intersection data flag is here, when LRT_VERT_HAS_INTERSECTION_DATA is set,
- * size of the struct is extended to include intersection data.
- * See #eLineArtVertFlags.
- */
- char flag;
-
} LineartVert;
-typedef struct LineartVertIntersection {
- struct LineartVert base;
- /** Use vert index because we only use this to check vertex equal. This way we save 8 Bytes. */
- int isec1, isec2;
- struct LineartTriangle *intersecting_with;
-} LineartVertIntersection;
-
-typedef enum eLineArtVertFlags {
- LRT_VERT_HAS_INTERSECTION_DATA = (1 << 0),
- LRT_VERT_EDGE_USED = (1 << 1),
-} eLineArtVertFlags;
-
typedef struct LineartEdge {
- /** We only need link node kind of list here. */
- struct LineartEdge *next;
struct LineartVert *v1, *v2;
+ /** These two variables are also used to specify original edge and segment during 3rd stage
+ * reprojection, So we can easily find out the line which results come from. */
struct LineartTriangle *t1, *t2;
+
ListBase segments;
- char min_occ;
+ int8_t min_occ;
/** Also for line type determination on chaining. */
uint16_t flags;
- unsigned char intersection_mask;
+ uint8_t intersection_mask;
+
+ /** Matches the shadow result, used to determine whether a line is in the shadow or not.
+ * #edge_identifier usages:
+ * - Intersection lines:
+ * ((e->t1->target_reference << 32) | e->t2->target_reference);
+ * - Other lines: LRT_EDGE_IDENTIFIER(obi, e);
+ * - After shadow calculation: (search the shadow result and set reference to that);
+ */
+ uint64_t edge_identifier;
+
+ /** - Light contour: original_e->t1->target_reference | original_e->t2->target_reference.
+ * - Cast shadow: triangle_projected_onto->target_reference. */
+ uint64_t target_reference;
/**
* Still need this entry because culled lines will not add to object
@@ -149,17 +194,19 @@ typedef struct LineartEdgeChain {
float length;
/** Used when re-connecting and grease-pencil stroke generation. */
- char picked;
- char level;
+ uint8_t picked;
+ uint8_t level;
/** Chain now only contains one type of segments */
int type;
/** Will only connect chains that has the same loop id. */
int loop_id;
- unsigned char material_mask_bits;
- unsigned char intersection_mask;
+ uint8_t material_mask_bits;
+ uint8_t intersection_mask;
+ uint32_t shadow_mask_bits;
struct Object *object_ref;
+ struct Object *silhouette_backdrop;
} LineartEdgeChain;
typedef struct LineartEdgeChainItem {
@@ -170,9 +217,10 @@ typedef struct LineartEdgeChainItem {
float gpos[3];
float normal[3];
uint16_t line_type;
- char occlusion;
- unsigned char material_mask_bits;
- unsigned char intersection_mask;
+ uint8_t occlusion;
+ uint8_t material_mask_bits;
+ uint8_t intersection_mask;
+ uint32_t shadow_mask_bits;
size_t index;
} LineartEdgeChainItem;
@@ -180,17 +228,17 @@ typedef struct LineartChainRegisterEntry {
struct LineartChainRegisterEntry *next, *prev;
LineartEdgeChain *ec;
LineartEdgeChainItem *eci;
- char picked;
+ int8_t picked;
/* left/right mark.
* Because we revert list in chaining so we need the flag. */
- char is_left;
+ int8_t is_left;
} LineartChainRegisterEntry;
typedef struct LineartAdjacentEdge {
- unsigned int v1;
- unsigned int v2;
- unsigned int e;
+ uint32_t v1;
+ uint32_t v2;
+ uint32_t e;
} LineartAdjacentEdge;
enum eLineArtTileRecursiveLimit {
@@ -204,135 +252,175 @@ enum eLineArtTileRecursiveLimit {
#define LRT_TILE_SPLITTING_TRIANGLE_LIMIT 100
#define LRT_TILE_EDGE_COUNT_INITIAL 32
+enum eLineartShadowCameraType {
+ LRT_SHADOW_CAMERA_DIRECTIONAL = 1,
+ LRT_SHADOW_CAMERA_POINT = 2,
+};
+
typedef struct LineartPendingEdges {
LineartEdge **array;
int max;
int next;
} LineartPendingEdges;
-typedef struct LineartRenderBuffer {
- struct LineartRenderBuffer *prev, *next;
+typedef struct LineartData {
+ int w, h;
int thread_count;
+ int sizeof_triangle;
- int w, h;
- int tile_size_w, tile_size_h;
- int tile_count_x, tile_count_y;
- double width_per_tile, height_per_tile;
- double view_projection[4][4];
- double view[4][4];
+ LineartStaticMemPool render_data_pool;
+ /* A pointer to LineartCache::chain_data_pool, which acts as a cache for edge chains. */
+ LineartStaticMemPool *chain_data_pool;
+ /* Reference to LineartCache::shadow_data_pool, stay available until the final round of line art
+ * calculation is finished. */
+ LineartStaticMemPool *shadow_data_pool;
- float overscan;
+ /* Storing shadow edge eln, array, and cuts for shadow information, so it's available when line
+ * art runs the second time for occlusion. Either a reference to LineartCache::shadow_data_pool
+ * (shadow stage) or a reference to LineartData::render_data_pool (final stage). */
+ LineartStaticMemPool *edge_data_pool;
- struct LineartBoundingArea *initial_bounding_areas;
- unsigned int bounding_area_count;
+ struct _qtree {
- /* When splitting bounding areas, if there's an ortho camera placed at a straight angle, there
- * will be a lot of triangles aligned in line which can not be separated by continue subdividing
- * the tile. So we set a strict limit when using ortho camera. See eLineArtTileRecursiveLimit. */
- int tile_recursive_level;
+ int count_x, count_y;
+ double tile_width, tile_height;
- ListBase vertex_buffer_pointers;
- ListBase line_buffer_pointers;
- ListBase triangle_buffer_pointers;
+ /* When splitting bounding areas, if there's an ortho camera placed at a straight angle, there
+ * will be a lot of triangles aligned in line which can not be separated by continue
+ * subdividing the tile. So we set a strict limit when using ortho camera. See
+ * eLineArtTileRecursiveLimit. */
+ int recursive_level;
- /** This one's memory is not from main pool and is free()ed after culling stage. */
- ListBase triangle_adjacent_pointers;
+ struct LineartBoundingArea *initials;
- ListBase intersecting_vertex_buffer;
- /** Use the one comes with Line Art. */
- LineartStaticMemPool render_data_pool;
- ListBase wasted_cuts;
- SpinLock lock_cuts;
+ uint32_t initial_tile_count;
- /* This is just a pointer to LineartCache::chain_data_pool, which acts as a cache for line
- * chains. */
- LineartStaticMemPool *chain_data_pool;
+ } qtree;
+
+ struct _geom {
+
+ ListBase vertex_buffer_pointers;
+ ListBase line_buffer_pointers;
+ ListBase triangle_buffer_pointers;
+
+ /** This one's memory is not from main pool and is free()ed after culling stage. */
+ ListBase triangle_adjacent_pointers;
+
+ ListBase intersecting_vertex_buffer;
+
+ } geom;
- /* Render status */
- double view_vector[3];
+ struct _conf {
- int triangle_size;
+ double view_projection[4][4];
+ double view[4][4];
- /* Note: Data inside #pending_edges are allocated with MEM_xxx call instead of in pool. */
+ float overscan;
+
+ int max_occlusion_level;
+ double crease_angle;
+ double crease_cos;
+
+ int draw_material_preview;
+ double material_transparency;
+
+ bool use_contour;
+ bool use_crease;
+ bool use_material;
+ bool use_edge_marks;
+ bool use_intersections;
+ bool use_loose;
+ bool use_light_contour;
+ bool use_shadow;
+ bool use_contour_secondary; /* From viewing camera, during shadow calculation. */
+
+ int shadow_selection; /* Needs to be numeric because it's not just on/off. */
+ bool shadow_enclose_shapes;
+ bool shadow_use_silhouette;
+
+ bool fuzzy_intersections;
+ bool fuzzy_everything;
+ bool allow_boundaries;
+ bool allow_overlapping_edges;
+ bool allow_duplicated_types;
+ bool remove_doubles;
+ bool use_loose_as_contour;
+ bool use_loose_edge_chain;
+ bool use_geometry_space_chain;
+ bool use_image_boundary_trimming;
+ bool use_back_face_culling;
+
+ bool filter_face_mark;
+ bool filter_face_mark_invert;
+ bool filter_face_mark_boundaries;
+ bool filter_face_mark_keep_contour;
+
+ bool force_crease;
+ bool sharp_as_crease;
+
+ bool chain_preserve_details;
+
+ bool do_shadow_cast;
+ bool light_reference_available;
+
+ /* Keep an copy of these data so when line art is running it's self-contained. */
+ bool cam_is_persp;
+ bool cam_is_persp_secondary; /* "Secondary" ones are from viewing camera (as opposed to shadow
+ camera), during shadow calculation. */
+ float cam_obmat[4][4];
+ float cam_obmat_secondary[4][4];
+ double camera_pos[3];
+ double camera_pos_secondary[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;
+ float chaining_image_threshold;
+ float angle_splitting_threshold;
+
+ float chain_smooth_tolerance;
+
+ double view_vector[3];
+ double view_vector_secondary[3]; /* For shadow. */
+ } conf;
+
+ LineartElementLinkNode *isect_scheduled_up_to;
+ int isect_scheduled_up_to_index;
+
+ /* NOTE: Data inside #pending_edges are allocated with MEM_xxx call instead of in pool. */
struct LineartPendingEdges pending_edges;
int scheduled_count;
+ /* Intermediate shadow results, list of LineartShadowEdge */
+ LineartShadowEdge *shadow_edges;
+ int shadow_edges_count;
+
ListBase chains;
- /* For managing calculation tasks for multiple threads. */
+ ListBase wasted_cuts;
+ ListBase wasted_shadow_cuts;
+ SpinLock lock_cuts;
SpinLock lock_task;
- /* settings */
-
- int max_occlusion_level;
- double crease_angle;
- double crease_cos;
-
- int draw_material_preview;
- double material_transparency;
-
- bool use_contour;
- bool use_crease;
- bool use_material;
- bool use_edge_marks;
- bool use_intersections;
- bool use_loose;
- bool fuzzy_intersections;
- bool fuzzy_everything;
- bool allow_boundaries;
- bool allow_overlapping_edges;
- bool allow_duplicated_types;
- bool remove_doubles;
- bool use_loose_as_contour;
- bool use_loose_edge_chain;
- bool use_geometry_space_chain;
- bool use_image_boundary_trimming;
- bool use_back_face_culling;
-
- bool filter_face_mark;
- bool filter_face_mark_invert;
- bool filter_face_mark_boundaries;
- bool filter_face_mark_keep_contour;
-
- 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];
- 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;
- float chaining_image_threshold;
- float angle_splitting_threshold;
-
- float chain_smooth_tolerance;
-
- /* FIXME(Yiming): Temporary solution for speeding up calculation by not including lines that
- * are not in the selected source. This will not be needed after we have a proper scene-wise
- * cache running because multiple modifiers can then select results from that without further
- * calculation. */
- int _source_type;
- struct Collection *_source_collection;
- struct Object *_source_object;
-
-} LineartRenderBuffer;
+} LineartData;
typedef struct LineartCache {
- /** Separate memory pool for chain data, this goes to the cache, so when we free the main pool,
- * chains will still be available. */
+ /** Separate memory pool for chain data and shadow, this goes to the cache, so when we free the
+ * main pool, chains and shadows will still be available. */
LineartStaticMemPool chain_data_pool;
+ LineartStaticMemPool shadow_data_pool;
- /** A copy of rb->chains so we have that data available after rb has been destroyed. */
+ /** A copy of ld->chains so we have that data available after ld has been destroyed. */
ListBase chains;
+ /** Shadow-computed feature lines from original meshes to be matched with the second load of
+ * meshes thus providing lit/shade info in the second run of line art. */
+ ListBase shadow_elns;
+
/** Cache only contains edge types specified in this variable. */
- char rb_edge_types;
+ uint16_t all_enabled_edge_types;
} LineartCache;
#define DBL_TRIANGLE_LIM 1e-8
@@ -350,6 +438,14 @@ typedef enum eLineartTriangleFlags {
LRT_TRIANGLE_MAT_BACK_FACE_CULLING = (1 << 5),
} eLineartTriangleFlags;
+#define LRT_SHADOW_MASK_UNDEFINED 0
+#define LRT_SHADOW_MASK_LIT (1 << 0)
+#define LRT_SHADOW_MASK_SHADED (1 << 1)
+#define LRT_SHADOW_MASK_ENCLOSED_SHAPE (1 << 2)
+#define LRT_SHADOW_MASK_INHIBITED (1 << 3)
+#define LRT_SHADOW_SILHOUETTE_ERASED_GROUP (1 << 4)
+#define LRT_SHADOW_SILHOUETTE_ERASED_OBJECT (1 << 5)
+
/**
* Controls how many edges a worker thread is processing at one request.
* There's no significant performance impact on choosing different values.
@@ -358,18 +454,26 @@ typedef enum eLineartTriangleFlags {
#define LRT_THREAD_EDGE_COUNT 1000
typedef struct LineartRenderTaskInfo {
- struct LineartRenderBuffer *rb;
+ struct LineartData *ld;
int thread_id;
/**
* #pending_edges here only stores a reference to a portion in
- * LineartRenderbuffer::pending_edges, assigned by the occlusion scheduler.
+ * LineartData::pending_edges, assigned by the occlusion scheduler.
*/
struct LineartPendingEdges pending_edges;
} LineartRenderTaskInfo;
+#define LRT_OBINDEX_SHIFT 20
+#define LRT_OBINDEX_LOWER 0x0FFFFF /* Lower 20 bits. */
+#define LRT_OBINDEX_HIGHER 0xFFF00000 /* Higher 12 bits. */
+#define LRT_EDGE_IDENTIFIER(obi, e) \
+ (((uint64_t)(obi->obindex | (e->v1->index & LRT_OBINDEX_LOWER)) << 32) | \
+ (obi->obindex | (e->v2->index & LRT_OBINDEX_LOWER)))
+#define LRT_LIGHT_CONTOUR_TARGET 0xFFFFFFFF
+
typedef struct LineartObjectInfo {
struct LineartObjectInfo *next;
struct Object *original_ob;
@@ -380,22 +484,27 @@ typedef struct LineartObjectInfo {
LineartElementLinkNode *v_eln;
int usage;
uint8_t override_intersection_mask;
+ uint8_t intersection_priority;
int global_i_offset;
+ /* Shifted LRT_OBINDEX_SHIFT bits to be combined with object triangle index. */
+ int obindex;
+
bool free_use_mesh;
- /* Note: Data inside #pending_edges are allocated with MEM_xxx call instead of in pool. */
+ /** NOTE: Data inside #pending_edges are allocated with MEM_xxx call instead of in pool. */
struct LineartPendingEdges pending_edges;
} LineartObjectInfo;
typedef struct LineartObjectLoadTaskInfo {
- struct LineartRenderBuffer *rb;
+ struct LineartData *ld;
int thread_id;
/* LinkNode styled list */
LineartObjectInfo *pending;
/* Used to spread the load across several threads. This can not overflow. */
- long unsigned int total_faces;
+ uint64_t total_faces;
+ ListBase *shadow_elns;
} LineartObjectLoadTaskInfo;
/**
@@ -429,15 +538,18 @@ typedef struct LineartBoundingArea {
/** 1,2,3,4 quadrant */
struct LineartBoundingArea *child;
+ SpinLock lock;
+
ListBase lp;
ListBase rp;
ListBase up;
ListBase bp;
- uint16_t triangle_count;
- uint16_t max_triangle_count;
- uint16_t line_count;
- uint16_t max_line_count;
+ uint32_t triangle_count;
+ uint32_t max_triangle_count;
+ uint32_t line_count;
+ uint32_t max_line_count;
+ uint32_t insider_triangle_count;
/* Use array for speeding up multiple accesses. */
struct LineartTriangle **linked_triangles;
@@ -459,15 +571,16 @@ 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 DBL_LOOSER 1e-5
#define LRT_DOUBLE_CLOSE_LOOSER(a, b) (((a) + DBL_LOOSER) >= (b) && ((a)-DBL_LOOSER) <= (b))
#define LRT_DOUBLE_CLOSE_ENOUGH(a, b) (((a) + DBL_EDGE_LIM) >= (b) && ((a)-DBL_EDGE_LIM) <= (b))
#define LRT_DOUBLE_CLOSE_ENOUGH_TRI(a, b) \
(((a) + DBL_TRIANGLE_LIM) >= (b) && ((a)-DBL_TRIANGLE_LIM) <= (b))
+#define LRT_CLOSE_LOOSER_v3(a, b) \
+ (LRT_DOUBLE_CLOSE_LOOSER(a[0], b[0]) && LRT_DOUBLE_CLOSE_LOOSER(a[1], b[1]) && \
+ LRT_DOUBLE_CLOSE_LOOSER(a[2], b[2]))
+
/* Notes on this function:
*
* r_ratio: The ratio on segment a1-a2. When r_ratio is very close to zero or one, it
@@ -480,10 +593,10 @@ typedef struct LineartBoundingArea {
* segment a is shared with segment b. If it's a1 then r_ratio is 0, else then r_ratio is 1. This
* extra information is needed for line art occlusion stage to work correctly in such cases.
*/
-BLI_INLINE int lineart_intersect_seg_seg(const double *a1,
- const double *a2,
- const double *b1,
- const double *b2,
+BLI_INLINE int lineart_intersect_seg_seg(const double a1[2],
+ const double a2[2],
+ const double b1[2],
+ const double b2[2],
double *r_ratio,
bool *r_aligned)
{
@@ -624,32 +737,124 @@ BLI_INLINE int lineart_intersect_seg_seg(const double *a1,
#endif
}
+/* This is a special convenience function to lineart_intersect_seg_seg which will return true when
+ * the intersection point falls in the range of a1-a2 but not necessarily in the range of b1-b2. */
+BLI_INLINE int lineart_line_isec_2d_ignore_line2pos(const double a1[2],
+ const double a2[2],
+ const double b1[2],
+ const double b2[2],
+ double *r_a_ratio)
+{
+ /* The define here is used to check how vector or slope method handles boundary cases. The result
+ * of `lim(div->0)` and `lim(k->0)` could both produce some unwanted flickers in line art, the
+ * influence of which is still not fully understood, so keep the switch there for further
+ * investigations. */
+#define USE_VECTOR_LINE_INTERSECTION_IGN
+#ifdef USE_VECTOR_LINE_INTERSECTION_IGN
+
+ /* from isect_line_line_v2_point() */
+
+ double s10[2], s32[2];
+ double div;
+
+ sub_v2_v2v2_db(s10, a2, a1);
+ sub_v2_v2v2_db(s32, b2, b1);
+
+ div = cross_v2v2_db(s10, s32);
+ if (div != 0.0f) {
+ const double u = cross_v2v2_db(a2, a1);
+ const double v = cross_v2v2_db(b2, b1);
+
+ const double rx = ((s32[0] * u) - (s10[0] * v)) / div;
+ const double ry = ((s32[1] * u) - (s10[1] * v)) / div;
+
+ if (fabs(a2[0] - a1[0]) > fabs(a2[1] - a1[1])) {
+ *r_a_ratio = ratiod(a1[0], a2[0], rx);
+ if ((*r_a_ratio) >= -DBL_EDGE_LIM && (*r_a_ratio) <= 1 + DBL_EDGE_LIM) {
+ return 1;
+ }
+ return 0;
+ }
+
+ *r_a_ratio = ratiod(a1[1], a2[1], ry);
+ if ((*r_a_ratio) >= -DBL_EDGE_LIM && (*r_a_ratio) <= 1 + DBL_EDGE_LIM) {
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+
+#else
+ double k1, k2;
+ double x;
+ double y;
+ double ratio;
+ double x_diff = (a2[0] - a1[0]);
+ double x_diff2 = (b2[0] - b1[0]);
+
+ if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff, 0)) {
+ if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
+ *r_a_ratio = 0;
+ return 0;
+ }
+ double r2 = ratiod(b1[0], b2[0], a1[0]);
+ x = interpd(b2[0], b1[0], r2);
+ y = interpd(b2[1], b1[1], r2);
+ *r_a_ratio = ratio = ratiod(a1[1], a2[1], y);
+ }
+ else {
+ if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
+ ratio = ratiod(a1[0], a2[0], b1[0]);
+ x = interpd(a2[0], a1[0], ratio);
+ *r_a_ratio = ratio;
+ }
+ else {
+ k1 = (a2[1] - a1[1]) / x_diff;
+ k2 = (b2[1] - b1[1]) / x_diff2;
+
+ if ((k1 == k2))
+ return 0;
+
+ x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
+
+ ratio = (x - a1[0]) / x_diff;
+
+ *r_a_ratio = ratio;
+ }
+ }
+
+ if (ratio <= 0 || ratio >= 1)
+ return 0;
+
+ return 1;
+#endif
+}
+
struct Depsgraph;
struct LineartGpencilModifierData;
-struct LineartRenderBuffer;
+struct LineartData;
struct Scene;
void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd);
-void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb);
-void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb);
+void MOD_lineart_chain_feature_lines(LineartData *ld);
+void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld);
/**
* This function only connects two different chains. It will not do any clean up or smart chaining.
* So no: removing overlapping chains, removal of short isolated segments, and no loop reduction is
* implemented yet.
*/
-void MOD_lineart_chain_connect(LineartRenderBuffer *rb);
-void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, float threshold);
-void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb);
+void MOD_lineart_chain_connect(LineartData *ld);
+void MOD_lineart_chain_discard_unused(LineartData *ld, float threshold, uint8_t max_occlusion);
+void MOD_lineart_chain_clip_at_border(LineartData *ld);
/**
* This should always be the last stage!, see the end of
* #MOD_lineart_chain_split_for_fixed_occlusion().
*/
-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);
+void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad);
+void MOD_lineart_smooth_chains(LineartData *ld, float tolerance);
+void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool use_custom_camera);
+void MOD_lineart_chain_find_silhouette_backdrop_objects(LineartData *ld);
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc);
@@ -669,14 +874,12 @@ struct Scene;
/**
* This only gets initial "biggest" tile.
*/
-LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *rb,
- double x,
- double y);
+LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartData *ld, double x, double y);
/**
* Wrapper for more convenience.
*/
-LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y);
+LineartBoundingArea *MOD_lineart_get_bounding_area(LineartData *ld, double x, double y);
struct bGPDframe;
struct bGPDlayer;
@@ -689,17 +892,19 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
struct Object *ob,
struct bGPDlayer *gpl,
struct bGPDframe *gpf,
- char source_type,
+ int8_t source_type,
void *source_reference,
int level_start,
int level_end,
int mat_nr,
- short edge_types,
- unsigned char mask_switches,
- unsigned char material_mask_bits,
- unsigned char intersection_mask,
- short thickness,
+ int16_t edge_types,
+ uint8_t mask_switches,
+ uint8_t material_mask_bits,
+ uint8_t intersection_mask,
+ int16_t thickness,
float opacity,
+ uint8_t shadow_selection,
+ uint8_t silhouette_mode,
const char *source_vgname,
const char *vgname,
int modifier_flags);