solidify modifier: thickness clamping helps prevent self intersections when there are small details on a larger model.

This commit is contained in:
Campbell Barton 2013-03-13 17:31:26 +00:00
parent 385650974a
commit 1d73ee50a4
4 changed files with 70 additions and 2 deletions

@ -750,6 +750,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "thickness")
col.prop(md, "thickness_clamp")
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
col.label(text="Crease:")
@ -761,6 +762,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "offset")
col.prop(md, "use_flip_normals")
sub = col.column()
sub.active = bool(md.vertex_group)
sub.prop(md, "invert_vertex_group", text="Invert")
@ -776,7 +778,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row = row.row()
row.active = md.use_rim
row.prop(md, "material_offset_rim", text="Rim")
sub.prop(md, "use_flip_normals")
def SUBSURF(self, layout, ob, md):
layout.row().prop(md, "subdivision_type", expand=True)

@ -744,6 +744,8 @@ typedef struct SolidifyModifierData {
float offset; /* new surface offset level*/
float offset_fac; /* midpoint of the offset */
float offset_fac_vg; /* factor for the minimum weight to use when vgroups are used, avoids 0.0 weights giving duplicate geometry */
float offset_clamp; /* clamp offset based on surrounding geometry */
float pad;
float crease_inner;
float crease_outer;
float crease_rim;

@ -2648,6 +2648,13 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Thickness", "Thickness of the shell");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "thickness_clamp", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "offset_clamp");
RNA_def_property_range(prop, 0, 100.0);
RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 4);
RNA_def_property_ui_text(prop, "Clamp", "Offset clamp based on geometry scale");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "thickness_vertex_group", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "offset_fac_vg");
RNA_def_property_range(prop, 0.0, 1.0);

@ -251,7 +251,8 @@ static DerivedMesh *applyModifier(
const float ofs_new = smd->offset + ofs_orig;
const float offset_fac_vg = smd->offset_fac_vg;
const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg;
const int do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0;
const bool do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0;
const bool do_clamp = (smd->offset_clamp != 0.0f);
/* weights */
MDeformVert *dvert, *dv = NULL;
@ -423,6 +424,20 @@ static DerivedMesh *applyModifier(
float scalar_short;
float scalar_short_vgroup;
/* for clamping */
float *vert_lens = NULL;
const float offset = fabsf(smd->offset) * smd->offset_clamp;
const float offset_sq = offset * offset;
if (do_clamp) {
vert_lens = MEM_callocN(sizeof(float) * numVerts, "vert_lens");
fill_vn_fl(vert_lens, numVerts, FLT_MAX);
for (i = 0; i < numEdges; i++) {
const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len);
vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len);
}
}
if (ofs_new != 0.0f) {
scalar_short = scalar_short_vgroup = ofs_new / 32767.0f;
@ -435,6 +450,16 @@ static DerivedMesh *applyModifier(
scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
dv++;
}
if (do_clamp) {
/* always reset becaise we may have set before */
if (dv == NULL) {
scalar_short_vgroup = scalar_short;
}
if (vert_lens[i] < offset_sq) {
float scalar = sqrtf(vert_lens[i]) / offset;
scalar_short_vgroup *= scalar;
}
}
madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
}
}
@ -450,9 +475,23 @@ static DerivedMesh *applyModifier(
scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
dv++;
}
if (do_clamp) {
/* always reset becaise we may have set before */
if (dv == NULL) {
scalar_short_vgroup = scalar_short;
}
if (vert_lens[i] < offset_sq) {
float scalar = sqrtf(vert_lens[i]) / offset;
scalar_short_vgroup *= scalar;
}
}
madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
}
}
if (do_clamp) {
MEM_freeN(vert_lens);
}
}
else {
/* make a face normal layer if not present */
@ -540,6 +579,25 @@ static DerivedMesh *applyModifier(
}
}
if (do_clamp) {
float *vert_lens = MEM_callocN(sizeof(float) * numVerts, "vert_lens");
const float offset = fabsf(smd->offset) * smd->offset_clamp;
const float offset_sq = offset * offset;
fill_vn_fl(vert_lens, numVerts, FLT_MAX);
for (i = 0; i < numEdges; i++) {
const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len);
vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len);
}
for (i = 0; i < numVerts; i++) {
if (vert_lens[i] < offset_sq) {
float scalar = sqrtf(vert_lens[i]) / offset;
vert_angles[i] *= scalar;
}
}
MEM_freeN(vert_lens);
}
if (ofs_new) {
mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? numVerts : 0);