EditNormal modifier: add some 'maximum angle' limit.
Allows to avoid generating flipped faces when using extreme normal modifications. Related to T48576.
This commit is contained in:
@@ -1418,6 +1418,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||||||
sub = row.row(align=True)
|
sub = row.row(align=True)
|
||||||
sub.active = has_vgroup
|
sub.active = has_vgroup
|
||||||
sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
|
sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
|
||||||
|
subcol.prop(md, "mix_limit")
|
||||||
|
|
||||||
def CORRECTIVE_SMOOTH(self, layout, ob, md):
|
def CORRECTIVE_SMOOTH(self, layout, ob, md):
|
||||||
is_bind = md.is_bind
|
is_bind = md.is_bind
|
||||||
|
@@ -1189,9 +1189,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
for (Camera *camera = main->camera.first; camera != NULL; camera = camera->id.next) {
|
for (Camera *camera = main->camera.first; camera != NULL; camera = camera->id.next) {
|
||||||
if (camera->stereo.pole_merge_angle_from == 0.0f &&
|
if (camera->stereo.pole_merge_angle_from == 0.0f &&
|
||||||
camera->stereo.pole_merge_angle_to == 0.0f)
|
camera->stereo.pole_merge_angle_to == 0.0f)
|
||||||
@@ -1200,5 +1198,19 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
camera->stereo.pole_merge_angle_to = DEG2RAD(75.0f);
|
camera->stereo.pole_merge_angle_to = DEG2RAD(75.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "NormalEditModifierData", "float", "mix_limit")) {
|
||||||
|
Object *ob;
|
||||||
|
|
||||||
|
for (ob = main->object.first; ob; ob = ob->id.next) {
|
||||||
|
ModifierData *md;
|
||||||
|
for (md = ob->modifiers.first; md; md = md->next) {
|
||||||
|
if (md->type == eModifierType_NormalEdit) {
|
||||||
|
NormalEditModifierData *nemd = (NormalEditModifierData *)md;
|
||||||
|
nemd->mix_limit = DEG2RADF(180.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1518,7 +1518,9 @@ typedef struct NormalEditModifierData {
|
|||||||
short mix_mode;
|
short mix_mode;
|
||||||
char pad[2];
|
char pad[2];
|
||||||
float mix_factor;
|
float mix_factor;
|
||||||
|
float mix_limit;
|
||||||
float offset[3];
|
float offset[3];
|
||||||
|
float pad_f1;
|
||||||
} NormalEditModifierData;
|
} NormalEditModifierData;
|
||||||
|
|
||||||
/* NormalEditModifierData.mode */
|
/* NormalEditModifierData.mode */
|
||||||
|
@@ -4602,6 +4602,11 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
|
|||||||
"How much of generated normals to mix with exiting ones", 0.0f, 1.0f);
|
"How much of generated normals to mix with exiting ones", 0.0f, 1.0f);
|
||||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_float(srna, "mix_limit", 1.0f, 0.0f, DEG2RADF(180.0f), "Max Angle",
|
||||||
|
"Maximum angle between old and new normals", 0.0f, DEG2RADF(180.0f));
|
||||||
|
RNA_def_property_subtype(prop, PROP_ANGLE);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
|
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
|
||||||
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
|
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
|
||||||
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for selecting/weighting the affected areas");
|
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for selecting/weighting the affected areas");
|
||||||
|
@@ -110,7 +110,7 @@ static void generate_vert_coordinates(
|
|||||||
/* Note this modifies nos_new in-place. */
|
/* Note this modifies nos_new in-place. */
|
||||||
static void mix_normals(
|
static void mix_normals(
|
||||||
const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
|
const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
|
||||||
const short mix_mode,
|
const float mix_limit, const short mix_mode,
|
||||||
const int num_verts, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int num_loops)
|
const int num_verts, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int num_loops)
|
||||||
{
|
{
|
||||||
/* Mix with org normals... */
|
/* Mix with org normals... */
|
||||||
@@ -143,7 +143,9 @@ static void mix_normals(
|
|||||||
case MOD_NORMALEDIT_MIX_COPY:
|
case MOD_NORMALEDIT_MIX_COPY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
interp_v3_v3v3_slerp_safe(*no_new, *no_old, *no_new, fac);
|
|
||||||
|
interp_v3_v3v3_slerp_safe(*no_new, *no_old, *no_new,
|
||||||
|
(mix_limit < M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_SAFE_FREE(facs);
|
MEM_SAFE_FREE(facs);
|
||||||
@@ -186,7 +188,7 @@ static bool polygons_check_flip(
|
|||||||
static void normalEditModifier_do_radial(
|
static void normalEditModifier_do_radial(
|
||||||
NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
|
NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
|
||||||
short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
|
short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
|
||||||
const short mix_mode, const float mix_factor,
|
const short mix_mode, const float mix_factor, const float mix_limit,
|
||||||
MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
|
MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
|
||||||
MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
|
MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
|
||||||
MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
|
MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
|
||||||
@@ -265,7 +267,7 @@ static void normalEditModifier_do_radial(
|
|||||||
|
|
||||||
if (loopnors) {
|
if (loopnors) {
|
||||||
mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
|
mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
|
||||||
mix_mode, num_verts, mloop, loopnors, nos, num_loops);
|
mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
|
if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
|
||||||
@@ -283,7 +285,7 @@ static void normalEditModifier_do_radial(
|
|||||||
static void normalEditModifier_do_directional(
|
static void normalEditModifier_do_directional(
|
||||||
NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
|
NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
|
||||||
short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
|
short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
|
||||||
const short mix_mode, const float mix_factor,
|
const short mix_mode, const float mix_factor, const float mix_limit,
|
||||||
MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
|
MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
|
||||||
MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
|
MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
|
||||||
MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
|
MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
|
||||||
@@ -342,7 +344,7 @@ static void normalEditModifier_do_directional(
|
|||||||
|
|
||||||
if (loopnors) {
|
if (loopnors) {
|
||||||
mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
|
mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
|
||||||
mix_mode, num_verts, mloop, loopnors, nos, num_loops);
|
mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
|
if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
|
||||||
@@ -384,7 +386,8 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o
|
|||||||
const bool use_invert_vgroup = ((smd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
|
const bool use_invert_vgroup = ((smd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
|
||||||
const bool use_current_clnors = !((smd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
|
const bool use_current_clnors = !((smd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
|
||||||
(smd->mix_factor == 1.0f) &&
|
(smd->mix_factor == 1.0f) &&
|
||||||
(smd->defgrp_name[0] == '\0'));
|
(smd->defgrp_name[0] == '\0') &&
|
||||||
|
(smd->mix_limit == M_PI));
|
||||||
|
|
||||||
int defgrp_index;
|
int defgrp_index;
|
||||||
MDeformVert *dvert;
|
MDeformVert *dvert;
|
||||||
@@ -439,13 +442,13 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o
|
|||||||
if (smd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
|
if (smd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
|
||||||
normalEditModifier_do_radial(
|
normalEditModifier_do_radial(
|
||||||
smd, ob, dm, clnors, loopnors, polynors,
|
smd, ob, dm, clnors, loopnors, polynors,
|
||||||
smd->mix_mode, smd->mix_factor, dvert, defgrp_index, use_invert_vgroup,
|
smd->mix_mode, smd->mix_factor, smd->mix_limit, dvert, defgrp_index, use_invert_vgroup,
|
||||||
mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
|
mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
|
||||||
}
|
}
|
||||||
else if (smd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
|
else if (smd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
|
||||||
normalEditModifier_do_directional(
|
normalEditModifier_do_directional(
|
||||||
smd, ob, dm, clnors, loopnors, polynors,
|
smd, ob, dm, clnors, loopnors, polynors,
|
||||||
smd->mix_mode, smd->mix_factor, dvert, defgrp_index, use_invert_vgroup,
|
smd->mix_mode, smd->mix_factor, smd->mix_limit, dvert, defgrp_index, use_invert_vgroup,
|
||||||
mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
|
mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,6 +467,7 @@ static void initData(ModifierData *md)
|
|||||||
|
|
||||||
smd->mix_mode = MOD_NORMALEDIT_MIX_COPY;
|
smd->mix_mode = MOD_NORMALEDIT_MIX_COPY;
|
||||||
smd->mix_factor = 1.0f;
|
smd->mix_factor = 1.0f;
|
||||||
|
smd->mix_limit = M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyData(ModifierData *md, ModifierData *target)
|
static void copyData(ModifierData *md, ModifierData *target)
|
||||||
|
Reference in New Issue
Block a user