19#define LRT_OTHER_VERT(e, vt) ((vt) == (e)->v1 ? (e)->v2 : ((vt) == (e)->v2 ? (e)->v1 : nullptr))
29 uint8_t match_isec_mask,
91 if (((eci->
pos[0] + threshold) >=
x) && ((eci->
pos[0] - threshold) <=
x) &&
92 ((eci->
pos[1] + threshold) >=
y) && ((eci->
pos[1] - threshold) <=
y))
106 uint8_t material_mask_bits,
107 uint32_t shadow_mask_bits,
149 uint8_t material_mask_bits,
150 uint32_t shadow_mask_bits,
184 uint8_t last_transparency;
185 uint32_t last_shadow;
187 float use_fbcoord[4];
190#define VERT_COORD_TO_FLOAT(a) \
191 copy_v4fl_v4db(use_fbcoord, (a)->fbcoord); \
192 copy_v3fl_v3db(use_gpos, (a)->gloc);
194#define POS_TO_FLOAT(lpos, gpos) \
195 copy_v3fl_v3db(use_fbcoord, lpos); \
196 copy_v3fl_v3db(use_gpos, gpos);
227 N[0] +=
e->t1->gn[0];
228 N[1] +=
e->t1->gn[1];
229 N[2] +=
e->t1->gn[2];
232 N[0] +=
e->t2->gn[0];
233 N[1] +=
e->t2->gn[1];
234 N[2] +=
e->t2->gn[2];
236 if (
e->t1 ||
e->t2) {
261 if (new_e->
t1 || new_e->
t2) {
264 N[0] += new_e->
t1->
gn[0];
265 N[1] += new_e->
t1->
gn[1];
266 N[2] += new_e->
t1->
gn[2];
269 N[0] += new_e->
t2->
gn[0];
270 N[1] += new_e->
t2->
gn[1];
271 N[2] += new_e->
t2->
gn[2];
276 if (new_vt == new_e->
v1) {
278 double gpos[3], lpos[3];
280 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
300 else if (new_vt == new_e->
v2) {
306 for (; es; es = es->
next) {
307 double gpos[3], lpos[3];
309 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
344 if (
e->t1 ||
e->t2) {
347 N[0] +=
e->t1->gn[0];
348 N[1] +=
e->t1->gn[1];
349 N[2] +=
e->t1->gn[2];
352 N[0] +=
e->t2->gn[0];
353 N[1] +=
e->t2->gn[1];
354 N[2] +=
e->t2->gn[2];
364 for (es = es->
next; es; es = es->
next) {
365 double gpos[3], lpos[3];
366 double *lfb =
e->v1->fbcoord, *rfb =
e->v2->fbcoord;
367 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
370 use_fbcoord[3] =
interpf(
e->v2->fbcoord[3],
e->v1->fbcoord[3], global_at);
406 if (new_e->
t1 || new_e->
t2) {
409 N[0] += new_e->
t1->
gn[0];
410 N[1] += new_e->
t1->
gn[1];
411 N[2] += new_e->
t1->
gn[2];
414 N[0] += new_e->
t2->
gn[0];
415 N[1] += new_e->
t2->
gn[1];
416 N[2] += new_e->
t2->
gn[2];
425 if (new_vt == new_e->
v1) {
435 double gpos[3], lpos[3];
437 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
457 else if (new_vt == new_e->
v2) {
466 for (; es; es = es->
next) {
467 double gpos[3], lpos[3];
469 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
516 if (root->
child ==
nullptr) {
521#define IN_BOUND(ba, eci) \
522 ba.l <= eci->pos[0] && ba.r >= eci->pos[0] && ba.b <= eci->pos[1] && ba.u >= eci->pos[1]
547 if (root ==
nullptr) {
564 if (root->
child ==
nullptr) {
578#define IN_BOUND(ba, eci) \
579 ba.l <= eci->pos[0] && ba.r >= eci->pos[0] && ba.b <= eci->pos[1] && ba.u >= eci->pos[1]
615 float distance_threshold,
616 bool preserve_details,
619 float dist_accum = 0;
621 int fixed_occ = last_matching_eci->
occlusion;
629 if (dist_accum > distance_threshold) {
635 if (eci->occlusion < fixed_occ) {
638 if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ &&
639 eci->shadow_mask_bits == fixed_shadow)
649 next_eci = eci->
next;
650 if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ &&
651 eci->shadow_mask_bits == fixed_shadow)
655 if (preserve_details) {
656 eci->material_mask_bits = fixed_mask;
657 eci->occlusion = fixed_occ;
658 eci->shadow_mask_bits = fixed_shadow;
664 *r_next_eci = can_skip_to;
682 ec->next = ec->prev =
nullptr;
685 ec->loop_id = loop_id;
692 ec->level = fixed_occ;
693 ec->material_mask_bits = fixed_mask;
694 ec->shadow_mask_bits = fixed_shadow;
695 for (eci = first_eci->
next; eci; eci = next_eci) {
696 next_eci = eci->
next;
726 ec->chain.last = eci->
prev;
742 new_ec->
type = ec->type;
748 ec->level = fixed_occ;
749 ec->material_mask_bits = fixed_mask;
750 ec->shadow_mask_bits = fixed_shadow;
830 uint8_t material_mask_bits,
832 uint32_t shadow_mask,
835 float *result_new_len,
859 if (cre->ec->picked || cre->picked) {
862 if (cre->ec == ec || (!cre->ec->chain.first) || (cre->ec->level != occlusion) ||
863 (cre->ec->material_mask_bits != material_mask_bits) ||
864 (cre->ec->intersection_mask != isec_mask) || (cre->ec->shadow_mask_bits != shadow_mask))
869 if (cre->ec->type != ec->
type) {
888 if (((cre->ec->loop_id == loop_id) && (new_len < dist)) ||
889 ((cre->ec->loop_id != loop_id) && (new_len < dist / 10)))
893 if (result_new_len) {
894 (*result_new_len) = new_len;
900 float adjacent_new_len = dist;
903#define LRT_TEST_ADJACENT_AREAS(dist_to, list) \
904 if (dist_to < dist && dist_to > 0) { \
905 LISTBASE_FOREACH (LinkData *, link, list) { \
906 LineartBoundingArea *sba = (LineartBoundingArea *)link->data; \
907 adjacent_closest = lineart_chain_get_closest_cre(ld, \
912 material_mask_bits, \
919 if (adjacent_new_len < dist) { \
920 dist = adjacent_new_len; \
921 closest_cre = adjacent_closest; \
931 if (result_new_len) {
932 (*result_new_len) = dist;
943 float dist_l, dist_r;
944 int reverse_main, loop_id;
945 uint8_t occlusion, material_mask_bits, isec_mask;
946 uint32_t shadow_mask;
959 ec->next = ec->prev =
nullptr;
960 if (ec->picked || ec->chain.first == ec->chain.last) {
964 loop_id = ec->loop_id;
970 occlusion = ec->level;
971 material_mask_bits = ec->material_mask_bits;
972 isec_mask = ec->intersection_mask;
973 shadow_mask = ec->shadow_mask_bits;
1004 if (closest_cre_l && closest_cre_r) {
1005 if (dist_l < dist_r) {
1006 closest_cre = closest_cre_l;
1010 closest_cre = closest_cre_r;
1014 else if (closest_cre_l) {
1015 closest_cre = closest_cre_l;
1018 else if (closest_cre_r) {
1019 closest_cre = closest_cre_r;
1045 float offset_accum = 0;
1047 float last_point[2];
1056 offset_accum += dist;
1059 return offset_accum;
1063 const float threshold,
1064 uint8_t max_occlusion)
1086 if (lc ==
nullptr) {
1097 if (eln->object_ref == ob) {
1131 for (
int times = 0; times < 2; times++) {
1133 *next_eci = eci->
next;
1139 if (!(eci2 = eci->
next) || !(eci3 = eci2->
next)) {
1141 next_eci = eci->next;
1157 float vec2[2], vec3[2], v2n[2], ratio, len2;
1171 if (ratio < len2 && ratio > -len2 * 10) {
1173 if ((eci4 = eci3->
next) &&
1192 next_eci = eci->
next;
1205 float ref_lu[2] = {-1.0f, 1.0f}, ref_lb[2] = {-1.0f, -1.0f}, ref_ru[2] = {1.0f, 1.0f},
1206 ref_rb[2] = {1.0f, -1.0f};
1209 if (eci2->
pos[0] < -1.0f) {
1212 if (!found && eci2->
pos[0] > 1.0f) {
1215 if (!found && eci2->
pos[1] < -1.0f) {
1218 if (!found && eci2->
pos[1] > 1.0f) {
1226 float ratio = (
fabs(eci2->
pos[0] - eci1->pos[0]) >
fabs(eci2->
pos[1] - eci1->pos[1])) ?
1227 ratiof(eci1->pos[0], eci2->
pos[0], isec[0]) :
1228 ratiof(eci1->pos[1], eci2->
pos[1], isec[1]);
1229 float gratio = eci1->pos[3] * ratio / (ratio * eci1->pos[3] + (1 - ratio) * eci2->
pos[3]);
1241#define LRT_ECI_INSIDE(eci) \
1242 ((eci)->pos[0] >= -1.0f && (eci)->pos[0] <= 1.0f && (eci)->pos[1] >= -1.0f && \
1243 (eci)->pos[1] <= 1.0f)
1255 bool ec_added =
false;
1261 for (eci = first_eci->
next; eci; eci = next_eci) {
1262 next_eci = eci->
next;
1263 prev_eci = eci->
prev;
1268 if (new_inside ==
false) {
1276 eci->
prev =
nullptr;
1277 prev_eci->
next =
nullptr;
1278 ec->chain.last = prev_eci;
1284 next_eci = eci->
next;
1291 ec->chain.first = eci;
1292 eci->
prev =
nullptr;
1298 next_eci = eci->
next;
1321 ec->next = ec->prev =
nullptr;
1324 for (eci = first_eci->
next; eci; eci = next_eci) {
1325 next_eci = eci->
next;
1326 prev_eci = eci->
prev;
1328 if (next_eci && prev_eci) {
1334 if (
angle < angle_threshold_rad) {
1339 ec->chain.last = eci->
prev;
1341 eci->
prev =
nullptr;
1355 new_ec->
type = ec->type;
1356 new_ec->
level = ec->level;
1357 new_ec->
loop_id = ec->loop_id;
1372 float view_clamp[3];
1374 if (use_custom_camera) {
1385 float orig_len =
len_v3(dir);
1399 mul_v3_fl(view_clamp, std::min(dist, len_lim));
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void void void void void void void BLI_listbase_reverse(ListBase *lb) ATTR_NONNULL(1)
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
MINLINE float interpf(float target, float origin, float t)
MINLINE float ratiof(float min, float max, float pos)
float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2])
float angle_v2v2v2(const float a[2], const float b[2], const float c[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v4_v4(float r[4], const float a[4])
void interp_v3_v3v3_db(double target[3], const double a[3], const double b[3], double t)
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE void copy_v3fl_v3db(float r[3], const double a[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v2_v2(float r[2], const float a[2])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ MOD_LINEART_EDGE_FLAG_PROJECTED_SHADOW
@ MOD_LINEART_EDGE_FLAG_CONTOUR
@ MOD_LINEART_EDGE_FLAG_LIGHT_CONTOUR
@ MOD_LINEART_EDGE_FLAG_INTERSECTION
@ MOD_LINEART_EDGE_FLAG_CHAIN_PICKED
@ MOD_LINEART_EDGE_FLAG_LOOSE
#define MOD_LINEART_EDGE_FLAG_ALL_TYPE
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
#define LRT_OBINDEX_HIGHER
#define LRT_SHADOW_SILHOUETTE_ERASED_GROUP
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static bool is_inside(int x, int y, int cols, int rows)
static LineartBoundingArea * lineart_bounding_area_get_eci_recursive(LineartData *ld, LineartBoundingArea *root, LineartEdgeChainItem *eci)
#define POS_TO_FLOAT(lpos, gpos)
static LineartEdgeChainItem * lineart_chain_create_crossing_point(LineartData *ld, LineartEdgeChainItem *eci_inside, LineartEdgeChainItem *eci_outside)
static bool lineart_chain_fix_ambiguous_segments(LineartEdgeChain *ec, LineartEdgeChainItem *last_matching_eci, float distance_threshold, bool preserve_details, LineartEdgeChainItem **r_next_eci)
#define LRT_ECI_INSIDE(eci)
LineartElementLinkNode * lineart_find_matching_eln_obj(ListBase *elns, Object *ob)
void MOD_lineart_chain_connect(LineartData *ld)
void MOD_lineart_chain_discard_unused(LineartData *ld, const float threshold, uint8_t max_occlusion)
static LineartEdge * lineart_line_get_connected(LineartBoundingArea *ba, LineartVert *vt, LineartVert **new_vt, int match_flag, uint8_t match_isec_mask, Object *match_isec_object)
static LineartBoundingArea * lineart_bounding_area_get_end_point(LineartData *ld, LineartEdgeChainItem *eci)
float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
static LineartEdgeChainItem * lineart_chain_append_point(LineartData *ld, LineartEdgeChain *ec, float fbcoord[4], float gpos[3], float normal[3], uint8_t type, int level, uint8_t material_mask_bits, uint32_t shadow_mask_bits, size_t index)
void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld)
static LineartChainRegisterEntry * lineart_chain_get_closest_cre(LineartData *ld, LineartBoundingArea *ba, LineartEdgeChain *ec, LineartEdgeChainItem *eci, int occlusion, uint8_t material_mask_bits, uint8_t isec_mask, uint32_t shadow_mask, int loop_id, float dist, float *result_new_len, LineartBoundingArea *caller_ba)
void MOD_lineart_chain_clip_at_border(LineartData *ld)
int MOD_lineart_chain_count(const LineartEdgeChain *ec)
#define VERT_COORD_TO_FLOAT(a)
void MOD_lineart_finalize_chains(LineartData *ld)
static LineartEdgeChainItem * lineart_chain_prepend_point(LineartData *ld, LineartEdgeChain *ec, float fbcoord[4], float gpos[3], float normal[3], uint8_t type, int level, uint8_t material_mask_bits, uint32_t shadow_mask_bits, size_t index)
static void lineart_bounding_area_link_chain(LineartData *ld, LineartEdgeChain *ec)
#define LRT_OTHER_VERT(e, vt)
void MOD_lineart_chain_find_silhouette_backdrop_objects(LineartData *ld)
static bool lineart_point_overlapping(LineartEdgeChainItem *eci, float x, float y, double threshold)
void MOD_lineart_chain_feature_lines(LineartData *ld)
#define LRT_TEST_ADJACENT_AREAS(dist_to, list)
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
static void lineart_bounding_area_link_point_recursive(LineartData *ld, LineartBoundingArea *root, LineartEdgeChain *ec, LineartEdgeChainItem *eci)
static LineartEdgeChain * lineart_chain_create(LineartData *ld)
void MOD_lineart_smooth_chains(LineartData *ld, float tolerance)
void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad)
void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool use_custom_camera)
static void lineart_chain_connect(LineartData *, LineartEdgeChain *onto, LineartEdgeChain *sub, int reverse_1, int reverse_2)
#define IN_BOUND(ba, eci)
LineartBoundingArea * MOD_lineart_get_parent_bounding_area(LineartData *ld, double x, double y)
LineartBoundingArea * MOD_lineart_get_bounding_area(LineartData *ld, double x, double y)
void * lineart_mem_acquire(struct LineartStaticMemPool *smp, size_t size)
void * lineart_list_append_pointer_pool_sized(ListBase *h, struct LineartStaticMemPool *smp, void *data, int size)
LineartElementLinkNode * lineart_find_matching_eln(struct ListBase *shadow_elns, int obindex)
#define LRT_ITER_ALL_LINES_END
#define LRT_ITER_ALL_LINES_NEXT
#define LRT_ITER_ALL_LINES_BEGIN
ccl_device_inline float2 fabs(const float2 a)
LineartBoundingArea * child
LineartEdge ** linked_lines
LineartEdgeChainItem * eci
bool use_loose_edge_chain
bool chain_preserve_details
float chaining_image_threshold
double active_camera_pos[3]
bool use_geometry_space_chain
ListBase vertex_buffer_pointers
ListBase line_buffer_pointers
struct LineartData::_conf conf
struct LineartData::_geom geom
LineartStaticMemPool * chain_data_pool
uint8_t material_mask_bits
LineartEdgeChainItem * prev
LineartEdgeChainItem * next
uint32_t shadow_mask_bits
uint8_t material_mask_bits
uint32_t shadow_mask_bits
uint8_t intersection_mask
LineartEdgeSegment * next
LineartEdgeSegment * prev
uint32_t shadow_mask_bits
uint8_t material_mask_bits
uint8_t intersection_mask