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)
1529 uint16_t edge_flag_result = 0;
1533 if (
i < edge_nabr[
i].
e) {
1537 bool face_mark_filtered =
false;
1540 bool only_contour =
false;
1541 if (enable_face_mark) {
1545 if (freestyle_face[tri_faces[
i / 3]]) {
1562 face_mark_filtered =
true;
1566 if (ff1 && ff2 && (ff2 != ff1)) {
1567 face_mark_filtered =
true;
1571 face_mark_filtered = !face_mark_filtered;
1573 if (!face_mark_filtered) {
1576 only_contour =
true;
1581 if (enable_face_mark && !face_mark_filtered && !only_contour) {
1586 if (edge_nabr[
i].
e == -1) {
1596 int f1 =
i / 3, f2 = edge_nabr[
i].
e / 3;
1602 vert = &e_feat_data->
v_array[edge_nabr[
i].
v1];
1604 double view_vector_persp[3];
1605 double *view_vector = view_vector_persp;
1606 double dot_v1 = 0, dot_v2 = 0;
1621 if ((
result = dot_v1 * dot_v2) <= 0 && (dot_v1 + dot_v2)) {
1633 if (material_back_face) {
1644 view_vector = view_vector_persp;
1655 if ((
result = dot_v1 * dot_v2) <= 0 && (dot_v1 + dot_v2)) {
1660 if (!only_contour) {
1662 bool do_crease =
true;
1673 int mat1 = material_indices.
is_empty() ? 0 : material_indices[tri_faces[f1]];
1674 int mat2 = material_indices.
is_empty() ? 0 : material_indices[tri_faces[f2]];
1693 if (!edge_flag_result) {
1701 corner_tris[
i / 3]);
1703 if (real_edges[
i % 3] >= 0) {
1717 edge_nabr[
i].
flags = edge_flag_result;
1719 if (edge_flag_result) {
1742 "LineartPendingEdges array");
1748 pe->
array = new_array;
1769 "LineartPendingEdges array final");
1770 pe->
array = new_array;
1824 const int face_i = tri_task_data->
tri_faces[
i];
1832 int v1 = corner_verts[corner_tri[0]];
1833 int v2 = corner_verts[corner_tri[1]];
1834 int v3 = corner_verts[corner_tri[2]];
1836 tri->
v[0] = &vert_arr[v1];
1837 tri->
v[1] = &vert_arr[
v2];
1838 tri->
v[2] = &vert_arr[v3];
1898 adj_e->
v1 = corner_verts[tri[
i % 3]];
1899 adj_e->
v2 = corner_verts[tri[(
i + 1) % 3]];
1900 if (adj_e->
v1 > adj_e->
v2) {
1901 std::swap(adj_e->
v1, adj_e->
v2);
1905 edge_nabr->
v1 = adj_e->
v1;
1906 edge_nabr->
v2 = adj_e->
v2;
1907 edge_nabr->
flags = 0;
1914 int a = p1.
v1 - p2.
v1;
1915 int b = p1.
v2 - p2.
v2;
1933 "LineartAdjacentEdge arr");
1935 size_t(total_edges),
"LineartEdgeNeighbor arr");
1943 en_data.
adj_e = adj_e;
1953 for (
int i = 0;
i < total_edges - 1;
i++) {
1954 if (adj_e[
i].v1 == adj_e[
i + 1].v1 && adj_e[
i].
v2 == adj_e[
i + 1].
v2) {
1955 edge_nabr[adj_e[
i].
e].
e = adj_e[
i + 1].
e;
1956 edge_nabr[adj_e[
i + 1].
e].
e = adj_e[
i].
e;
1971 if (!
mesh->edges_num) {
2001 ob_info->
v_eln = elem_link_node;
2003 bool use_auto_smooth =
false;
2004 float crease_angle = 0;
2026 int usage = ob_info->
usage;
2031 elem_link_node->
flags |
2036 size_t(corner_tris.
size()),
"LineartTriangleAdjacent");
2051 vert_data.
v_arr = la_v_arr;
2073 tri_data.
tri_arr = la_tri_arr;
2077 uint32_t total_edges = corner_tris.
size() * 3;
2100 edge_feat_data.
ld = la_data;
2101 edge_feat_data.mesh =
mesh;
2103 edge_feat_data.material_indices = material_indices;
2104 edge_feat_data.edges =
mesh->edges();
2105 edge_feat_data.corner_verts =
mesh->corner_verts();
2106 edge_feat_data.corner_edges =
mesh->corner_edges();
2107 edge_feat_data.corner_tris = corner_tris;
2108 edge_feat_data.tri_faces =
mesh->corner_tri_faces();
2109 edge_feat_data.sharp_edges = sharp_edges;
2110 edge_feat_data.sharp_faces = sharp_faces;
2112 edge_feat_data.tri_array = la_tri_arr;
2113 edge_feat_data.v_array = la_v_arr;
2114 edge_feat_data.crease_threshold = crease_angle;
2115 edge_feat_data.use_auto_smooth = use_auto_smooth;
2118 edge_feat_data.use_freestyle_face = bool(edge_feat_data.freestyle_face);
2119 edge_feat_data.use_freestyle_edge = bool(edge_feat_data.freestyle_edge);
2125 &edge_feat_settings);
2134 if (loose_edges.
count > 0) {
2170 la_edge = la_edge_arr;
2171 la_seg = la_seg_arr;
2173 for (
int i = 0;
i < total_edges;
i++) {
2181 if (edge_nabr->
flags == 0) {
2190 if (!(use_type & edge_nabr->
flags)) {
2194 la_edge->
v1 = &la_v_arr[edge_nabr->
v1];
2195 la_edge->
v2 = &la_v_arr[edge_nabr->
v2];
2201 if (edge_nabr->
e != -1) {
2202 findex = edge_nabr->
e / 3;
2208 la_edge->
flags = use_type;
2236 edge_added = la_edge;
2251 la_edge->
v1 = &la_v_arr[edge[0]];
2252 la_edge->
v2 = &la_v_arr[edge[1]];
2343 if (object_has_special_usage) {
2386 int this_face_count)
2390 for (
int i = 0;
i < thread_count;
i++) {
2391 if (olti_list[
i].total_faces < min_face) {
2393 use_olti = &olti_list[
i];
2411 const std::optional<Bounds<float3>>
bounds = use_mesh->bounds_min_max();
2412 if (!
bounds.has_value()) {
2419 for (
int i = 0;
i < 8;
i++) {
2423 co[
i][0] -= shift_x * 2 * co[
i][3];
2424 co[
i][1] -= shift_y * 2 * co[
i][3];
2427 bool cond[6] = {
true,
true,
true,
true,
true,
true};
2430 for (
int i = 0;
i < 8;
i++) {
2431 cond[0] &= (co[
i][0] < -co[
i][3]);
2432 cond[1] &= (co[
i][0] > co[
i][3]);
2433 cond[2] &= (co[
i][1] < -co[
i][3]);
2434 cond[3] &= (co[
i][1] > co[
i][3]);
2435 cond[4] &= (co[
i][2] < -co[
i][3]);
2436 cond[5] &= (co[
i][2] > co[
i][3]);
2438 for (
int i = 0;
i < 6;
i++) {
2451 const float use_mat[4][4],
2480 if ((!use_mesh) || use_mesh->
runtime->edit_mesh) {
2522 bool allow_duplicates,
2523 bool do_shadow_casting,
2530 if (!do_shadow_casting) {
2534 double asp = (double(ld->
w) / double(ld->
h));
2550 BLI_assert(!
"Unsupported camera type in lineart_main_load_geometries");
2567 if (
G.debug_value == 4000) {
2572 int bound_box_discard_count = 0;
2586 if (allow_duplicates) {
2592 deg_iter_settings.
flags = flags;
2617 eval_ob->object_to_world().ptr(),
2628 if (
G.debug_value == 4000) {
2629 printf(
"thread count: %d\n", thread_count);
2631 for (
int i = 0;
i < thread_count;
i++) {
2645 for (
int i = 0;
i < thread_count;
i++) {
2650 edge_count += obi->pending_edges.next;
2655 for (
int i = 0;
i < thread_count;
i++) {
2661 int v_count = obi->v_eln->element_count;
2662 obi->v_eln->global_index_offset = global_i;
2663 for (
int vi = 0; vi < v_count; vi++) {
2664 v[vi].index += global_i;
2670 obi->global_i_offset = global_i;
2671 global_i += v_count;
2676 if (
G.debug_value == 4000) {
2678 printf(
"Line art loading time: %lf\n", t_elapsed);
2679 printf(
"Discarded %d object from bound box check\n", bound_box_discard_count);
2692 if (tri->
v[0] == vt) {
2697 if (tri->
v[1] == vt) {
2702 if (tri->
v[2] == vt) {
2712 bool allow_overlapping_edges)
2733 if (allow_overlapping_edges) {
2734#define LRT_TRI_SAME_POINT(tri, i, pt) \
2735 ((LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[0], pt->gloc[0]) && \
2736 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[1], pt->gloc[1]) && \
2737 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[2], pt->gloc[2])) || \
2738 (LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[0], pt->gloc[0]) && \
2739 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[1], pt->gloc[1]) && \
2740 LRT_DOUBLE_CLOSE_ENOUGH(tri->v[i]->gloc[2], pt->gloc[2])))
2748#undef LRT_TRI_SAME_POINT
2755#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst) \
2757 lst[0] = LRT_MIN3_INDEX(ia, ib, ic); \
2758 lst[1] = (((ia <= ib && ib <= ic) || (ic <= ib && ib <= ia)) ? \
2760 (((ic <= ia && ia <= ib) || (ib < ia && ia <= ic)) ? 0 : 2)); \
2761 lst[2] = LRT_MAX3_INDEX(ia, ib, ic); \
2765#define INTERSECT_JUST_GREATER(is, order, num, index) \
2767 index = (num < is[order[0]] ? \
2769 (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : -1))); \
2773#define INTERSECT_JUST_SMALLER(is, order, num, index) \
2775 index = (num > is[order[2]] ? \
2777 (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : -1))); \
2780#define LRT_ISEC(index) (index == 0 ? isec_e1 : (index == 1 ? isec_e2 : isec_e3))
2781#define LRT_PARALLEL(index) (index == 0 ? para_e1 : (index == 1 ? para_e2 : para_e3))
2807 const double *override_camera_loc,
2808 const bool override_cam_is_persp,
2809 const bool allow_overlapping_edges,
2810 const double m_view_projection[4][4],
2811 const double camera_dir[3],
2812 const float cam_shift_x,
2813 const float cam_shift_y,
2817 double cross_ratios[3] = {0};
2819 int cross_v1 = -1, cross_v2 = -1;
2821 int isec_e1, isec_e2, isec_e3;
2823 bool para_e1, para_e2, para_e3;
2828 double view_vector[4];
2830 double dot_v1, dot_v2, dot_v1a, dot_v2a;
2832 double gloc[4], trans[4];
2835 double *LFBC =
e->v1->fbcoord, *RFBC =
e->v2->fbcoord, *FBC0 = tri->
v[0]->
fbcoord,
2839 if ((std::max({FBC0[0], FBC1[0], FBC2[0]}) < std::min(LFBC[0], RFBC[0])) ||
2840 (std::min({FBC0[0], FBC1[0], FBC2[0]}) > std::max(LFBC[0], RFBC[0])) ||
2841 (std::max({FBC0[1], FBC1[1], FBC2[1]}) < std::min(LFBC[1], RFBC[1])) ||
2842 (std::min({FBC0[1], FBC1[1], FBC2[1]}) > std::max(LFBC[1], RFBC[1])) ||
2843 (std::min({FBC0[3], FBC1[3], FBC2[3]}) > std::max(LFBC[3], RFBC[3])))
2866 if (override_cam_is_persp) {
2893 if (
fabs(dot_f) < FLT_EPSILON) {
2902 if (!isec_e1 && !isec_e2 && !isec_e3) {
2904 if ((!state_v1) && (!state_v2)) {
2911 dot_v1a =
fabs(dot_v1);
2912 if (dot_v1a < DBL_EPSILON) {
2916 dot_v2a =
fabs(dot_v2);
2917 if (dot_v2a < DBL_EPSILON) {
2921 if (dot_v1 - dot_v2 == 0) {
2924 else if (dot_v1 * dot_v2 <= 0) {
2925 cut = dot_v1a /
fabs(dot_v1 - dot_v2);
2928 cut =
fabs(dot_v2 + dot_v1) /
fabs(dot_v1 - dot_v2);
2929 cut = dot_v2a > dot_v1a ? 1 - cut : cut;
2933 if (override_cam_is_persp) {
2937 trans[0] -= cam_shift_x * 2;
2938 trans[1] -= cam_shift_y * 2;
2940 if (
fabs(
e->v1->fbcoord[0] -
e->v2->fbcoord[0]) >
fabs(
e->v1->fbcoord[1] -
e->v2->fbcoord[1]))
2942 cut =
ratiod(
e->v1->fbcoord[0],
e->v2->fbcoord[0], trans[0]);
2945 cut =
ratiod(
e->v1->fbcoord[1],
e->v2->fbcoord[1], trans[1]);
2949#define LRT_GUARD_NOT_FOUND \
2950 if (cross_v1 < 0 || cross_v2 < 0) { \
3043 if (cross_v1 >= 0 &&
LRT_ISEC(cross_v1)) {
3047 if (cross_v1 >= 0) {
3049 if (cross_v1 >= 0) {
3059 double dot_1f = dot_v1 * dot_f, dot_2f = dot_v2 * dot_f;
3062 if (dot_1f <= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) {
3063 *from = std::max(0.0, cross_ratios[cross_v1]);
3064 *to = std::min(1.0, cross_ratios[cross_v2]);
3070 if (dot_1f >= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) {
3071 *from = std::max(cut, cross_ratios[cross_v1]);
3072 *to = std::min(1.0, cross_ratios[cross_v2]);
3078 if (dot_1f <= 0 && dot_2f >= 0 && (dot_v1 || dot_v2)) {
3079 *from = std::max(0.0, cross_ratios[cross_v1]);
3080 *to = std::min(cut, cross_ratios[cross_v2]);
3091#undef INTERSECT_SORT_MIN_TO_MAX_3
3092#undef INTERSECT_JUST_GREATER
3093#undef INTERSECT_JUST_SMALLER
3103 if (
l->v[0]->index == r->
v[0]->
index) {
3104 if (
l->v[1]->index == r->
v[1]->
index ||
l->v[1]->index == r->
v[2]->
index ||
3105 l->v[2]->index == r->
v[2]->
index ||
l->v[2]->index == r->
v[1]->
index)
3110 if (
l->v[0]->index == r->
v[1]->
index) {
3111 if (
l->v[1]->index == r->
v[0]->
index ||
l->v[1]->index == r->
v[2]->
index ||
3112 l->v[2]->index == r->
v[2]->
index ||
l->v[2]->index == r->
v[0]->
index)
3117 if (
l->v[0]->index == r->
v[2]->
index) {
3118 if (
l->v[1]->index == r->
v[1]->
index ||
l->v[1]->index == r->
v[0]->
index ||
3119 l->v[2]->index == r->
v[0]->
index ||
l->v[2]->index == r->
v[1]->
index)
3124 if (
l->v[1]->index == r->
v[0]->
index) {
3125 if (
l->v[2]->index == r->
v[1]->
index ||
l->v[2]->index == r->
v[2]->
index ||
3126 l->v[0]->index == r->
v[2]->
index ||
l->v[0]->index == r->
v[1]->
index)
3131 if (
l->v[1]->index == r->
v[1]->
index) {
3132 if (
l->v[2]->index == r->
v[0]->
index ||
l->v[2]->index == r->
v[2]->
index ||
3133 l->v[0]->index == r->
v[2]->
index ||
l->v[0]->index == r->
v[0]->
index)
3138 if (
l->v[1]->index == r->
v[2]->
index) {
3139 if (
l->v[2]->index == r->
v[1]->
index ||
l->v[2]->index == r->
v[0]->
index ||
3140 l->v[0]->index == r->
v[0]->
index ||
l->v[0]->index == r->
v[1]->
index)
3153 if (
l->v[0] == r->
v[0]) {
3156 if (
l->v[0] == r->
v[1]) {
3159 if (
l->v[0] == r->
v[2]) {
3162 if (
l->v[1] == r->
v[0]) {
3165 if (
l->v[1] == r->
v[1]) {
3168 if (
l->v[1] == r->
v[2]) {
3171 if (
l->v[2] == r->
v[0]) {
3174 if (
l->v[2] == r->
v[1]) {
3177 if (
l->v[2] == r->
v[2]) {
3188 double dir_v1[3], dir_v2[3];
3189 double dot_v1, dot_v2;
3198 if (dot_v1 * dot_v2 > 0 || (!dot_v1 && !dot_v2)) {
3202 dot_v1 =
fabs(dot_v1);
3203 dot_v2 =
fabs(dot_v2);
3228 double *
next = v1, *last =
nullptr;
3305 "LineartIsecSingle");
3309 th->
array = new_array;
3314 isec_single->
tri1 = tri1;
3315 isec_single->
tri2 = tri2;
3317 std::swap(isec_single->
tri1, isec_single->
tri2);
3322#define LRT_ISECT_TRIANGLE_PER_THREAD 4096
3340 while (remaining > 0 && eln) {
3342 int added_count = std::min(remaining, remaining_this_eln);
3343 remaining -= added_count;
3344 if (remaining || added_count == remaining_this_eln) {
3379 for (
int i = 0;
i < thread_count;
i++) {
3409 double *G0 = tri->
v[0]->
gloc, *G1 = tri->
v[1]->
gloc, *G2 = tri->
v[2]->
gloc;
3412 for (
int i = 0;
i < up_to;
i++) {
3431 double *RG0 = testing_triangle->
v[0]->
gloc, *RG1 = testing_triangle->
v[1]->
gloc,
3432 *RG2 = testing_triangle->
v[2]->
gloc;
3435 if ((std::min({G0[2], G1[2], G2[2]}) > std::max({RG0[2], RG1[2], RG2[2]})) ||
3436 (std::max({G0[2], G1[2], G2[2]}) < std::min({RG0[2], RG1[2], RG2[2]})) ||
3437 (std::min({G0[0], G1[0], G2[0]}) > std::max({RG0[0], RG1[0], RG2[0]})) ||
3438 (std::max({G0[0], G1[0], G2[0]}) < std::min({RG0[0], RG1[0], RG2[0]})) ||
3439 (std::min({G0[1], G1[1], G2[1]}) > std::max({RG0[1], RG1[1], RG2[1]})) ||
3440 (std::max({G0[1], G1[1], G2[1]}) < std::min({RG0[1], RG1[1], RG2[1]})) ||
3448 double iv1[3], iv2[3];
3457 float direction[3] = {0, 0, 1};
3460 float obmat_no_scale[4][4];
3489 for (
int i = 0;
i < 4;
i++) {
3497 if (ld ==
nullptr) {
3522 if (ld ==
nullptr) {
3546 if (
G.debug_value == 4000) {
3547 printf(
"LRT: Destroyed render data.\n");
3578 if (!scene || !camera || !lc) {
3582 double clipping_offset = 0;
3586 clipping_offset = 0.0001;
3590 if (active_camera) {
3613 double asp = double(ld->
w) / double(ld->
h);
3733 if (ld->
w > ld->
h) {
3734 sp_w = sp_h * ld->
w / ld->
h;
3737 sp_h = sp_w * ld->
h / ld->
w;
3742 double span_w = 1.0 / sp_w * 2.0;
3743 double span_h = 1.0 / sp_h * 2.0;
3758 for (row = 0; row < sp_h; row++) {
3763 ba->
l = span_w *
col - 1.0;
3764 ba->
r = (
col == sp_w - 1) ? 1.0 : (span_w * (
col + 1) - 1.0);
3765 ba->
u = 1.0 - span_h * row;
3766 ba->
b = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1));
3768 ba->
cx = (ba->
l + ba->
r) / 2;
3769 ba->
cy = (ba->
u + ba->
b) / 2;
3775 "ba_linked_triangles");
3813 if (ba[1].u > tba->
b && ba[1].
b < tba->u) {
3817 if (ba[2].u > tba->
b && ba[2].
b < tba->u) {
3824 if (ba[0].u > tba->
b && ba[0].
b < tba->u) {
3828 if (ba[3].u > tba->
b && ba[3].
b < tba->u) {
3835 if (ba[0].r > tba->
l && ba[0].
l < tba->r) {
3839 if (ba[1].r > tba->
l && ba[1].
l < tba->r) {
3846 if (ba[2].r > tba->
l && ba[2].
l < tba->r) {
3850 if (ba[3].r > tba->
l && ba[3].
l < tba->r) {
3862 next_lip = lip2->
next;
3866 if (ba[1].u > tba->
b && ba[1].
b < tba->u) {
3869 if (ba[2].u > tba->
b && ba[2].
b < tba->u) {
3879 next_lip = lip2->
next;
3883 if (ba[0].u > tba->
b && ba[0].
b < tba->u) {
3886 if (ba[3].u > tba->
b && ba[3].
b < tba->u) {
3896 next_lip = lip2->
next;
3900 if (ba[0].r > tba->
l && ba[0].
l < tba->r) {
3903 if (ba[1].r > tba->
l && ba[1].
l < tba->r) {
3913 next_lip = lip2->
next;
3917 if (ba[2].r > tba->
l && ba[2].
l < tba->r) {
3920 if (ba[3].r > tba->
l && ba[3].
l < tba->r) {
3938 for (
int i = 0;
i < 4;
i++) {
3971 for (
int i = 0;
i < total_tile_initial;
i++) {
3982 int recursive_level)
3990 ba[0].
cx = (ba[0].
l + ba[0].
r) / 2;
3991 ba[0].
cy = (ba[0].
u + ba[0].
b) / 2;
3997 ba[1].
cx = (ba[1].
l + ba[1].
r) / 2;
3998 ba[1].
cy = (ba[1].
u + ba[1].
b) / 2;
4004 ba[2].
cx = (ba[2].
l + ba[2].
r) / 2;
4005 ba[2].
cy = (ba[2].
u + ba[2].
b) / 2;
4011 ba[3].
cx = (ba[3].
l + ba[3].
r) / 2;
4012 ba[3].
cy = (ba[3].
u + ba[3].
b) / 2;
4015 for (
int i = 0;
i < 4;
i++) {
4019 "ba_linked_triangles");
4037 ld, &ba[0], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4041 ld, &ba[1], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4045 ld, &ba[2], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4049 ld, &ba[3], tri,
b, 0, recursive_level + 1,
false,
nullptr);
4064 double converted[4];
4067 if (((converted[0] = ba->
l) > std::max(
l[0], r[0])) ||
4068 ((converted[1] = ba->
r) < std::min(
l[0], r[0])) ||
4069 ((converted[2] = ba->
b) > std::max(
l[1], r[1])) ||
4070 ((converted[3] = ba->
u) < std::min(
l[1], r[1])))
4078 c1 = dx * (converted[2] -
l[1]) - dy * (converted[0] -
l[0]);
4081 c1 = dx * (converted[2] -
l[1]) - dy * (converted[1] -
l[0]);
4087 c1 = dx * (converted[3] -
l[1]) - dy * (converted[0] -
l[0]);
4093 c1 = dx * (converted[3] -
l[1]) - dy * (converted[1] -
l[0]);
4105 bool *r_triangle_vert_inside)
4107 double p1[2], p2[2], p3[2], p4[2];
4110 p3[0] = p1[0] = ba->
l;
4111 p2[1] = p1[1] = ba->
b;
4112 p2[0] = p4[0] = ba->
r;
4113 p3[1] = p4[1] = ba->
u;
4115 if ((FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) ||
4116 (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) ||
4117 (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1]))
4119 *r_triangle_vert_inside =
true;
4123 *r_triangle_vert_inside =
false;
4160 int recursive_level,
4161 bool do_intersection,
4164 bool triangle_vert_inside;
4171 if (old_ba->
child) {
4174 double *B1 = l_r_u_b;
4183 for (
int iba = 0; iba < 4; iba++) {
4186 ld, &old_ba->
child[iba], tri, B1, recursive, recursive_level + 1, do_intersection, th);
4204 if (triangle_vert_inside) {
4220 if (recursive_level < ld->qtree.recursive_level &&
4223 if (!old_ba->
child) {
4242 ld, root_ba, tri, l_r_u_b, recursive, recursive_level, do_intersection, th);
4255 if (recursive && ba->
child) {
4256 for (
int i = 0;
i < 4;
i++) {
4274 if (root_ba->
child ==
nullptr) {
4279 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[0]))
4284 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[1]))
4289 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[2]))
4294 ld,
e->v1->fbcoord,
e->v2->fbcoord, &root_ba->
child[3]))
4303 if (root_ba->
child) {
4304 for (
int i = 0;
i < 4;
i++) {
4314 "cleared lineart edges");
4330 int r1, r2, c1, c2, row,
col;
4332 for (row = r1; row != r2 + 1; row++) {
4344 uint8_t max_occlusion)
4347 for (
int i = 0;
i < 4;
i++) {
4357 int usable_count = 0;
4360 if (
e->min_occ > max_occlusion) {
4366 if (!usable_count) {
4372 "cleaned lineart edge array");
4377 if (
e->min_occ > max_occlusion) {
4380 new_array[new_i] =
e;
4405 if (!tri->
v[0] || !tri->
v[1] || !tri->
v[2]) {
4414 if (
b[0] > 1 ||
b[1] < -1 ||
b[2] > 1 ||
b[3] < -1) {
4418 (*colbegin) = int((
b[0] + 1.0) / sp_w);
4419 (*colend) = int((
b[1] + 1.0) / sp_w);
4420 (*rowend) = ld->
qtree.
count_y - int((
b[2] + 1.0) / sp_h) - 1;
4421 (*rowbegin) = ld->
qtree.
count_y - int((
b[3] + 1.0) / sp_h) - 1;
4429 *colbegin = std::max(*colbegin, 0);
4430 *rowbegin = std::max(*rowbegin, 0);
4441 if (!
e->v1 || !
e->v2) {
4445 if (
e->v1->fbcoord[0] !=
e->v1->fbcoord[0] ||
e->v2->fbcoord[0] !=
e->v2->fbcoord[0]) {
4449 b[0] = std::min(
e->v1->fbcoord[0],
e->v2->fbcoord[0]);
4450 b[1] = std::max(
e->v1->fbcoord[0],
e->v2->fbcoord[0]);
4451 b[2] = std::min(
e->v1->fbcoord[1],
e->v2->fbcoord[1]);
4452 b[3] = std::max(
e->v1->fbcoord[1],
e->v2->fbcoord[1]);
4454 if (
b[0] > 1 ||
b[1] < -1 ||
b[2] > 1 ||
b[3] < -1) {
4458 (*colbegin) = int((
b[0] + 1.0) / sp_w);
4459 (*colend) = int((
b[1] + 1.0) / sp_w);
4460 (*rowend) = ld->
qtree.
count_y - int((
b[2] + 1.0) / sp_h) - 1;
4461 (*rowbegin) = ld->
qtree.
count_y - int((
b[3] + 1.0) / sp_h) - 1;
4464 if ((*rowend) < (*rowbegin)) {
4468 if ((*colend) < (*colbegin)) {
4489 col = int((
x + 1.0) / sp_w);
4499 row = std::max(row, 0);
4508 int c = int((
x + 1.0) / sp_w);
4520 while (iba->
child) {
4523 iba = &iba->
child[0];
4526 iba = &iba->
child[3];
4531 iba = &iba->
child[1];
4534 iba = &iba->
child[2];
4562 for (
int ei = index_start; ei < index_end; ei++) {
4571 for (co = x1; co <= x2; co++) {
4572 for (r = y1; r <= y2; r++) {
4595 int total_lines = 0;
4599 if (
G.debug_value == 4000) {
4634 for (
int j = 0; j < th->
current; j++) {
4657 v2->fbcoord[2] = ZMin * ZMax / (ZMax -
fabs(
v2->fbcoord[2]) * (ZMax - ZMin));
4663 e->edge_identifier = (
uint64_t(
e->t1->target_reference) << 32) |
e->t2->target_reference;
4677 if (
e->t1->intersection_priority >
e->t2->intersection_priority) {
4678 e->object_ref = ob1;
4680 else if (
e->t1->intersection_priority <
e->t2->intersection_priority) {
4681 e->object_ref = ob2;
4686 e->object_ref = ob1;
4702 if (
G.debug_value == 4000) {
4725 if (
G.debug_value == 4000) {
4727 printf(
"Line art intersection time: %f\n", t_elapsed);
4735 double data[2] = {fbcoord1[0], fbcoord1[1]};
4736 double LU[2] = {-1, 1}, RU[2] = {1, 1},
LB[2] = {-1, -1},
RB[2] = {1, -1};
4737 double r = 1, sr = 1;
4772 double rx, ry, ux, uy, lx, ly, bx, by;
4777 if (positive_x > 0) {
4779 ry =
y + k * (rx -
x);
4782 if (positive_y > 0) {
4784 ux =
x + (uy -
y) / k;
4785 r1 =
ratiod(fbcoord1[0], fbcoord2[0], rx);
4786 r2 =
ratiod(fbcoord1[0], fbcoord2[0], ux);
4787 if (std::min(r1, r2) > 1) {
4795 if (ba->
u >= ry && ba->
b < ry) {
4806 if (ba->
r >= ux && ba->
l < ux) {
4815 else if (positive_y < 0) {
4817 bx =
x + (by -
y) / k;
4818 r1 =
ratiod(fbcoord1[0], fbcoord2[0], rx);
4819 r2 =
ratiod(fbcoord1[0], fbcoord2[0], bx);
4820 if (std::min(r1, r2) > 1) {
4826 if (ba->
u >= ry && ba->
b < ry) {
4836 if (ba->
r >= bx && ba->
l < bx) {
4846 r1 =
ratiod(fbcoord1[0], fbcoord2[0],
self->r);
4852 if (ba->
u >=
y && ba->
b <
y) {
4862 else if (positive_x < 0) {
4864 ly =
y + k * (lx -
x);
4867 if (positive_y > 0) {
4869 ux =
x + (uy -
y) / k;
4870 r1 =
ratiod(fbcoord1[0], fbcoord2[0], lx);
4871 r2 =
ratiod(fbcoord1[0], fbcoord2[0], ux);
4872 if (std::min(r1, r2) > 1) {
4878 if (ba->
u >= ly && ba->
b < ly) {
4888 if (ba->
r >= ux && ba->
l < ux) {
4898 else if (positive_y < 0) {
4900 bx =
x + (by -
y) / k;
4901 r1 =
ratiod(fbcoord1[0], fbcoord2[0], lx);
4902 r2 =
ratiod(fbcoord1[0], fbcoord2[0], bx);
4903 if (std::min(r1, r2) > 1) {
4909 if (ba->
u >= ly && ba->
b < ly) {
4919 if (ba->
r >= bx && ba->
l < bx) {
4929 r1 =
ratiod(fbcoord1[0], fbcoord2[0],
self->l);
4935 if (ba->
u >=
y && ba->
b <
y) {
4945 if (positive_y > 0) {
4946 r1 =
ratiod(fbcoord1[1], fbcoord2[1],
self->u);
4952 if (ba->
r >
x && ba->
l <=
x) {
4959 else if (positive_y < 0) {
4960 r1 =
ratiod(fbcoord1[1], fbcoord2[1],
self->b);
4966 if (ba->
r >
x && ba->
l <=
x) {
4984 bool enable_stroke_depth_offset)
4988 int intersections_only = 0;
4989 Object *lineart_camera =
nullptr;
4992 if (
G.debug_value == 4000) {
4996 bool use_render_camera_override =
false;
5008 use_render_camera_override =
true;
5010 if (!lineart_camera) {
5015 lineart_camera = scene->
camera;
5022 *cached_result = lc;
5028 use_render_camera_override ? lineart_camera : scene->
camera,
5064 if (shadow_generated) {
5112 if (!intersections_only) {
5174 if (
G.debug_value == 4000) {
5178 printf(
"Line art total time: %lf\n", t_elapsed);
5193 const int8_t source_type,
5196 const int level_start,
5197 const int level_end,
5199 const int16_t edge_types,
5200 const uchar mask_switches,
5201 const uchar material_mask_bits,
5202 const uchar intersection_mask,
5203 const float thickness,
5204 const float opacity,
5205 const uchar shadow_selection,
5206 const uchar silhouette_mode,
5207 const char *source_vgname,
5209 const int modifier_flags,
5210 const int modifier_calculation_flags)
5212 if (
G.debug_value == 4000) {
5213 printf(
"Line Art v3: Generating...\n");
5216 if (cache ==
nullptr) {
5217 if (
G.debug_value == 4000) {
5218 printf(
"nullptr Lineart cache!\n");
5223 Object *orig_ob =
nullptr;
5227 if (!source_object) {
5234 if (!source_collection) {
5251 int total_point_count = 0;
5252 int stroke_count = 0;
5258 if (!(ec->type & (edge_types & enabled_types))) {
5261 if (ec->level > level_end || ec->level < level_start) {
5264 if (orig_ob && orig_ob != ec->object_ref) {
5267 if (orig_col && ec->object_ref) {
5281 if (ec->material_mask_bits != material_mask_bits) {
5286 if (!(ec->material_mask_bits & material_mask_bits)) {
5293 if (ec->intersection_mask != intersection_mask) {
5298 if ((intersection_mask) && !(ec->intersection_mask & intersection_mask)) {
5303 if (shadow_selection) {
5327 bool is_silhouette =
false;
5329 if (!ec->silhouette_backdrop) {
5330 is_silhouette =
true;
5334 is_silhouette =
true;
5338 if ((!orig_ob) && (!ec->silhouette_backdrop)) {
5339 is_silhouette =
true;
5344 ec->silhouette_backdrop != ec->object_ref)
5346 is_silhouette =
true;
5349 if (inverse_silhouette) {
5350 is_silhouette = !is_silhouette;
5352 if (!is_silhouette) {
5365 total_point_count +=
count;
5371 if (!total_point_count || !stroke_count) {
5392 const bool weight_transfer_match_output = modifier_calculation_flags &
5398 auto ensure_target_defgroup = [&](
StringRef group_name) {
5399 if (group_name.is_empty()) {
5402 int group_index = 0;
5404 if (group_name ==
StringRef(group->name)) {
5409 group_name.copy_utf8_truncated(defgroup->
name);
5414 int up_to_point = 0;
5421 Mesh *src_mesh =
nullptr;
5423 int target_defgroup = ensure_target_defgroup(vgname);
5424 if (source_vgname) {
5428 src_dvert = src_mesh->deform_verts();
5434 int group_index = 0;
5437 const int target_group_index = weight_transfer_match_output ?
5438 ensure_target_defgroup(defgroup->name) :
5440 src_to_dst_defgroup.
append(target_group_index);
5443 src_to_dst_defgroup.
append(-1);
5448 auto transfer_to_matching_groups = [&](
const int64_t source_index,
const int target_index) {
5449 for (
const int from_group : src_to_dst_defgroup.
index_range()) {
5450 if (from_group < 0 ||
UNLIKELY(source_index >= src_dvert.
size())) {
5456 src_to_dst_defgroup[from_group]);
5457 const float source_weight = mdw_from ? mdw_from->
weight : 0.0f;
5458 mdw_to->
weight = invert_input ? (1 - source_weight) : source_weight;
5462 auto transfer_to_singular_group = [&](
const int64_t source_index,
const int target_index) {
5463 float highest_weight = 0.0f;
5464 for (
const int from_group : src_to_dst_defgroup.
index_range()) {
5465 if (from_group < 0 ||
UNLIKELY(source_index >= src_dvert.
size())) {
5470 const float source_weight = mdw_from ? mdw_from->
weight : 0.0f;
5471 highest_weight = std::max(highest_weight, source_weight);
5474 mdw_to->
weight = invert_input ? (1 - highest_weight) : highest_weight;
5479 int point_i =
i + up_to_point;
5481 point_radii.
span[point_i] = thickness / 2.0f;
5482 if (point_opacities) {
5483 point_opacities.span[point_i] = opacity;
5488 if (!src_to_dst_defgroup.
is_empty()) {
5489 if (weight_transfer_match_output) {
5490 transfer_to_matching_groups(vindex, point_i);
5493 transfer_to_singular_group(vindex, point_i);
5498 offsets[chain_i] = up_to_point;
5499 stroke_materials.span[chain_i] =
max_ii(mat_nr, 0);
5507 stroke_cyclic.
span.fill(
false);
5511 point_opacities.finish();
5512 stroke_materials.finish();
5516 std::array<blender::bke::GeometrySet, 2> geometry_sets{
5524 if (
G.debug_value == 4000) {
5525 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.
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)
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_LRT_INTERSECTION_ONLY
@ COLLECTION_LRT_FORCE_INTERSECTION
@ COLLECTION_LRT_OCCLUSION_ONLY
@ COLLECTION_LRT_NO_INTERSECTION
@ COLLECTION_HIDE_VIEWPORT
@ 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 MEM_recallocN(vmemh, len)
#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_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
GAttributeReader lookup(const StringRef attribute_id) 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, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_topology_changed()
float length(VecOp< float, D >) RET
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)
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
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, bool allow_merging_instance_references=true)
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
blender::VArray< bool > freestyle_face
blender::VArray< bool > freestyle_edge
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