Cleanup: Use simpler loops in weld modifier

In this commit I changed many loops to range-based for loops.
I also removed some of the redundant iterator variables, using
indexing inside the loop instead. Generally an optimizing compiler
should have no problem doing the smartest thing in that situation,
and this way makes it much easier to tell where data is coming from.

I only changed the loops I was confident about, so there is still more
that could be done in the future.

Differential Revision: https://developer.blender.org/D13637
This commit is contained in:
Hans Goudey 2021-12-20 18:03:06 -06:00
parent 59221476b0
commit 7acd3ad7d8
Notes: blender-bot 2023-02-14 02:30:10 +01:00
Referenced by issue #94453, Custom Extrude geometry node setup crashes when adding 'weld' after
1 changed files with 138 additions and 176 deletions

View File

@ -37,6 +37,7 @@
#include "BLI_array.hh"
#include "BLI_bitmap.h"
#include "BLI_index_range.hh"
#include "BLI_kdtree.h"
#include "BLI_math.h"
#include "BLI_span.hh"
@ -72,6 +73,7 @@
#include "MOD_ui_common.h"
using blender::Array;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::Vector;
@ -374,23 +376,20 @@ static void weld_assert_poly_len(const WeldPoly *wp, const Span<WeldLoop> wloop)
/** \name Weld Vert API
* \{ */
static Vector<WeldVert> weld_vert_ctx_alloc_and_setup(const int mvert_len,
Span<int> vert_dest_map)
static Vector<WeldVert> weld_vert_ctx_alloc_and_setup(Span<int> vert_dest_map)
{
Vector<WeldVert> wvert;
wvert.reserve(mvert_len);
wvert.reserve(vert_dest_map.size());
const int *v_dest_iter = &vert_dest_map[0];
for (int i = 0; i < mvert_len; i++, v_dest_iter++) {
if (*v_dest_iter != OUT_OF_CONTEXT) {
wvert.append({*v_dest_iter, i});
for (const int i : vert_dest_map.index_range()) {
if (vert_dest_map[i] != OUT_OF_CONTEXT) {
wvert.append({vert_dest_map[i], i});
}
}
return wvert;
}
static void weld_vert_groups_setup(const int mvert_len,
Span<WeldVert> wvert,
static void weld_vert_groups_setup(Span<WeldVert> wvert,
Span<int> vert_dest_map,
MutableSpan<int> r_vert_groups_map,
Array<int> &r_vert_groups_buffer,
@ -399,21 +398,19 @@ static void weld_vert_groups_setup(const int mvert_len,
/* Get weld vert groups. */
int wgroups_len = 0;
const int *vert_dest_iter = &vert_dest_map[0];
int *group_map_iter = &r_vert_groups_map[0];
for (int i = 0; i < mvert_len; i++, group_map_iter++, vert_dest_iter++) {
int vert_dest = *vert_dest_iter;
for (const int i : vert_dest_map.index_range()) {
const int vert_dest = vert_dest_map[i];
if (vert_dest != OUT_OF_CONTEXT) {
if (vert_dest != i) {
*group_map_iter = ELEM_MERGED;
r_vert_groups_map[i] = ELEM_MERGED;
}
else {
*group_map_iter = wgroups_len;
r_vert_groups_map[i] = wgroups_len;
wgroups_len++;
}
}
else {
*group_map_iter = OUT_OF_CONTEXT;
r_vert_groups_map[i] = OUT_OF_CONTEXT;
}
}
@ -421,31 +418,27 @@ static void weld_vert_groups_setup(const int mvert_len,
r_vert_groups.fill({0, 0});
MutableSpan<WeldGroup> wgroups = r_vert_groups;
const WeldVert *wv = &wvert[0];
for (int i = wvert.size(); i--; wv++) {
int group_index = r_vert_groups_map[wv->vert_dest];
for (const WeldVert &wv : wvert) {
int group_index = r_vert_groups_map[wv.vert_dest];
wgroups[group_index].len++;
}
int ofs = 0;
WeldGroup *wg_iter = &wgroups[0];
for (int i = wgroups_len; i--; wg_iter++) {
wg_iter->ofs = ofs;
ofs += wg_iter->len;
for (WeldGroup &wg : wgroups) {
wg.ofs = ofs;
ofs += wg.len;
}
BLI_assert(ofs == wvert.size());
r_vert_groups_buffer.reinitialize(ofs);
wv = &wvert[0];
for (int i = wvert.size(); i--; wv++) {
int group_index = r_vert_groups_map[wv->vert_dest];
r_vert_groups_buffer[wgroups[group_index].ofs++] = wv->vert_orig;
for (const WeldVert &wv : wvert) {
int group_index = r_vert_groups_map[wv.vert_dest];
r_vert_groups_buffer[wgroups[group_index].ofs++] = wv.vert_orig;
}
wg_iter = &wgroups[0];
for (int i = wgroups_len; i--; wg_iter++) {
wg_iter->ofs -= wg_iter->len;
for (WeldGroup &wg : wgroups) {
wg.ofs -= wg.len;
}
}
@ -455,29 +448,24 @@ static void weld_vert_groups_setup(const int mvert_len,
/** \name Weld Edge API
* \{ */
static void weld_edge_ctx_setup(const int mvert_len,
MutableSpan<WeldGroup> r_vlinks,
static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks,
MutableSpan<int> r_edge_dest_map,
MutableSpan<WeldEdge> r_wedge,
int *r_edge_kiil_len)
{
WeldEdge *we;
/* Setup Edge Overlap. */
int edge_kill_len = 0;
MutableSpan<WeldGroup> v_links = r_vlinks;
WeldGroup *vl_iter = &r_vlinks[0];
we = &r_wedge[0];
for (int i = r_wedge.size(); i--; we++) {
int dst_vert_a = we->vert_a;
int dst_vert_b = we->vert_b;
for (WeldEdge &we : r_wedge) {
int dst_vert_a = we.vert_a;
int dst_vert_b = we.vert_b;
if (dst_vert_a == dst_vert_b) {
BLI_assert(we->edge_dest == OUT_OF_CONTEXT);
r_edge_dest_map[we->edge_orig] = ELEM_COLLAPSED;
we->flag = ELEM_COLLAPSED;
BLI_assert(we.edge_dest == OUT_OF_CONTEXT);
r_edge_dest_map[we.edge_orig] = ELEM_COLLAPSED;
we.flag = ELEM_COLLAPSED;
edge_kill_len++;
continue;
}
@ -487,44 +475,42 @@ static void weld_edge_ctx_setup(const int mvert_len,
}
int link_len = 0;
vl_iter = &v_links[0];
for (int i = mvert_len; i--; vl_iter++) {
vl_iter->ofs = link_len;
link_len += vl_iter->len;
for (WeldGroup &vl : r_vlinks) {
vl.ofs = link_len;
link_len += vl.len;
}
if (link_len > 0) {
Array<int> link_edge_buffer(link_len);
we = &r_wedge[0];
for (int i = 0; i < r_wedge.size(); i++, we++) {
if (we->flag == ELEM_COLLAPSED) {
for (const int i : r_wedge.index_range()) {
const WeldEdge &we = r_wedge[i];
if (we.flag == ELEM_COLLAPSED) {
continue;
}
int dst_vert_a = we->vert_a;
int dst_vert_b = we->vert_b;
int dst_vert_a = we.vert_a;
int dst_vert_b = we.vert_b;
link_edge_buffer[v_links[dst_vert_a].ofs++] = i;
link_edge_buffer[v_links[dst_vert_b].ofs++] = i;
}
vl_iter = &v_links[0];
for (int i = mvert_len; i--; vl_iter++) {
for (WeldGroup &vl : r_vlinks) {
/* Fix offset */
vl_iter->ofs -= vl_iter->len;
vl.ofs -= vl.len;
}
we = &r_wedge[0];
for (int i = 0; i < r_wedge.size(); i++, we++) {
if (we->edge_dest != OUT_OF_CONTEXT) {
for (const int i : r_wedge.index_range()) {
const WeldEdge &we = r_wedge[i];
if (we.edge_dest != OUT_OF_CONTEXT) {
/* No need to retest edges.
* (Already includes collapsed edges). */
continue;
}
int dst_vert_a = we->vert_a;
int dst_vert_b = we->vert_b;
int dst_vert_a = we.vert_a;
int dst_vert_b = we.vert_b;
struct WeldGroup *link_a = &v_links[dst_vert_a];
struct WeldGroup *link_b = &v_links[dst_vert_b];
@ -538,7 +524,7 @@ static void weld_edge_ctx_setup(const int mvert_len,
int *edges_ctx_a = &link_edge_buffer[link_a->ofs];
int *edges_ctx_b = &link_edge_buffer[link_b->ofs];
int edge_orig = we->edge_orig;
int edge_orig = we.edge_orig;
for (; edges_len_a--; edges_ctx_a++) {
int e_ctx_a = *edges_ctx_a;
@ -586,12 +572,9 @@ static Vector<WeldEdge> weld_edge_ctx_alloc(const MEdge *medge,
Vector<WeldEdge> wedge;
wedge.reserve(medge_len);
const MEdge *me = &medge[0];
int *e_dest_iter = &r_edge_dest_map[0];
int *iter = &r_edge_ctx_map[0];
for (int i = 0; i < medge_len; i++, me++, iter++, e_dest_iter++) {
int v1 = me->v1;
int v2 = me->v2;
for (const int i : IndexRange(medge_len)) {
int v1 = medge[i].v1;
int v2 = medge[i].v2;
int v_dest_1 = vert_dest_map[v1];
int v_dest_2 = vert_dest_map[v2];
if ((v_dest_1 != OUT_OF_CONTEXT) || (v_dest_2 != OUT_OF_CONTEXT)) {
@ -601,12 +584,12 @@ static Vector<WeldEdge> weld_edge_ctx_alloc(const MEdge *medge,
we.edge_dest = OUT_OF_CONTEXT;
we.edge_orig = i;
wedge.append(we);
*e_dest_iter = i;
*iter = wedge_len++;
r_edge_dest_map[i] = i;
r_edge_ctx_map[i] = wedge_len++;
}
else {
*e_dest_iter = OUT_OF_CONTEXT;
*iter = OUT_OF_CONTEXT;
r_edge_dest_map[i] = OUT_OF_CONTEXT;
r_edge_ctx_map[i] = OUT_OF_CONTEXT;
}
}
@ -633,62 +616,56 @@ static void weld_edge_groups_setup(const int medge_len,
wegrp_iter = &r_edge_groups[0];
wgroups_len = 0;
const int *edge_ctx_iter = &wedge_map[0];
int *group_map_iter = &r_edge_groups_map[0];
for (int i = medge_len; i--; edge_ctx_iter++, group_map_iter++) {
int edge_ctx = *edge_ctx_iter;
for (const int i : IndexRange(medge_len)) {
int edge_ctx = wedge_map[i];
if (edge_ctx != OUT_OF_CONTEXT) {
WeldEdge *we = &wedge[edge_ctx];
int edge_dest = we->edge_dest;
if (edge_dest != OUT_OF_CONTEXT) {
BLI_assert(edge_dest != we->edge_orig);
*group_map_iter = ELEM_MERGED;
r_edge_groups_map[i] = ELEM_MERGED;
}
else {
we->edge_dest = we->edge_orig;
wegrp_iter->v1 = we->vert_a;
wegrp_iter->v2 = we->vert_b;
*group_map_iter = wgroups_len;
r_edge_groups_map[i] = wgroups_len;
wgroups_len++;
wegrp_iter++;
}
}
else {
*group_map_iter = OUT_OF_CONTEXT;
r_edge_groups_map[i] = OUT_OF_CONTEXT;
}
}
BLI_assert(wgroups_len == wedge.size() - edge_kill_len);
WeldEdge *we = &wedge[0];
for (int i = wedge.size(); i--; we++) {
if (we->flag == ELEM_COLLAPSED) {
for (const WeldEdge &we : wedge) {
if (we.flag == ELEM_COLLAPSED) {
continue;
}
int group_index = r_edge_groups_map[we->edge_dest];
int group_index = r_edge_groups_map[we.edge_dest];
wegroups[group_index].group.len++;
}
int ofs = 0;
wegrp_iter = &wegroups[0];
for (int i = wgroups_len; i--; wegrp_iter++) {
wegrp_iter->group.ofs = ofs;
ofs += wegrp_iter->group.len;
for (WeldGroupEdge &wegrp : wegroups) {
wegrp.group.ofs = ofs;
ofs += wegrp.group.len;
}
r_edge_groups_buffer.reinitialize(ofs);
we = &wedge[0];
for (int i = wedge.size(); i--; we++) {
if (we->flag == ELEM_COLLAPSED) {
for (const WeldEdge &we : wedge) {
if (we.flag == ELEM_COLLAPSED) {
continue;
}
int group_index = r_edge_groups_map[we->edge_dest];
r_edge_groups_buffer[wegroups[group_index].group.ofs++] = we->edge_orig;
int group_index = r_edge_groups_map[we.edge_dest];
r_edge_groups_buffer[wegroups[group_index].group.ofs++] = we.edge_orig;
}
wegrp_iter = &wegroups[0];
for (int i = wgroups_len; i--; wegrp_iter++) {
wegrp_iter->group.ofs -= wegrp_iter->group.len;
for (WeldGroupEdge &wegrp : wegroups) {
wegrp.group.ofs -= wegrp.group.len;
}
}
@ -824,21 +801,17 @@ static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly,
int maybe_new_poly = 0;
const MPoly *mp = &mpoly[0];
int *iter = &poly_map[0];
int *loop_map_iter = &loop_map[0];
for (int i = 0; i < mpoly.size(); i++, mp++, iter++) {
const int loopstart = mp->loopstart;
const int totloop = mp->totloop;
for (const int i : mpoly.index_range()) {
const MPoly &mp = mpoly[i];
const int loopstart = mp.loopstart;
const int totloop = mp.totloop;
int vert_ctx_len = 0;
int l = loopstart;
int prev_wloop_len = wloop_len;
const MLoop *ml = &mloop[l];
for (int j = totloop; j--; l++, ml++, loop_map_iter++) {
int v = ml->v;
int e = ml->e;
for (const int i_loop : mloop.index_range().slice(loopstart, totloop)) {
int v = mloop[i_loop].v;
int e = mloop[i_loop].e;
int v_dest = vert_dest_map[v];
int e_dest = edge_dest_map[e];
bool is_vert_ctx = v_dest != OUT_OF_CONTEXT;
@ -850,14 +823,14 @@ static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly,
WeldLoop wl{};
wl.vert = is_vert_ctx ? v_dest : v;
wl.edge = is_edge_ctx ? e_dest : e;
wl.loop_orig = l;
wl.loop_orig = i_loop;
wl.loop_skip_to = OUT_OF_CONTEXT;
wloop.append(wl);
*loop_map_iter = wloop_len++;
loop_map[i_loop] = wloop_len++;
}
else {
*loop_map_iter = OUT_OF_CONTEXT;
loop_map[i_loop] = OUT_OF_CONTEXT;
}
}
if (wloop_len != prev_wloop_len) {
@ -872,7 +845,7 @@ static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly,
wp.len = totloop;
wpoly.append(wp);
*iter = wpoly_len++;
poly_map[i] = wpoly_len++;
if (totloop > 5 && vert_ctx_len > 1) {
int max_new = (totloop / 3) - 1;
vert_ctx_len /= 2;
@ -881,7 +854,7 @@ static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly,
}
}
else {
*iter = OUT_OF_CONTEXT;
poly_map[i] = OUT_OF_CONTEXT;
}
}
@ -1054,7 +1027,7 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
{
int poly_kill_len, loop_kill_len, wpoly_len, wpoly_new_len;
WeldPoly *wpoly_new, *wp;
WeldPoly *wpoly_new;
WeldLoop *wl;
MutableSpan<WeldPoly> wpoly = r_weld_mesh->wpoly;
@ -1071,12 +1044,11 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
/* Setup Poly/Loop. */
wp = &wpoly[0];
for (int i = wpoly_len; i--; wp++) {
const int ctx_loops_len = wp->loops.len;
const int ctx_loops_ofs = wp->loops.ofs;
for (WeldPoly &wp : wpoly) {
const int ctx_loops_len = wp.loops.len;
const int ctx_loops_ofs = wp.loops.ofs;
int poly_len = wp->len;
int poly_len = wp.len;
int ctx_verts_len = 0;
wl = &wloop[ctx_loops_ofs];
for (int l = ctx_loops_len; l--; wl++) {
@ -1084,7 +1056,7 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
if (edge_dest == ELEM_COLLAPSED) {
wl->flag = ELEM_COLLAPSED;
if (poly_len == 3) {
wp->flag = ELEM_COLLAPSED;
wp.flag = ELEM_COLLAPSED;
poly_kill_len++;
loop_kill_len += 3;
poly_len = 0;
@ -1102,7 +1074,7 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
}
if (poly_len) {
wp->len = poly_len;
wp.len = poly_len;
#ifdef USE_WELD_DEBUG
weld_assert_poly_len(wp, wloop);
#endif
@ -1112,7 +1084,7 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
mloop,
#endif
ctx_verts_len,
wp,
&wp,
r_weld_mesh,
&poly_kill_len,
&loop_kill_len);
@ -1137,13 +1109,13 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
int wpoly_and_new_len = wpoly_len + wpoly_new_len;
struct WeldGroup *vl_iter, *v_links = r_vlinks.data();
memset(v_links, 0, sizeof(*v_links) * mvert_len);
r_vlinks.fill({0, 0});
MutableSpan<WeldGroup> v_links = r_vlinks;
wp = &wpoly[0];
for (int i = wpoly_and_new_len; i--; wp++) {
for (const int i : IndexRange(wpoly_and_new_len)) {
const WeldPoly &wp = wpoly[i];
WeldLoopOfPolyIter iter;
if (weld_iter_loop_of_poly_begin(&iter, *wp, wloop, mloop, loop_map, nullptr)) {
if (weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, nullptr)) {
while (weld_iter_loop_of_poly_next(&iter)) {
v_links[iter.v].len++;
}
@ -1151,44 +1123,42 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
}
int link_len = 0;
vl_iter = &v_links[0];
for (int i = mvert_len; i--; vl_iter++) {
vl_iter->ofs = link_len;
link_len += vl_iter->len;
for (const int i : IndexRange(mvert_len)) {
v_links[i].ofs = link_len;
link_len += v_links[i].len;
}
if (link_len) {
Array<int> link_poly_buffer(link_len);
wp = &wpoly[0];
for (int i = 0; i < wpoly_and_new_len; i++, wp++) {
for (const int i : IndexRange(wpoly_and_new_len)) {
const WeldPoly &wp = wpoly[i];
WeldLoopOfPolyIter iter;
if (weld_iter_loop_of_poly_begin(&iter, *wp, wloop, mloop, loop_map, nullptr)) {
if (weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, nullptr)) {
while (weld_iter_loop_of_poly_next(&iter)) {
link_poly_buffer[v_links[iter.v].ofs++] = i;
}
}
}
vl_iter = &v_links[0];
for (int i = mvert_len; i--; vl_iter++) {
for (WeldGroup &vl : r_vlinks) {
/* Fix offset */
vl_iter->ofs -= vl_iter->len;
vl.ofs -= vl.len;
}
int polys_len_a, polys_len_b, *polys_ctx_a, *polys_ctx_b, p_ctx_a, p_ctx_b;
polys_len_b = p_ctx_b = 0; /* silence warnings */
wp = &wpoly[0];
for (int i = 0; i < wpoly_and_new_len; i++, wp++) {
if (wp->poly_dst != OUT_OF_CONTEXT) {
for (const int i : IndexRange(wpoly_and_new_len)) {
const WeldPoly &wp = wpoly[i];
if (wp.poly_dst != OUT_OF_CONTEXT) {
/* No need to retest poly.
* (Already includes collapsed polygons). */
continue;
}
WeldLoopOfPolyIter iter;
weld_iter_loop_of_poly_begin(&iter, *wp, wloop, mloop, loop_map, nullptr);
weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, nullptr);
weld_iter_loop_of_poly_next(&iter);
struct WeldGroup *link_a = &v_links[iter.v];
polys_len_a = link_a->len;
@ -1196,7 +1166,7 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
BLI_assert(link_poly_buffer[link_a->ofs] == i);
continue;
}
int wp_len = wp->len;
int wp_len = wp.len;
polys_ctx_a = &link_poly_buffer[link_a->ofs];
for (; polys_len_a--; polys_ctx_a++) {
p_ctx_a = *polys_ctx_a;
@ -1243,7 +1213,7 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
BLI_assert(p_ctx_a == p_ctx_b);
BLI_assert(wp_tmp->poly_dst == OUT_OF_CONTEXT);
BLI_assert(wp_tmp != wp);
wp_tmp->poly_dst = wp->poly_orig;
wp_tmp->poly_dst = wp.poly_orig;
loop_kill_len += wp_tmp->len;
poly_kill_len++;
}
@ -1254,9 +1224,8 @@ static void weld_poly_loop_ctx_setup(Span<MLoop> mloop,
poly_kill_len = r_weld_mesh->wpoly_len;
loop_kill_len = r_weld_mesh->wloop_len;
wp = &wpoly[0];
for (int i = wpoly_len; i--; wp++) {
wp->flag = ELEM_COLLAPSED;
for (WeldPoly &wp : wpoly) {
wp.flag = ELEM_COLLAPSED;
}
}
@ -1294,7 +1263,7 @@ static void weld_mesh_context_create(const Mesh *mesh,
const int mvert_len = mesh->totvert;
const int medge_len = mesh->totedge;
Vector<WeldVert> wvert = weld_vert_ctx_alloc_and_setup(mvert_len, vert_dest_map);
Vector<WeldVert> wvert = weld_vert_ctx_alloc_and_setup(vert_dest_map);
r_weld_mesh->vert_kill_len = vert_kill_len;
Array<int> edge_dest_map(medge_len);
@ -1303,7 +1272,7 @@ static void weld_mesh_context_create(const Mesh *mesh,
medge, medge_len, vert_dest_map, edge_dest_map, edge_ctx_map);
Array<WeldGroup> v_links(mvert_len, {0, 0});
weld_edge_ctx_setup(mvert_len, v_links, edge_dest_map, wedge, &r_weld_mesh->edge_kill_len);
weld_edge_ctx_setup(v_links, edge_dest_map, wedge, &r_weld_mesh->edge_kill_len);
weld_poly_loop_ctx_alloc(mpoly, mloop, vert_dest_map, edge_dest_map, r_weld_mesh);
@ -1318,8 +1287,7 @@ static void weld_mesh_context_create(const Mesh *mesh,
v_links,
r_weld_mesh);
weld_vert_groups_setup(mvert_len,
wvert,
weld_vert_groups_setup(wvert,
vert_dest_map,
vert_dest_map,
r_weld_mesh->vert_groups_buffer,
@ -1516,24 +1484,21 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
BLI_bitmap *v_mask = nullptr;
int v_mask_act = 0;
const MVert *mvert;
const MPoly *mp;
Span<MVert> mvert{mesh->mvert, mesh->totvert};
int totvert, totedge, totloop, totpoly;
mvert = mesh->mvert;
totvert = mesh->totvert;
/* Vertex Group. */
const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
if (defgrp_index != -1) {
MDeformVert *dvert, *dv;
MDeformVert *dvert;
dvert = static_cast<MDeformVert *>(CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT));
if (dvert) {
const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0;
dv = &dvert[0];
v_mask = BLI_BITMAP_NEW(totvert, __func__);
for (int i = 0; i < totvert; i++, dv++) {
const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f;
for (const int i : IndexRange(totvert)) {
const bool found = BKE_defvert_find_weight(&dvert[i], defgrp_index) > 0.0f;
if (found != invert_vgroup) {
BLI_BITMAP_ENABLE(v_mask, i);
v_mask_act++;
@ -1552,7 +1517,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
/* Get overlap map. */
struct BVHTreeFromMesh treedata;
BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata,
mvert,
mvert.data(),
totvert,
false,
v_mask,
@ -1629,7 +1594,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
#else
{
KDTree_3d *tree = BLI_kdtree_3d_new(v_mask ? v_mask_act : totvert);
for (int i = 0; i < totvert; i++) {
for (const int i : IndexRange(totvert)) {
if (!v_mask || BLI_BITMAP_TEST(v_mask, i)) {
BLI_kdtree_3d_insert(tree, i, mvert[i].co);
}
@ -1645,30 +1610,27 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
else {
BLI_assert(wmd->mode == MOD_WELD_MODE_CONNECTED);
MEdge *medge, *me;
Span<MEdge> medge{mesh->medge, mesh->totedge};
medge = mesh->medge;
totvert = mesh->totvert;
totedge = mesh->totedge;
Array<WeldVertexCluster> vert_clusters(totvert);
struct WeldVertexCluster *vc = &vert_clusters[0];
for (int i = 0; i < totvert; i++, vc++) {
copy_v3_v3(vc->co, mvert[i].co);
vc->merged_verts = 0;
for (const int i : mvert.index_range()) {
WeldVertexCluster &vc = vert_clusters[i];
copy_v3_v3(vc.co, mvert[i].co);
vc.merged_verts = 0;
}
const float merge_dist_sq = square_f(wmd->merge_dist);
range_vn_i(vert_dest_map.data(), totvert, 0);
/* Collapse Edges that are shorter than the threshold. */
me = &medge[0];
for (int i = 0; i < totedge; i++, me++) {
int v1 = me->v1;
int v2 = me->v2;
for (const int i : medge.index_range()) {
int v1 = medge[i].v1;
int v2 = medge[i].v2;
if (wmd->flag & MOD_WELD_LOOSE_EDGES && (me->flag & ME_LOOSEEDGE) == 0) {
if (wmd->flag & MOD_WELD_LOOSE_EDGES && (medge[i].flag & ME_LOOSEEDGE) == 0) {
continue;
}
while (v1 != vert_dest_map[v1]) {
@ -1703,7 +1665,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
}
}
for (int i = 0; i < totvert; i++) {
for (const int i : IndexRange(totvert)) {
if (i == vert_dest_map[i]) {
vert_dest_map[i] = OUT_OF_CONTEXT;
}
@ -1823,18 +1785,18 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
/* Polys/Loops */
mp = &mpoly[0];
MPoly *r_mp = &result->mpoly[0];
MLoop *r_ml = &result->mloop[0];
int r_i = 0;
int loop_cur = 0;
Array<int, 64> group_buffer(weld_mesh.max_poly_len);
for (int i = 0; i < totpoly; i++, mp++) {
for (const int i : mpoly.index_range()) {
const MPoly &mp = mpoly[i];
int loop_start = loop_cur;
int poly_ctx = weld_mesh.poly_map[i];
if (poly_ctx == OUT_OF_CONTEXT) {
int mp_loop_len = mp->totloop;
CustomData_copy_data(&mesh->ldata, &result->ldata, mp->loopstart, loop_cur, mp_loop_len);
int mp_loop_len = mp.totloop;
CustomData_copy_data(&mesh->ldata, &result->ldata, mp.loopstart, loop_cur, mp_loop_len);
loop_cur += mp_loop_len;
for (; mp_loop_len--; r_ml++) {
r_ml->v = vert_final[r_ml->v];
@ -1875,16 +1837,16 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd,
r_i++;
}
const WeldPoly *wp = &weld_mesh.wpoly_new[0];
for (int i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) {
for (const int i : IndexRange(weld_mesh.wpoly_new_len)) {
const WeldPoly &wp = weld_mesh.wpoly_new[i];
int loop_start = loop_cur;
WeldLoopOfPolyIter iter;
if (!weld_iter_loop_of_poly_begin(
&iter, *wp, weld_mesh.wloop, mloop, weld_mesh.loop_map, group_buffer.data())) {
&iter, wp, weld_mesh.wloop, mloop, weld_mesh.loop_map, group_buffer.data())) {
continue;
}
if (wp->poly_dst != OUT_OF_CONTEXT) {
if (wp.poly_dst != OUT_OF_CONTEXT) {
continue;
}
while (weld_iter_loop_of_poly_next(&iter)) {