Fix #113752: Explode modifier edge cut option broken

`EdgeHash` was replaced by `VectorSet`, but the changes in the data
structure hid some other changes, causing incorrect indices to be used.
Instead use `Map` and explicitly build the indices similar to how they
were counted in a separate loop before.

Caused by: 425b87160716276ab2583f035b0c67c59dcd526e
This commit is contained in:
Hans Goudey 2023-10-24 18:44:24 +02:00
parent 753e9e0f2b
commit 74af0528f4

@ -11,11 +11,11 @@
#include "BLI_utildefines.h"
#include "BLI_kdtree.h"
#include "BLI_map.hh"
#include "BLI_math_matrix.h"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_rand.h"
#include "BLI_vector_set.hh"
#include "BLT_translation.h"
@ -208,9 +208,9 @@ static void createFacepa(ExplodeModifierData *emd, ParticleSystemModifierData *p
BLI_rng_free(rng);
}
static int edgecut_get(const blender::VectorSet<blender::OrderedEdge> &edgehash, uint v1, uint v2)
static int edgecut_get(const blender::Map<blender::OrderedEdge, int> &edgehash, uint v1, uint v2)
{
return edgehash.index_of({int(v1), int(v2)});
return edgehash.lookup({int(v1), int(v2)});
}
static const short add_faces[24] = {
@ -249,7 +249,7 @@ static void remap_faces_3_6_9_12(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -319,7 +319,7 @@ static void remap_faces_5_10(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -377,7 +377,7 @@ static void remap_faces_15(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -463,7 +463,7 @@ static void remap_faces_7_11_13_14(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -534,7 +534,7 @@ static void remap_faces_19_21_22(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -590,7 +590,7 @@ static void remap_faces_23(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -670,7 +670,8 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
int layers_num;
blender::VectorSet<blender::OrderedEdge> edgehash;
int totesplit = totvert;
blender::Map<blender::OrderedEdge, int> edgehash;
/* recreate vertpa from facepa calculation */
for (i = 0, mf = mface; i < totface; i++, mf++) {
@ -689,12 +690,12 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
v3 = vertpa[mf->v3];
if (v1 != v2) {
edgehash.add({mf->v1, mf->v2});
edgehash.lookup_or_add_cb({mf->v1, mf->v2}, [&]() { return totesplit++; });
(*fs) |= 1;
}
if (v2 != v3) {
edgehash.add({mf->v2, mf->v3});
edgehash.lookup_or_add_cb({mf->v2, mf->v3}, [&]() { return totesplit++; });
(*fs) |= 2;
}
@ -702,25 +703,25 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
v4 = vertpa[mf->v4];
if (v3 != v4) {
edgehash.add({mf->v3, mf->v4});
edgehash.lookup_or_add_cb({mf->v3, mf->v4}, [&]() { return totesplit++; });
(*fs) |= 4;
}
if (v1 != v4) {
edgehash.add({mf->v1, mf->v4});
edgehash.lookup_or_add_cb({mf->v1, mf->v4}, [&]() { return totesplit++; });
(*fs) |= 8;
}
/* mark center vertex as a fake edge split */
if (*fs == 15) {
edgehash.add({mf->v1, mf->v3});
edgehash.lookup_or_add_cb({mf->v1, mf->v3}, [&]() { return totesplit++; });
}
}
else {
(*fs) |= 16; /* mark face as tri */
if (v1 != v3) {
edgehash.add({mf->v1, mf->v3});
edgehash.lookup_or_add_cb({mf->v1, mf->v3}, [&]() { return totesplit++; });
(*fs) |= 4;
}
}
@ -734,7 +735,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
}
split_m = BKE_mesh_new_nomain_from_template_ex(
mesh, totvert + edgehash.size(), 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING);
mesh, totesplit, 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING);
layers_num = CustomData_number_of_layers(&split_m->fdata_legacy, CD_MTFACE);
@ -757,9 +758,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
emd->facepa = facepa;
/* create new verts */
for (const int esplit : edgehash.index_range()) {
const int ed_v1 = edgehash[esplit].v_low;
const int ed_v2 = edgehash[esplit].v_high;
for (const auto [edge, esplit] : edgehash.items()) {
const int ed_v1 = edge.v_low;
const int ed_v2 = edge.v_high;
CustomData_free_elem(&split_m->vert_data, esplit, 1);
CustomData_copy_data(&split_m->vert_data, &split_m->vert_data, ed_v2, esplit, 1);
@ -912,7 +913,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
float ctime;
// float timestep;
const int *facepa = emd->facepa;
int totvert = 0, totface = 0, totpart = 0, delface = 0;
int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
int i, u;
uint mindex = 0;
@ -933,7 +934,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
ctime = BKE_scene_ctime_get(scene);
/* hash table for vertex <-> particle relations */
blender::VectorSet<blender::OrderedEdge> vertpahash;
blender::Map<blender::OrderedEdge, int> vertpahash;
for (i = 0; i < totface; i++) {
if (facepa[i] != totpart) {
@ -962,17 +963,17 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
mf = &mface[i];
/* set face vertices to exist in particle group */
vertpahash.add({mf->v1, mindex});
vertpahash.add({mf->v2, mindex});
vertpahash.add({mf->v3, mindex});
vertpahash.lookup_or_add_cb({mf->v1, mindex}, [&]() { return totdup++; });
vertpahash.lookup_or_add_cb({mf->v2, mindex}, [&]() { return totdup++; });
vertpahash.lookup_or_add_cb({mf->v3, mindex}, [&]() { return totdup++; });
if (mf->v4) {
vertpahash.add({mf->v4, mindex});
vertpahash.lookup_or_add_cb({mf->v4, mindex}, [&]() { return totdup++; });
}
}
/* the final duplicated vertices */
explode = BKE_mesh_new_nomain_from_template_ex(
mesh, vertpahash.size(), 0, totface - delface, 0, 0, CD_MASK_EVERYTHING);
mesh, totdup, 0, totface - delface, 0, 0, CD_MASK_EVERYTHING);
MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer_named_for_write(
&explode->fdata_legacy, CD_MTFACE, emd->uvname, explode->totface_legacy));
@ -985,10 +986,9 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
const blender::Span<blender::float3> positions = mesh->vert_positions();
blender::MutableSpan<blender::float3> explode_positions = explode->vert_positions_for_write();
for (const int v : vertpahash.index_range()) {
/* get particle + vertex from hash */
int ed_v1 = vertpahash[v].v_low;
int ed_v2 = vertpahash[v].v_high;
for (const auto [edge, v] : vertpahash.items()) {
int ed_v1 = edge.v_low;
int ed_v2 = edge.v_high;
ed_v2 -= totvert;
copy_v3_v3(explode_positions[v], positions[ed_v1]);