Fix T75032: New complex solidify algorithm handles poorly merging threshold of small geometry details.
* Implemented the algortihm that would merge vertices to the weighted center between them. * Exposed the merge threshold to the user. The new default tolerance is 0.0001 (versionning code ensures that previous default value remains in use to avoid any change in existing files). Review and minor changes/cleanups from Bastien Montagne (@mont29).
This commit is contained in:
parent
c19f37764d
commit
5cf7283342
Notes:
blender-bot
2023-02-14 05:04:52 +01:00
Referenced by issue #75032, New complex solidify algorithm handles poorly merging threshold of small geometry details.
|
@ -1049,6 +1049,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||
col.prop(md, "edge_crease_inner", text="Inner")
|
||||
col.prop(md, "edge_crease_outer", text="Outer")
|
||||
col.prop(md, "edge_crease_rim", text="Rim")
|
||||
else:
|
||||
col.prop(md, "nonmanifold_merge_threshold")
|
||||
|
||||
col = split.column()
|
||||
|
||||
|
|
|
@ -4890,7 +4890,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 283, 12)) {
|
||||
|
||||
/* Activate f-curve drawing in the sequencer. */
|
||||
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
|
||||
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
|
||||
|
@ -4929,5 +4928,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
/* Solidify modifier merge tolerance. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "SolidifyModifierData", "float", "merge_tolerance")) {
|
||||
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
|
||||
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
|
||||
if (md->type == eModifierType_Solidify) {
|
||||
SolidifyModifierData *smd = (SolidifyModifierData *)md;
|
||||
/* set to 0.0003 since that is what was used before, default now is 0.0001 */
|
||||
smd->merge_tolerance = 0.0003f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1175,6 +1175,9 @@ typedef struct SolidifyModifierData {
|
|||
int flag;
|
||||
short mat_ofs;
|
||||
short mat_ofs_rim;
|
||||
|
||||
float merge_tolerance;
|
||||
char _pad1[4];
|
||||
} SolidifyModifierData;
|
||||
|
||||
/** #SolidifyModifierData.flag */
|
||||
|
|
|
@ -4523,6 +4523,13 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
|
|||
RNA_def_property_enum_items(prop, nonmanifold_boundary_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Boundary Shape", "Selects the boundary adjustment algorithm");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "nonmanifold_merge_threshold", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "merge_tolerance");
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
|
||||
RNA_def_property_ui_text(prop, "Merge Threshold", "Distance within which degenerated geometry is merged");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_screw(BlenderRNA *brna)
|
||||
|
|
|
@ -53,6 +53,7 @@ static void initData(ModifierData *md)
|
|||
smd->mode = MOD_SOLIDIFY_MODE_EXTRUDE;
|
||||
smd->nonmanifold_offset_mode = MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS;
|
||||
smd->nonmanifold_boundary_mode = MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE;
|
||||
smd->merge_tolerance = 0.0001f;
|
||||
}
|
||||
|
||||
static void requiredDataMask(Object *UNUSED(ob),
|
||||
|
|
|
@ -291,6 +291,15 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
/* Vert edge adjacent map. */
|
||||
OldVertEdgeRef **vert_adj_edges = MEM_calloc_arrayN(
|
||||
numVerts, sizeof(*vert_adj_edges), "vert_adj_edges in solidify");
|
||||
/* Original vertex positions (changed for degenerated geometry). */
|
||||
float(*orig_mvert_co)[3] = MEM_malloc_arrayN(
|
||||
numVerts, sizeof(*orig_mvert_co), "orig_mvert_co in solidify");
|
||||
/* Fill in the original vertex positions. */
|
||||
for (uint i = 0; i < numVerts; i++) {
|
||||
orig_mvert_co[i][0] = orig_mvert[i].co[0];
|
||||
orig_mvert_co[i][1] = orig_mvert[i].co[1];
|
||||
orig_mvert_co[i][2] = orig_mvert[i].co[2];
|
||||
}
|
||||
|
||||
/* Create edge to #NewEdgeRef map. */
|
||||
{
|
||||
|
@ -344,33 +353,35 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
bool *face_singularity = MEM_calloc_arrayN(
|
||||
numPolys, sizeof(*face_singularity), "face_sides_arr in solidify");
|
||||
|
||||
const float merge_tolerance_sqr = smd->merge_tolerance * smd->merge_tolerance;
|
||||
uint *combined_verts = MEM_calloc_arrayN(
|
||||
numVerts, sizeof(*combined_verts), "combined_verts in solidify");
|
||||
|
||||
ed = orig_medge;
|
||||
for (uint i = 0; i < numEdges; i++, ed++) {
|
||||
if (edge_adj_faces_len[i] > 0) {
|
||||
const uint v1 = vm[ed->v1];
|
||||
const uint v2 = vm[ed->v2];
|
||||
uint v1 = vm[ed->v1];
|
||||
uint v2 = vm[ed->v2];
|
||||
if (v1 != v2) {
|
||||
sub_v3_v3v3(edgedir, orig_mvert[v2].co, orig_mvert[v1].co);
|
||||
if (v2 < v1) {
|
||||
SWAP(uint, v1, v2);
|
||||
}
|
||||
sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]);
|
||||
orig_edge_lengths[i] = len_squared_v3(edgedir);
|
||||
if (orig_edge_lengths[i] <= FLT_EPSILON) {
|
||||
if (v2 > v1) {
|
||||
for (uint j = v2; j < numVerts; j++) {
|
||||
if (vm[j] == v2) {
|
||||
vm[j] = v1;
|
||||
vert_adj_edges_len[v1] += vert_adj_edges_len[j];
|
||||
vert_adj_edges_len[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (v2 < v1) {
|
||||
for (uint j = v1; j < numVerts; j++) {
|
||||
if (vm[j] == v1) {
|
||||
vm[j] = v2;
|
||||
vert_adj_edges_len[v2] += vert_adj_edges_len[j];
|
||||
vert_adj_edges_len[j] = 0;
|
||||
}
|
||||
if (orig_edge_lengths[i] <= merge_tolerance_sqr) {
|
||||
mul_v3_fl(edgedir,
|
||||
(combined_verts[v2] + 1) /
|
||||
(float)(combined_verts[v1] + combined_verts[v2] + 2));
|
||||
add_v3_v3(orig_mvert_co[v1], edgedir);
|
||||
for (uint j = v2; j < numVerts; j++) {
|
||||
if (vm[j] == v2) {
|
||||
vm[j] = v1;
|
||||
}
|
||||
}
|
||||
vert_adj_edges_len[v1] += vert_adj_edges_len[v2];
|
||||
vert_adj_edges_len[v2] = 0;
|
||||
combined_verts[v1] += combined_verts[v2] + 1;
|
||||
|
||||
if (do_shell) {
|
||||
numNewLoops -= edge_adj_faces_len[i] * 2;
|
||||
}
|
||||
|
@ -429,6 +440,7 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
}
|
||||
|
||||
MEM_freeN(face_singularity);
|
||||
MEM_freeN(combined_verts);
|
||||
}
|
||||
|
||||
/* Create vert_adj_edges for verts. */
|
||||
|
@ -668,7 +680,7 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
const uint v1 = vm[ed->v1];
|
||||
const uint v2 = vm[ed->v2];
|
||||
if (edge_adj_faces_len[i] > 0) {
|
||||
sub_v3_v3v3(edgedir, orig_mvert[v2].co, orig_mvert[v1].co);
|
||||
sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]);
|
||||
mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]);
|
||||
|
||||
OldEdgeFaceRef *adj_faces = edge_adj_faces[i];
|
||||
|
@ -1496,8 +1508,9 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
ml_prev = ml;
|
||||
ml = ml_next;
|
||||
}
|
||||
angle = angle_v3v3v3(
|
||||
orig_mvert[vm[ml_prev->v]].co, mv->co, orig_mvert[vm[ml_next->v]].co);
|
||||
angle = angle_v3v3v3(orig_mvert_co[vm[ml_prev->v]],
|
||||
orig_mvert_co[i],
|
||||
orig_mvert_co[vm[ml_next->v]]);
|
||||
if (face->reversed) {
|
||||
total_angle_back += angle * ofs * ofs;
|
||||
}
|
||||
|
@ -1591,7 +1604,8 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
uint k;
|
||||
for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) {
|
||||
MEdge *e = orig_medge + (*edge_ptr)->old_edge;
|
||||
sub_v3_v3v3(tmp, orig_mvert[vm[e->v1] == i ? e->v2 : e->v1].co, mv->co);
|
||||
sub_v3_v3v3(
|
||||
tmp, orig_mvert_co[vm[e->v1] == i ? e->v2 : e->v1], orig_mvert_co[i]);
|
||||
add_v3_v3(move_nor, tmp);
|
||||
}
|
||||
if (k == 1) {
|
||||
|
@ -1613,10 +1627,12 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
MEdge *e1_edge = orig_medge + g->edges[g->edges_len - 1]->old_edge;
|
||||
float e0[3];
|
||||
float e1[3];
|
||||
sub_v3_v3v3(
|
||||
e0, orig_mvert[vm[e0_edge->v1] == i ? e0_edge->v2 : e0_edge->v1].co, mv->co);
|
||||
sub_v3_v3v3(
|
||||
e1, orig_mvert[vm[e1_edge->v1] == i ? e1_edge->v2 : e1_edge->v1].co, mv->co);
|
||||
sub_v3_v3v3(e0,
|
||||
orig_mvert_co[vm[e0_edge->v1] == i ? e0_edge->v2 : e0_edge->v1],
|
||||
orig_mvert_co[i]);
|
||||
sub_v3_v3v3(e1,
|
||||
orig_mvert_co[vm[e1_edge->v1] == i ? e1_edge->v2 : e1_edge->v1],
|
||||
orig_mvert_co[i]);
|
||||
if (smd->nonmanifold_boundary_mode == MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT) {
|
||||
cross_v3_v3v3(constr_nor, e0, e1);
|
||||
}
|
||||
|
@ -1702,16 +1718,17 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
|
|||
}
|
||||
}
|
||||
mul_v3_fl(nor, scalar_vgroup);
|
||||
add_v3_v3v3(g->co, nor, mv->co);
|
||||
add_v3_v3v3(g->co, nor, orig_mvert_co[i]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(g->co, mv->co);
|
||||
copy_v3_v3(g->co, orig_mvert_co[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(orig_mvert_co);
|
||||
if (null_faces) {
|
||||
MEM_freeN(null_faces);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue