[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