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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs