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_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);
|
||||
|
@@ -62,6 +62,7 @@ set(SRC
|
||||
operators/bmo_smooth_laplacian.c
|
||||
operators/bmo_split_edges.c
|
||||
operators/bmo_subdivide.c
|
||||
operators/bmo_subdivide_edgering.c
|
||||
operators/bmo_symmetrize.c
|
||||
operators/bmo_triangulate.c
|
||||
operators/bmo_unsubdivide.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;
|
||||
|
@@ -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__ */
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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__ */
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include "intern/bmesh_operators_private.h" /* own include */
|
||||
|
||||
#define EDGE_MARK 4
|
||||
#define EDGE_OUT 8
|
||||
#define FACE_OUT 16
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
bool el_store_b_free = false;
|
||||
float el_dir[3];
|
||||
const bool use_edgeout = true;
|
||||
|
||||
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);
|
||||
@@ -188,7 +199,7 @@ static void bridge_loop_pair(BMesh *bm,
|
||||
for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
|
||||
LinkData *el;
|
||||
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) {
|
||||
BMEdge *e = BM_edge_exists(el->data, el_next->data);
|
||||
if (e && BM_edge_is_boundary(e)) {
|
||||
@@ -242,8 +253,8 @@ static void bridge_loop_pair(BMesh *bm,
|
||||
BMLoop *l_2_next = NULL;
|
||||
|
||||
if (is_closed) {
|
||||
el_a_next = BM_EDGELOOP_NEXT(el_store_a, el_a);
|
||||
el_b_next = BM_EDGELOOP_NEXT(el_store_b, el_b);
|
||||
el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a);
|
||||
el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b);
|
||||
}
|
||||
else {
|
||||
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);
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
@@ -349,12 +365,52 @@ static void bridge_loop_pair(BMesh *bm,
|
||||
BMO_op_initf(bm, &op_sub, 0,
|
||||
"beautify_fill faces=%hf edges=ae use_restrict_tag=%b",
|
||||
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);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
BM_edgeloop_free(el_store_b);
|
||||
}
|
||||
@@ -434,22 +490,13 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
|
||||
change = true;
|
||||
}
|
||||
|
||||
if ((count == 2) && (BM_edgeloop_length_get(eloops.first) == BM_edgeloop_length_get(eloops.last))) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (count == 2) {
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
cleanup:
|
||||
BM_mesh_edgeloops_free(&eloops);
|
||||
|
||||
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 */
|
||||
val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
|
||||
|
||||
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);
|
||||
}
|
||||
val = bmesh_subd_falloff_calc(params->smooth_falloff, val);
|
||||
|
||||
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_editmesh.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_access.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);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* 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)
|
||||
{
|
||||
@@ -3823,6 +3922,22 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
|
||||
"delete geom=%hf context=%i",
|
||||
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) {
|
||||
@@ -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_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)
|
||||
|
@@ -159,6 +159,7 @@ extern struct EnumPropertyItem *corner_type_items;
|
||||
|
||||
/* *** editmesh_tools.c *** */
|
||||
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_normals_make_consistent(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_merge);
|
||||
WM_operatortype_append(MESH_OT_subdivide);
|
||||
WM_operatortype_append(MESH_OT_subdivide_edgering);
|
||||
WM_operatortype_append(MESH_OT_unsubdivide);
|
||||
WM_operatortype_append(MESH_OT_faces_select_linked_flat);
|
||||
WM_operatortype_append(MESH_OT_edges_select_sharp);
|
||||
|
Reference in New Issue
Block a user