From 0ff22044cd130c1a1b534522ee89b1194a91d0ac Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 May 2013 06:19:04 +0000 Subject: Support for bridge tool subdivisions, smoothing and shape along the profile. also added the underlying subdivision as a standalone operator in the edge menu, named: subdivide edge-ring. http://www.graphicall.org/ftp/ideasman42/bridge_subd.png --- source/blender/bmesh/intern/bmesh_edgeloop.c | 21 +++++++++++++++++- source/blender/bmesh/intern/bmesh_edgeloop.h | 7 +++++- source/blender/bmesh/intern/bmesh_opdefines.c | 24 +++++++++++++++++++++ source/blender/bmesh/intern/bmesh_operators.h | 12 +++++++++++ .../blender/bmesh/intern/bmesh_operators_private.h | 1 + source/blender/bmesh/intern/bmesh_queries.c | 25 ++++++++++++++++++++++ source/blender/bmesh/intern/bmesh_queries.h | 3 +++ 7 files changed, 91 insertions(+), 2 deletions(-) (limited to 'source/blender/bmesh/intern') diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index 7ebefbb8d92..816b2a1547e 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -504,9 +504,28 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store) return el_store->co; } - +#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data) #define NODE_AS_CO(n) ((BMVert *)((LinkData *)n)->data)->co +/** + * edges are assined to one vert -> the next. + */ +void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr) +{ + LinkData *node; + int i = 0; + for (node = el_store->verts.first; node && node->next; node = node->next) { + e_arr[i++] = BM_edge_exists(NODE_AS_V(node), NODE_AS_V(node->next)); + BLI_assert(e_arr[i - 1] != NULL); + } + + if (el_store->flag & BM_EDGELOOP_IS_CLOSED) { + e_arr[i] = BM_edge_exists(NODE_AS_V(el_store->verts.first), NODE_AS_V(el_store->verts.last)); + BLI_assert(e_arr[i] != NULL); + } + BLI_assert(el_store->len == i + 1); +} + void BM_edgeloop_calc_center(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store) { LinkData *node_curr = el_store->verts.last; diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h index 1a3a75be8ae..fcb8b4869f2 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.h +++ b/source/blender/bmesh/intern/bmesh_edgeloop.h @@ -54,6 +54,7 @@ int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store); struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store); const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store); const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store); +void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr); void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store); void BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store); void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store); @@ -61,7 +62,11 @@ void BM_edgeloop_expand(BMesh *bm, struct BMEdgeLoopStore *el_sto bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b); -#define BM_EDGELOOP_NEXT(el_store, elink) \ +#define BM_EDGELINK_NEXT(el_store, elink) \ (elink)->next ? elink->next : (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL) +#define BM_EDGELOOP_NEXT(el_store) \ + (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore), \ + (struct BMEdgeLoopStore *)((LinkData *)el_store)->next) + #endif /* __BMESH_EDGELOOP_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 88fc7652885..59de3622adb 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -523,6 +523,7 @@ static BMOpDefine bmo_bridge_loops_def = { }, /* slots_out */ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ {{'\0'}}, }, bmo_bridge_loops_exec, @@ -1021,6 +1022,28 @@ static BMOpDefine bmo_subdivide_edges_def = { BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH, }; +/* + * Subdivide Edge-Ring. + * + * Take an edge-ring, and supdivide with interpolation options. + */ +static BMOpDefine bmo_subdivide_edgering_def = { + "subdivide_edgering", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {"interp_mode", BMO_OP_SLOT_INT}, + {"smooth", BMO_OP_SLOT_FLT}, + {"cuts", BMO_OP_SLOT_INT}, + {"profile_shape", BMO_OP_SLOT_INT}, + {"profile_shape_factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}}, /* no output */ + bmo_subdivide_edgering_exec, + BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH, +}; + /* * Delete Geometry. * @@ -1756,6 +1779,7 @@ const BMOpDefine *bmo_opdefines[] = { &bmo_split_def, &bmo_split_edges_def, &bmo_subdivide_edges_def, + &bmo_subdivide_edgering_def, &bmo_symmetrize_def, &bmo_transform_def, &bmo_translate_def, diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index e169bf740de..efb0c65408b 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -61,6 +61,18 @@ enum { SIM_CMP_LT }; +/* subdivide_edgering */ +enum { + /* just subdiv */ + SUBD_RING_INTERP_LINEAR, + + /* single bezier spline - curve follows bezier rotation */ + SUBD_RING_INTERP_PATH, + + /* beziers based on adjacent faces (fallback to tangent) */ + SUBD_RING_INTERP_SURF, +}; + /* similar face selection slot values */ enum { SIMFACE_MATERIAL = 201, diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index bce599736d4..e0a4b1563f9 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -97,6 +97,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op); void bmo_split_edges_exec(BMesh *bm, BMOperator *op); void bmo_split_exec(BMesh *bm, BMOperator *op); void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op); +void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op); void bmo_symmetrize_exec(BMesh *bm, BMOperator *op); void bmo_transform_exec(BMesh *bm, BMOperator *op); void bmo_translate_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index aefea576563..be186e0441b 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1416,6 +1416,7 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) BMEdge *e; BLI_assert(v1 != v2); + BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT); BM_ITER_ELEM (e, &iter, v1, BM_EDGES_OF_VERT) { if (e->v1 == v2 || e->v2 == v2) @@ -1756,3 +1757,27 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed) return vol; } + +float bmesh_subd_falloff_calc(const int falloff, float val) +{ + switch (falloff) { + case SUBD_FALLOFF_SMOOTH: + val = 3.0f * val * val - 2.0f * val * val * val; + break; + case SUBD_FALLOFF_SPHERE: + val = sqrtf(2.0f * val - val * val); + break; + case SUBD_FALLOFF_ROOT: + val = sqrtf(val); + break; + case SUBD_FALLOFF_SHARP: + val = val * val; + break; + case SUBD_FALLOFF_LIN: + break; + default: + BLI_assert(0); + } + + return val; +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 47b6d87f91a..7d599a9c8af 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -116,4 +116,7 @@ bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); float BM_mesh_calc_volume(BMesh *bm, bool is_signed); +/* not really any good place to put this */ +float bmesh_subd_falloff_calc(const int falloff, float val); + #endif /* __BMESH_QUERIES_H__ */ -- cgit v1.2.3