Commit: 55f15f10fada80ba6c2098982c89f07f332c6e88 Author: Hans Goudey Date: Mon Aug 12 09:30:27 2019 -0400 Branches: soc-2019-bevel-profiles https://developer.blender.org/rB55f15f10fada80ba6c2098982c89f07f332c6e88
Bevel: New profile orientation regularization implementation The new implementation has cleaner shorter code than the last. It's recursive and it walks along edges rather then edge halves. It fails at 4 way intersections but a single chain of beveled edges works better than the last code which is still included in this commit behind an #if 0. =================================================================== M source/blender/bmesh/tools/bmesh_bevel.c =================================================================== diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 62e209901f8..f6ce9101a9d 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -53,6 +53,8 @@ #define BEVEL_EPSILON_BIG_SQ 1e-8f #define BEVEL_EPSILON_ANG DEG2RADF(2.0f) #define BEVEL_SMALL_ANG DEG2RADF(10.0f) +/** Difference in dots that corresponds to 10 degree difference */ +#define BEVEL_SMALL_ANG_DOT 1 - cosf(BEVEL_SMALL_ANG) #define BEVEL_MAX_ADJUST_PCT 10.0f #define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f #define BEVEL_MATCH_SPEC_WEIGHT 0.2 @@ -61,8 +63,9 @@ #define DEBUG_CUSTOM_PROFILE_WELD 0 #define DEBUG_CUSTOM_PROFILE_ADJ 0 #define DEBUG_CUSTOM_PROFILE_PIPE 0 -#define DEBUG_CUSTOM_PROFILE_ORIENTATION 0 -#define DEBUG_CUSTOM_PROFILE_ORIENTATION_DRAW DEBUG_CUSTOM_PROFILE_ORIENTATION | 0 +#define DEBUG_CUSTOM_PROFILE_ORIENTATION 1 +#define DEBUG_CUSTOM_PROFILE_NEXT_EDGEHALF_BEV 1 +#define DEBUG_CUSTOM_PROFILE_ORIENTATION_DRAW DEBUG_CUSTOM_PROFILE_NEXT_EDGEHALF_BEV | 1 #define DEBUG_CUSTOM_PROFILE_CUTOFF 0 #if DEBUG_CUSTOM_PROFILE_ORIENTATION_DRAW | DEBUG_CUSTOM_PROFILE_PIPE @@ -87,7 +90,7 @@ struct BoundVert; /* Data for one end of an edge involved in a bevel */ typedef struct EdgeHalf { - /** In CCW order */ + /** Other EdgeHalves connected to the same BevVert, in CCW order. */ struct EdgeHalf *next, *prev; /** Original mesh edge */ BMEdge *e; @@ -118,7 +121,7 @@ typedef struct EdgeHalf { /** Is e a seam for custom loopdata (e.g., UVs)? */ bool is_seam; /** Used during the custom profile orientation pass */ - bool visited_custom; + bool visited_rpo; char _pad[4]; } EdgeHalf; @@ -697,7 +700,7 @@ static BMFace *bev_create_ngon(BMesh *bm, } if (mat_nr >= 0) { - f->mat_nr = mat_nr; + f->mat_nr = (short)mat_nr; } return f; } @@ -1047,7 +1050,7 @@ static void offset_meet( normalize_v3(norm_perp1); copy_v3_v3(off1a, v->co); d = max_ff(e1->offset_r, e2->offset_l); - d = d / cos(ang / 2.0f); + d = d / cosf(ang / 2.0f); madd_v3_v3fl(off1a, norm_perp1, d); copy_v3_v3(meetco, off1a); } @@ -2310,9 +2313,14 @@ static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm) bndv = vm->boundstart; do { set_profile_params(bp, bv, bndv); + /* Use the miter profile spacing struct if the default is filled with the custom profile. */ bool miter_profile = bp->use_custom_profile && (bndv->is_arc_start || bndv->is_patch_start); - /* We probably don't know the orientation at this point, so don't reverse the profiles */ - calculate_profile(bp, bndv, false, miter_profile); + /* Don't bother reversing the profile if it's a miter profile */ + bool reverse_profile = !bndv->is_profile_start && !miter_profile; +// printf("miter_profile: %d, reverse_profile: %d\n", miter_profile, reverse_profile); + BLI_assert(!(miter_profile && reverse_profile)); + + calculate_profile(bp, bndv, reverse_profile, miter_profile); } while ((bndv = bndv->next) != vm->boundstart); } @@ -2415,7 +2423,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, /* TODO: should do something else if angle between e and e->prev > 180 */ offset_meet(e->prev, e, bv->v, e->fprev, false, co); if (construct) { - bndv = add_new_bound_vert(mem_arena, vm, co); + bndv = add_new_bound_vert(mem_arena, vm, co); bndv->efirst = e->prev; bndv->elast = bndv->ebev = e; e->leftv = bndv; @@ -2439,7 +2447,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, /* For the edges not adjacent to the beveled edge, slide the bevel amount along. */ d = efirst->offset_l_spec; if (bp->use_custom_profile || bp->profile < 0.25f) { - d *= sqrtf(2.0f); /* Need to go further down the edge to make room for full profile area */ + d *= sqrtf(2.0f); /* Need to go further along the edge to make room for full profile area. */ } for (e = e->next; e->next != efirst; e = e->next) { slide_dist(e, bv->v, d, co); @@ -2457,13 +2465,12 @@ static void build_boundary_terminal_edge(BevelParams *bp, calculate_vm_profiles(bp, bv, vm); if (bv->edgecount >= 3) { - /* special case: snap profile to plane of adjacent two edges */ + /* Special case: snap profile to plane of adjacent two edges. */ bndv = vm->boundstart; BLI_assert(bndv->ebev != NULL); move_profile_plane(bndv, bv->v); - /* This step happens before profile orientation regularization, so don't reverse the profile */ + /* This step happens before the profile orientation pass so don't reverse the profile. */ calculate_profile(bp, bndv, false, false); - } if (construct) { @@ -3018,192 +3025,141 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc } #endif +#if 0 /** Helper function to return the next Beveled EdgeHalf along a path. - * - * \note Right now this returns the most parallel edge if it's the most parallel by - * at least 10 degrees. This is a somewhat arbitrary choice, and we may find it's not even - * worth it to continue the path across a BevVert with 3 or more connected beveled edges - * * \param toward_bv Whether the direction to travel points toward or away from the BevVert * connected to the current EdgeHalf - * \param r_bv The BevVert conencted to the EdgeHalf which is updated if the we switch - EdgeHalves in the current edge */ + * \param r_bv The BevVert conencted to the EdgeHalf-- updated if we're travelling to the other + * EdgeHalf of an original edge + * \note Right now this returns the most parallel edge if it's the most parallel by + * at least 10 degrees. This is a somewhat arbitrary choice, and we may find it's not even + * worth it to continue the path across a BevVert with 3 or more connected beveled edges. */ static EdgeHalf *next_edgehalf_bev(BevelParams *bp, - EdgeHalf *start_edge, - bool toward_bv, - BevVert **r_bv) + EdgeHalf *start_edge, + bool toward_bv, + BevVert **r_bv) { EdgeHalf *new_edge; EdgeHalf *next_edge = NULL; - float d_start[3]; - float d_new[3]; - float v1_dist_to_bv; - float v2_dist_to_bv; - float new_angle; - float best_angle = (float)M_PI; /* Initialized to the LEAST parallel angle */ + float d_start_edge[3], d_new_edge[3]; + float best_angle = FLT_MAX; /* Initialized to the biggest angle ever. */ float second_best_angle = best_angle; -#if DEBUG_CUSTOM_PROFILE_ORIENTATION - printf("NEXT EDGEHALF BEV"); -#endif + float new_angle; + printf("Next EdgeHalf Bev:"); BLI_assert(r_bv != NULL); - /* Case 1: The next EdgeHalf is across a BevVert from the current EdgeHalf */ + /* Case 1: The next EdgeHalf is across a BevVert from the current EdgeHalf. */ if (toward_bv) { - /* Find the direction vector of the current edge (pointing INTO the BevVert) . - * v1 and v2 don't necessarily have an order, so we need to check which is closer to bv */ - v1_dist_to_bv = fabsf(len_v3v3(start_edge->e->v1->co, (*r_bv)->v->co)); - v2_dist_to_bv = fabsf(len_v3v3(start_edge->e->v2->co, (*r_bv)->v->co)); - if (v1_dist_to_bv < v2_dist_to_bv) { - sub_v3_v3v3(d_start, start_edge->e->v1->co, start_edge->e->v2->co); + /* Check for one or two total beveled edges, everything else gets a general solution. */ + if ((*r_bv)->selcount == 1) { + if (start_edge->e->v1 == (*r_bv)->v) { + sub_v3_v3v3(d_start_edge, start_edge->e->v1->co, start_edge->e->v2->co); + } + else { + sub_v3_v3v3(d_start_edge, start_edge->e->v2->co, start_edge->e->v1->co); + } + printf("[d_start:{%.2f, %.2f, %.2f}]", (double)d_start_edge[0], + (double)d_start_edge[1], + (double)d_start_edge[2]); + printf("[toward_bv](NULL -- only 1)\n"); + return NULL; /* No other edges to go to. */ + } + + /* Find the direction vector of the current edge (pointing INTO the BevVert). + * v1 and v2 don't necessarily have an order, so we need to check which is closer to bv. */ + if (start_edge->e->v1 == (*r_bv)->v) { + sub_v3_v3v3(d_start_edge, start_edge->e->v1->co, start_edge->e->v2->co); } else { - sub_v3_v3v3(d_start, start_edge->e->v2->co, start_edge->e->v1->co); + sub_v3_v3v3(d_start_edge, start_edge->e->v2->co, start_edge->e->v1->co); } -#if DEBUG_CUSTOM_PROFILE_ORIENTATION + BLI_assert((start_edge->e->v1 == (*r_bv)->v) == + compare_v3v3(start_edge->e->v1->co, (*r_bv)->v->co, BEVEL_EPSILON)); printf("[toward_bv]"); - printf("[d_start:(%0.2f, %0.2f, %0.2f)]", (double)d_start[0], - (double)d_start[1], - (double)d_start[2]); -#endif - - /* Find the beveled edge coming out of the BevVert most parallel to the current edge */ - new_edge = start_edge; - new_edge = new_edge->next; -#if DEBUG_CUSTOM_PROFILE_ORIENTATION -// if (new_edge) { -// printf("[new_edge]"); -// if (new_edge == start_edge) { -// printf("[new_edge == cur_edge]\n"); -// printf("Beveled Edge Count for BevVert: %d\n", (*r_bv)->selcount); -//// dump_bv(*r_bv); -// } -// } else { -// printf("[!new_edge]"); -// } -#endif - while (new_edge && new_edge != start_edge) { + printf("[d_start:(%.2f, %.2f, %.2f)]", (double)d_start_edge[0], + (double)d_start_edge[1], + (double)d_start_edge[2]); + /* Find the beveled edge coming out of the BevVert that's most parallel to the current edge. */ + new_edge = start_edge->next; + BLI_assert(new_edge); + while (new_edge != start_edge) { if (!new_edge->is_bev) { new_edge = new_edge->next; continue; } -#if DEBUG_CUSTOM_PROFILE_ORIENTATION printf("[new_edge]"); -#endif - /* Find dir @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs