19#define LRT_OTHER_VERT(e, vt) ((vt) == (e)->v1 ? (e)->v2 : ((vt) == (e)->v2 ? (e)->v1 : nullptr))
91 if (((eci->
pos[0] + threshold) >= x) && ((eci->
pos[0] - threshold) <= x) &&
92 ((eci->
pos[1] + threshold) >= y) && ((eci->
pos[1] - threshold) <= y))
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);
221 N[0] +=
e->t1->gn[0];
222 N[1] +=
e->t1->gn[1];
223 N[2] +=
e->t1->gn[2];
226 N[0] +=
e->t2->gn[0];
227 N[1] +=
e->t2->gn[1];
228 N[2] +=
e->t2->gn[2];
230 if (
e->t1 ||
e->t2) {
254 if (new_e->
t1 || new_e->
t2) {
257 N[0] += new_e->
t1->
gn[0];
258 N[1] += new_e->
t1->
gn[1];
259 N[2] += new_e->
t1->
gn[2];
262 N[0] += new_e->
t2->
gn[0];
263 N[1] += new_e->
t2->
gn[1];
264 N[2] += new_e->
t2->
gn[2];
269 if (new_vt == new_e->
v1) {
271 double gpos[3], lpos[3];
273 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
293 else if (new_vt == new_e->
v2) {
299 for (; es; es = es->
next) {
300 double gpos[3], lpos[3];
302 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
337 if (
e->t1 ||
e->t2) {
340 N[0] +=
e->t1->gn[0];
341 N[1] +=
e->t1->gn[1];
342 N[2] +=
e->t1->gn[2];
345 N[0] +=
e->t2->gn[0];
346 N[1] +=
e->t2->gn[1];
347 N[2] +=
e->t2->gn[2];
357 for (es = es->
next; es; es = es->
next) {
358 double gpos[3], lpos[3];
359 double *lfb =
e->v1->fbcoord, *rfb =
e->v2->fbcoord;
360 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
363 use_fbcoord[3] =
interpf(
e->v2->fbcoord[3],
e->v1->fbcoord[3], global_at);
399 if (new_e->
t1 || new_e->
t2) {
402 N[0] += new_e->
t1->
gn[0];
403 N[1] += new_e->
t1->
gn[1];
404 N[2] += new_e->
t1->
gn[2];
407 N[0] += new_e->
t2->
gn[0];
408 N[1] += new_e->
t2->
gn[1];
409 N[2] += new_e->
t2->
gn[2];
418 if (new_vt == new_e->
v1) {
428 double gpos[3], lpos[3];
430 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
450 else if (new_vt == new_e->
v2) {
459 for (; es; es = es->
next) {
460 double gpos[3], lpos[3];
462 double global_at = lfb[3] * es->
ratio / (es->
ratio * lfb[3] + (1 - es->
ratio) * rfb[3]);
509 if (root->
child ==
nullptr) {
514#define IN_BOUND(ba, eci) \
515 ba.l <= eci->pos[0] && ba.r >= eci->pos[0] && ba.b <= eci->pos[1] && ba.u >= eci->pos[1]
540 if (root ==
nullptr) {
557 if (root->
child ==
nullptr) {
571#define IN_BOUND(ba, eci) \
572 ba.l <= eci->pos[0] && ba.r >= eci->pos[0] && ba.b <= eci->pos[1] && ba.u >= eci->pos[1]
608 float distance_threshold,
609 bool preserve_details,
612 float dist_accum = 0;
614 int fixed_occ = last_matching_eci->
occlusion;
622 if (dist_accum > distance_threshold) {
628 if (eci->occlusion < fixed_occ) {
631 if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ &&
632 eci->shadow_mask_bits == fixed_shadow)
642 next_eci = eci->
next;
643 if (eci->material_mask_bits == fixed_mask && eci->occlusion == fixed_occ &&
644 eci->shadow_mask_bits == fixed_shadow)
648 if (preserve_details) {
650 eci->occlusion = fixed_occ;
651 eci->shadow_mask_bits = fixed_shadow;
657 *r_next_eci = can_skip_to;
675 ec->next = ec->prev =
nullptr;
678 ec->loop_id = loop_id;
685 ec->level = fixed_occ;
686 ec->material_mask_bits = fixed_mask;
687 ec->shadow_mask_bits = fixed_shadow;
688 for (eci = first_eci->
next; eci; eci = next_eci) {
689 next_eci = eci->
next;
719 ec->chain.last = eci->
prev;
735 new_ec->
type = ec->type;
741 ec->level = fixed_occ;
742 ec->material_mask_bits = fixed_mask;
743 ec->shadow_mask_bits = fixed_shadow;
806 if (onto->chain.first ==
nullptr) {
828 float *result_new_len,
852 if (cre->ec->picked || cre->picked) {
855 if (cre->ec == ec || (!cre->ec->chain.first) || (cre->ec->level != occlusion) ||
856 (cre->ec->material_mask_bits != material_mask_bits) ||
857 (cre->ec->intersection_mask != isec_mask) || (cre->ec->shadow_mask_bits != shadow_mask))
862 if (cre->ec->type != ec->
type) {
881 if (((cre->ec->loop_id == loop_id) && (new_len < dist)) ||
882 ((cre->ec->loop_id != loop_id) && (new_len < dist / 10)))
886 if (result_new_len) {
887 (*result_new_len) = new_len;
893 float adjacent_new_len = dist;
896#define LRT_TEST_ADJACENT_AREAS(dist_to, list) \
897 if (dist_to < dist && dist_to > 0) { \
898 LISTBASE_FOREACH (LinkData *, link, list) { \
899 LineartBoundingArea *sba = (LineartBoundingArea *)link->data; \
900 adjacent_closest = lineart_chain_get_closest_cre(ld, \
905 material_mask_bits, \
912 if (adjacent_new_len < dist) { \
913 dist = adjacent_new_len; \
914 closest_cre = adjacent_closest; \
924 if (result_new_len) {
925 (*result_new_len) = dist;
936 float dist_l, dist_r;
937 int reverse_main, loop_id;
938 uint8_t occlusion, material_mask_bits, isec_mask;
952 ec->next = ec->prev =
nullptr;
953 if (ec->picked || ec->chain.first == ec->chain.last) {
957 loop_id = ec->loop_id;
963 occlusion = ec->level;
964 material_mask_bits = ec->material_mask_bits;
965 isec_mask = ec->intersection_mask;
966 shadow_mask = ec->shadow_mask_bits;
997 if (closest_cre_l && closest_cre_r) {
998 if (dist_l < dist_r) {
999 closest_cre = closest_cre_l;
1003 closest_cre = closest_cre_r;
1007 else if (closest_cre_l) {
1008 closest_cre = closest_cre_l;
1011 else if (closest_cre_r) {
1012 closest_cre = closest_cre_r;
1038 float offset_accum = 0;
1040 float last_point[2];
1049 offset_accum += dist;
1052 return offset_accum;
1056 const float threshold,
1079 if (lc ==
nullptr) {
1090 if (eln->object_ref == ob) {
1124 for (
int times = 0; times < 2; times++) {
1126 *next_eci = eci->
next;
1132 if (!(eci2 = eci->
next) || !(eci3 = eci2->
next)) {
1134 next_eci = eci->
next;
1150 float vec2[2],
vec3[2], v2n[2], ratio, len2;
1164 if (ratio < len2 && ratio > -len2 * 10) {
1166 if ((eci4 = eci3->
next) &&
1185 next_eci = eci->next;
1198 float ref_lu[2] = {-1.0f, 1.0f}, ref_lb[2] = {-1.0f, -1.0f}, ref_ru[2] = {1.0f, 1.0f},
1199 ref_rb[2] = {1.0f, -1.0f};
1202 if (eci2->
pos[0] < -1.0f) {
1205 if (!found && eci2->
pos[0] > 1.0f) {
1208 if (!found && eci2->
pos[1] < -1.0f) {
1211 if (!found && eci2->
pos[1] > 1.0f) {
1219 float ratio = (
fabs(eci2->
pos[0] - eci1->pos[0]) >
fabs(eci2->
pos[1] - eci1->pos[1])) ?
1220 ratiof(eci1->pos[0], eci2->
pos[0], isec[0]) :
1221 ratiof(eci1->pos[1], eci2->
pos[1], isec[1]);
1222 float gratio = eci1->pos[3] * ratio / (ratio * eci1->pos[3] + (1 - ratio) * eci2->
pos[3]);
1234#define LRT_ECI_INSIDE(eci) \
1235 ((eci)->pos[0] >= -1.0f && (eci)->pos[0] <= 1.0f && (eci)->pos[1] >= -1.0f && \
1236 (eci)->pos[1] <= 1.0f)
1248 bool ec_added =
false;
1254 for (eci = first_eci->
next; eci; eci = next_eci) {
1255 next_eci = eci->
next;
1256 prev_eci = eci->
prev;
1261 if (new_inside ==
false) {
1269 eci->
prev =
nullptr;
1270 prev_eci->
next =
nullptr;
1271 ec->chain.last = prev_eci;
1277 next_eci = eci->
next;
1284 ec->chain.first = eci;
1285 eci->
prev =
nullptr;
1291 next_eci = eci->
next;
1314 ec->next = ec->prev =
nullptr;
1317 for (eci = first_eci->
next; eci; eci = next_eci) {
1318 next_eci = eci->
next;
1319 prev_eci = eci->
prev;
1321 if (next_eci && prev_eci) {
1327 if (angle < angle_threshold_rad) {
1332 ec->chain.last = eci->
prev;
1334 eci->
prev =
nullptr;
1348 new_ec->
type = ec->type;
1349 new_ec->
level = ec->level;
1350 new_ec->
loop_id = ec->loop_id;
1365 float view_clamp[3];
1367 if (use_custom_camera) {
1378 float orig_len =
len_v3(dir);
1392 mul_v3_fl(view_clamp, std::min(dist, len_lim));
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void void void void void void void BLI_listbase_reverse(struct 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
#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)
struct LineartBoundingArea * child
struct 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
struct LineartEdgeChainItem * next
uint32_t shadow_mask_bits
struct LineartEdgeChainItem * prev
uint8_t material_mask_bits
struct LineartEdgeChain * next
uint32_t shadow_mask_bits
uint8_t intersection_mask
struct Object * object_ref
struct LineartEdgeSegment * prev
struct LineartEdgeSegment * next
uint32_t shadow_mask_bits
uint8_t material_mask_bits
struct LineartTriangle * t2
uint8_t intersection_mask
struct LineartTriangle * t1
struct Object * object_ref