mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Modeling: Support interpolation of vertex custom data when merging vertices
Implements support for merged vertices to properly interpolate vertex custom data when merged. Merging at center averages the data but in the case of merging at last or at first, it keeps the data of the surviving vertex. Pull Request: https://projects.blender.org/blender/blender/pulls/147755
This commit is contained in:
parent
0f4b405089
commit
672c2cac52
3 changed files with 53 additions and 17 deletions
|
|
@ -612,8 +612,8 @@ static BMOpDefine bmo_pointmerge_facedata_def = {
|
|||
{
|
||||
/* Input vertices. */
|
||||
{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
|
||||
/* Snap vertex. */
|
||||
{"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}},
|
||||
/* Target vertex to merge into. */
|
||||
{"vert_target", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}},
|
||||
{{'\0'}},
|
||||
},
|
||||
/*slot_types_out*/
|
||||
|
|
@ -657,6 +657,9 @@ static BMOpDefine bmo_pointmerge_def = {
|
|||
{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
|
||||
/* Position to merge at. */
|
||||
{"merge_co", BMO_OP_SLOT_VEC},
|
||||
/* Optional target vertex to merge into. Does not override merge_co.
|
||||
* Set this to preserve the custom data of the target vertex. */
|
||||
{"vert_target", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}},
|
||||
{{'\0'}},
|
||||
},
|
||||
/*slot_types_out*/
|
||||
|
|
@ -704,6 +707,8 @@ static BMOpDefine bmo_weld_verts_def = {
|
|||
/* Merge vertices to their centroid position,
|
||||
* otherwise use the position of the target vertex. */
|
||||
{"use_centroid", BMO_OP_SLOT_BOOL},
|
||||
/* Whether to average custom data of merged vertices. */
|
||||
{"average_vert_data", BMO_OP_SLOT_BOOL},
|
||||
{{'\0'}},
|
||||
},
|
||||
/*slot_types_out*/
|
||||
|
|
|
|||
|
|
@ -194,13 +194,15 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
|
|||
BMFace *f;
|
||||
BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap");
|
||||
const bool use_centroid = BMO_slot_bool_get(op->slots_in, "use_centroid");
|
||||
const bool average_vert_data = BMO_slot_bool_get(op->slots_in, "average_vert_data") ||
|
||||
use_centroid;
|
||||
|
||||
/* Maintain selection history. */
|
||||
const bool has_selected = !bm->selected.is_empty();
|
||||
const bool use_targetmap_all = has_selected;
|
||||
Map<void *, void *> targetmap_all;
|
||||
|
||||
/* Used when use_centroid is true. */
|
||||
/* Used when use_centroid or average_vert_data is true. */
|
||||
MultiValueMap<BMVert *, BMVert *> clusters;
|
||||
|
||||
/* Mark merge verts for deletion. */
|
||||
|
|
@ -221,7 +223,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
|
|||
}
|
||||
|
||||
/* Group vertices by their survivor. */
|
||||
if (use_centroid && LIKELY(v_dst != v)) {
|
||||
if (average_vert_data && LIKELY(v_dst != v)) {
|
||||
clusters.add(v_dst, v);
|
||||
}
|
||||
}
|
||||
|
|
@ -246,6 +248,21 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
if (average_vert_data) {
|
||||
for (const auto &item : clusters.items()) {
|
||||
BMVert *v_dst = item.key;
|
||||
Span<BMVert *> merged_verts = item.value;
|
||||
|
||||
Array<const void *> src_blocks(merged_verts.size() + 1);
|
||||
src_blocks[0] = v_dst->head.data;
|
||||
for (const int i : merged_verts.index_range()) {
|
||||
src_blocks[i + 1] = merged_verts[i]->head.data;
|
||||
}
|
||||
CustomData_bmesh_interp(
|
||||
&bm->vdata, src_blocks.data(), nullptr, src_blocks.size(), v_dst->head.data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if any faces are getting their own corners merged
|
||||
* together, split face if so. */
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
|
|
@ -356,21 +373,21 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
|
|||
{
|
||||
BMOIter siter;
|
||||
BMIter iter;
|
||||
BMVert *v, *vert_snap;
|
||||
BMVert *v, *vert_target;
|
||||
BMLoop *l, *l_first = nullptr;
|
||||
float fac;
|
||||
int i, tot;
|
||||
|
||||
vert_snap = static_cast<BMVert *>(
|
||||
BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_snap")));
|
||||
tot = BM_vert_face_count(vert_snap);
|
||||
vert_target = static_cast<BMVert *>(
|
||||
BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_target")));
|
||||
tot = BM_vert_face_count(vert_target);
|
||||
|
||||
if (!tot) {
|
||||
return;
|
||||
}
|
||||
|
||||
fac = 1.0f / tot;
|
||||
BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) {
|
||||
BM_ITER_ELEM (l, &iter, vert_target, BM_LOOPS_OF_VERT) {
|
||||
if (l_first == nullptr) {
|
||||
l_first = l;
|
||||
}
|
||||
|
|
@ -447,7 +464,7 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op)
|
|||
{
|
||||
BMOperator weldop;
|
||||
BMOIter siter;
|
||||
BMVert *v, *vert_snap = nullptr;
|
||||
BMVert *v, *vert_target = nullptr;
|
||||
float vec[3];
|
||||
BMOpSlot *slot_targetmap;
|
||||
|
||||
|
|
@ -458,16 +475,25 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op)
|
|||
|
||||
slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
|
||||
|
||||
vert_target = static_cast<BMVert *>(
|
||||
BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_target")));
|
||||
|
||||
const bool is_explicit_snap = vert_target != nullptr;
|
||||
|
||||
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
|
||||
if (!vert_snap) {
|
||||
vert_snap = v;
|
||||
copy_v3_v3(vert_snap->co, vec);
|
||||
if (!vert_target) {
|
||||
vert_target = v;
|
||||
copy_v3_v3(vert_target->co, vec);
|
||||
}
|
||||
else {
|
||||
BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap);
|
||||
else if (v != vert_target) {
|
||||
BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_target);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_explicit_snap) {
|
||||
BMO_slot_bool_set(weldop.slots_in, "average_vert_data", true);
|
||||
}
|
||||
|
||||
BMO_op_exec(bm, &weldop);
|
||||
BMO_op_finish(bm, &weldop);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3412,13 +3412,18 @@ static bool merge_firstlast(BMEditMesh *em,
|
|||
|
||||
if (use_uvmerge) {
|
||||
if (!EDBM_op_callf(
|
||||
em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert))
|
||||
em, wmop, "pointmerge_facedata verts=%hv vert_target=%e", BM_ELEM_SELECT, mergevert))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mergevert->co))
|
||||
if (!EDBM_op_callf(em,
|
||||
wmop,
|
||||
"pointmerge verts=%hv merge_co=%v vert_target=%e",
|
||||
BM_ELEM_SELECT,
|
||||
mergevert->co,
|
||||
mergevert))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue