[Bf-blender-cvs] [ce689964a4b] lineart-object-load: LineArt: Index calculation based adjacent lookup WIP
YimingWu
noreply at git.blender.org
Wed Apr 20 16:12:59 CEST 2022
Commit: ce689964a4b3d3604b252bcfb3cf50297be3ff23
Author: YimingWu
Date: Wed Apr 20 10:53:21 2022 +0800
Branches: lineart-object-load
https://developer.blender.org/rBce689964a4b3d3604b252bcfb3cf50297be3ff23
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 acc36062152..dd08fc6493f 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -1429,6 +1429,41 @@ static void lineart_main_discard_out_of_frame_edges(LineartRenderBuffer *rb)
}
}
+/**
+ * Transform a single vert to it's viewing position.
+ */
+static void lineart_vert_transform(
+ BMVert *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);
+}
+
+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;
@@ -1657,6 +1692,146 @@ 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;
+ }
+
+ /* 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 void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e)
{
switch (e->flags) {
@@ -1750,6 +1925,7 @@ typedef struct TriData {
LineartTriangle *tri_arr;
int lineart_triangle_size;
LineartTriangleAdjacent *tri_adj;
+ LineartEdgeNeighbor *en;
} TriData;
typedef struct TriDataReduce {
@@ -1894,6 +2070,58 @@ 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;
+ }
+
+ qsort(ai, total_edges, sizeof(LineartAdjacentItem), cmp_adjacent_items);
+
+ if (0) {
+ printf("Edge Adjacent tuples ");
+ for (int n = 0; n < total_edges; n++) {
+ printf("(%d %d %d) ", ai[n].v1, ai[n].v2, ai[n].e);
+ }
+ printf("\n");
+ }
+ 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 + 1].e].e = ai[i].e;
+ }
+ }
+
+ MEM_freeN(ai);
+
+ return en;
+}
+
static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info,
LineartRenderBuffer *re_buf)
{
@@ -2028,6 +2256,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;
@@ -2226,25 +2457,281 @@ static void lineart_geometry_object_load_no_bmesh(LineartObjectInfo *ob_info,
}
}
-static void lineart_object_load_worker(TaskPool *__restrict UNUSED(pool),
- LineartObjectLoadTaskInfo *olti)
+#define LRT_EDGE_FLAG_TYPE_MAX_BITS 6
+
+static void lineart_geometry_object_load_edge_neighbor(LineartObjectInfo *obi,
+ LineartRenderBuffer *rb)
{
- // TODO
- //- Print size of pending objects.
- //- Try to feed this with an array instead of via the pool instead of a custom list
- //- Assign the number of objects instead of number of threads
- bool use_debug = (G.debug_value == 4000);
- if (use_debug) {
- printf("thread start: %d\n", olti->thread_id);
+ 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;
}
- for (LineartObjectInfo *obi = olti->pending; obi; obi = obi->next) {
- lineart_geometry_object_load_no_bmesh(obi, olti->rb);
- if (use_debug) {
-
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list