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;
1828 const int face_i = tri_task_data->
tri_faces[
i];
1836 int v1 = corner_verts[corner_tri[0]];
1837 int v2 = corner_verts[corner_tri[1]];
1838 int v3 = corner_verts[corner_tri[2]];
1840 tri->
v[0] = &vert_arr[v1];
1841 tri->
v[1] = &vert_arr[
v2];
1842 tri->
v[2] = &vert_arr[v3];
1881 const bool has_mark = tri_task_data->
face_marks[face_i];
1882 const bool filtered = tri_task_data->
invert_face_marks ? has_mark : (!has_mark);
1910 adj_e->
v1 = corner_verts[tri[
i % 3]];
1911 adj_e->
v2 = corner_verts[tri[(
i + 1) % 3]];
1912 if (adj_e->
v1 > adj_e->
v2) {
1913 std::swap(adj_e->
v1, adj_e->
v2);
1917 edge_nabr->
v1 = adj_e->
v1;
1918 edge_nabr->
v2 = adj_e->
v2;
1919 edge_nabr->
flags = 0;
1926 int a = p1.
v1 - p2.
v1;
1927 int b = p1.
v2 - p2.
v2;
1945 "LineartAdjacentEdge arr");
1947 size_t(total_edges),
"LineartEdgeNeighbor arr");
1955 en_data.
adj_e = adj_e;
1965 for (
int i = 0;
i < total_edges - 1;
i++) {
1966 if (adj_e[
i].v1 == adj_e[
i + 1].v1 && adj_e[
i].
v2 == adj_e[
i + 1].
v2) {
1967 edge_nabr[adj_e[
i].
e].
e = adj_e[
i + 1].
e;
1968 edge_nabr[adj_e[
i + 1].
e].
e = adj_e[
i].
e;
1983 if (!
mesh->edges_num) {
1994 bool can_find_freestyle_edge =
false;
1996 if (layer_index != -1) {
1997 can_find_freestyle_edge =
true;
2000 bool can_find_freestyle_face =
false;
2002 if (layer_index != -1) {
2003 can_find_freestyle_face =
true;
2027 ob_info->
v_eln = elem_link_node;
2029 bool use_auto_smooth =
false;
2030 float crease_angle = 0;
2052 int usage = ob_info->
usage;
2057 elem_link_node->
flags |
2062 size_t(corner_tris.
size()),
"LineartTriangleAdjacent");
2077 vert_data.
v_arr = la_v_arr;
2099 tri_data.
tri_arr = la_tri_arr;
2107 uint32_t total_edges = corner_tris.
size() * 3;
2130 edge_feat_data.
ld = la_data;
2131 edge_feat_data.mesh =
mesh;
2133 edge_feat_data.material_indices = material_indices;
2134 edge_feat_data.edges =
mesh->edges();
2135 edge_feat_data.corner_verts =
mesh->corner_verts();
2136 edge_feat_data.corner_edges =
mesh->corner_edges();
2137 edge_feat_data.corner_tris = corner_tris;
2138 edge_feat_data.tri_faces =
mesh->corner_tri_faces();
2139 edge_feat_data.sharp_edges = sharp_edges;
2140 edge_feat_data.sharp_faces = sharp_faces;
2142 edge_feat_data.tri_array = la_tri_arr;
2143 edge_feat_data.v_array = la_v_arr;
2144 edge_feat_data.crease_threshold = crease_angle;
2145 edge_feat_data.use_auto_smooth = use_auto_smooth;
2146 edge_feat_data.use_freestyle_face = can_find_freestyle_face;
2147 edge_feat_data.use_freestyle_edge = can_find_freestyle_edge;
2148 if (edge_feat_data.use_freestyle_face) {
2152 if (edge_feat_data.use_freestyle_edge) {
2161 &edge_feat_settings);
2170 if (loose_edges.
count > 0) {
2206 la_edge = la_edge_arr;
2207 la_seg = la_seg_arr;
2209 for (
int i = 0;
i < total_edges;
i++) {
2217 if (edge_nabr->
flags == 0) {
2226 if (!(use_type & edge_nabr->
flags)) {
2230 la_edge->
v1 = &la_v_arr[edge_nabr->
v1];
2231 la_edge->
v2 = &la_v_arr[edge_nabr->
v2];
2237 if (edge_nabr->
e != -1) {
2238 findex = edge_nabr->
e / 3;
2244 la_edge->
flags = use_type;
2272 edge_added = la_edge;
2287 la_edge->
v1 = &la_v_arr[edge[0]];
2288 la_edge->
v2 = &la_v_arr[edge[1]];
2386 if (object_has_special_usage) {
2429 int this_face_count)
2433 for (
int i = 0;
i < thread_count;
i++) {
2434 if (olti_list[
i].total_faces < min_face) {
2436 use_olti = &olti_list[
i];
2454 const std::optional<Bounds<float3>>
bounds = use_mesh->bounds_min_max();
2455 if (!
bounds.has_value()) {
2463 for (
int i = 0;
i < 8;
i++) {
2467 co[
i][0] -= shift_x * 2 * co[
i][3];
2468 co[
i][1] -= shift_y * 2 * co[
i][3];
2471 bool cond[6] = {
true,
true,
true,
true,
true,
true};
2474 for (
int i = 0;
i < 8;
i++) {
2475 cond[0] &= (co[
i][0] < -co[
i][3]);
2476 cond[1] &= (co[
i][0] > co[
i][3]);
2477 cond[2] &= (co[
i][1] < -co[
i][3]);
2478 cond[3] &= (co[
i][1] > co[
i][3]);
2479 cond[4] &= (co[
i][2] < -co[
i][3]);
2480 cond[5] &= (co[
i][2] > co[
i][3]);
2482 for (
int i = 0;
i < 6;
i++) {
2495 const float use_mat[4][4],
2524 if ((!use_mesh) || use_mesh->
runtime->edit_mesh) {
2566 bool allow_duplicates,
2567 bool do_shadow_casting,
2574 if (!do_shadow_casting) {
2578 double asp = (double(ld->
w) / double(ld->
h));
2591 double vertical = horizontal;
2602 BLI_assert(!
"Unsupported camera type in lineart_main_load_geometries");
2619 if (
G.debug_value == 4000) {
2624 int bound_box_discard_count = 0;
2638 if (allow_duplicates) {
2644 deg_iter_settings.
flags = flags;
2669 eval_ob->object_to_world().ptr(),
2680 if (
G.debug_value == 4000) {
2681 printf(
"thread count: %d\n", thread_count);
2683 for (
int i = 0;
i < thread_count;
i++) {
2697 for (
int i = 0;
i < thread_count;
i++) {
2702 edge_count += obi->pending_edges.next;
2707 for (
int i = 0;
i < thread_count;
i++) {
2713 int v_count = obi->v_eln->element_count;
2714 obi->v_eln->global_index_offset = global_i;
2715 for (
int vi = 0; vi < v_count; vi++) {
2716 v[vi].index += global_i;
2722 obi->global_i_offset = global_i;
2723 global_i += v_count;
2728 if (
G.debug_value == 4000) {
2730 printf(
"Line art loading time: %lf\n", t_elapsed);
2731 printf(
"Discarded %d object from bound box check\n", bound_box_discard_count);
2744 if (tri->
v[0] == vt) {
2749 if (tri->
v[1] == vt) {
2754 if (tri->
v[2] == vt) {
2764 bool allow_overlapping_edges)
2785 if (allow_overlapping_edges) {
2786#define LRT_TRI_SAME_POINT(tri, i, pt) \
2787 ((LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[0], pt->gloc[0]) && \
2788 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[1], pt->gloc[1]) && \
2789 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[2], pt->gloc[2])) || \
2790 (LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[0], pt->gloc[0]) && \
2791 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[1], pt->gloc[1]) && \
2792 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[2], pt->gloc[2])))
2800#undef LRT_TRI_SAME_POINT
2807#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst) \
2809 lst[0] = LRT_MIN3_INDEX(ia, ib, ic); \
2810 lst[1] = (((ia <= ib && ib <= ic) || (ic <= ib && ib <= ia)) ? \
2812 (((ic <= ia && ia <= ib) || (ib < ia && ia <= ic)) ? 0 : 2)); \
2813 lst[2] = LRT_MAX3_INDEX(ia, ib, ic); \
2817#define INTERSECT_JUST_GREATER(is, order, num, index) \
2819 index = (num < is[order[0]] ? \
2821 (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : -1))); \
2825#define INTERSECT_JUST_SMALLER(is, order, num, index) \
2827 index = (num > is[order[2]] ? \
2829 (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : -1))); \
2832#define LRT_ISEC(index) (index == 0 ? isec_e1 : (index == 1 ? isec_e2 : isec_e3))
2833#define LRT_PARALLEL(index) (index == 0 ? para_e1 : (index == 1 ? para_e2 : para_e3))
2859 const double *override_camera_loc,
2860 const bool override_cam_is_persp,
2861 const bool allow_overlapping_edges,
2862 const double m_view_projection[4][4],
2863 const double camera_dir[3],
2864 const float cam_shift_x,
2865 const float cam_shift_y,
2869 double cross_ratios[3] = {0};
2871 int cross_v1 = -1, cross_v2 = -1;
2873 int isec_e1, isec_e2, isec_e3;
2875 bool para_e1, para_e2, para_e3;
2880 double view_vector[4];
2882 double dot_v1, dot_v2, dot_v1a, dot_v2a;
2884 double gloc[4], trans[4];
2887 double *LFBC =
e->v1->fbcoord, *RFBC =
e->v2->fbcoord, *FBC0 = tri->
v[0]->
fbcoord,
2891 if ((std::max({FBC0[0], FBC1[0], FBC2[0]}) < std::min(LFBC[0], RFBC[0])) ||
2892 (std::min({FBC0[0], FBC1[0], FBC2[0]}) > std::max(LFBC[0], RFBC[0])) ||
2893 (std::max({FBC0[1], FBC1[1], FBC2[1]}) < std::min(LFBC[1], RFBC[1])) ||
2894 (std::min({FBC0[1], FBC1[1], FBC2[1]}) > std::max(LFBC[1], RFBC[1])) ||
2895 (std::min({FBC0[3], FBC1[3], FBC2[3]}) > std::max(LFBC[3], RFBC[3])))
2918 if (override_cam_is_persp) {
2945 if (
fabs(dot_f) < FLT_EPSILON) {
2954 if (!isec_e1 && !isec_e2 && !isec_e3) {
2956 if ((!state_v1) && (!state_v2)) {
2963 dot_v1a =
fabs(dot_v1);
2964 if (dot_v1a < DBL_EPSILON) {
2968 dot_v2a =
fabs(dot_v2);
2969 if (dot_v2a < DBL_EPSILON) {
2973 if (dot_v1 - dot_v2 == 0) {
2976 else if (dot_v1 * dot_v2 <= 0) {
2977 cut = dot_v1a /
fabs(dot_v1 - dot_v2);
2980 cut =
fabs(dot_v2 + dot_v1) /
fabs(dot_v1 - dot_v2);
2981 cut = dot_v2a > dot_v1a ? 1 - cut : cut;
2985 if (override_cam_is_persp) {
2989 trans[0] -= cam_shift_x * 2;
2990 trans[1] -= cam_shift_y * 2;
2992 if (
fabs(
e->v1->fbcoord[0] -
e->v2->fbcoord[0]) >
fabs(
e->v1->fbcoord[1] -
e->v2->fbcoord[1]))
2994 cut =
ratiod(
e->v1->fbcoord[0],
e->v2->fbcoord[0], trans[0]);
2997 cut =
ratiod(
e->v1->fbcoord[1],
e->v2->fbcoord[1], trans[1]);
3001#define LRT_GUARD_NOT_FOUND \
3002 if (cross_v1 < 0 || cross_v2 < 0) { \
3095 if (cross_v1 >= 0 &&
LRT_ISEC(cross_v1)) {
3099 if (cross_v1 >= 0) {
3101 if (cross_v1 >= 0) {
3111 double dot_1f = dot_v1 * dot_f, dot_2f = dot_v2 * dot_f;
3114 if (dot_1f <= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) {
3115 *from = std::max(0.0, cross_ratios[cross_v1]);
3116 *to = std::min(1.0, cross_ratios[cross_v2]);
3122 if (dot_1f >= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) {
3123 *from = std::max(cut, cross_ratios[cross_v1]);
3124 *to = std::min(1.0, cross_ratios[cross_v2]);
3130 if (dot_1f <= 0 && dot_2f >= 0 && (dot_v1 || dot_v2)) {
3131 *from = std::max(0.0, cross_ratios[cross_v1]);
3132 *to = std::min(cut, cross_ratios[cross_v2]);
3143#undef INTERSECT_SORT_MIN_TO_MAX_3
3144#undef INTERSECT_JUST_GREATER
3145#undef INTERSECT_JUST_SMALLER
3155 if (
l->v[0]->index == r->
v[0]->
index) {
3156 if (
l->v[1]->index == r->
v[1]->
index ||
l->v[1]->index == r->
v[2]->
index ||
3157 l->v[2]->index == r->
v[2]->
index ||
l->v[2]->index == r->
v[1]->
index)
3162 if (
l->v[0]->index == r->
v[1]->
index) {
3163 if (
l->v[1]->index == r->
v[0]->
index ||
l->v[1]->index == r->
v[2]->
index ||
3164 l->v[2]->index == r->
v[2]->
index ||
l->v[2]->index == r->
v[0]->
index)
3169 if (
l->v[0]->index == r->
v[2]->
index) {
3170 if (
l->v[1]->index == r->
v[1]->
index ||
l->v[1]->index == r->
v[0]->
index ||
3171 l->v[2]->index == r->
v[0]->
index ||
l->v[2]->index == r->
v[1]->
index)
3176 if (
l->v[1]->index == r->
v[0]->
index) {
3177 if (
l->v[2]->index == r->
v[1]->
index ||
l->v[2]->index == r->
v[2]->
index ||
3178 l->v[0]->index == r->
v[2]->
index ||
l->v[0]->index == r->
v[1]->
index)
3183 if (
l->v[1]->index == r->
v[1]->
index) {
3184 if (
l->v[2]->index == r->
v[0]->
index ||
l->v[2]->index == r->
v[2]->
index ||
3185 l->v[0]->index == r->
v[2]->
index ||
l->v[0]->index == r->
v[0]->
index)
3190 if (
l->v[1]->index == r->
v[2]->
index) {
3191 if (
l->v[2]->index == r->
v[1]->
index ||
l->v[2]->index == r->
v[0]->
index ||
3192 l->v[0]->index == r->
v[0]->
index ||
l->v[0]->index == r->
v[1]->
index)
3205 if (
l->v[0] == r->
v[0]) {
3208 if (
l->v[0] == r->
v[1]) {
3211 if (
l->v[0] == r->
v[2]) {
3214 if (
l->v[1] == r->
v[0]) {
3217 if (
l->v[1] == r->
v[1]) {
3220 if (
l->v[1] == r->
v[2]) {
3223 if (
l->v[2] == r->
v[0]) {
3226 if (
l->v[2] == r->
v[1]) {
3229 if (
l->v[2] == r->
v[2]) {
3240 double dir_v1[3], dir_v2[3];
3241 double dot_v1, dot_v2;
3250 if (dot_v1 * dot_v2 > 0 || (!dot_v1 && !dot_v2)) {
3254 dot_v1 =
fabs(dot_v1);
3255 dot_v2 =
fabs(dot_v2);
3280 double *
next = v1, *last =
nullptr;
3357 "LineartIsecSingle");
3361 th->
array = new_array;
3366 isec_single->
tri1 = tri1;
3367 isec_single->
tri2 = tri2;
3369 std::swap(isec_single->
tri1, isec_single->
tri2);
3374#define LRT_ISECT_TRIANGLE_PER_THREAD 4096
3392 while (remaining > 0 && eln) {
3394 int added_count = std::min(remaining, remaining_this_eln);
3395 remaining -= added_count;
3396 if (remaining || added_count == remaining_this_eln) {
3431 for (
int i = 0;
i < thread_count;
i++) {
3461 double *G0 = tri->
v[0]->
gloc, *G1 = tri->
v[1]->
gloc, *G2 = tri->
v[2]->
gloc;
3464 for (
int i = 0;
i < up_to;
i++) {
3483 double *RG0 = testing_triangle->
v[0]->
gloc, *RG1 = testing_triangle->
v[1]->
gloc,
3484 *RG2 = testing_triangle->
v[2]->
gloc;
3487 if ((std::min({G0[2], G1[2], G2[2]}) > std::max({RG0[2], RG1[2], RG2[2]})) ||
3488 (std::max({G0[2], G1[2], G2[2]}) < std::min({RG0[2], RG1[2], RG2[2]})) ||
3489 (std::min({G0[0], G1[0], G2[0]}) > std::max({RG0[0], RG1[0], RG2[0]})) ||
3490 (std::max({G0[0], G1[0], G2[0]}) < std::min({RG0[0], RG1[0], RG2[0]})) ||
3491 (std::min({G0[1], G1[1], G2[1]}) > std::max({RG0[1], RG1[1], RG2[1]})) ||
3492 (std::max({G0[1], G1[1], G2[1]}) < std::min({RG0[1], RG1[1], RG2[1]})) ||
3500 double iv1[3], iv2[3];
3509 float direction[3] = {0, 0, 1};
3512 float obmat_no_scale[4][4];
3541 for (
int i = 0;
i < 4;
i++) {
3549 if (ld ==
nullptr) {
3574 if (ld ==
nullptr) {
3598 if (
G.debug_value == 4000) {
3599 printf(
"LRT: Destroyed render data.\n");
3630 if (!scene || !camera || !lc) {
3634 double clipping_offset = 0;
3638 clipping_offset = 0.0001;
3642 if (active_camera) {
3665 double asp = double(ld->
w) / double(ld->
h);
3785 if (ld->
w > ld->
h) {
3786 sp_w = sp_h * ld->
w / ld->
h;
3789 sp_h = sp_w * ld->
h / ld->
w;
3794 double span_w = 1.0 / sp_w * 2.0;
3795 double span_h = 1.0 / sp_h * 2.0;
3810 for (row = 0; row < sp_h; row++) {
3815 ba->
l = span_w *
col - 1.0;
3816 ba->
r = (
col == sp_w - 1) ? 1.0 : (span_w * (
col + 1) - 1.0);
3817 ba->
u = 1.0 - span_h * row;
3818 ba->
b = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1));
3820 ba->
cx = (ba->
l + ba->
r) / 2;
3821 ba->
cy = (ba->
u + ba->
b) / 2;
3827 "ba_linked_triangles");
3865 if (ba[1].u > tba->
b && ba[1].
b < tba->u) {
3869 if (ba[2].u > tba->
b && ba[2].
b < tba->u) {
3876 if (ba[0].u > tba->
b && ba[0].
b < tba->u) {
3880 if (ba[3].u > tba->
b && ba[3].
b < tba->u) {
3887 if (ba[0].r > tba->
l && ba[0].
l < tba->r) {
3891 if (ba[1].r > tba->
l && ba[1].
l < tba->r) {
3898 if (ba[2].r > tba->
l && ba[2].
l < tba->r) {
3902 if (ba[3].r > tba->
l && ba[3].
l < tba->r) {
3914 next_lip = lip2->
next;
3918 if (ba[1].u > tba->
b && ba[1].
b < tba->u) {
3921 if (ba[2].u > tba->
b && ba[2].
b < tba->u) {
3931 next_lip = lip2->
next;
3935 if (ba[0].u > tba->
b && ba[0].
b < tba->u) {
3938 if (ba[3].u > tba->
b && ba[3].
b < tba->u) {
3948 next_lip = lip2->
next;
3952 if (ba[0].r > tba->
l && ba[0].
l < tba->r) {
3955 if (ba[1].r > tba->
l && ba[1].
l < tba->r) {
3965 next_lip = lip2->
next;
3969 if (ba[2].r > tba->
l && ba[2].
l < tba->r) {
3972 if (ba[3].r > tba->
l && ba[3].
l < tba->r) {
3990 for (
int i = 0;
i < 4;
i++) {
4023 for (
int i = 0;
i < total_tile_initial;
i++) {
4034 int recursive_level)
4042 ba[0].
cx = (ba[0].
l + ba[0].
r) / 2;
4043 ba[0].
cy = (ba[0].
u + ba[0].
b) / 2;
4049 ba[1].
cx = (ba[1].
l + ba[1].
r) / 2;
4050 ba[1].
cy = (ba[1].
u + ba[1].
b) / 2;
4056 ba[2].
cx = (ba[2].
l + ba[2].
r) / 2;
4057 ba[2].
cy = (ba[2].
u + ba[2].
b) / 2;
4063 ba[3].
cx = (ba[3].
l + ba[3].
r) / 2;
4064 ba[3].
cy = (ba[3].
u + ba[3].
b) / 2;
4067 for (
int i = 0;
i < 4;
i++) {
4071 "ba_linked_triangles");
4089 ld, &ba[0], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4093 ld, &ba[1], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4097 ld, &ba[2], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4101 ld, &ba[3], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4116 double converted[4];
4119 if (((converted[0] = ba->
l) > std::max(
l[0], r[0])) ||
4120 ((converted[1] = ba->
r) < std::min(
l[0], r[0])) ||
4121 ((converted[2] = ba->
b) > std::max(
l[1], r[1])) ||
4122 ((converted[3] = ba->
u) < std::min(
l[1], r[1])))
4130 c1 = dx * (converted[2] -
l[1]) - dy * (converted[0] -
l[0]);
4133 c1 = dx * (converted[2] -
l[1]) - dy * (converted[1] -
l[0]);
4139 c1 = dx * (converted[3] -
l[1]) - dy * (converted[0] -
l[0]);
4145 c1 = dx * (converted[3] -
l[1]) - dy * (converted[1] -
l[0]);
4157 bool *r_triangle_vert_inside)
4159 double p1[2], p2[2], p3[2], p4[2];
4162 p3[0] = p1[0] = ba->
l;
4163 p2[1] = p1[1] = ba->
b;
4164 p2[0] = p4[0] = ba->
r;
4165 p3[1] = p4[1] = ba->
u;
4167 if ((FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) ||
4168 (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) ||
4169 (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1]))
4171 *r_triangle_vert_inside =
true;
4175 *r_triangle_vert_inside =
false;
4212 int recursive_level,
4213 bool do_intersection,
4216 bool triangle_vert_inside;
4223 if (old_ba->
child) {
4226 double *B1 = l_r_u_b;
4235 for (
int iba = 0; iba < 4; iba++) {
4238 ld, &old_ba->
child[iba], tri, B1, recursive, recursive_level + 1, do_intersection, th);
4256 if (triangle_vert_inside) {
4272 if (recursive_level < ld->qtree.recursive_level &&
4275 if (!old_ba->
child) {
4294 ld, root_ba, tri, l_r_u_b, recursive, recursive_level, do_intersection, th);
4307 if (recursive && ba->
child) {
4308 for (
int i = 0;
i < 4;
i++) {
4326 if (root_ba->
child ==
nullptr) {
4331 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[0]))
4336 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[1]))
4341 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[2]))
4346 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[3]))
4355 if (root_ba->
child) {
4356 for (
int i = 0;
i < 4;
i++) {
4366 "cleared lineart edges");
4382 int r1, r2, c1, c2, row,
col;
4384 for (row = r1; row != r2 + 1; row++) {
4396 uint8_t max_occlusion)
4399 for (
int i = 0;
i < 4;
i++) {
4409 int usable_count = 0;
4412 if (
e->min_occ > max_occlusion) {
4418 if (!usable_count) {
4424 "cleaned lineart edge array");
4429 if (
e->min_occ > max_occlusion) {
4432 new_array[new_i] =
e;
4457 if (!tri->
v[0] || !tri->
v[1] || !tri->
v[2]) {
4466 if (
b[0] > 1 ||
b[1] < -1 ||
b[2] > 1 ||
b[3] < -1) {
4470 (*colbegin) = int((
b[0] + 1.0) / sp_w);
4471 (*colend) = int((
b[1] + 1.0) / sp_w);
4472 (*rowend) = ld->
qtree.
count_y - int((
b[2] + 1.0) / sp_h) - 1;
4473 (*rowbegin) = ld->
qtree.
count_y - int((
b[3] + 1.0) / sp_h) - 1;
4481 *colbegin = std::max(*colbegin, 0);
4482 *rowbegin = std::max(*rowbegin, 0);
4493 if (!
e->v1 || !
e->v2) {
4497 if (
e->v1->fbcoord[0] !=
e->v1->fbcoord[0] ||
e->v2->fbcoord[0] !=
e->v2->fbcoord[0]) {
4501 b[0] = std::min(
e->v1->fbcoord[0],
e->v2->fbcoord[0]);
4502 b[1] = std::max(
e->v1->fbcoord[0],
e->v2->fbcoord[0]);
4503 b[2] = std::min(
e->v1->fbcoord[1],
e->v2->fbcoord[1]);
4504 b[3] = std::max(
e->v1->fbcoord[1],
e->v2->fbcoord[1]);
4506 if (
b[0] > 1 ||
b[1] < -1 ||
b[2] > 1 ||
b[3] < -1) {
4510 (*colbegin) = int((
b[0] + 1.0) / sp_w);
4511 (*colend) = int((
b[1] + 1.0) / sp_w);
4512 (*rowend) = ld->
qtree.
count_y - int((
b[2] + 1.0) / sp_h) - 1;
4513 (*rowbegin) = ld->
qtree.
count_y - int((
b[3] + 1.0) / sp_h) - 1;
4516 if ((*rowend) < (*rowbegin)) {
4520 if ((*colend) < (*colbegin)) {
4541 col = int((
x + 1.0) / sp_w);
4551 row = std::max(row, 0);
4560 int c = int((
x + 1.0) / sp_w);
4572 while (iba->
child) {
4575 iba = &iba->
child[0];
4578 iba = &iba->
child[3];
4583 iba = &iba->
child[1];
4586 iba = &iba->
child[2];
4614 for (
int ei = index_start; ei < index_end; ei++) {
4623 for (co = x1; co <= x2; co++) {
4624 for (r = y1; r <= y2; r++) {
4647 int total_lines = 0;
4651 if (
G.debug_value == 4000) {
4686 for (
int j = 0; j < th->
current; j++) {
4709 v2->fbcoord[2] = ZMin * ZMax / (ZMax -
fabs(
v2->fbcoord[2]) * (ZMax - ZMin));
4715 e->edge_identifier = (
uint64_t(
e->t1->target_reference) << 32) |
e->t2->target_reference;
4729 if (
e->t1->intersection_priority >=
e->t2->intersection_priority) {
4732 e->object_ref = ob1;
4734 else if (
e->t1->intersection_priority <
e->t2->intersection_priority) {
4735 e->object_ref = ob2;
4750 if (
G.debug_value == 4000) {
4773 if (
G.debug_value == 4000) {
4775 printf(
"Line art intersection time: %f\n", t_elapsed);
4783 double data[2] = {fbcoord1[0], fbcoord1[1]};
4784 double LU[2] = {-1, 1}, RU[2] = {1, 1},
LB[2] = {-1, -1},
RB[2] = {1, -1};
4785 double r = 1, sr = 1;
4820 double rx, ry, ux, uy, lx, ly, bx, by;
4825 if (positive_x > 0) {
4827 ry =
y + k * (rx -
x);
4830 if (positive_y > 0) {
4832 ux =
x + (uy -
y) / k;
4833 r1 =
ratiod(fbcoord1[0], fbcoord2[0], rx);
4834 r2 =
ratiod(fbcoord1[0], fbcoord2[0], ux);
4835 if (std::min(r1, r2) > 1) {
4843 if (ba->
u >= ry && ba->
b < ry) {
4854 if (ba->
r >= ux && ba->
l < ux) {
4863 else if (positive_y < 0) {
4865 bx =
x + (by -
y) / k;
4866 r1 =
ratiod(fbcoord1[0], fbcoord2[0], rx);
4867 r2 =
ratiod(fbcoord1[0], fbcoord2[0], bx);
4868 if (std::min(r1, r2) > 1) {
4874 if (ba->
u >= ry && ba->
b < ry) {
4884 if (ba->
r >= bx && ba->
l < bx) {
4894 r1 =
ratiod(fbcoord1[0], fbcoord2[0],
self->r);
4900 if (ba->
u >=
y && ba->
b <
y) {
4910 else if (positive_x < 0) {
4912 ly =
y + k * (lx -
x);
4915 if (positive_y > 0) {
4917 ux =
x + (uy -
y) / k;
4918 r1 =
ratiod(fbcoord1[0], fbcoord2[0], lx);
4919 r2 =
ratiod(fbcoord1[0], fbcoord2[0], ux);
4920 if (std::min(r1, r2) > 1) {
4926 if (ba->
u >= ly && ba->
b < ly) {
4936 if (ba->
r >= ux && ba->
l < ux) {
4946 else if (positive_y < 0) {
4948 bx =
x + (by -
y) / k;
4949 r1 =
ratiod(fbcoord1[0], fbcoord2[0], lx);
4950 r2 =
ratiod(fbcoord1[0], fbcoord2[0], bx);
4951 if (std::min(r1, r2) > 1) {
4957 if (ba->
u >= ly && ba->
b < ly) {
4967 if (ba->
r >= bx && ba->
l < bx) {
4977 r1 =
ratiod(fbcoord1[0], fbcoord2[0],
self->l);
4983 if (ba->
u >=
y && ba->
b <
y) {
4993 if (positive_y > 0) {
4994 r1 =
ratiod(fbcoord1[1], fbcoord2[1],
self->u);
5000 if (ba->
r >
x && ba->
l <=
x) {
5007 else if (positive_y < 0) {
5008 r1 =
ratiod(fbcoord1[1], fbcoord2[1],
self->b);
5014 if (ba->
r >
x && ba->
l <=
x) {
5032 bool enable_stroke_depth_offset)
5036 int intersections_only = 0;
5037 Object *lineart_camera =
nullptr;
5040 if (
G.debug_value == 4000) {
5044 bool use_render_camera_override =
false;
5056 use_render_camera_override =
true;
5058 if (!lineart_camera) {
5063 lineart_camera = scene->
camera;
5070 *cached_result = lc;
5076 use_render_camera_override ? lineart_camera : scene->
camera,
5112 if (shadow_generated) {
5160 if (!intersections_only) {
5222 if (
G.debug_value == 4000) {
5226 printf(
"Line art total time: %lf\n", t_elapsed);
5241 const int8_t source_type,
5244 const int level_start,
5245 const int level_end,
5247 const int16_t edge_types,
5248 const uchar mask_switches,
5249 const uchar material_mask_bits,
5250 const uchar intersection_mask,
5251 const float thickness,
5252 const float opacity,
5253 const uchar shadow_selection,
5254 const uchar silhouette_mode,
5255 const char *source_vgname,
5257 const int modifier_flags,
5258 const int modifier_calculation_flags)
5260 if (
G.debug_value == 4000) {
5261 printf(
"Line Art v3: Generating...\n");
5264 if (cache ==
nullptr) {
5265 if (
G.debug_value == 4000) {
5266 printf(
"nullptr Lineart cache!\n");
5271 Object *orig_ob =
nullptr;
5275 if (!source_object) {
5282 if (!source_collection) {
5299 int total_point_count = 0;
5300 int stroke_count = 0;
5306 if (!(ec->type & (edge_types & enabled_types))) {
5309 if (ec->level > level_end || ec->level < level_start) {
5312 if (orig_ob && orig_ob != ec->object_ref) {
5315 if (orig_col && ec->object_ref) {
5329 if (ec->material_mask_bits != material_mask_bits) {
5334 if (!(ec->material_mask_bits & material_mask_bits)) {
5341 if (ec->intersection_mask != intersection_mask) {
5346 if ((intersection_mask) && !(ec->intersection_mask & intersection_mask)) {
5351 if (shadow_selection) {
5375 bool is_silhouette =
false;
5377 if (!ec->silhouette_backdrop) {
5378 is_silhouette =
true;
5382 is_silhouette =
true;
5386 if ((!orig_ob) && (!ec->silhouette_backdrop)) {
5387 is_silhouette =
true;
5392 ec->silhouette_backdrop != ec->object_ref)
5394 is_silhouette =
true;
5397 if (inverse_silhouette) {
5398 is_silhouette = !is_silhouette;
5400 if (!is_silhouette) {
5413 total_point_count +=
count;
5419 if (!total_point_count || !stroke_count) {
5440 const bool weight_transfer_match_output = modifier_calculation_flags &
5446 auto ensure_target_defgroup = [&](
StringRef group_name) {
5447 if (group_name.is_empty()) {
5450 int group_index = 0;
5452 if (group_name ==
StringRef(group->name)) {
5457 group_name.copy_utf8_truncated(defgroup->
name);
5462 int up_to_point = 0;
5469 Mesh *src_mesh =
nullptr;
5471 int target_defgroup = ensure_target_defgroup(vgname);
5472 if (source_vgname) {
5476 src_dvert = src_mesh->deform_verts();
5482 int group_index = 0;
5485 const int target_group_index = weight_transfer_match_output ?
5486 ensure_target_defgroup(defgroup->name) :
5488 src_to_dst_defgroup.
append(target_group_index);
5491 src_to_dst_defgroup.
append(-1);
5496 auto transfer_to_matching_groups = [&](
const int64_t source_index,
const int target_index) {
5497 for (
const int from_group : src_to_dst_defgroup.
index_range()) {
5498 if (from_group < 0 || src_to_dst_defgroup[from_group] < 0 ||
5506 src_to_dst_defgroup[from_group]);
5507 const float source_weight = mdw_from ? mdw_from->
weight : 0.0f;
5508 mdw_to->
weight = invert_input ? (1 - source_weight) : source_weight;
5512 auto transfer_to_singular_group = [&](
const int64_t source_index,
const int target_index) {
5513 if (target_defgroup < 0) {
5516 float highest_weight = 0.0f;
5517 for (
const int from_group : src_to_dst_defgroup.
index_range()) {
5518 if (from_group < 0 ||
UNLIKELY(source_index >= src_dvert.
size())) {
5523 const float source_weight = mdw_from ? mdw_from->
weight : 0.0f;
5524 highest_weight = std::max(highest_weight, source_weight);
5527 mdw_to->
weight = invert_input ? (1 - highest_weight) : highest_weight;
5532 int point_i =
i + up_to_point;
5534 point_radii.
span[point_i] = thickness / 2.0f;
5535 if (point_opacities) {
5536 point_opacities.span[point_i] = opacity;
5541 if (!src_to_dst_defgroup.
is_empty()) {
5542 if (weight_transfer_match_output) {
5543 transfer_to_matching_groups(vindex, point_i);
5546 transfer_to_singular_group(vindex, point_i);
5551 offsets[chain_i] = up_to_point;
5552 stroke_materials.span[chain_i] =
max_ii(mat_nr, 0);
5560 stroke_cyclic.
span.fill(
false);
5564 point_opacities.finish();
5565 stroke_materials.finish();
5569 std::array<blender::bke::GeometrySet, 2> geometry_sets{
5577 if (
G.debug_value == 4000) {
5578 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)
constexpr int64_t size() const
constexpr bool is_empty() 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
blender::Span< bool > face_marks
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