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
This commit is contained in:
@@ -139,6 +139,11 @@ bool BLI_ghashIterator_done(GHashIterator *ghi);
|
|||||||
BLI_ghashIterator_done(&gh_iter_) == false; \
|
BLI_ghashIterator_done(&gh_iter_) == false; \
|
||||||
BLI_ghashIterator_step(&gh_iter_))
|
BLI_ghashIterator_step(&gh_iter_))
|
||||||
|
|
||||||
|
#define GHASH_ITER_INDEX(gh_iter_, ghash_, i_) \
|
||||||
|
for (BLI_ghashIterator_init(&gh_iter_, ghash_), i_ = 0; \
|
||||||
|
BLI_ghashIterator_done(&gh_iter_) == false; \
|
||||||
|
BLI_ghashIterator_step(&gh_iter_), i_++)
|
||||||
|
|
||||||
/* *** */
|
/* *** */
|
||||||
|
|
||||||
unsigned int BLI_ghashutil_ptrhash(const void *key);
|
unsigned int BLI_ghashutil_ptrhash(const void *key);
|
||||||
|
@@ -62,6 +62,7 @@ set(SRC
|
|||||||
operators/bmo_smooth_laplacian.c
|
operators/bmo_smooth_laplacian.c
|
||||||
operators/bmo_split_edges.c
|
operators/bmo_split_edges.c
|
||||||
operators/bmo_subdivide.c
|
operators/bmo_subdivide.c
|
||||||
|
operators/bmo_subdivide_edgering.c
|
||||||
operators/bmo_symmetrize.c
|
operators/bmo_symmetrize.c
|
||||||
operators/bmo_triangulate.c
|
operators/bmo_triangulate.c
|
||||||
operators/bmo_unsubdivide.c
|
operators/bmo_unsubdivide.c
|
||||||
|
@@ -504,9 +504,28 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store)
|
|||||||
return el_store->co;
|
return el_store->co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data)
|
||||||
#define NODE_AS_CO(n) ((BMVert *)((LinkData *)n)->data)->co
|
#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)
|
void BM_edgeloop_calc_center(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
|
||||||
{
|
{
|
||||||
LinkData *node_curr = el_store->verts.last;
|
LinkData *node_curr = el_store->verts.last;
|
||||||
|
@@ -54,6 +54,7 @@ int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store);
|
|||||||
struct ListBase *BM_edgeloop_verts_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_normal_get(struct BMEdgeLoopStore *el_store);
|
||||||
const float *BM_edgeloop_center_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_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
|
||||||
void BM_edgeloop_calc_normal(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);
|
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);
|
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)
|
(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__ */
|
#endif /* __BMESH_EDGELOOP_H__ */
|
||||||
|
@@ -523,6 +523,7 @@ static BMOpDefine bmo_bridge_loops_def = {
|
|||||||
},
|
},
|
||||||
/* slots_out */
|
/* slots_out */
|
||||||
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
|
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
|
||||||
|
{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */
|
||||||
{{'\0'}},
|
{{'\0'}},
|
||||||
},
|
},
|
||||||
bmo_bridge_loops_exec,
|
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,
|
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.
|
* Delete Geometry.
|
||||||
*
|
*
|
||||||
@@ -1756,6 +1779,7 @@ const BMOpDefine *bmo_opdefines[] = {
|
|||||||
&bmo_split_def,
|
&bmo_split_def,
|
||||||
&bmo_split_edges_def,
|
&bmo_split_edges_def,
|
||||||
&bmo_subdivide_edges_def,
|
&bmo_subdivide_edges_def,
|
||||||
|
&bmo_subdivide_edgering_def,
|
||||||
&bmo_symmetrize_def,
|
&bmo_symmetrize_def,
|
||||||
&bmo_transform_def,
|
&bmo_transform_def,
|
||||||
&bmo_translate_def,
|
&bmo_translate_def,
|
||||||
|
@@ -61,6 +61,18 @@ enum {
|
|||||||
SIM_CMP_LT
|
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 */
|
/* similar face selection slot values */
|
||||||
enum {
|
enum {
|
||||||
SIMFACE_MATERIAL = 201,
|
SIMFACE_MATERIAL = 201,
|
||||||
|
@@ -97,6 +97,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op);
|
|||||||
void bmo_split_edges_exec(BMesh *bm, BMOperator *op);
|
void bmo_split_edges_exec(BMesh *bm, BMOperator *op);
|
||||||
void bmo_split_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_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_symmetrize_exec(BMesh *bm, BMOperator *op);
|
||||||
void bmo_transform_exec(BMesh *bm, BMOperator *op);
|
void bmo_transform_exec(BMesh *bm, BMOperator *op);
|
||||||
void bmo_translate_exec(BMesh *bm, BMOperator *op);
|
void bmo_translate_exec(BMesh *bm, BMOperator *op);
|
||||||
|
@@ -1416,6 +1416,7 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2)
|
|||||||
BMEdge *e;
|
BMEdge *e;
|
||||||
|
|
||||||
BLI_assert(v1 != v2);
|
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) {
|
BM_ITER_ELEM (e, &iter, v1, BM_EDGES_OF_VERT) {
|
||||||
if (e->v1 == v2 || e->v2 == v2)
|
if (e->v1 == v2 || e->v2 == v2)
|
||||||
@@ -1756,3 +1757,27 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
|
|||||||
|
|
||||||
return vol;
|
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;
|
||||||
|
}
|
||||||
|
@@ -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);
|
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__ */
|
#endif /* __BMESH_QUERIES_H__ */
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "intern/bmesh_operators_private.h" /* own include */
|
#include "intern/bmesh_operators_private.h" /* own include */
|
||||||
|
|
||||||
#define EDGE_MARK 4
|
#define EDGE_MARK 4
|
||||||
|
#define EDGE_OUT 8
|
||||||
#define FACE_OUT 16
|
#define FACE_OUT 16
|
||||||
|
|
||||||
/* el_a and el_b _must_ be same size */
|
/* el_a and el_b _must_ be same size */
|
||||||
@@ -129,6 +130,15 @@ static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bm_face_edges_tag_out(BMesh *bm, BMFace *f)
|
||||||
|
{
|
||||||
|
BMLoop *l_iter, *l_first;
|
||||||
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||||
|
do {
|
||||||
|
BMO_elem_flag_enable(bm, l_iter->e, EDGE_OUT);
|
||||||
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
|
}
|
||||||
|
|
||||||
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
|
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
|
||||||
{
|
{
|
||||||
return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
|
return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
|
||||||
@@ -144,6 +154,7 @@ static void bridge_loop_pair(BMesh *bm,
|
|||||||
int el_store_a_len, el_store_b_len;
|
int el_store_a_len, el_store_b_len;
|
||||||
bool el_store_b_free = false;
|
bool el_store_b_free = false;
|
||||||
float el_dir[3];
|
float el_dir[3];
|
||||||
|
const bool use_edgeout = true;
|
||||||
|
|
||||||
el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a);
|
el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a);
|
||||||
el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b);
|
el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b);
|
||||||
@@ -188,7 +199,7 @@ static void bridge_loop_pair(BMesh *bm,
|
|||||||
for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
|
for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
|
||||||
LinkData *el;
|
LinkData *el;
|
||||||
for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
|
for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
|
||||||
LinkData *el_next = BM_EDGELOOP_NEXT(estore_pair[i], el);
|
LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
|
||||||
if (el_next) {
|
if (el_next) {
|
||||||
BMEdge *e = BM_edge_exists(el->data, el_next->data);
|
BMEdge *e = BM_edge_exists(el->data, el_next->data);
|
||||||
if (e && BM_edge_is_boundary(e)) {
|
if (e && BM_edge_is_boundary(e)) {
|
||||||
@@ -242,8 +253,8 @@ static void bridge_loop_pair(BMesh *bm,
|
|||||||
BMLoop *l_2_next = NULL;
|
BMLoop *l_2_next = NULL;
|
||||||
|
|
||||||
if (is_closed) {
|
if (is_closed) {
|
||||||
el_a_next = BM_EDGELOOP_NEXT(el_store_a, el_a);
|
el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a);
|
||||||
el_b_next = BM_EDGELOOP_NEXT(el_store_b, el_b);
|
el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
el_a_next = el_a->next;
|
el_a_next = el_a->next;
|
||||||
@@ -309,6 +320,11 @@ static void bridge_loop_pair(BMesh *bm,
|
|||||||
BMO_elem_flag_enable(bm, f, FACE_OUT);
|
BMO_elem_flag_enable(bm, f, FACE_OUT);
|
||||||
BM_elem_flag_enable(f, BM_ELEM_TAG);
|
BM_elem_flag_enable(f, BM_ELEM_TAG);
|
||||||
|
|
||||||
|
/* tag all edges of the face, untag the loop edges after */
|
||||||
|
if (use_edgeout) {
|
||||||
|
bm_face_edges_tag_out(bm, f);
|
||||||
|
}
|
||||||
|
|
||||||
if (el_a_next == el_a_first) {
|
if (el_a_next == el_a_first) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -349,12 +365,52 @@ static void bridge_loop_pair(BMesh *bm,
|
|||||||
BMO_op_initf(bm, &op_sub, 0,
|
BMO_op_initf(bm, &op_sub, 0,
|
||||||
"beautify_fill faces=%hf edges=ae use_restrict_tag=%b",
|
"beautify_fill faces=%hf edges=ae use_restrict_tag=%b",
|
||||||
BM_ELEM_TAG, true);
|
BM_ELEM_TAG, true);
|
||||||
|
|
||||||
|
if (use_edgeout) {
|
||||||
|
BMOIter siter;
|
||||||
|
BMFace *f;
|
||||||
|
BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
|
||||||
|
BMO_elem_flag_enable(bm, f, FACE_OUT);
|
||||||
|
bm_face_edges_tag_out(bm, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BMO_op_exec(bm, &op_sub);
|
BMO_op_exec(bm, &op_sub);
|
||||||
/* there may also be tagged faces that didnt rotate, mark input */
|
/* there may also be tagged faces that didnt rotate, mark input */
|
||||||
BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT);
|
|
||||||
|
if (use_edgeout) {
|
||||||
|
BMOIter siter;
|
||||||
|
BMFace *f;
|
||||||
|
BMO_ITER (f, &siter, op_sub.slots_out, "geom.out", BM_FACE) {
|
||||||
|
BMO_elem_flag_enable(bm, f, FACE_OUT);
|
||||||
|
bm_face_edges_tag_out(bm, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
BMO_op_finish(bm, &op_sub);
|
BMO_op_finish(bm, &op_sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_edgeout && use_merge == false) {
|
||||||
|
/* we've enabled all face edges above, now disable all loop edges */
|
||||||
|
struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
LinkData *el;
|
||||||
|
for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
|
||||||
|
LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
|
||||||
|
if (el_next) {
|
||||||
|
if (el->data != el_next->data) {
|
||||||
|
BMEdge *e = BM_edge_exists(el->data, el_next->data);
|
||||||
|
BMO_elem_flag_disable(bm, e, EDGE_OUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (el_store_b_free) {
|
if (el_store_b_free) {
|
||||||
BM_edgeloop_free(el_store_b);
|
BM_edgeloop_free(el_store_b);
|
||||||
}
|
}
|
||||||
@@ -434,22 +490,13 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
|
|||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((count == 2) && (BM_edgeloop_length_get(eloops.first) == BM_edgeloop_length_get(eloops.last))) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (count == 2) {
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
BM_mesh_edgeloops_free(&eloops);
|
BM_mesh_edgeloops_free(&eloops);
|
||||||
|
|
||||||
if (change) {
|
if (change) {
|
||||||
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
|
if (use_merge == false) {
|
||||||
|
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
|
||||||
|
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -178,25 +178,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar
|
|||||||
|
|
||||||
/* falloff for multi subdivide */
|
/* falloff for multi subdivide */
|
||||||
val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
|
val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
|
||||||
|
val = bmesh_subd_falloff_calc(params->smooth_falloff, val);
|
||||||
switch (params->smooth_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
mul_v3_fl(tvec, params->smooth * val * len);
|
mul_v3_fl(tvec, params->smooth * val * len);
|
||||||
|
|
||||||
|
1187
source/blender/bmesh/operators/bmo_subdivide_edgering.c
Normal file
1187
source/blender/bmesh/operators/bmo_subdivide_edgering.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,8 @@
|
|||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
|
|
||||||
|
#include "BLF_translation.h"
|
||||||
|
|
||||||
#include "RNA_define.h"
|
#include "RNA_define.h"
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
#include "RNA_enum_types.h"
|
#include "RNA_enum_types.h"
|
||||||
@@ -143,6 +145,103 @@ void MESH_OT_subdivide(wmOperatorType *ot)
|
|||||||
RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
|
RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/* Edge Ring Subdiv
|
||||||
|
* (bridge code shares props)
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct EdgeRingOpSubdProps {
|
||||||
|
int interp_mode;
|
||||||
|
int cuts;
|
||||||
|
float smooth;
|
||||||
|
|
||||||
|
int profile_shape;
|
||||||
|
float profile_shape_factor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_default)
|
||||||
|
{
|
||||||
|
/* Note, these values must match delete_mesh() event values */
|
||||||
|
static EnumPropertyItem prop_subd_edgering_types[] = {
|
||||||
|
{SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
|
||||||
|
{SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""},
|
||||||
|
{SUBD_RING_INTERP_SURF, "SURFACE", 0, "Blend Surface", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
prop = RNA_def_int(ot->srna, "number_cuts", cuts_default, 0, INT_MAX, "Number of Cuts", "", 0, 64);
|
||||||
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||||
|
|
||||||
|
RNA_def_enum(ot->srna, "interpolation", prop_subd_edgering_types, SUBD_RING_INTERP_PATH,
|
||||||
|
"Interpolation", "Interpolation method");
|
||||||
|
|
||||||
|
RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, FLT_MAX,
|
||||||
|
"Smoothness", "Smoothness factor", 0.0f, 2.0f);
|
||||||
|
|
||||||
|
/* profile-shape */
|
||||||
|
RNA_def_float(ot->srna, "profile_shape_factor", 0.0f, -FLT_MAX, FLT_MAX,
|
||||||
|
"Profile Factor", "", -2.0f, 2.0f);
|
||||||
|
|
||||||
|
prop = RNA_def_property(ot->srna, "profile_shape", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
|
||||||
|
RNA_def_property_enum_default(prop, PROP_SMOOTH);
|
||||||
|
RNA_def_property_ui_text(prop, "Profile Shape", "Shape of the profile");
|
||||||
|
RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mesh_operator_edgering_props_get(wmOperator *op, struct EdgeRingOpSubdProps *op_props)
|
||||||
|
{
|
||||||
|
op_props->interp_mode = RNA_enum_get(op->ptr, "interpolation");
|
||||||
|
op_props->cuts = RNA_int_get(op->ptr, "number_cuts");
|
||||||
|
op_props->smooth = RNA_float_get(op->ptr, "smoothness");
|
||||||
|
|
||||||
|
op_props->profile_shape = RNA_enum_get(op->ptr, "profile_shape");
|
||||||
|
op_props->profile_shape_factor = RNA_float_get(op->ptr, "profile_shape_factor");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Object *obedit = CTX_data_edit_object(C);
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
struct EdgeRingOpSubdProps op_props;
|
||||||
|
|
||||||
|
mesh_operator_edgering_props_get(op, &op_props);
|
||||||
|
|
||||||
|
if (!EDBM_op_callf(em, op,
|
||||||
|
"subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
|
||||||
|
"profile_shape=%i profile_shape_factor=%f",
|
||||||
|
BM_ELEM_SELECT, op_props.interp_mode, op_props.cuts, op_props.smooth,
|
||||||
|
op_props.profile_shape, op_props.profile_shape_factor))
|
||||||
|
{
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MESH_OT_subdivide_edgering(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name = "Subdivide Edge-Ring";
|
||||||
|
ot->description = "";
|
||||||
|
ot->idname = "MESH_OT_subdivide_edgering";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->exec = edbm_subdivide_edge_ring_exec;
|
||||||
|
ot->poll = ED_operator_editmesh;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
mesh_operator_edgering_props(ot, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
|
static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
@@ -3823,6 +3922,22 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
|
|||||||
"delete geom=%hf context=%i",
|
"delete geom=%hf context=%i",
|
||||||
BM_ELEM_TAG, DEL_FACES);
|
BM_ELEM_TAG, DEL_FACES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_merge == false) {
|
||||||
|
struct EdgeRingOpSubdProps op_props;
|
||||||
|
mesh_operator_edgering_props_get(op, &op_props);
|
||||||
|
|
||||||
|
if (op_props.cuts) {
|
||||||
|
/* we only need face normals updated */
|
||||||
|
EDBM_mesh_normals_update(em);
|
||||||
|
|
||||||
|
BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
|
||||||
|
"subdivide_edgering edges=%S interp_mode=%i cuts=%i smooth=%f "
|
||||||
|
"profile_shape=%i profile_shape_factor=%f",
|
||||||
|
&bmop, "edges.out", op_props.interp_mode, op_props.cuts, op_props.smooth,
|
||||||
|
op_props.profile_shape, op_props.profile_shape_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totface_del_arr) {
|
if (totface_del_arr) {
|
||||||
@@ -3865,6 +3980,8 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
|
|||||||
|
|
||||||
RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces");
|
RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces");
|
||||||
RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
|
RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
|
||||||
|
|
||||||
|
mesh_operator_edgering_props(ot, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int edbm_wireframe_exec(bContext *C, wmOperator *op)
|
static int edbm_wireframe_exec(bContext *C, wmOperator *op)
|
||||||
|
@@ -159,6 +159,7 @@ extern struct EnumPropertyItem *corner_type_items;
|
|||||||
|
|
||||||
/* *** editmesh_tools.c *** */
|
/* *** editmesh_tools.c *** */
|
||||||
void MESH_OT_subdivide(struct wmOperatorType *ot);
|
void MESH_OT_subdivide(struct wmOperatorType *ot);
|
||||||
|
void MESH_OT_subdivide_edgering(struct wmOperatorType *ot);
|
||||||
void MESH_OT_unsubdivide(struct wmOperatorType *ot);
|
void MESH_OT_unsubdivide(struct wmOperatorType *ot);
|
||||||
void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
|
void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
|
||||||
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
|
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
|
||||||
|
@@ -62,6 +62,7 @@ void ED_operatortypes_mesh(void)
|
|||||||
WM_operatortype_append(MESH_OT_normals_make_consistent);
|
WM_operatortype_append(MESH_OT_normals_make_consistent);
|
||||||
WM_operatortype_append(MESH_OT_merge);
|
WM_operatortype_append(MESH_OT_merge);
|
||||||
WM_operatortype_append(MESH_OT_subdivide);
|
WM_operatortype_append(MESH_OT_subdivide);
|
||||||
|
WM_operatortype_append(MESH_OT_subdivide_edgering);
|
||||||
WM_operatortype_append(MESH_OT_unsubdivide);
|
WM_operatortype_append(MESH_OT_unsubdivide);
|
||||||
WM_operatortype_append(MESH_OT_faces_select_linked_flat);
|
WM_operatortype_append(MESH_OT_faces_select_linked_flat);
|
||||||
WM_operatortype_append(MESH_OT_edges_select_sharp);
|
WM_operatortype_append(MESH_OT_edges_select_sharp);
|
||||||
|
Reference in New Issue
Block a user