[Bf-blender-cvs] [7ef1f7648f4] temp-lineart-contained: LineArt: Index calculation based adjacent lookup WIP
YimingWu
noreply at git.blender.org
Wed Apr 20 05:09:10 CEST 2022
Commit: 7ef1f7648f423cc2991c7599a7b3743971fdd184
Author: YimingWu
Date: Wed Apr 20 10:53:21 2022 +0800
Branches: temp-lineart-contained
https://developer.blender.org/rB7ef1f7648f423cc2991c7599a7b3743971fdd184
LineArt: Index calculation based adjacent lookup WIP
===================================================================
M source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
===================================================================
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 2a3f7653bdb..af82edfd0aa 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -1450,6 +1450,28 @@ static void lineart_vert_transform(
mul_v4_m4v3_db(vt->fbcoord, mvp_mat, co);
}
+static void lineart_vert_transform_me(
+ MVert *v, int index, LineartVert *RvBuf, double (*mv_mat)[4], double (*mvp_mat)[4])
+{
+ double co[4];
+ LineartVert *vt = &RvBuf[index];
+ copy_v3db_v3fl(co, v->co);
+ mul_v3_m4v3_db(vt->gloc, mv_mat, co);
+ mul_v4_m4v3_db(vt->fbcoord, mvp_mat, co);
+}
+
+typedef struct LineartAdjacentItem {
+ unsigned int v1;
+ unsigned int v2;
+ unsigned int e;
+} LineartAdjacentItem;
+
+typedef struct LineartEdgeNeighbor {
+ int e;
+ short flags;
+ int v1, v2;
+} LineartEdgeNeighbor;
+
typedef struct VertData {
MVert *mvert;
LineartVert *v_arr;
@@ -1678,6 +1700,163 @@ static uint16_t lineart_identify_medge_feature_edges(
return edge_flag_result;
}
+__attribute__((optimize("O0"))) static uint16_t lineart_identify_feature_line_me(
+ LineartRenderBuffer *rb,
+ int eindex,
+ LineartTriangle *rt_array,
+ LineartVert *rv_array,
+ float crease_threshold,
+ bool use_auto_smooth,
+ bool use_freestyle_edge,
+ bool use_freestyle_face,
+ Mesh *me,
+ LineartEdgeNeighbor *en,
+ float (*normals)[3])
+{
+
+ MPoly *ll = NULL, *lr = NULL;
+
+ int t1i = -1, t1e = -1, t2i = -1;
+ if (en[eindex].e >= 0) {
+ t1i = en[eindex].e / 3;
+ t1e = en[eindex].e;
+ }
+ if (t1e >= 0 && en[t1e].e >= 0) {
+ t2i = en[t1e].e / 3;
+ }
+
+ if (t1i >= 0) {
+ ll = &me->mpoly[me->runtime.looptris.array[t1i].poly];
+ }
+ if (t2i >= 0) {
+ lr = &me->mpoly[me->runtime.looptris.array[t2i].poly];
+ }
+
+ if (t1i < 0 && t2i < 0) {
+ if (!rb->use_loose_as_contour) {
+ if (use_freestyle_face && rb->filter_face_mark) {
+ if (rb->filter_face_mark_invert) {
+ return LRT_EDGE_FLAG_LOOSE;
+ }
+ return 0;
+ }
+ return LRT_EDGE_FLAG_LOOSE;
+ }
+ }
+
+ FreestyleEdge *fel, *fer;
+ bool face_mark_filtered = false;
+ bool only_contour = false;
+
+ uint16_t edge_flag_result = 0;
+
+ /* Mesh boundary */
+ if (!ll || !lr) {
+ return (edge_flag_result | LRT_EDGE_FLAG_CONTOUR);
+ }
+
+ LineartTriangle *tri1, *tri2;
+ LineartVert *l;
+
+ /* The mesh should already be triangulated now, so we can assume each face is a triangle. */
+ tri1 = lineart_triangle_from_index(rb, rt_array, t1i);
+ tri2 = lineart_triangle_from_index(rb, rt_array, t2i);
+
+ l = &rv_array[en[eindex].v1];
+
+ double vv[3];
+ double *view_vector = vv;
+ double dot_1 = 0, dot_2 = 0;
+ double result;
+ bool material_back_face = ((tri1->flags | tri2->flags) & LRT_TRIANGLE_MAT_BACK_FACE_CULLING);
+
+ if (rb->use_contour || rb->use_back_face_culling || material_back_face) {
+
+ if (rb->cam_is_persp) {
+ sub_v3_v3v3_db(view_vector, rb->camera_pos, l->gloc);
+ }
+ else {
+ view_vector = rb->view_vector;
+ }
+
+ dot_1 = dot_v3v3_db(view_vector, tri1->gn);
+ dot_2 = dot_v3v3_db(view_vector, tri2->gn);
+
+ if (rb->use_contour && (result = dot_1 * dot_2) <= 0 && (fabs(dot_1) + fabs(dot_2))) {
+ edge_flag_result |= LRT_EDGE_FLAG_CONTOUR;
+ }
+
+ /* Because the ray points towards the camera, so backface is when dot value being negative.*/
+ if (rb->use_back_face_culling) {
+ if (dot_1 < 0) {
+ tri1->flags |= LRT_CULL_DISCARD;
+ }
+ if (dot_2 < 0) {
+ tri2->flags |= LRT_CULL_DISCARD;
+ }
+ }
+ if (material_back_face) {
+ if (tri1->flags & LRT_TRIANGLE_MAT_BACK_FACE_CULLING && dot_1 < 0) {
+ tri1->flags |= LRT_CULL_DISCARD;
+ }
+ if (tri2->flags & LRT_TRIANGLE_MAT_BACK_FACE_CULLING && dot_2 < 0) {
+ tri2->flags |= LRT_CULL_DISCARD;
+ }
+ }
+ }
+
+ /* For when face mark filtering decided that we discard the face but keep_contour option is on.
+ * so we still have correct full contour around the object. */
+ if (only_contour) {
+ return edge_flag_result;
+ }
+
+ if (rb->use_light_contour) {
+ if (rb->light_is_sun) {
+ view_vector = rb->light_vector;
+ }
+ else {
+ view_vector = vv;
+ sub_v3_v3v3_db(view_vector, l->gloc, rb->light_vector);
+ }
+
+ dot_1 = dot_v3v3_db(view_vector, tri1->gn);
+ dot_2 = dot_v3v3_db(view_vector, tri2->gn);
+
+ if ((result = dot_1 * dot_2) <= 0 && (dot_1 + dot_2)) {
+ edge_flag_result |= LRT_EDGE_FLAG_LIGHT_CONTOUR;
+ }
+ }
+
+ /* For when face mark filtering decided that we discard the face but keep_contour option is on.
+ * so we still have correct full contour around the object. */
+ if (only_contour) {
+ return edge_flag_result;
+ }
+
+ /* Do not show lines other than contour on back face (because contour has one adjacent face that
+ * isn't a back face).
+ * TODO(Yiming): Do we need separate option for this? */
+ if (rb->use_back_face_culling ||
+ ((tri1->flags & tri2->flags) & LRT_TRIANGLE_MAT_BACK_FACE_CULLING)) {
+ if (dot_1 < 0 && dot_2 < 0) {
+ return edge_flag_result;
+ }
+ }
+
+ if (rb->use_crease) {
+ if (dot_v3v3_db(tri1->gn, tri2->gn) < crease_threshold) {
+ edge_flag_result |= LRT_EDGE_FLAG_CREASE;
+ }
+ }
+
+ if (rb->use_material && (ll->mat_nr != lr->mat_nr)) {
+ edge_flag_result |= LRT_EDGE_FLAG_MATERIAL;
+ }
+
+ return edge_flag_result;
+}
+
static uint16_t lineart_identify_feature_line(LineartRenderBuffer *rb,
BMEdge *e,
LineartTriangle *rt_array,
@@ -1943,6 +2122,7 @@ typedef struct TriData {
LineartTriangle *tri_arr;
int lineart_triangle_size;
LineartTriangleAdjacent *tri_adj;
+ LineartEdgeNeighbor *en;
} TriData;
typedef struct TriDataReduce {
@@ -2087,6 +2267,54 @@ static void lineart_load_tri_reduce(const void *__restrict UNUSED(userdata),
BLI_edgehash_free(data_reduce->edge_hash, NULL);
}
+static int cmp_adjacent_items(const void *ps1, const void *ps2)
+{
+ LineartAdjacentItem *p1 = (LineartAdjacentItem *)ps1;
+ LineartAdjacentItem *p2 = (LineartAdjacentItem *)ps2;
+ int a = (int)p1->v1 - (int)p2->v1;
+ int b = (int)p1->v2 - (int)p2->v2;
+ return a ? a : b;
+}
+static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edges)
+{
+ /* Because the mesh is traingulated, so me->totedge should be reliable? */
+ LineartAdjacentItem *ai = MEM_mallocN(sizeof(LineartAdjacentItem) * total_edges,
+ "LineartAdjacentItem arr");
+ LineartEdgeNeighbor *en = MEM_mallocN(sizeof(LineartEdgeNeighbor) * total_edges,
+ "LineartEdgeNeighbor arr");
+
+ MLoopTri *lt = me->runtime.looptris.array;
+
+ for (int i = 0; i < total_edges; i++) {
+ ai[i].e = i;
+ ai[i].v1 = me->mloop[lt[i / 3].tri[i % 3]].v;
+ ai[i].v2 = me->mloop[lt[i / 3].tri[(i + 1) % 3]].v;
+ if (ai[i].v1 > ai[i].v2) {
+ SWAP(unsigned int, ai[i].v1, ai[i].v2);
+ }
+ en[i].e = -1;
+
+ en[i].v1 = ai[i].v1;
+ en[i].v2 = ai[i].v2;
+ }
+
+ en[total_edges - 1].v1 = ai[total_edges - 1].v1;
+ en[total_edges - 1].v2 = ai[total_edges - 1].v2;
+
+ qsort(ai, total_edges, sizeof(LineartAdjacentItem), cmp_adjacent_items);
+
+ for (int i = 0; i < total_edges - 1; i++) {
+ if (ai[i].v1 == ai[i + 1].v1 && ai[i].v2 == ai[i + 1].v2) {
+ en[ai[i].e].e = ai[i + 1].e;
+ en[ai[i].e + 1].e = ai[i].e;
+ }
+ }
+
+ MEM_freeN(ai);
+
+ return en;
+}
+
static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info,
LineartRenderBuffer *re_buf)
{
@@ -2249,6 +2477,9 @@ static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info,
tri_data.lineart_triangle_size = re_buf->triangle_size;
tri_data.tri_adj = tri_adj;
+ unsigned int total_edges = me->runtime.looptris.len * 3;
+ tri_data.en = lineart_build_edge_neighbor(me, total_edges);
+
BLI_task_parallel_range(0, tot_tri, &tri_data, lineart_load_tri_task, &tri_settings);
EdgeHash *edge_hash = reduce_data.edge_hash;
@@ -2445,6 +2676,262 @@ static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info,
}
}
+static void lineart_geometry_object_load_edge_neighbor(LineartObjectInfo *obi,
+ LineartRenderBuffer *rb)
+{
+ MVert *v;
+ MPoly *f;
+ MEdge *e;
+ MLoop *loop;
+ MLoopTri *looptri;
+ LineartEdge *la_e;
+ LineartEdgeSegment *la_s;
+ LineartTriangle *tri;
+ LineartTriangleAdjacent *orta;
+ double(*model_view_proj)[4] = obi->model_view_proj, (*model_view)[4] = obi->model_view,
+ (*normal)[4] = obi->normal;
+ LineartElementLinkNode *eln;
+ LineartVert *orv;
+ LineartEdge *o_la_e;
+ LineartEdgeSegment *o_la_s;
+ LineartTriangle *ort;
+ Object *orig_ob;
+ bool can_find_freestyle_edge = false;
+ bool can_find_freestyle_face = false;
+ int i;
+ float use_crease = 0;
+
+ int usage = obi->usage;
+
+ Mesh *me = obi->original_me;
+
+ BKE_mesh_runtime_looptri_ensure(me);
+ float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(me);
+ const int tot_tri = me->runtime.looptris.len;
+
+ unsigned int total_edges = me->runtime.looptris.len * 3;
+ LineartEdgeNeighbor *en = lineart_build_edge_neighbor(me, total_edges);
+
+ if (CustomData_has_layer(&me->edata, CD_FREESTYLE_EDGE)) {
+ can_find_freestyle_edge = true;
+ }
+ if (CustomData_has_layer(&me->pdata, CD_FREESTYLE_FACE)) {
+ can_find_freestyle_face = true;
+ }
+
+ /* If we allow duplicated edges, one edge should get added multiple times if is has been
+ * classified as more than one edge type. This is so we can create multiple different line type
+ * chains containing the same edge. */
+ orv = lineart_mem_acquire_thread(&rb->render_data_pool, sizeof(LineartVert) * me->totvert);
+ ort = lineart_mem_acquire_thread(&rb->render_data_pool, tot_tri * rb->triangle_size);
+
+ orig_ob = obi->original_ob;
+
+ BLI_spin
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list