106 const double *override_camera_loc,
107 const bool override_cam_is_persp,
108 const bool allow_overlapping_edges,
109 const double m_view_projection[4][4],
110 const double camera_dir[3],
111 const float cam_shift_x,
112 const float cam_shift_y,
122 bool do_intersection,
164 uchar material_mask_bits,
166 uint32_t shadow_bits)
199 cut_start_before = seg;
200 new_seg1 = cut_start_before;
203 if (seg->next ==
nullptr) {
207 if (i_seg->
ratio > start + 1
e-09 && start > seg->ratio) {
208 cut_start_before = i_seg;
220 cut_end_before = seg;
221 new_seg2 = cut_end_before;
227 cut_end_before = seg;
228 new_seg2 = cut_end_before;
233 if (seg->ratio > end) {
234 cut_end_before = seg;
241 if (new_seg1 ==
nullptr) {
244 if (new_seg2 ==
nullptr) {
247 cut_end_before = new_seg2;
254 if (cut_start_before) {
255 if (cut_start_before != new_seg1) {
257 i_seg = cut_start_before->
prev ? cut_start_before->
prev :
nullptr;
276 if (cut_end_before) {
278 if (cut_end_before != new_seg2) {
279 i_seg = cut_end_before->
prev ? cut_end_before->
prev :
nullptr;
300 new_seg1->
ratio = start;
302 new_seg2->ratio = end;
306 new_seg2 = new_seg2->next;
311 seg->occlusion += mat_occlusion;
312 seg->material_mask_bits |= material_mask_bits;
327 seg->shadow_mask_bits |= shadow_bits;
332 int8_t min_occ = 127;
336 if (prev_seg && prev_seg->
occlusion == seg->occlusion &&
347 min_occ = std::min<int8_t>(min_occ, seg->occlusion);
351 e->min_occ = min_occ;
395 for (
int i = 0;
i < nba->triangle_count;
i++) {
407 tri->testing_e[thread_id] =
e;
479 for (
i = 0;
i < thread_count;
i++) {
504 cl = (v0[0] -
v[0]) * (v1[1] -
v[1]) - (v0[1] -
v[1]) * (v1[0] -
v[0]);
507 cl = (v1[0] -
v[0]) * (
v2[1] -
v[1]) - (v1[1] -
v[1]) * (
v2[0] -
v[0]);
514 cl = (
v2[0] -
v[0]) * (v0[1] -
v[1]) - (
v2[1] -
v[1]) * (v0[0] -
v[0]);
531 double c1 = 1, c2 = 0;
537 if (v1[0] == v0[0] && v1[1] == v0[1]) {
542 c1 =
ratiod(v0[0], v1[0],
v[0]);
546 c2 =
ratiod(v0[1], v1[1],
v[1]);
553 c2 =
ratiod(v0[1], v1[1],
v[1]);
557 c1 =
ratiod(v0[0], v1[0],
v[0]);
593 cl = (v0[0] -
v[0]) * (v1[1] -
v[1]) - (v0[1] -
v[1]) * (v1[0] -
v[0]);
596 cl = (v1[0] -
v[0]) * (
v2[1] -
v[1]) - (v1[1] -
v[1]) * (
v2[0] -
v[0]);
597 if ((r = c * cl) < 0) {
603 cl = (
v2[0] -
v[0]) * (v0[1] -
v[1]) - (
v2[1] -
v[1]) * (v0[0] -
v[0]);
604 if ((r = c * cl) < 0) {
610 cl = (v0[0] -
v[0]) * (v1[1] -
v[1]) - (v0[1] -
v[1]) * (v1[0] -
v[0]);
611 if ((r = c * cl) < 0) {
734 tri->
flags |= intersection_only;
739 return ((tri->
v[v1] ==
e->v1 && tri->
v[
v2] ==
e->v2) ||
740 (tri->
v[
v2] ==
e->v1 && tri->
v[v1] ==
e->v2));
763 bool allow_boundaries,
764 double m_view_projection[4][4],
773 double span_v1[3], span_v2[3], dot_v1, dot_v2;
775 int v_count = *r_v_count;
776 int e_count = *r_e_count;
777 int t_count = *r_t_count;
778 uint16_t new_flag = 0;
802#define INCREASE_EDGE \
803 new_e = &((LineartEdge *)e_eln->pointer)[e_count]; \
806 es = static_cast<LineartEdgeSegment *>( \
807 lineart_mem_acquire(&ld->render_data_pool, sizeof(LineartEdgeSegment))); \
808 BLI_addtail(&e->segments, es);
810#define SELECT_EDGE(e_num, v1_link, v2_link, new_tri) \
811 if (tri_adj->e[e_num]) { \
812 old_e = tri_adj->e[e_num]; \
813 new_flag = old_e->flags; \
814 old_e->flags = MOD_LINEART_EDGE_FLAG_CHAIN_PICKED; \
815 lineart_discard_duplicated_edges(old_e); \
819 e->v1->index = (v1_link)->index; \
820 e->v2->index = (v1_link)->index; \
821 e->flags = new_flag; \
822 e->object_ref = ob; \
823 e->t1 = ((old_e->t1 == tri) ? (new_tri) : (old_e->t1)); \
824 e->t2 = ((old_e->t2 == tri) ? (new_tri) : (old_e->t2)); \
825 lineart_add_edge_to_array(&ld->pending_edges, e); \
828#define RELINK_EDGE(e_num, new_tri) \
829 if (tri_adj->e[e_num]) { \
830 old_e = tri_adj->e[e_num]; \
831 old_e->t1 = ((old_e->t1 == tri) ? (new_tri) : (old_e->t1)); \
832 old_e->t2 = ((old_e->t2 == tri) ? (new_tri) : (old_e->t2)); \
835#define REMOVE_TRIANGLE_EDGE \
836 if (tri_adj->e[0]) { \
837 tri_adj->e[0]->flags = MOD_LINEART_EDGE_FLAG_CHAIN_PICKED; \
838 lineart_discard_duplicated_edges(tri_adj->e[0]); \
840 if (tri_adj->e[1]) { \
841 tri_adj->e[1]->flags = MOD_LINEART_EDGE_FLAG_CHAIN_PICKED; \
842 lineart_discard_duplicated_edges(tri_adj->e[1]); \
844 if (tri_adj->e[2]) { \
845 tri_adj->e[2]->flags = MOD_LINEART_EDGE_FLAG_CHAIN_PICKED; \
846 lineart_discard_duplicated_edges(tri_adj->e[2]); \
849 switch (in0 + in1 + in2) {
890 a = dot_v1 / (dot_v1 + dot_v2);
901 a = dot_v1 / (dot_v1 + dot_v2);
909 if (allow_boundaries) {
929 tri1->
v[0] = tri->
v[0];
943 a = dot_v1 / (dot_v1 + dot_v2);
952 a = dot_v1 / (dot_v1 + dot_v2);
958 if (allow_boundaries) {
972 tri1->
v[2] = tri->
v[2];
984 a = dot_v1 / (dot_v1 + dot_v2);
993 a = dot_v1 / (dot_v1 + dot_v2);
999 if (allow_boundaries) {
1011 tri1->
v[0] = &vt[0];
1012 tri1->
v[1] = tri->
v[1];
1013 tri1->
v[2] = &vt[1];
1055 a = dot_v2 / (dot_v1 + dot_v2);
1066 a = dot_v2 / (dot_v1 + dot_v2);
1074 if (allow_boundaries) {
1091 tri1->
v[0] = tri->
v[1];
1092 tri1->
v[1] = &vt[1];
1093 tri1->
v[2] = &vt[0];
1095 tri2->
v[0] = &vt[1];
1096 tri2->
v[1] = tri->
v[1];
1097 tri2->
v[2] = tri->
v[2];
1111 a = dot_v1 / (dot_v1 + dot_v2);
1120 a = dot_v1 / (dot_v1 + dot_v2);
1126 if (allow_boundaries) {
1140 tri1->
v[0] = tri->
v[2];
1141 tri1->
v[1] = &vt[1];
1142 tri1->
v[2] = &vt[0];
1144 tri2->
v[0] = &vt[1];
1145 tri2->
v[1] = tri->
v[2];
1146 tri2->
v[2] = tri->
v[0];
1160 a = dot_v1 / (dot_v1 + dot_v2);
1169 a = dot_v1 / (dot_v1 + dot_v2);
1175 if (allow_boundaries) {
1189 tri1->
v[0] = tri->
v[0];
1190 tri1->
v[1] = &vt[1];
1191 tri1->
v[2] = &vt[0];
1193 tri2->
v[0] = &vt[1];
1194 tri2->
v[1] = tri->
v[0];
1195 tri2->
v[2] = tri->
v[1];
1205 *r_v_count = v_count;
1206 *r_e_count = e_count;
1207 *r_t_count = t_count;
1212#undef REMOVE_TRIANGLE_EDGE
1221 int v_count = 0, t_count = 0, e_count = 0;
1226 double view_dir[3], clip_advance[3];
1251#define LRT_CULL_ENSURE_MEMORY \
1252 if (v_count > 60) { \
1253 v_eln->element_count = v_count; \
1254 v_eln = lineart_memory_get_vert_space(ld); \
1257 if (t_count > 60) { \
1258 t_eln->element_count = t_count; \
1259 t_eln = lineart_memory_get_triangle_space(ld); \
1262 if (e_count > 60) { \
1263 e_eln->element_count = e_count; \
1264 e_eln = lineart_memory_get_edge_space(ld); \
1268#define LRT_CULL_DECIDE_INSIDE \
1270 in0 = 0, in1 = 0, in2 = 0; \
1273 if (tri->v[0]->fbcoord[use_w] > clip_end) { \
1276 if (tri->v[1]->fbcoord[use_w] > clip_end) { \
1279 if (tri->v[2]->fbcoord[use_w] > clip_end) { \
1285 if (tri->v[0]->fbcoord[use_w] < clip_start) { \
1288 if (tri->v[1]->fbcoord[use_w] < clip_start) { \
1291 if (tri->v[2]->fbcoord[use_w] < clip_start) { \
1297 int in0 = 0, in1 = 0, in2 = 0;
1310 ob =
static_cast<Object *
>(eln->object_ref);
1311 for (
i = 0;
i < eln->element_count;
i++) {
1343#undef LRT_CULL_ENSURE_MEMORY
1344#undef LRT_CULL_DECIDE_INSIDE
1357 for (
i = 0;
i < eln->element_count;
i++) {
1370 for (
int i = 0;
i < eln->element_count;
i++) {
1391 const float bounds[4][2] = {{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, -1.0f}, {1.0f, 1.0f}};
1393#define LRT_VERT_OUT_OF_BOUND(v) \
1394 (v->fbcoord[0] < -1 || v->fbcoord[0] > 1 || v->fbcoord[1] < -1 || v->fbcoord[1] > 1)
1398 for (
int i = 0;
i < eln->element_count;
i++) {
1399 if (!
e[
i].v1 || !
e[
i].
v2) {
1454#define LRT_MESH_EDGE_TYPES_COUNT 6
1476 int8_t *
b = (int8_t *)rt_array;
1509 void *__restrict chunk_join,
1510 void *__restrict chunk)
1530 uint16_t edge_flag_result = 0;
1534 if (
i < edge_nabr[
i].
e) {
1538 bool face_mark_filtered =
false;
1541 bool only_contour =
false;
1542 if (enable_face_mark) {
1548 if (edge_nabr[
i].
e > -1) {
1549 ff2 = &((
FreestyleFace *)
mesh->face_data.layers[index].data)[tri_faces[edge_nabr[
i].
e / 3]];
1561 face_mark_filtered =
true;
1566 face_mark_filtered =
true;
1570 face_mark_filtered = !face_mark_filtered;
1572 if (!face_mark_filtered) {
1575 only_contour =
true;
1580 if (enable_face_mark && !face_mark_filtered && !only_contour) {
1585 if (edge_nabr[
i].
e == -1) {
1595 int f1 =
i / 3, f2 = edge_nabr[
i].
e / 3;
1601 vert = &e_feat_data->
v_array[edge_nabr[
i].
v1];
1603 double view_vector_persp[3];
1604 double *view_vector = view_vector_persp;
1605 double dot_v1 = 0, dot_v2 = 0;
1620 if ((
result = dot_v1 * dot_v2) <= 0 && (dot_v1 + dot_v2)) {
1632 if (material_back_face) {
1643 view_vector = view_vector_persp;
1654 if ((
result = dot_v1 * dot_v2) <= 0 && (dot_v1 + dot_v2)) {
1659 if (!only_contour) {
1661 bool do_crease =
true;
1672 int mat1 = material_indices.
is_empty() ? 0 : material_indices[tri_faces[f1]];
1673 int mat2 = material_indices.
is_empty() ? 0 : material_indices[tri_faces[f2]];
1692 if (!edge_flag_result) {
1700 corner_tris[
i / 3]);
1702 if (real_edges[
i % 3] >= 0) {
1719 edge_nabr[
i].
flags = edge_flag_result;
1721 if (edge_flag_result) {
1744 "LineartPendingEdges array");
1750 pe->
array = new_array;
1771 "LineartPendingEdges array final");
1772 pe->
array = new_array;
1826 const int face_i = tri_task_data->
tri_faces[
i];
1834 int v1 = corner_verts[corner_tri[0]];
1835 int v2 = corner_verts[corner_tri[1]];
1836 int v3 = corner_verts[corner_tri[2]];
1838 tri->
v[0] = &vert_arr[v1];
1839 tri->
v[1] = &vert_arr[
v2];
1840 tri->
v[2] = &vert_arr[v3];
1900 adj_e->
v1 = corner_verts[tri[
i % 3]];
1901 adj_e->
v2 = corner_verts[tri[(
i + 1) % 3]];
1902 if (adj_e->
v1 > adj_e->
v2) {
1903 std::swap(adj_e->
v1, adj_e->
v2);
1907 edge_nabr->
v1 = adj_e->
v1;
1908 edge_nabr->
v2 = adj_e->
v2;
1909 edge_nabr->
flags = 0;
1916 int a = p1.
v1 - p2.
v1;
1917 int b = p1.
v2 - p2.
v2;
1935 "LineartAdjacentEdge arr");
1937 size_t(total_edges),
"LineartEdgeNeighbor arr");
1945 en_data.
adj_e = adj_e;
1955 for (
int i = 0;
i < total_edges - 1;
i++) {
1956 if (adj_e[
i].v1 == adj_e[
i + 1].v1 && adj_e[
i].
v2 == adj_e[
i + 1].
v2) {
1957 edge_nabr[adj_e[
i].
e].
e = adj_e[
i + 1].
e;
1958 edge_nabr[adj_e[
i + 1].
e].
e = adj_e[
i].
e;
1973 if (!
mesh->edges_num) {
1983 bool can_find_freestyle_edge =
false;
1985 if (layer_index != -1) {
1986 can_find_freestyle_edge =
true;
1989 bool can_find_freestyle_face =
false;
1991 if (layer_index != -1) {
1992 can_find_freestyle_face =
true;
2016 ob_info->
v_eln = elem_link_node;
2018 bool use_auto_smooth =
false;
2019 float crease_angle = 0;
2041 int usage = ob_info->
usage;
2046 elem_link_node->
flags |
2051 size_t(corner_tris.
size()),
"LineartTriangleAdjacent");
2066 vert_data.
v_arr = la_v_arr;
2088 tri_data.
tri_arr = la_tri_arr;
2092 uint32_t total_edges = corner_tris.
size() * 3;
2115 edge_feat_data.
ld = la_data;
2116 edge_feat_data.mesh =
mesh;
2118 edge_feat_data.material_indices = material_indices;
2119 edge_feat_data.edges =
mesh->edges();
2120 edge_feat_data.corner_verts =
mesh->corner_verts();
2121 edge_feat_data.corner_edges =
mesh->corner_edges();
2122 edge_feat_data.corner_tris = corner_tris;
2123 edge_feat_data.tri_faces =
mesh->corner_tri_faces();
2124 edge_feat_data.sharp_edges = sharp_edges;
2125 edge_feat_data.sharp_faces = sharp_faces;
2127 edge_feat_data.tri_array = la_tri_arr;
2128 edge_feat_data.v_array = la_v_arr;
2129 edge_feat_data.crease_threshold = crease_angle;
2130 edge_feat_data.use_auto_smooth = use_auto_smooth;
2131 edge_feat_data.use_freestyle_face = can_find_freestyle_face;
2132 edge_feat_data.use_freestyle_edge = can_find_freestyle_edge;
2133 if (edge_feat_data.use_freestyle_face) {
2137 if (edge_feat_data.use_freestyle_edge) {
2146 &edge_feat_settings);
2155 if (loose_edges.
count > 0) {
2191 la_edge = la_edge_arr;
2192 la_seg = la_seg_arr;
2194 for (
int i = 0;
i < total_edges;
i++) {
2202 if (edge_nabr->
flags == 0) {
2211 if (!(use_type & edge_nabr->
flags)) {
2215 la_edge->
v1 = &la_v_arr[edge_nabr->
v1];
2216 la_edge->
v2 = &la_v_arr[edge_nabr->
v2];
2222 if (edge_nabr->
e != -1) {
2223 findex = edge_nabr->
e / 3;
2229 la_edge->
flags = use_type;
2257 edge_added = la_edge;
2272 la_edge->
v1 = &la_v_arr[edge[0]];
2273 la_edge->
v2 = &la_v_arr[edge[1]];
2364 if (object_has_special_usage) {
2407 int this_face_count)
2411 for (
int i = 0;
i < thread_count;
i++) {
2412 if (olti_list[
i].total_faces < min_face) {
2414 use_olti = &olti_list[
i];
2432 const std::optional<Bounds<float3>>
bounds = use_mesh->bounds_min_max();
2433 if (!
bounds.has_value()) {
2441 for (
int i = 0;
i < 8;
i++) {
2445 co[
i][0] -= shift_x * 2 * co[
i][3];
2446 co[
i][1] -= shift_y * 2 * co[
i][3];
2449 bool cond[6] = {
true,
true,
true,
true,
true,
true};
2452 for (
int i = 0;
i < 8;
i++) {
2453 cond[0] &= (co[
i][0] < -co[
i][3]);
2454 cond[1] &= (co[
i][0] > co[
i][3]);
2455 cond[2] &= (co[
i][1] < -co[
i][3]);
2456 cond[3] &= (co[
i][1] > co[
i][3]);
2457 cond[4] &= (co[
i][2] < -co[
i][3]);
2458 cond[5] &= (co[
i][2] > co[
i][3]);
2460 for (
int i = 0;
i < 6;
i++) {
2473 const float use_mat[4][4],
2502 if ((!use_mesh) || use_mesh->
runtime->edit_mesh) {
2544 bool allow_duplicates,
2545 bool do_shadow_casting,
2552 if (!do_shadow_casting) {
2556 double asp = (double(ld->
w) / double(ld->
h));
2572 BLI_assert(!
"Unsupported camera type in lineart_main_load_geometries");
2589 if (
G.debug_value == 4000) {
2594 int bound_box_discard_count = 0;
2608 if (allow_duplicates) {
2614 deg_iter_settings.
flags = flags;
2639 eval_ob->object_to_world().ptr(),
2650 if (
G.debug_value == 4000) {
2651 printf(
"thread count: %d\n", thread_count);
2653 for (
int i = 0;
i < thread_count;
i++) {
2667 for (
int i = 0;
i < thread_count;
i++) {
2672 edge_count += obi->pending_edges.next;
2677 for (
int i = 0;
i < thread_count;
i++) {
2683 int v_count = obi->v_eln->element_count;
2684 obi->v_eln->global_index_offset = global_i;
2685 for (
int vi = 0; vi < v_count; vi++) {
2686 v[vi].index += global_i;
2692 obi->global_i_offset = global_i;
2693 global_i += v_count;
2698 if (
G.debug_value == 4000) {
2700 printf(
"Line art loading time: %lf\n", t_elapsed);
2701 printf(
"Discarded %d object from bound box check\n", bound_box_discard_count);
2714 if (tri->
v[0] == vt) {
2719 if (tri->
v[1] == vt) {
2724 if (tri->
v[2] == vt) {
2734 bool allow_overlapping_edges)
2755 if (allow_overlapping_edges) {
2756#define LRT_TRI_SAME_POINT(tri, i, pt) \
2757 ((LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[0], pt->gloc[0]) && \
2758 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[1], pt->gloc[1]) && \
2759 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[2], pt->gloc[2])) || \
2760 (LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[0], pt->gloc[0]) && \
2761 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[1], pt->gloc[1]) && \
2762 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[2], pt->gloc[2])))
2770#undef LRT_TRI_SAME_POINT
2777#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst) \
2779 lst[0] = LRT_MIN3_INDEX(ia, ib, ic); \
2780 lst[1] = (((ia <= ib && ib <= ic) || (ic <= ib && ib <= ia)) ? \
2782 (((ic <= ia && ia <= ib) || (ib < ia && ia <= ic)) ? 0 : 2)); \
2783 lst[2] = LRT_MAX3_INDEX(ia, ib, ic); \
2787#define INTERSECT_JUST_GREATER(is, order, num, index) \
2789 index = (num < is[order[0]] ? \
2791 (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : -1))); \
2795#define INTERSECT_JUST_SMALLER(is, order, num, index) \
2797 index = (num > is[order[2]] ? \
2799 (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : -1))); \
2802#define LRT_ISEC(index) (index == 0 ? isec_e1 : (index == 1 ? isec_e2 : isec_e3))
2803#define LRT_PARALLEL(index) (index == 0 ? para_e1 : (index == 1 ? para_e2 : para_e3))
2829 const double *override_camera_loc,
2830 const bool override_cam_is_persp,
2831 const bool allow_overlapping_edges,
2832 const double m_view_projection[4][4],
2833 const double camera_dir[3],
2834 const float cam_shift_x,
2835 const float cam_shift_y,
2839 double cross_ratios[3] = {0};
2841 int cross_v1 = -1, cross_v2 = -1;
2843 int isec_e1, isec_e2, isec_e3;
2845 bool para_e1, para_e2, para_e3;
2850 double view_vector[4];
2852 double dot_v1, dot_v2, dot_v1a, dot_v2a;
2854 double gloc[4], trans[4];
2857 double *LFBC =
e->v1->fbcoord, *RFBC =
e->v2->fbcoord, *FBC0 = tri->
v[0]->
fbcoord,
2861 if ((std::max({FBC0[0], FBC1[0], FBC2[0]}) < std::min(LFBC[0], RFBC[0])) ||
2862 (std::min({FBC0[0], FBC1[0], FBC2[0]}) > std::max(LFBC[0], RFBC[0])) ||
2863 (std::max({FBC0[1], FBC1[1], FBC2[1]}) < std::min(LFBC[1], RFBC[1])) ||
2864 (std::min({FBC0[1], FBC1[1], FBC2[1]}) > std::max(LFBC[1], RFBC[1])) ||
2865 (std::min({FBC0[3], FBC1[3], FBC2[3]}) > std::max(LFBC[3], RFBC[3])))
2888 if (override_cam_is_persp) {
2915 if (
fabs(dot_f) < FLT_EPSILON) {
2924 if (!isec_e1 && !isec_e2 && !isec_e3) {
2926 if ((!state_v1) && (!state_v2)) {
2933 dot_v1a =
fabs(dot_v1);
2934 if (dot_v1a < DBL_EPSILON) {
2938 dot_v2a =
fabs(dot_v2);
2939 if (dot_v2a < DBL_EPSILON) {
2943 if (dot_v1 - dot_v2 == 0) {
2946 else if (dot_v1 * dot_v2 <= 0) {
2947 cut = dot_v1a /
fabs(dot_v1 - dot_v2);
2950 cut =
fabs(dot_v2 + dot_v1) /
fabs(dot_v1 - dot_v2);
2951 cut = dot_v2a > dot_v1a ? 1 - cut : cut;
2955 if (override_cam_is_persp) {
2959 trans[0] -= cam_shift_x * 2;
2960 trans[1] -= cam_shift_y * 2;
2962 if (
fabs(
e->v1->fbcoord[0] -
e->v2->fbcoord[0]) >
fabs(
e->v1->fbcoord[1] -
e->v2->fbcoord[1]))
2964 cut =
ratiod(
e->v1->fbcoord[0],
e->v2->fbcoord[0], trans[0]);
2967 cut =
ratiod(
e->v1->fbcoord[1],
e->v2->fbcoord[1], trans[1]);
2971#define LRT_GUARD_NOT_FOUND \
2972 if (cross_v1 < 0 || cross_v2 < 0) { \
3065 if (cross_v1 >= 0 &&
LRT_ISEC(cross_v1)) {
3069 if (cross_v1 >= 0) {
3071 if (cross_v1 >= 0) {
3081 double dot_1f = dot_v1 * dot_f, dot_2f = dot_v2 * dot_f;
3084 if (dot_1f <= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) {
3085 *from = std::max(0.0, cross_ratios[cross_v1]);
3086 *to = std::min(1.0, cross_ratios[cross_v2]);
3092 if (dot_1f >= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) {
3093 *from = std::max(cut, cross_ratios[cross_v1]);
3094 *to = std::min(1.0, cross_ratios[cross_v2]);
3100 if (dot_1f <= 0 && dot_2f >= 0 && (dot_v1 || dot_v2)) {
3101 *from = std::max(0.0, cross_ratios[cross_v1]);
3102 *to = std::min(cut, cross_ratios[cross_v2]);
3113#undef INTERSECT_SORT_MIN_TO_MAX_3
3114#undef INTERSECT_JUST_GREATER
3115#undef INTERSECT_JUST_SMALLER
3125 if (
l->v[0]->index == r->
v[0]->
index) {
3126 if (
l->v[1]->index == r->
v[1]->
index ||
l->v[1]->index == r->
v[2]->
index ||
3127 l->v[2]->index == r->
v[2]->
index ||
l->v[2]->index == r->
v[1]->
index)
3132 if (
l->v[0]->index == r->
v[1]->
index) {
3133 if (
l->v[1]->index == r->
v[0]->
index ||
l->v[1]->index == r->
v[2]->
index ||
3134 l->v[2]->index == r->
v[2]->
index ||
l->v[2]->index == r->
v[0]->
index)
3139 if (
l->v[0]->index == r->
v[2]->
index) {
3140 if (
l->v[1]->index == r->
v[1]->
index ||
l->v[1]->index == r->
v[0]->
index ||
3141 l->v[2]->index == r->
v[0]->
index ||
l->v[2]->index == r->
v[1]->
index)
3146 if (
l->v[1]->index == r->
v[0]->
index) {
3147 if (
l->v[2]->index == r->
v[1]->
index ||
l->v[2]->index == r->
v[2]->
index ||
3148 l->v[0]->index == r->
v[2]->
index ||
l->v[0]->index == r->
v[1]->
index)
3153 if (
l->v[1]->index == r->
v[1]->
index) {
3154 if (
l->v[2]->index == r->
v[0]->
index ||
l->v[2]->index == r->
v[2]->
index ||
3155 l->v[0]->index == r->
v[2]->
index ||
l->v[0]->index == r->
v[0]->
index)
3160 if (
l->v[1]->index == r->
v[2]->
index) {
3161 if (
l->v[2]->index == r->
v[1]->
index ||
l->v[2]->index == r->
v[0]->
index ||
3162 l->v[0]->index == r->
v[0]->
index ||
l->v[0]->index == r->
v[1]->
index)
3175 if (
l->v[0] == r->
v[0]) {
3178 if (
l->v[0] == r->
v[1]) {
3181 if (
l->v[0] == r->
v[2]) {
3184 if (
l->v[1] == r->
v[0]) {
3187 if (
l->v[1] == r->
v[1]) {
3190 if (
l->v[1] == r->
v[2]) {
3193 if (
l->v[2] == r->
v[0]) {
3196 if (
l->v[2] == r->
v[1]) {
3199 if (
l->v[2] == r->
v[2]) {
3210 double dir_v1[3], dir_v2[3];
3211 double dot_v1, dot_v2;
3220 if (dot_v1 * dot_v2 > 0 || (!dot_v1 && !dot_v2)) {
3224 dot_v1 =
fabs(dot_v1);
3225 dot_v2 =
fabs(dot_v2);
3250 double *
next = v1, *last =
nullptr;
3327 "LineartIsecSingle");
3331 th->
array = new_array;
3336 isec_single->
tri1 = tri1;
3337 isec_single->
tri2 = tri2;
3339 std::swap(isec_single->
tri1, isec_single->
tri2);
3344#define LRT_ISECT_TRIANGLE_PER_THREAD 4096
3362 while (remaining > 0 && eln) {
3364 int added_count = std::min(remaining, remaining_this_eln);
3365 remaining -= added_count;
3366 if (remaining || added_count == remaining_this_eln) {
3401 for (
int i = 0;
i < thread_count;
i++) {
3431 double *G0 = tri->
v[0]->
gloc, *G1 = tri->
v[1]->
gloc, *G2 = tri->
v[2]->
gloc;
3434 for (
int i = 0;
i < up_to;
i++) {
3453 double *RG0 = testing_triangle->
v[0]->
gloc, *RG1 = testing_triangle->
v[1]->
gloc,
3454 *RG2 = testing_triangle->
v[2]->
gloc;
3457 if ((std::min({G0[2], G1[2], G2[2]}) > std::max({RG0[2], RG1[2], RG2[2]})) ||
3458 (std::max({G0[2], G1[2], G2[2]}) < std::min({RG0[2], RG1[2], RG2[2]})) ||
3459 (std::min({G0[0], G1[0], G2[0]}) > std::max({RG0[0], RG1[0], RG2[0]})) ||
3460 (std::max({G0[0], G1[0], G2[0]}) < std::min({RG0[0], RG1[0], RG2[0]})) ||
3461 (std::min({G0[1], G1[1], G2[1]}) > std::max({RG0[1], RG1[1], RG2[1]})) ||
3462 (std::max({G0[1], G1[1], G2[1]}) < std::min({RG0[1], RG1[1], RG2[1]})) ||
3470 double iv1[3], iv2[3];
3479 float direction[3] = {0, 0, 1};
3482 float obmat_no_scale[4][4];
3511 for (
int i = 0;
i < 4;
i++) {
3519 if (ld ==
nullptr) {
3544 if (ld ==
nullptr) {
3568 if (
G.debug_value == 4000) {
3569 printf(
"LRT: Destroyed render data.\n");
3600 if (!scene || !camera || !lc) {
3604 double clipping_offset = 0;
3608 clipping_offset = 0.0001;
3612 if (active_camera) {
3635 double asp = double(ld->
w) / double(ld->
h);
3755 if (ld->
w > ld->
h) {
3756 sp_w = sp_h * ld->
w / ld->
h;
3759 sp_h = sp_w * ld->
h / ld->
w;
3764 double span_w = 1.0 / sp_w * 2.0;
3765 double span_h = 1.0 / sp_h * 2.0;
3780 for (row = 0; row < sp_h; row++) {
3785 ba->
l = span_w *
col - 1.0;
3786 ba->
r = (
col == sp_w - 1) ? 1.0 : (span_w * (
col + 1) - 1.0);
3787 ba->
u = 1.0 - span_h * row;
3788 ba->
b = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1));
3790 ba->
cx = (ba->
l + ba->
r) / 2;
3791 ba->
cy = (ba->
u + ba->
b) / 2;
3797 "ba_linked_triangles");
3835 if (ba[1].u > tba->
b && ba[1].
b < tba->u) {
3839 if (ba[2].u > tba->
b && ba[2].
b < tba->u) {
3846 if (ba[0].u > tba->
b && ba[0].
b < tba->u) {
3850 if (ba[3].u > tba->
b && ba[3].
b < tba->u) {
3857 if (ba[0].r > tba->
l && ba[0].
l < tba->r) {
3861 if (ba[1].r > tba->
l && ba[1].
l < tba->r) {
3868 if (ba[2].r > tba->
l && ba[2].
l < tba->r) {
3872 if (ba[3].r > tba->
l && ba[3].
l < tba->r) {
3884 next_lip = lip2->
next;
3888 if (ba[1].u > tba->
b && ba[1].
b < tba->u) {
3891 if (ba[2].u > tba->
b && ba[2].
b < tba->u) {
3901 next_lip = lip2->
next;
3905 if (ba[0].u > tba->
b && ba[0].
b < tba->u) {
3908 if (ba[3].u > tba->
b && ba[3].
b < tba->u) {
3918 next_lip = lip2->
next;
3922 if (ba[0].r > tba->
l && ba[0].
l < tba->r) {
3925 if (ba[1].r > tba->
l && ba[1].
l < tba->r) {
3935 next_lip = lip2->
next;
3939 if (ba[2].r > tba->
l && ba[2].
l < tba->r) {
3942 if (ba[3].r > tba->
l && ba[3].
l < tba->r) {
3960 for (
int i = 0;
i < 4;
i++) {
3993 for (
int i = 0;
i < total_tile_initial;
i++) {
4004 int recursive_level)
4012 ba[0].
cx = (ba[0].
l + ba[0].
r) / 2;
4013 ba[0].
cy = (ba[0].
u + ba[0].
b) / 2;
4019 ba[1].
cx = (ba[1].
l + ba[1].
r) / 2;
4020 ba[1].
cy = (ba[1].
u + ba[1].
b) / 2;
4026 ba[2].
cx = (ba[2].
l + ba[2].
r) / 2;
4027 ba[2].
cy = (ba[2].
u + ba[2].
b) / 2;
4033 ba[3].
cx = (ba[3].
l + ba[3].
r) / 2;
4034 ba[3].
cy = (ba[3].
u + ba[3].
b) / 2;
4037 for (
int i = 0;
i < 4;
i++) {
4041 "ba_linked_triangles");
4059 ld, &ba[0], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4063 ld, &ba[1], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4067 ld, &ba[2], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4071 ld, &ba[3], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4086 double converted[4];
4089 if (((converted[0] = ba->
l) > std::max(
l[0], r[0])) ||
4090 ((converted[1] = ba->
r) < std::min(
l[0], r[0])) ||
4091 ((converted[2] = ba->
b) > std::max(
l[1], r[1])) ||
4092 ((converted[3] = ba->
u) < std::min(
l[1], r[1])))
4100 c1 = dx * (converted[2] -
l[1]) - dy * (converted[0] -
l[0]);
4103 c1 = dx * (converted[2] -
l[1]) - dy * (converted[1] -
l[0]);
4109 c1 = dx * (converted[3] -
l[1]) - dy * (converted[0] -
l[0]);
4115 c1 = dx * (converted[3] -
l[1]) - dy * (converted[1] -
l[0]);
4127 bool *r_triangle_vert_inside)
4129 double p1[2], p2[2], p3[2], p4[2];
4132 p3[0] = p1[0] = ba->
l;
4133 p2[1] = p1[1] = ba->
b;
4134 p2[0] = p4[0] = ba->
r;
4135 p3[1] = p4[1] = ba->
u;
4137 if ((FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) ||
4138 (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) ||
4139 (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1]))
4141 *r_triangle_vert_inside =
true;
4145 *r_triangle_vert_inside =
false;
4182 int recursive_level,
4183 bool do_intersection,
4186 bool triangle_vert_inside;
4193 if (old_ba->
child) {
4196 double *B1 = l_r_u_b;
4205 for (
int iba = 0; iba < 4; iba++) {
4208 ld, &old_ba->
child[iba], tri, B1, recursive, recursive_level + 1, do_intersection, th);
4226 if (triangle_vert_inside) {
4242 if (recursive_level < ld->qtree.recursive_level &&
4245 if (!old_ba->
child) {
4264 ld, root_ba, tri, l_r_u_b, recursive, recursive_level, do_intersection, th);
4277 if (recursive && ba->
child) {
4278 for (
int i = 0;
i < 4;
i++) {
4296 if (root_ba->
child ==
nullptr) {
4301 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[0]))
4306 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[1]))
4311 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[2]))
4316 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[3]))
4325 if (root_ba->
child) {
4326 for (
int i = 0;
i < 4;
i++) {
4336 "cleared lineart edges");
4352 int r1, r2, c1, c2, row,
col;
4354 for (row = r1; row != r2 + 1; row++) {
4366 uint8_t max_occlusion)
4369 for (
int i = 0;
i < 4;
i++) {
4379 int usable_count = 0;
4382 if (
e->min_occ > max_occlusion) {
4388 if (!usable_count) {
4394 "cleaned lineart edge array");
4399 if (
e->min_occ > max_occlusion) {
4402 new_array[new_i] =
e;
4427 if (!tri->
v[0] || !tri->
v[1] || !tri->
v[2]) {
4436 if (
b[0] > 1 ||
b[1] < -1 ||
b[2] > 1 ||
b[3] < -1) {
4440 (*colbegin) = int((
b[0] + 1.0) / sp_w);
4441 (*colend) = int((
b[1] + 1.0) / sp_w);
4442 (*rowend) = ld->
qtree.
count_y - int((
b[2] + 1.0) / sp_h) - 1;
4443 (*rowbegin) = ld->
qtree.
count_y - int((
b[3] + 1.0) / sp_h) - 1;
4451 *colbegin = std::max(*colbegin, 0);
4452 *rowbegin = std::max(*rowbegin, 0);
4463 if (!
e->v1 || !
e->v2) {
4467 if (
e->v1->fbcoord[0] !=
e->v1->fbcoord[0] ||
e->v2->fbcoord[0] !=
e->v2->fbcoord[0]) {
4471 b[0] = std::min(
e->v1->fbcoord[0],
e->v2->fbcoord[0]);
4472 b[1] = std::max(
e->v1->fbcoord[0],
e->v2->fbcoord[0]);
4473 b[2] = std::min(
e->v1->fbcoord[1],
e->v2->fbcoord[1]);
4474 b[3] = std::max(
e->v1->fbcoord[1],
e->v2->fbcoord[1]);
4476 if (
b[0] > 1 ||
b[1] < -1 ||
b[2] > 1 ||
b[3] < -1) {
4480 (*colbegin) = int((
b[0] + 1.0) / sp_w);
4481 (*colend) = int((
b[1] + 1.0) / sp_w);
4482 (*rowend) = ld->
qtree.
count_y - int((
b[2] + 1.0) / sp_h) - 1;
4483 (*rowbegin) = ld->
qtree.
count_y - int((
b[3] + 1.0) / sp_h) - 1;
4486 if ((*rowend) < (*rowbegin)) {
4490 if ((*colend) < (*colbegin)) {
4511 col = int((
x + 1.0) / sp_w);
4521 row = std::max(row, 0);
4530 int c = int((
x + 1.0) / sp_w);
4542 while (iba->
child) {
4545 iba = &iba->
child[0];
4548 iba = &iba->
child[3];
4553 iba = &iba->
child[1];
4556 iba = &iba->
child[2];
4584 for (
int ei = index_start; ei < index_end; ei++) {
4593 for (co = x1; co <= x2; co++) {
4594 for (r = y1; r <= y2; r++) {
4617 int total_lines = 0;
4621 if (
G.debug_value == 4000) {
4656 for (
int j = 0; j < th->
current; j++) {
4679 v2->fbcoord[2] = ZMin * ZMax / (ZMax -
fabs(
v2->fbcoord[2]) * (ZMax - ZMin));
4685 e->edge_identifier = (
uint64_t(
e->t1->target_reference) << 32) |
e->t2->target_reference;
4699 if (
e->t1->intersection_priority >
e->t2->intersection_priority) {
4700 e->object_ref = ob1;
4702 else if (
e->t1->intersection_priority <
e->t2->intersection_priority) {
4703 e->object_ref = ob2;
4708 e->object_ref = ob1;
4724 if (
G.debug_value == 4000) {
4747 if (
G.debug_value == 4000) {
4749 printf(
"Line art intersection time: %f\n", t_elapsed);
4757 double data[2] = {fbcoord1[0], fbcoord1[1]};
4758 double LU[2] = {-1, 1}, RU[2] = {1, 1},
LB[2] = {-1, -1},
RB[2] = {1, -1};
4759 double r = 1, sr = 1;
4794 double rx, ry, ux, uy, lx, ly, bx, by;
4799 if (positive_x > 0) {
4801 ry =
y + k * (rx -
x);
4804 if (positive_y > 0) {
4806 ux =
x + (uy -
y) / k;
4807 r1 =
ratiod(fbcoord1[0], fbcoord2[0], rx);
4808 r2 =
ratiod(fbcoord1[0], fbcoord2[0], ux);
4809 if (std::min(r1, r2) > 1) {
4817 if (ba->
u >= ry && ba->
b < ry) {
4828 if (ba->
r >= ux && ba->
l < ux) {
4837 else if (positive_y < 0) {
4839 bx =
x + (by -
y) / k;
4840 r1 =
ratiod(fbcoord1[0], fbcoord2[0], rx);
4841 r2 =
ratiod(fbcoord1[0], fbcoord2[0], bx);
4842 if (std::min(r1, r2) > 1) {
4848 if (ba->
u >= ry && ba->
b < ry) {
4858 if (ba->
r >= bx && ba->
l < bx) {
4868 r1 =
ratiod(fbcoord1[0], fbcoord2[0],
self->r);
4874 if (ba->
u >=
y && ba->
b <
y) {
4884 else if (positive_x < 0) {
4886 ly =
y + k * (lx -
x);
4889 if (positive_y > 0) {
4891 ux =
x + (uy -
y) / k;
4892 r1 =
ratiod(fbcoord1[0], fbcoord2[0], lx);
4893 r2 =
ratiod(fbcoord1[0], fbcoord2[0], ux);
4894 if (std::min(r1, r2) > 1) {
4900 if (ba->
u >= ly && ba->
b < ly) {
4910 if (ba->
r >= ux && ba->
l < ux) {
4920 else if (positive_y < 0) {
4922 bx =
x + (by -
y) / k;
4923 r1 =
ratiod(fbcoord1[0], fbcoord2[0], lx);
4924 r2 =
ratiod(fbcoord1[0], fbcoord2[0], bx);
4925 if (std::min(r1, r2) > 1) {
4931 if (ba->
u >= ly && ba->
b < ly) {
4941 if (ba->
r >= bx && ba->
l < bx) {
4951 r1 =
ratiod(fbcoord1[0], fbcoord2[0],
self->l);
4957 if (ba->
u >=
y && ba->
b <
y) {
4967 if (positive_y > 0) {
4968 r1 =
ratiod(fbcoord1[1], fbcoord2[1],
self->u);
4974 if (ba->
r >
x && ba->
l <=
x) {
4981 else if (positive_y < 0) {
4982 r1 =
ratiod(fbcoord1[1], fbcoord2[1],
self->b);
4988 if (ba->
r >
x && ba->
l <=
x) {
5006 bool enable_stroke_depth_offset)
5010 int intersections_only = 0;
5011 Object *lineart_camera =
nullptr;
5014 if (
G.debug_value == 4000) {
5018 bool use_render_camera_override =
false;
5030 use_render_camera_override =
true;
5032 if (!lineart_camera) {
5037 lineart_camera = scene->
camera;
5044 *cached_result = lc;
5050 use_render_camera_override ? lineart_camera : scene->
camera,
5086 if (shadow_generated) {
5134 if (!intersections_only) {
5196 if (
G.debug_value == 4000) {
5200 printf(
"Line art total time: %lf\n", t_elapsed);
5215 const int8_t source_type,
5218 const int level_start,
5219 const int level_end,
5221 const int16_t edge_types,
5222 const uchar mask_switches,
5223 const uchar material_mask_bits,
5224 const uchar intersection_mask,
5225 const float thickness,
5226 const float opacity,
5227 const uchar shadow_selection,
5228 const uchar silhouette_mode,
5229 const char *source_vgname,
5231 const int modifier_flags,
5232 const int modifier_calculation_flags)
5234 if (
G.debug_value == 4000) {
5235 printf(
"Line Art v3: Generating...\n");
5238 if (cache ==
nullptr) {
5239 if (
G.debug_value == 4000) {
5240 printf(
"nullptr Lineart cache!\n");
5245 Object *orig_ob =
nullptr;
5249 if (!source_object) {
5256 if (!source_collection) {
5273 int total_point_count = 0;
5274 int stroke_count = 0;
5280 if (!(ec->type & (edge_types & enabled_types))) {
5283 if (ec->level > level_end || ec->level < level_start) {
5286 if (orig_ob && orig_ob != ec->object_ref) {
5289 if (orig_col && ec->object_ref) {
5303 if (ec->material_mask_bits != material_mask_bits) {
5308 if (!(ec->material_mask_bits & material_mask_bits)) {
5315 if (ec->intersection_mask != intersection_mask) {
5320 if ((intersection_mask) && !(ec->intersection_mask & intersection_mask)) {
5325 if (shadow_selection) {
5349 bool is_silhouette =
false;
5351 if (!ec->silhouette_backdrop) {
5352 is_silhouette =
true;
5356 is_silhouette =
true;
5360 if ((!orig_ob) && (!ec->silhouette_backdrop)) {
5361 is_silhouette =
true;
5366 ec->silhouette_backdrop != ec->object_ref)
5368 is_silhouette =
true;
5371 if (inverse_silhouette) {
5372 is_silhouette = !is_silhouette;
5374 if (!is_silhouette) {
5387 total_point_count +=
count;
5393 if (!total_point_count || !stroke_count) {
5414 const bool weight_transfer_match_output = modifier_calculation_flags &
5420 auto ensure_target_defgroup = [&](
StringRef group_name) {
5421 if (group_name.is_empty()) {
5424 int group_index = 0;
5426 if (group_name ==
StringRef(group->name)) {
5431 group_name.copy_utf8_truncated(defgroup->
name);
5436 int up_to_point = 0;
5443 Mesh *src_mesh =
nullptr;
5445 int target_defgroup = ensure_target_defgroup(vgname);
5446 if (source_vgname) {
5450 src_dvert = src_mesh->deform_verts();
5456 int group_index = 0;
5459 const int target_group_index = weight_transfer_match_output ?
5460 ensure_target_defgroup(defgroup->name) :
5462 src_to_dst_defgroup.
append(target_group_index);
5465 src_to_dst_defgroup.
append(-1);
5470 auto transfer_to_matching_groups = [&](
const int64_t source_index,
const int target_index) {
5471 for (
const int from_group : src_to_dst_defgroup.
index_range()) {
5472 if (from_group < 0 || src_to_dst_defgroup[from_group] < 0 ||
5480 src_to_dst_defgroup[from_group]);
5481 const float source_weight = mdw_from ? mdw_from->
weight : 0.0f;
5482 mdw_to->
weight = invert_input ? (1 - source_weight) : source_weight;
5486 auto transfer_to_singular_group = [&](
const int64_t source_index,
const int target_index) {
5487 if (target_defgroup < 0) {
5490 float highest_weight = 0.0f;
5491 for (
const int from_group : src_to_dst_defgroup.
index_range()) {
5492 if (from_group < 0 ||
UNLIKELY(source_index >= src_dvert.
size())) {
5497 const float source_weight = mdw_from ? mdw_from->
weight : 0.0f;
5498 highest_weight = std::max(highest_weight, source_weight);
5501 mdw_to->
weight = invert_input ? (1 - highest_weight) : highest_weight;
5506 int point_i =
i + up_to_point;
5508 point_radii.
span[point_i] = thickness / 2.0f;
5509 if (point_opacities) {
5510 point_opacities.span[point_i] = opacity;
5515 if (!src_to_dst_defgroup.
is_empty()) {
5516 if (weight_transfer_match_output) {
5517 transfer_to_matching_groups(vindex, point_i);
5520 transfer_to_singular_group(vindex, point_i);
5525 offsets[chain_i] = up_to_point;
5526 stroke_materials.span[chain_i] =
max_ii(mat_nr, 0);
5534 stroke_cyclic.
span.fill(
false);
5538 point_opacities.finish();
5539 stroke_materials.finish();
5543 std::array<blender::bke::GeometrySet, 2> geometry_sets{
5551 if (
G.debug_value == 4000) {
5552 printf(
"LRT: Generated %d strokes.\n", stroke_count);
Camera data-block and utility functions.
float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y)
int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
bool BKE_collection_has_object_recursive_instanced(Collection *collection, Object *ob)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_layer_index(const CustomData *data, eCustomDataType type)
int CustomData_get_active_layer_index(const CustomData *data, eCustomDataType type)
Low-level operations for grease pencil.
void BKE_id_free(Main *bmain, void *idv)
General operations, lookup, etc. for materials.
Material * BKE_object_material_get(Object *ob, short act)
Material * BKE_object_material_get_eval(Object *ob, short act)
Mesh * BKE_mesh_new_from_object(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers, bool preserve_origindex, bool ensure_subdivision)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
int BKE_object_visibility(const Object *ob, int dag_eval_mode)
int BKE_render_num_threads(const RenderData *r)
bool BKE_scene_camera_switch_update(Scene *scene)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
MINLINE double ratiod(double min, double max, double pos)
MINLINE int max_ii(int a, int b)
int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
#define ISECT_LINE_LINE_NONE
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3])
void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3])
void mul_m4db_m4db_m4fl(double R[4][4], const double A[4][4], const float B[4][4])
void unit_m4_db(double m[4][4])
void copy_m4d_m4(double m1[4][4], const float m2[4][4])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_mat3_m4v3_db(double r[3], const double mat[4][4], const double vec[3])
void transpose_m4(float R[4][4])
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void copy_m4_m4_db(double m1[4][4], const double m2[4][4])
float focallength_to_fov(float focal_length, float sensor)
MINLINE double normalize_v3_db(double n[3])
void interp_v3_v3v3_db(double target[3], const double a[3], const double b[3], double t)
MINLINE void mul_v3db_db(double r[3], double f)
MINLINE void add_v3_v3_db(double r[3], const double a[3])
MINLINE double dot_v3v3_db(const double a[3], const double b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3db_v3fl(double r[3], const float a[3])
MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3])
MINLINE void copy_v3_v3_db(double r[3], const double a[3])
void interp_v2_v2v2_db(double target[2], const double a[2], const double b[2], double t)
MINLINE float normalize_v3(float n[3])
MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3])
MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2])
void BLI_task_pool_work_and_wait(TaskPool *pool)
void(* TaskRunFunction)(TaskPool *__restrict pool, void *taskdata)
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
void BLI_task_pool_free(TaskPool *pool)
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
void BLI_spin_init(SpinLock *spin)
void BLI_spin_unlock(SpinLock *spin)
void BLI_spin_lock(SpinLock *spin)
void BLI_spin_end(SpinLock *spin)
Platform independent time functions.
double BLI_time_now_seconds(void)
#define DEG_OBJECT_ITER_BEGIN(settings_, instance_)
#define DEG_OBJECT_ITER_END
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_VISIBLE
@ DEG_ITER_OBJECT_FLAG_DUPLI
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_VIEWPORT
@ COLLECTION_LRT_INTERSECTION_ONLY
@ COLLECTION_LRT_FORCE_INTERSECTION
@ COLLECTION_LRT_OCCLUSION_ONLY
@ COLLECTION_LRT_NO_INTERSECTION
@ COLLECTION_LRT_USE_INTERSECTION_MASK
@ COLLECTION_LRT_USE_INTERSECTION_PRIORITY
@ MOD_LINEART_EDGE_FLAG_PROJECTED_SHADOW
@ MOD_LINEART_EDGE_FLAG_CONTOUR
@ MOD_LINEART_EDGE_FLAG_LIGHT_CONTOUR
@ MOD_LINEART_EDGE_FLAG_SHADOW_FACING_LIGHT
@ MOD_LINEART_EDGE_FLAG_INTERSECTION
@ MOD_LINEART_EDGE_FLAG_INHIBIT
@ MOD_LINEART_EDGE_FLAG_CHAIN_PICKED
@ MOD_LINEART_EDGE_FLAG_CREASE
@ MOD_LINEART_EDGE_FLAG_CONTOUR_SECONDARY
@ MOD_LINEART_EDGE_FLAG_NEXT_IS_DUPLICATION
@ MOD_LINEART_EDGE_FLAG_MATERIAL
@ MOD_LINEART_EDGE_FLAG_EDGE_MARK
@ MOD_LINEART_EDGE_FLAG_LOOSE
@ MOD_LINEART_FILTER_FACE_MARK
@ MOD_LINEART_FILTER_FACE_MARK_BOUNDARIES
@ MOD_LINEART_USE_CREASE_ON_SMOOTH_SURFACES
@ MOD_LINEART_USE_IMAGE_BOUNDARY_TRIMMING
@ MOD_LINEART_LOOSE_AS_CONTOUR
@ MOD_LINEART_CHAIN_PRESERVE_DETAILS
@ MOD_LINEART_USE_BACK_FACE_CULLING
@ MOD_LINEART_CHAIN_LOOSE_EDGES
@ MOD_LINEART_USE_CUSTOM_CAMERA
@ MOD_LINEART_USE_CREASE_ON_SHARP_EDGES
@ MOD_LINEART_INVERT_SOURCE_VGROUP
@ MOD_LINEART_EVERYTHING_AS_CONTOUR
@ MOD_LINEART_ALLOW_DUPLI_OBJECTS
@ MOD_LINEART_MATCH_OUTPUT_VGROUP
@ MOD_LINEART_CHAIN_GEOMETRY_SPACE
@ MOD_LINEART_FILTER_FACE_MARK_KEEP_CONTOUR
@ MOD_LINEART_INTERSECTION_AS_CONTOUR
@ MOD_LINEART_ALLOW_OVERLAP_EDGE_TYPES
@ MOD_LINEART_ALLOW_OVERLAPPING_EDGES
@ MOD_LINEART_ALLOW_CLIPPING_BOUNDARIES
@ MOD_LINEART_FILTER_FACE_MARK_INVERT
@ LRT_MATERIAL_CUSTOM_INTERSECTION_PRIORITY
@ LRT_MATERIAL_MASK_ENABLED
@ LINEART_SHADOW_FILTER_ILLUMINATED_ENCLOSED_SHAPES
@ LINEART_SHADOW_FILTER_SHADED
@ LINEART_SHADOW_FILTER_ILLUMINATED
@ MOD_LINEART_MATERIAL_MASK_ENABLE
@ MOD_LINEART_INTERSECTION_MATCH
@ MOD_LINEART_MATERIAL_MASK_MATCH
@ LINEART_SILHOUETTE_FILTER_INDIVIDUAL
@ MOD_LINEART_INVERT_SILHOUETTE_FILTER
@ MOD_LINEART_OFFSET_TOWARDS_CUSTOM_CAMERA
@ MOD_LINEART_INVERT_COLLECTION
@ LINEART_SOURCE_COLLECTION
@ OBJECT_LRT_OWN_INTERSECTION_PRIORITY
@ OBJECT_LRT_NO_INTERSECTION
@ OBJECT_LRT_OCCLUSION_ONLY
@ OBJECT_LRT_INTERSECTION_ONLY
@ OBJECT_LRT_FORCE_INTERSECTION
Read Guarded memory(de)allocation.
#define LRT_TILE_EDGE_COUNT_INITIAL
#define LRT_DOUBLE_CLOSE_ENOUGH(a, b)
#define LRT_SHADOW_MASK_INHIBITED
#define LRT_SHADOW_MASK_UNDEFINED
#define LRT_OBINDEX_LOWER
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)
#define LRT_OBINDEX_SHIFT
#define LRT_SHADOW_MASK_ILLUMINATED_SHAPE
#define LRT_LIGHT_CONTOUR_TARGET
#define LRT_SHADOW_MASK_ENCLOSED_SHAPE
#define LRT_SHADOW_TEST_SHAPE_BITS
#define LRT_OBINDEX_HIGHER
@ LRT_TILE_RECURSIVE_PERSPECTIVE
@ LRT_TILE_RECURSIVE_ORTHO
#define LRT_SHADOW_MASK_ILLUMINATED
#define LRT_TILE_SPLITTING_TRIANGLE_LIMIT
@ LRT_TRIANGLE_NO_INTERSECTION
@ LRT_TRIANGLE_MAT_BACK_FACE_CULLING
@ LRT_TRIANGLE_INTERSECTION_ONLY
@ LRT_TRIANGLE_FORCE_INTERSECTION
#define LRT_THREAD_EDGE_COUNT
#define LRT_SHADOW_MASK_SHADED
@ LRT_ELEMENT_NO_INTERSECTION
@ LRT_ELEMENT_BORDER_ONLY
@ LRT_ELEMENT_INTERSECTION_DATA
@ LRT_ELEMENT_IS_ADDITIONAL
#define LRT_EDGE_IDENTIFIER(obi, e)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
constexpr int64_t size() const
void append(const T &value)
IndexRange index_range() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr bool startswith(StringRef prefix) const
void append(const T &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
MutableSpan< float3 > positions_for_write()
MutableSpan< MDeformVert > deform_verts_for_write()
MutableAttributeAccessor attributes_for_write()
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_topology_changed()
float length(VecOp< float, D >) RET
#define MEM_recallocN(vmemh, len)
BLI_INLINE float fb(float length, float L)
void MOD_lineart_chain_connect(LineartData *ld)
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_chain_find_silhouette_backdrop_objects(LineartData *ld)
void MOD_lineart_chain_feature_lines(LineartData *ld)
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
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_bounding_area_line_add(LineartBoundingArea *ba, LineartEdge *e)
LineartCache * MOD_lineart_init_cache()
static void lineart_bounding_areas_connect_recursive(LineartData *ld, LineartBoundingArea *root)
void lineart_main_load_geometries(Depsgraph *depsgraph, Scene *scene, Object *camera, LineartData *ld, bool allow_duplicates, bool do_shadow_casting, ListBase *shadow_elns, blender::Set< const Object * > *included_objects)
static int lineart_triangle_size_get(LineartData *ld)
static LineartEdgeSegment * lineart_give_segment(LineartData *ld)
void lineart_main_occlusion_begin(LineartData *ld)
static void lineart_add_triangles_worker(TaskPool *__restrict, LineartIsecThread *th)
#define INTERSECT_JUST_SMALLER(is, order, num, index)
static void lineart_init_isec_thread(LineartIsecData *d, LineartData *ld, int thread_count)
static LineartBoundingArea * lineart_get_bounding_area(LineartData *ld, double x, double y)
#define LRT_MESH_EDGE_TYPES_COUNT
#define RELINK_EDGE(e_num, new_tri)
static void lineart_destroy_isec_thread(LineartIsecData *d)
static void lineart_occlusion_worker(TaskPool *__restrict, LineartRenderTaskInfo *rti)
static bool lineart_triangle_intersect_math(LineartTriangle *tri, LineartTriangle *t2, double *v1, double *v2)
static bool lineart_bounding_area_triangle_intersect(LineartData *fb, LineartTriangle *tri, LineartBoundingArea *ba, bool *r_triangle_vert_inside)
void lineart_main_discard_out_of_frame_edges(LineartData *ld)
void lineart_main_get_view_vector(LineartData *ld)
void lineart_main_link_lines(LineartData *ld)
LineartBoundingArea * MOD_lineart_get_parent_bounding_area(LineartData *ld, double x, double y)
bool lineart_edge_from_triangle(const LineartTriangle *tri, const LineartEdge *e, bool allow_overlapping_edges)
static bool lineart_edge_match(LineartTriangle *tri, LineartEdge *e, int v1, int v2)
static void lineart_create_edges_from_isec_data(LineartIsecData *d)
static LineartVert * lineart_triangle_share_point(const LineartTriangle *l, const LineartTriangle *r)
static void lineart_sort_adjacent_items(LineartAdjacentEdge *ai, int length)
static bool lineart_bounding_area_edge_intersect(LineartData *, const double l[2], const double r[2], LineartBoundingArea *ba)
static void lineart_add_isec_thread(LineartIsecThread *th, const double *v1, const double *v2, LineartTriangle *tri1, LineartTriangle *tri2)
static bool lineart_triangle_2v_intersection_math(LineartVert *v1, LineartVert *v2, LineartTriangle *tri, const double *last, double *rv)
void lineart_main_bounding_areas_connect_post(LineartData *ld)
static const int LRT_MESH_EDGE_TYPES[]
static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartData *la_data, ListBase *shadow_elns)
static void lineart_edge_neighbor_init_task(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict)
#define LRT_VERT_OUT_OF_BOUND(v)
static void lineart_destroy_render_data(LineartData *ld)
void lineart_main_add_triangles(LineartData *ld)
LineartBoundingArea * lineart_bounding_area_next(LineartBoundingArea *self, double *fbcoord1, double *fbcoord2, double x, double y, double k, int positive_x, int positive_y, double *next_x, double *next_y)
static LineartElementLinkNode * lineart_memory_get_vert_space(LineartData *ld)
static bool lineart_triangle_share_edge(const LineartTriangle *l, const LineartTriangle *r)
static uchar lineart_intersection_mask_check(Collection *c, Object *ob)
void lineart_add_edge_to_array(LineartPendingEdges *pe, LineartEdge *e)
static bool lineart_point_inside_triangle3d(double v[3], double v0[3], double v1[3], double v2[3])
static int lineart_occlusion_make_task_info(LineartData *ld, LineartRenderTaskInfo *rti)
#define LRT_CULL_DECIDE_INSIDE
void lineart_main_clear_linked_edges(LineartData *ld)
static void lineart_triangle_adjacent_assign(LineartTriangle *tri, LineartTriangleAdjacent *tri_adj, LineartEdge *e)
static void lineart_bounding_area_triangle_reallocate(LineartBoundingArea *ba)
static void lineart_free_bounding_area_memories(LineartData *ld)
static bool lineart_triangle_edge_image_space_occlusion(const LineartTriangle *tri, const LineartEdge *e, const double *override_camera_loc, const bool override_cam_is_persp, const bool allow_overlapping_edges, const double m_view_projection[4][4], const double camera_dir[3], const float cam_shift_x, const float cam_shift_y, double *from, double *to)
static int lineart_edge_type_duplication_count(int eflag)
void lineart_main_cull_triangles(LineartData *ld, bool clip_far)
static LineartTriangle * lineart_triangle_from_index(LineartData *ld, LineartTriangle *rt_array, int index)
void MOD_lineart_clear_cache(LineartCache **lc)
static void lineart_bounding_area_split(LineartData *ld, LineartBoundingArea *root, int recursive_level)
void lineart_main_bounding_area_make_initial(LineartData *ld)
static void lineart_add_edge_to_array_thread(LineartObjectInfo *obi, LineartEdge *e)
int3 corner_tri_get_real_edges(Span< int2 > edges, Span< int > corner_verts, Span< int > corner_edges, const int3 &corner_tri)
#define LRT_ISECT_TRIANGLE_PER_THREAD
static void lineart_load_tri_task(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict)
static void lineart_triangle_post(LineartTriangle *tri, LineartTriangle *orig)
static bool lineart_get_triangle_bounding_areas(LineartData *ld, LineartTriangle *tri, int *rowbegin, int *rowend, int *colbegin, int *colend)
static void lineart_object_load_single_instance(LineartData *ld, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *ref_ob, const float use_mat[4][4], bool is_render, LineartObjectLoadTaskInfo *olti, int thread_count, int obindex)
static void lineart_triangle_intersect_in_bounding_area(LineartTriangle *tri, LineartBoundingArea *ba, LineartIsecThread *th, int up_to)
static void lineart_triangle_set_cull_flag(LineartTriangle *tri, uchar flag)
static LineartElementLinkNode * lineart_memory_get_triangle_space(LineartData *ld)
static void lineart_finalize_object_edge_array(LineartPendingEdges *pe, LineartObjectInfo *obi)
LineartBoundingArea * MOD_lineart_get_bounding_area(LineartData *ld, double x, double y)
void lineart_main_free_adjacent_data(LineartData *ld)
static void lineart_occlusion_single_line(LineartData *ld, LineartEdge *e, int thread_id)
static void lineart_triangle_cull_single(LineartData *ld, LineartTriangle *tri, int in0, int in1, int in2, double cam_pos[3], double view_dir[3], bool allow_boundaries, double m_view_projection[4][4], Object *ob, int *r_v_count, int *r_e_count, int *r_t_count, LineartElementLinkNode *v_eln, LineartElementLinkNode *e_eln, LineartElementLinkNode *t_eln)
static void lineart_free_bounding_area_memory(LineartBoundingArea *ba, bool recursive)
#define REMOVE_TRIANGLE_EDGE
static bool lineart_point_inside_triangle(const double v[2], const double v0[2], const double v1[2], const double v2[2])
static void lineart_end_bounding_area_recursive(LineartBoundingArea *ba)
static LineartPointTri lineart_point_triangle_relation(double v[2], double v0[2], double v1[2], double v2[2])
static void lineart_bounding_area_link_edge(LineartData *ld, LineartBoundingArea *root_ba, LineartEdge *e)
#define LRT_PARALLEL(index)
static LineartData * lineart_create_render_buffer_v3(Scene *scene, GreasePencilLineartModifierData *lmd, Object *camera, Object *active_camera, LineartCache *lc)
static void lineart_geometry_load_assign_thread(LineartObjectLoadTaskInfo *olti_list, LineartObjectInfo *obi, int thread_count, int this_face_count)
static void lineart_object_load_worker(TaskPool *__restrict, LineartObjectLoadTaskInfo *olti)
void MOD_lineart_destroy_render_data_v3(GreasePencilLineartModifierData *lmd)
void lineart_destroy_render_data_keep_init(LineartData *ld)
static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2])
static uchar lineart_intersection_priority_check(Collection *c, Object *ob)
static void lineart_mvert_transform_task(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict)
#define INTERSECT_JUST_GREATER(is, order, num, index)
static void lineart_identify_corner_tri_feature_edges(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
static bool lineart_schedule_new_triangle_task(LineartIsecThread *th)
static void lineart_discard_duplicated_edges(LineartEdge *old_e)
static void feat_data_sum_reduce(const void *__restrict, void *__restrict chunk_join, void *__restrict chunk)
#define LRT_TRI_SAME_POINT(tri, i, pt)
static void lineart_clear_linked_edges_recursive(LineartData *ld, LineartBoundingArea *root_ba)
void lineart_edge_cut(LineartData *ld, LineartEdge *e, double start, double end, uchar material_mask_bits, uchar mat_occlusion, uint32_t shadow_bits)
static int lineart_usage_check(Collection *c, Object *ob, bool is_render)
static bool lineart_get_edge_bounding_areas(LineartData *ld, LineartEdge *e, int *rowbegin, int *rowend, int *colbegin, int *colend)
static void lineart_discard_segment(LineartData *ld, LineartEdgeSegment *es)
void lineart_main_perspective_division(LineartData *ld)
void MOD_lineart_gpencil_generate_v3(const LineartCache *cache, const blender::float4x4 &inverse_mat, Depsgraph *depsgraph, blender::bke::greasepencil::Drawing &drawing, const int8_t source_type, Object *source_object, Collection *source_collection, const int level_start, const int level_end, const int mat_nr, const int16_t edge_types, const uchar mask_switches, const uchar material_mask_bits, const uchar intersection_mask, const float thickness, const float opacity, const uchar shadow_selection, const uchar silhouette_mode, const char *source_vgname, const char *vgname, const int modifier_flags, const int modifier_calculation_flags)
static LineartElementLinkNode * lineart_memory_get_edge_space(LineartData *ld)
LineartBoundingArea * lineart_edge_first_bounding_area(LineartData *ld, double *fbcoord1, double *fbcoord2)
static LineartEdgeNeighbor * lineart_build_edge_neighbor(Mesh *mesh, int total_edges)
static void lineart_main_remove_unused_lines_from_tiles(LineartData *ld)
static void lineart_bounding_areas_connect_new(LineartData *ld, LineartBoundingArea *root)
#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst)
void lineart_finalize_object_edge_array_reserve(LineartPendingEdges *pe, int count)
#define SELECT_EDGE(e_num, v1_link, v2_link, new_tri)
static void lineart_main_remove_unused_lines_recursive(LineartBoundingArea *ba, uint8_t max_occlusion)
BLI_INLINE bool lineart_occlusion_is_adjacent_intersection(LineartEdge *e, LineartTriangle *tri)
static bool lineart_triangle_get_other_verts(const LineartTriangle *tri, const LineartVert *vt, LineartVert **l, LineartVert **r)
static void lineart_bounding_area_link_triangle(LineartData *ld, LineartBoundingArea *root_ba, LineartTriangle *tri, double l_r_u_b[4], int recursive, int recursive_level, bool do_intersection, LineartIsecThread *th)
#define LRT_CULL_ENSURE_MEMORY
bool MOD_lineart_compute_feature_lines_v3(Depsgraph *depsgraph, GreasePencilLineartModifierData &lmd, LineartCache **cached_result, bool enable_stroke_depth_offset)
static bool lineart_geometry_check_visible(double model_view_proj[4][4], double shift_x, double shift_y, Mesh *use_mesh)
#define LRT_GUARD_NOT_FOUND
void lineart_register_intersection_shadow_cuts(struct LineartData *ld, struct ListBase *shadow_elns)
#define LRT_BOUND_AREA_CROSSES(b1, b2)
#define LRT_EDGE_BA_MARCHING_BEGIN(fb1, fb2)
#define LRT_EDGE_BA_MARCHING_NEXT(fb1, fb2)
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)
void lineart_register_shadow_cuts(struct LineartData *ld, struct LineartEdge *e, struct LineartEdge *shadow_edge)
LineartElementLinkNode * lineart_find_matching_eln(struct ListBase *shadow_elns, int obindex)
#define LRT_EDGE_BA_MARCHING_END
void * lineart_list_append_pointer_pool_thread(ListBase *h, struct LineartStaticMemPool *smp, void *data)
void lineart_main_make_enclosed_shapes(struct LineartData *ld, struct LineartData *shadow_ld)
#define LRT_ITER_ALL_LINES_END
void lineart_count_and_print_render_buffer_memory(struct LineartData *ld)
LineartEdge * lineart_find_matching_edge(struct LineartElementLinkNode *shadow_eln, uint64_t edge_identifier)
void lineart_matrix_perspective_44d(double(*mProjection)[4], double fFov_rad, double fAspect, double zMin, double zMax)
void * lineart_mem_acquire_thread(struct LineartStaticMemPool *smp, size_t size)
void * lineart_list_append_pointer_pool(ListBase *h, struct LineartStaticMemPool *smp, void *data)
void lineart_list_remove_pointer_item_no_free(ListBase *h, LinkData *lip)
#define LRT_ITER_ALL_LINES_BEGIN
void lineart_main_transform_and_add_shadow(struct LineartData *ld, struct LineartElementLinkNode *veln, struct LineartElementLinkNode *eeln)
bool lineart_main_try_generate_shadow_v3(struct Depsgraph *depsgraph, struct Scene *scene, struct LineartData *original_ld, struct GreasePencilLineartModifierData *lmd, struct LineartStaticMemPool *shadow_data_pool, struct LineartElementLinkNode **r_veln, struct LineartElementLinkNode **r_eeln, struct ListBase *r_calculated_edges_eln_list, struct LineartData **r_shadow_ld_if_reproject)
void lineart_mem_destroy(struct LineartStaticMemPool *smp)
void * lineart_list_append_pointer_pool_sized_thread(ListBase *h, LineartStaticMemPool *smp, void *data, int size)
void lineart_matrix_ortho_44d(double(*mProjection)[4], double xMin, double xMax, double yMin, double yMax, double zMin, double zMax)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 fabs(const float2 a)
int3 corner_tri_get_real_edges(Span< int2 > edges, Span< int > corner_verts, Span< int > corner_edges, const int3 &corner_tri)
Curves * curves_new_nomain(int points_num, int curves_num)
bke::GeometrySet join_geometries(Span< bke::GeometrySet > geometries, const bke::AttributeFilter &attribute_filter, const std::optional< Span< bke::GeometryComponent::Type > > &component_types_to_join=std::nullopt)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
Render * RE_GetSceneRender(const Scene *scene)
uint8_t lineart_intersection_priority
uint8_t lineart_intersection_mask
ListBase vertex_group_names
blender::Set< const Object * > * included_objects
blender::Span< int > corner_verts
blender::VArray< bool > sharp_edges
LineartEdgeNeighbor * edge_nabr
blender::Span< blender::int2 > edges
blender::Span< int > corner_edges
blender::Span< int > material_indices
blender::VArray< bool > sharp_faces
blender::Span< int3 > corner_tris
LineartTriangle * tri_array
blender::Span< int > tri_faces
LineartAdjacentEdge * adj_e
blender::Span< int > corner_verts
LineartEdgeNeighbor * edge_nabr
blender::Span< int > tri_faces
blender::Span< int3 > corner_tris
float chaining_image_threshold
struct LineartCache * cache
float angle_splitting_threshold
struct LineartData * la_data_ptr
struct Object * source_camera
char shadow_use_silhouette_override
float stroke_depth_offset
short edge_types_override
char shadow_selection_override
struct LineartModifierRuntime * runtime
struct Object * light_contour_object
float chain_smooth_tolerance
LineartBoundingArea * child
uint32_t insider_triangle_count
LineartTriangle ** linked_triangles
LineartEdge ** linked_lines
uint32_t max_triangle_count
LineartStaticMemPool chain_data_pool
uint16_t all_enabled_edge_types
LineartStaticMemPool shadow_data_pool
float cam_obmat_secondary[4][4]
bool use_contour_secondary
bool filter_face_mark_invert
bool cam_is_persp_secondary
bool use_loose_edge_chain
double view_projection[4][4]
bool shadow_enclose_shapes
bool chain_preserve_details
double view_vector_secondary[3]
double camera_pos_secondary[3]
float chaining_image_threshold
bool filter_face_mark_keep_contour
double active_camera_pos[3]
float chain_smooth_tolerance
bool use_loose_as_contour
bool use_image_boundary_trimming
bool shadow_use_silhouette
bool filter_face_mark_boundaries
bool allow_overlapping_edges
bool allow_duplicated_types
bool use_back_face_culling
float angle_splitting_threshold
bool use_geometry_space_chain
bool light_reference_available
ListBase vertex_buffer_pointers
ListBase line_buffer_pointers
ListBase triangle_adjacent_pointers
ListBase triangle_buffer_pointers
uint32_t initial_tile_count
LineartBoundingArea * initials
LineartStaticMemPool render_data_pool
struct LineartData::_conf conf
struct LineartData::_geom geom
struct LineartData::_qtree qtree
int isect_scheduled_up_to_index
LineartElementLinkNode * isect_scheduled_up_to
LineartStaticMemPool * edge_data_pool
struct LineartPendingEdges pending_edges
LineartStaticMemPool * chain_data_pool
LineartEdgeSegment * next
LineartEdgeSegment * prev
uint32_t shadow_mask_bits
uint8_t material_mask_bits
LineartElementLinkNode * next
eLineArtElementNodeFlag flags
LineartIsecThread * threads
LineartElementLinkNode * pending_from
LineartIsecSingle * array
LineartElementLinkNode * pending_to
blender::Set< const Object * > object_dependencies
LineartElementLinkNode * v_eln
Object * original_ob_eval
double model_view_proj[4][4]
uint8_t override_intersection_mask
uint8_t intersection_priority
LineartPendingEdges pending_edges
LineartObjectInfo * pending
struct LineartPendingEdges pending_edges
LineartEdge * testing_e[1]
uint8_t material_mask_bits
LinkNode * intersecting_verts
uint8_t intersection_priority
uint8_t intersection_mask
uint32_t target_reference
unsigned char mat_occlusion
unsigned char intersection_priority
unsigned char material_mask_bits
struct MaterialLineArt lineart
MeshRuntimeHandle * runtime
ListBase vertex_group_names
unsigned char intersection_priority
struct Collection * master_collection
TaskParallelReduceFunc func_reduce
size_t userdata_chunk_size
int lineart_triangle_size
LineartTriangleAdjacent * tri_adj
blender::Span< blender::float3 > positions
blender::Span< int3 > corner_tris
LineartObjectInfo * ob_info
blender::Span< int > corner_verts
blender::Span< int > tri_faces
blender::Span< int > material_indices
LineartTriangle * tri_arr
double(* model_view_proj)[4]
blender::Span< blender::float3 > positions
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Curves * get_curves_for_write()
blender::BitVector is_loose_bits
MutableVArraySpan< T > span