diff options
Diffstat (limited to 'source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h')
-rw-r--r-- | source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h | 561 |
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); |