Blender V5.0
MOD_lineart.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "BLI_linklist.h"
13#include "BLI_math_vector.h"
14#include "BLI_set.hh"
15#include "BLI_threads.h"
16
17#include "ED_grease_pencil.hh"
18
19#include <algorithm>
20#include <cmath>
21
23struct LineartEdge;
24struct LineartVert;
25struct Mesh;
26struct Object;
27
29 /* This list is constructed during `update_depsgraph()` call, and stays valid until the next
30 * update. This way line art can load objects from this list instead of iterating over all
31 * objects that may or may not have finished evaluating. */
33};
34
37 size_t size;
38 size_t used_byte;
39 /* User memory starts here */
40};
41
46
50
53
54 /* first culled in line list to use adjacent triangle info, then go through triangle list. */
55 double gn[3];
56
60 uint8_t flags; /* #eLineartTriangleFlags */
61
62 /* target_reference = (obi->obindex | triangle_index) */
63 /* higher 12 bits-------^ ^-----index in object, lower 20 bits */
65
67
74};
75
88
96
99 void *pointer;
103
104 /* For edge element link nodes, used for shadow edge matching. */
107
110};
111
116 double ratio;
118 uint8_t occlusion;
119
120 /* Used to filter line art occlusion edges */
122
123 /* Lit/shaded flag for shadow is stored here.
124 * TODO(Yiming): Transfer material masks from shadow results
125 * onto here so then we can even filter transparent shadows. */
127};
128
131 /* Two end points in frame-buffer coordinates viewed from the light source. */
132 double fbc1[4], fbc2[4];
133 double g1[3], g2[3];
137 LineartEdgeSegment *es_ref; /* Only for 3rd stage casting. */
139};
140
145
146/* Represents a cutting point on a #LineartShadowEdge */
149 /* eLineartShadowSegmentFlag */
150 int flag;
151 /* The point after which a property of the segment is changed. e.g. shadow mask/target_ref etc.
152 * Coordinates in NDC during shadow calculation but transformed to global linear before cutting
153 * onto edges during the loading stage of the "actual" rendering. */
154 double ratio;
155 /* Left and right pos, because when casting shadows at some point there will be
156 * non-continuous cuts, see #lineart_shadow_edge_cut for detailed explanation. */
157 double fbc1[4], fbc2[4];
158 /* Global position. */
159 double g1[4], g2[4];
162};
163
165 double gloc[3];
166 double fbcoord[4];
167
168 /* Scene global index. */
169 int index;
170};
171
211
215
217 float length;
218
220 uint8_t picked;
221 uint8_t level;
222
224 int type;
230
231 /* We need local index for correct weight transfer, line art index is global, thus
232 * local_index=lineart_index-index_offset. */
233 uint32_t index_offset;
234
237};
238
253
258 int8_t picked;
259
260 /* left/right mark.
261 * Because we revert list in chaining so we need the flag. */
262 int8_t is_left;
263};
264
266 uint32_t v1;
267 uint32_t v2;
268 uint32_t e;
269};
270
272 /* If tile gets this small, it's already much smaller than a pixel. No need to continue
273 * splitting. */
275 /* This is a tried-and-true safe value for high poly models that also needed ortho rendering. */
277};
278
279#define LRT_TILE_SPLITTING_TRIANGLE_LIMIT 100
280#define LRT_TILE_EDGE_COUNT_INITIAL 32
281
286
292
294 int w, h;
297
299 /* A pointer to LineartCache::chain_data_pool, which acts as a cache for edge chains. */
301 /* Reference to LineartCache::shadow_data_pool, stay available until the final round of line art
302 * calculation is finished. */
304
305 /* Storing shadow edge eln, array, and cuts for shadow information, so it's available when line
306 * art runs the second time for occlusion. Either a reference to LineartCache::shadow_data_pool
307 * (shadow stage) or a reference to LineartData::render_data_pool (final stage). */
309
310 struct _qtree {
311
314
315 /* When splitting bounding areas, if there's an ortho camera placed at a straight angle, there
316 * will be a lot of triangles aligned in line which can not be separated by continue
317 * subdividing the tile. So we set a strict limit when using ortho camera. See
318 * eLineArtTileRecursiveLimit. */
320
322
324
326
339
340 struct _conf {
341
342 double view_projection[4][4];
343 double view[4][4];
344
345 float overscan;
346
350
353
362 bool use_contour_secondary; /* From viewing camera, during shadow calculation. */
363
364 int shadow_selection; /* Needs to be numeric because it's not just on/off. */
367
379
384
387
389
392
393 /* Keep an copy of these data so when line art is running itself contained. */
395 /* "Secondary" ones are from viewing camera
396 * (as opposed to shadow camera), during shadow calculation. */
398 float cam_obmat[4][4];
400 double camera_pos[3];
402 double active_camera_pos[3]; /* Stroke offset calculation may use active or selected camera. */
405
409
411
412 double view_vector[3];
413 double view_vector_secondary[3]; /* For shadow. */
415
418
419 /* NOTE: Data inside #pending_edges are allocated with MEM_xxx call instead of in pool. */
422
423 /* Intermediate shadow results, list of LineartShadowEdge */
426
428
433};
434
452
453#define DBL_TRIANGLE_LIM 1e-8
454#define DBL_EDGE_LIM 1e-9
455
456#define LRT_MEMORY_POOL_1MB (1 << 20)
457
468
469#define LRT_SHADOW_MASK_UNDEFINED 0
470#define LRT_SHADOW_MASK_ILLUMINATED (1 << 0)
471#define LRT_SHADOW_MASK_SHADED (1 << 1)
472#define LRT_SHADOW_MASK_ENCLOSED_SHAPE (1 << 2)
473#define LRT_SHADOW_MASK_INHIBITED (1 << 3)
474#define LRT_SHADOW_SILHOUETTE_ERASED_GROUP (1 << 4)
475#define LRT_SHADOW_SILHOUETTE_ERASED_OBJECT (1 << 5)
476#define LRT_SHADOW_MASK_ILLUMINATED_SHAPE (1 << 6)
477
478#define LRT_SHADOW_TEST_SHAPE_BITS \
479 (LRT_SHADOW_MASK_ILLUMINATED | LRT_SHADOW_MASK_SHADED | LRT_SHADOW_MASK_INHIBITED | \
480 LRT_SHADOW_MASK_ILLUMINATED_SHAPE)
481
487#define LRT_THREAD_EDGE_COUNT 1000
488
500
501#define LRT_OBINDEX_SHIFT 20
502#define LRT_OBINDEX_LOWER 0x0FFFFF /* Lower 20 bits. */
503#define LRT_OBINDEX_HIGHER 0xFFF00000 /* Higher 12 bits. */
504#define LRT_EDGE_IDENTIFIER(obi, e) \
505 (((uint64_t)(obi->obindex | (e->v1->index & LRT_OBINDEX_LOWER)) << 32) | \
506 (obi->obindex | (e->v2->index & LRT_OBINDEX_LOWER)))
507#define LRT_LIGHT_CONTOUR_TARGET 0xFFFFFFFF
508
512 Object *original_ob_eval; /* For evaluated materials */
514 double model_view_proj[4][4];
515 double model_view[4][4];
516 double normal[4][4];
518 int usage;
522
523 /* Shifted LRT_OBINDEX_SHIFT bits to be combined with object triangle index. */
525
527
530};
531
535 /* LinkNode styled list */
537 /* Used to spread the load across several threads. This can not overflow. */
540};
541
593
594#define LRT_TILE(tile, r, c, CCount) tile[r * CCount + c]
595
596#define LRT_CLAMP(a, Min, Max) a = a < Min ? Min : (a > Max ? Max : a)
597
598#define LRT_MAX3_INDEX(a, b, c) (a > b ? (a > c ? 0 : (b > c ? 1 : 2)) : (b > c ? 1 : 2))
599
600#define LRT_MIN3_INDEX(a, b, c) (a < b ? (a < c ? 0 : (b < c ? 1 : 2)) : (b < c ? 1 : 2))
601
602#define LRT_MAX3_INDEX_ABC(x, y, z) (x > y ? (x > z ? a : (y > z ? b : c)) : (y > z ? b : c))
603
604#define LRT_MIN3_INDEX_ABC(x, y, z) (x < y ? (x < z ? a : (y < z ? b : c)) : (y < z ? b : c))
605
606#define DBL_LOOSER 1e-5
607#define LRT_DOUBLE_CLOSE_LOOSER(a, b) (((a) + DBL_LOOSER) >= (b) && ((a) - DBL_LOOSER) <= (b))
608#define LRT_DOUBLE_CLOSE_ENOUGH(a, b) (((a) + DBL_EDGE_LIM) >= (b) && ((a) - DBL_EDGE_LIM) <= (b))
609#define LRT_DOUBLE_CLOSE_ENOUGH_TRI(a, b) \
610 (((a) + DBL_TRIANGLE_LIM) >= (b) && ((a) - DBL_TRIANGLE_LIM) <= (b))
611
612#define LRT_CLOSE_LOOSER_v3(a, b) \
613 (LRT_DOUBLE_CLOSE_LOOSER(a[0], b[0]) && LRT_DOUBLE_CLOSE_LOOSER(a[1], b[1]) && \
614 LRT_DOUBLE_CLOSE_LOOSER(a[2], b[2]))
615
616/* Notes on this function:
617 *
618 * r_ratio: The ratio on segment a1-a2. When r_ratio is very close to zero or one, it
619 * fixes the value to zero or one, this makes it easier to identify "on the tip" situations.
620 *
621 * r_aligned: True when 1) a and b is exactly on the same straight line and 2) a and b share a
622 * common end-point.
623 *
624 * IMPORTANT: if r_aligned is true, r_ratio will be either 0 or 1 depending on which point from
625 * segment a is shared with segment b. If it's a1 then r_ratio is 0, else then r_ratio is 1. This
626 * extra information is needed for line art occlusion stage to work correctly in such cases.
627 */
629 const double a2[2],
630 const double b1[2],
631 const double b2[2],
632 double *r_ratio,
633 bool *r_aligned)
634{
635/* Legacy intersection math aligns better with occlusion function quirks. */
636// #define USE_VECTOR_LINE_INTERSECTION
637#ifdef USE_VECTOR_LINE_INTERSECTION
638
639 /* from isect_line_line_v2_point() */
640
641 double s10[2], s32[2];
642 double div;
643
644 sub_v2_v2v2_db(s10, a2, a1);
645 sub_v2_v2v2_db(s32, b2, b1);
646
647 div = cross_v2v2_db(s10, s32);
648 if (div != 0.0f) {
649 const double u = cross_v2v2_db(a2, a1);
650 const double v = cross_v2v2_db(b2, b1);
651
652 const double rx = ((s32[0] * u) - (s10[0] * v)) / div;
653 const double ry = ((s32[1] * u) - (s10[1] * v)) / div;
654 double rr;
655
656 if (fabs(a2[0] - a1[0]) > fabs(a2[1] - a1[1])) {
657 *r_ratio = ratiod(a1[0], a2[0], rx);
658 if (fabs(b2[0] - b1[0]) > fabs(b2[1] - b1[1])) {
659 rr = ratiod(b1[0], b2[0], rx);
660 }
661 else {
662 rr = ratiod(b1[1], b2[1], ry);
663 }
664 if ((*r_ratio) > 0 && (*r_ratio) < 1 && rr > 0 && rr < 1) {
665 return 1;
666 }
667 return 0;
668 }
669
670 *r_ratio = ratiod(a1[1], a2[1], ry);
671 if (fabs(b2[0] - b1[0]) > fabs(b2[1] - b1[1])) {
672 rr = ratiod(b1[0], b2[0], rx);
673 }
674 else {
675 rr = ratiod(b1[1], b2[1], ry);
676 }
677 if ((*r_ratio) > 0 && (*r_ratio) < 1 && rr > 0 && rr < 1) {
678 return 1;
679 }
680 return 0;
681 }
682 return 0;
683
684#else
685 double k1, k2;
686 double x;
687 double y;
688 double ratio;
689 double x_diff = (a2[0] - a1[0]);
690 double x_diff2 = (b2[0] - b1[0]);
691
692 *r_aligned = false;
693
694 if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff, 0)) {
695 if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
696 /* This means two segments are both vertical. */
697 if ((LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b1[1])) ||
698 (LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b2[1])))
699 {
700 *r_aligned = true;
701 *r_ratio = 1;
702 }
703 else if ((LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b1[1])) ||
704 (LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b2[1])))
705 {
706 *r_aligned = true;
707 *r_ratio = 0;
708 }
709 return 0;
710 }
711 double r2 = ratiod(b1[0], b2[0], a1[0]);
712 x = interpd(b2[0], b1[0], r2);
713 y = interpd(b2[1], b1[1], r2);
714 *r_ratio = ratio = ratiod(a1[1], a2[1], y);
715 }
716 else {
717 if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
718 ratio = ratiod(a1[0], a2[0], b1[0]);
719 x = interpd(a2[0], a1[0], ratio);
720 *r_ratio = ratio;
721 }
722 else {
723 double y_diff = a2[1] - a1[1], y_diff2 = b2[1] - b1[1];
724 k1 = y_diff / x_diff;
725 k2 = y_diff2 / x_diff2;
726
727 if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(k2, k1)) {
728 /* This means two segments are parallel. This also handles k==0 (both completely
729 * horizontal) cases. */
730 if ((LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b1[1])) ||
731 (LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b2[1])))
732 {
733 *r_aligned = true;
734 *r_ratio = 1;
735 }
736 else if ((LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b1[0]) &&
737 LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b1[1])) ||
738 (LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b2[1])))
739 {
740 *r_aligned = true;
741 *r_ratio = 0;
742 }
743 return 0;
744 }
745
746 x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
747
748 ratio = (x - a1[0]) / x_diff;
749
750 *r_ratio = ratio;
751 }
752 }
753
754 if (LRT_DOUBLE_CLOSE_ENOUGH(b1[0], b2[0])) {
755 y = interpd(a2[1], a1[1], ratio);
756 if (y > std::max(b1[1], b2[1]) || y < std::min(b1[1], b2[1])) {
757 return 0;
758 }
759 }
760 else if (ratio <= 0 || ratio > 1 || (b1[0] > b2[0] && x > b1[0]) ||
761 (b1[0] < b2[0] && x < b1[0]) || (b2[0] > b1[0] && x > b2[0]) ||
762 (b2[0] < b1[0] && x < b2[0]))
763 {
764 return 0;
765 }
766
767 if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(*r_ratio, 1)) {
768 *r_ratio = 1;
769 }
770 else if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(*r_ratio, 0)) {
771 *r_ratio = 0;
772 }
773
774 return 1;
775#endif
776}
777
778/* This is a special convenience function to lineart_intersect_seg_seg which will return true when
779 * the intersection point falls in the range of a1-a2 but not necessarily in the range of b1-b2. */
781 const double a2[2],
782 const double b1[2],
783 const double b2[2],
784 double *r_a_ratio)
785{
786 /* The define here is used to check how vector or slope method handles boundary cases. The result
787 * of `lim(div->0)` and `lim(k->0)` could both produce some unwanted flickers in line art, the
788 * influence of which is still not fully understood, so keep the switch there for further
789 * investigations. */
790#define USE_VECTOR_LINE_INTERSECTION_IGN
791#ifdef USE_VECTOR_LINE_INTERSECTION_IGN
792
793 /* from isect_line_line_v2_point() */
794
795 double s10[2], s32[2];
796 double div;
797
798 sub_v2_v2v2_db(s10, a2, a1);
799 sub_v2_v2v2_db(s32, b2, b1);
800
801 div = cross_v2v2_db(s10, s32);
802 if (div != 0.0f) {
803 const double u = cross_v2v2_db(a2, a1);
804 const double v = cross_v2v2_db(b2, b1);
805
806 const double rx = ((s32[0] * u) - (s10[0] * v)) / div;
807 const double ry = ((s32[1] * u) - (s10[1] * v)) / div;
808
809 if (fabs(a2[0] - a1[0]) > fabs(a2[1] - a1[1])) {
810 *r_a_ratio = ratiod(a1[0], a2[0], rx);
811 if ((*r_a_ratio) >= -DBL_EDGE_LIM && (*r_a_ratio) <= 1 + DBL_EDGE_LIM) {
812 return 1;
813 }
814 return 0;
815 }
816
817 *r_a_ratio = ratiod(a1[1], a2[1], ry);
818 if ((*r_a_ratio) >= -DBL_EDGE_LIM && (*r_a_ratio) <= 1 + DBL_EDGE_LIM) {
819 return 1;
820 }
821 return 0;
822 }
823 return 0;
824
825#else
826 double k1, k2;
827 double x;
828 double y;
829 double ratio;
830 double x_diff = (a2[0] - a1[0]);
831 double x_diff2 = (b2[0] - b1[0]);
832
833 if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff, 0)) {
834 if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
835 *r_a_ratio = 0;
836 return 0;
837 }
838 double r2 = ratiod(b1[0], b2[0], a1[0]);
839 x = interpd(b2[0], b1[0], r2);
840 y = interpd(b2[1], b1[1], r2);
841 *r_a_ratio = ratio = ratiod(a1[1], a2[1], y);
842 }
843 else {
844 if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
845 ratio = ratiod(a1[0], a2[0], b1[0]);
846 x = interpd(a2[0], a1[0], ratio);
847 *r_a_ratio = ratio;
848 }
849 else {
850 k1 = (a2[1] - a1[1]) / x_diff;
851 k2 = (b2[1] - b1[1]) / x_diff2;
852
853 if ((k1 == k2)) {
854 return 0;
855 }
856 x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
857
858 ratio = (x - a1[0]) / x_diff;
859
860 *r_a_ratio = ratio;
861 }
862 }
863
864 if (ratio <= 0 || ratio >= 1) {
865 return 0;
866 }
867 return 1;
868#endif
869}
870
871struct bGPDframe;
872struct bGPDlayer;
873struct Depsgraph;
876struct LineartData;
877struct Scene;
878
880
889void MOD_lineart_chain_discard_unused(LineartData *ld, float threshold, uint8_t max_occlusion);
895void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad);
896void MOD_lineart_smooth_chains(LineartData *ld, float tolerance);
897void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool use_custom_camera);
899
903
911 LineartCache **cached_result,
912 bool enable_stroke_depth_offset);
913
918
923
925class Drawing;
926}
928 const blender::float4x4 &mat,
929 Depsgraph *depsgraph,
931 int8_t source_type,
932 Object *source_object,
933 Collection *source_collection,
934 int level_start,
935 int level_end,
936 int mat_nr,
937 int16_t edge_types,
938 uchar mask_switches,
939 uchar material_mask_bits,
940 uchar intersection_mask,
941 float thickness,
942 float opacity,
943 uchar shadow_selection,
944 uchar silhouette_mode,
945 const char *source_vgname,
946 const char *vgname,
947 int modifier_flags,
948 int modifier_calculation_flags);
949
954
#define BLI_INLINE
MINLINE double ratiod(double min, double max, double pos)
MINLINE double interpd(double target, double origin, double t)
MINLINE double cross_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2])
unsigned char uchar
pthread_spinlock_t SpinLock
#define ENUM_OPERATORS(_type, _max)
LineartCache * MOD_lineart_init_cache()
#define LRT_DOUBLE_CLOSE_ENOUGH(a, b)
#define LRT_DOUBLE_CLOSE_ENOUGH_TRI(a, b)
void MOD_lineart_chain_connect(LineartData *ld)
void MOD_lineart_chain_discard_unused(LineartData *ld, float threshold, uint8_t max_occlusion)
LineartBoundingArea * MOD_lineart_get_parent_bounding_area(LineartData *ld, double x, double y)
#define DBL_EDGE_LIM
float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
void MOD_lineart_gpencil_generate_v3(const LineartCache *cache, const blender::float4x4 &mat, Depsgraph *depsgraph, blender::bke::greasepencil::Drawing &drawing, int8_t source_type, Object *source_object, Collection *source_collection, int level_start, int level_end, int mat_nr, int16_t edge_types, uchar mask_switches, uchar material_mask_bits, uchar intersection_mask, float thickness, float opacity, uchar shadow_selection, uchar silhouette_mode, const char *source_vgname, const char *vgname, int modifier_flags, int modifier_calculation_flags)
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)
void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld)
void MOD_lineart_chain_clip_at_border(LineartData *ld)
int MOD_lineart_chain_count(const LineartEdgeChain *ec)
void MOD_lineart_finalize_chains(LineartData *ld)
void MOD_lineart_clear_cache(LineartCache **lc)
eLineArtTileRecursiveLimit
@ LRT_TILE_RECURSIVE_PERSPECTIVE
@ LRT_TILE_RECURSIVE_ORTHO
void MOD_lineart_chain_find_silhouette_backdrop_objects(LineartData *ld)
LineartBoundingArea * MOD_lineart_get_bounding_area(LineartData *ld, double x, double y)
void MOD_lineart_chain_feature_lines(LineartData *ld)
void MOD_lineart_destroy_render_data_v3(GreasePencilLineartModifierData *lmd)
eLineartTriangleFlags
@ LRT_TRIANGLE_NO_INTERSECTION
@ LRT_CULL_GENERATED
@ LRT_CULL_DISCARD
@ LRT_TRIANGLE_MAT_BACK_FACE_CULLING
@ LRT_CULL_DONT_CARE
@ LRT_TRIANGLE_INTERSECTION_ONLY
@ LRT_TRIANGLE_FORCE_INTERSECTION
@ LRT_CULL_USED
eLineArtElementNodeFlag
@ LRT_ELEMENT_NO_INTERSECTION
@ LRT_ELEMENT_BORDER_ONLY
@ LRT_ELEMENT_INTERSECTION_DATA
@ LRT_ELEMENT_IS_ADDITIONAL
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
eLineartShadowCameraType
@ LRT_SHADOW_CAMERA_POINT
@ LRT_SHADOW_CAMERA_DIRECTIONAL
void MOD_lineart_smooth_chains(LineartData *ld, float tolerance)
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)
void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad)
eLineartShadowSegmentFlag
@ LRT_SHADOW_CASTED
@ LRT_SHADOW_FACING_LIGHT
void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool use_custom_camera)
bool MOD_lineart_compute_feature_lines_v3(Depsgraph *depsgraph, GreasePencilLineartModifierData &lmd, LineartCache **cached_result, bool enable_stroke_depth_offset)
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
ccl_device_inline float2 fabs(const float2 a)
MatBase< float, 4, 4 > float4x4
LineartBoundingArea * child
uint32_t insider_triangle_count
LineartTriangle ** linked_triangles
LineartEdge ** linked_lines
uint32_t max_triangle_count
blender::ed::greasepencil::LineartLimitInfo LimitInfo
ListBase shadow_elns
ListBase chains
LineartStaticMemPool chain_data_pool
uint16_t all_enabled_edge_types
LineartStaticMemPool shadow_data_pool
LineartChainRegisterEntry * prev
LineartChainRegisterEntry * next
LineartEdgeChainItem * eci
LineartEdgeChain * ec
float cam_obmat_secondary[4][4]
double view_projection[4][4]
double view_vector_secondary[3]
double camera_pos_secondary[3]
bool filter_face_mark_keep_contour
double active_camera_pos[3]
double view[4][4]
float angle_splitting_threshold
float cam_obmat[4][4]
ListBase vertex_buffer_pointers
ListBase line_buffer_pointers
ListBase triangle_adjacent_pointers
ListBase intersecting_vertex_buffer
ListBase triangle_buffer_pointers
uint32_t initial_tile_count
LineartBoundingArea * initials
LineartShadowEdge * shadow_edges
ListBase wasted_shadow_cuts
LineartStaticMemPool render_data_pool
struct LineartData::_conf conf
struct LineartData::_geom geom
struct LineartData::_qtree qtree
int isect_scheduled_up_to_index
ListBase chains
LineartElementLinkNode * isect_scheduled_up_to
ListBase wasted_cuts
SpinLock lock_task
LineartStaticMemPool * edge_data_pool
SpinLock lock_cuts
struct LineartPendingEdges pending_edges
int shadow_edges_count
LineartStaticMemPool * shadow_data_pool
LineartStaticMemPool * chain_data_pool
LineartEdgeChainItem * prev
LineartEdgeChainItem * next
LineartEdgeChain * prev
uint8_t material_mask_bits
uint32_t index_offset
Object * silhouette_backdrop
uint32_t shadow_mask_bits
LineartEdgeChain * next
uint8_t intersection_mask
LineartEdgeSegment * next
LineartEdgeSegment * prev
uint32_t shadow_mask_bits
uint16_t flags
LineartVert * v1
LineartVert * v2
ListBase segments
LineartTriangle * t2
uint64_t edge_identifier
uint8_t intersection_mask
LineartTriangle * t1
Object * object_ref
uint64_t target_reference
LineartElementLinkNode * next
LineartElementLinkNode * prev
eLineArtElementNodeFlag flags
blender::Set< const Object * > object_dependencies
LineartElementLinkNode * v_eln
LineartObjectInfo * next
double model_view[4][4]
Object * original_ob_eval
double normal[4][4]
double model_view_proj[4][4]
uint8_t override_intersection_mask
uint8_t intersection_priority
LineartPendingEdges pending_edges
LineartObjectInfo * pending
LineartEdge ** array
struct LineartData * ld
struct LineartPendingEdges pending_edges
LineartEdge * e_ref_light_contour
ListBase shadow_segments
LineartShadowEdge * next
LineartEdgeSegment * es_ref
LineartShadowEdge * prev
LineartEdge * e_ref
LineartShadowSegment * next
LineartShadowSegment * prev
LineartEdge * e[3]
LineartEdge * testing_e[1]
LineartTriangle base
LineartVert * v[3]
uint8_t material_mask_bits
LinkNode * intersecting_verts
uint8_t intersection_priority
uint8_t intersection_mask
uint32_t target_reference
uint8_t mat_occlusion
double fbcoord[4]
double gloc[3]