[Bf-blender-cvs] [5c28955d3a0] master: Modifiers: option to preserve custom normals for subsurf & multires

Cody Winchester noreply at git.blender.org
Wed Jul 22 07:08:50 CEST 2020


Commit: 5c28955d3a018adf9986cc601837cde9fc011496
Author: Cody Winchester
Date:   Wed Jul 22 15:03:17 2020 +1000
Branches: master
https://developer.blender.org/rB5c28955d3a018adf9986cc601837cde9fc011496

Modifiers: option to preserve custom normals for subsurf & multires

===================================================================

M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/intern/rna_modifier.c
M	source/blender/modifiers/intern/MOD_multires.c
M	source/blender/modifiers/intern/MOD_subsurf.c

===================================================================

diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 661799b4256..8c564bda3d0 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -155,6 +155,7 @@ typedef enum {
   /* DEPRECATED, ONLY USED FOR DO-VERSIONS */
   eSubsurfModifierFlag_SubsurfUv_DEPRECATED = (1 << 3),
   eSubsurfModifierFlag_UseCrease = (1 << 4),
+  eSubsurfModifierFlag_UseCustomNormals = (1 << 5),
 } SubsurfModifierFlag;
 
 typedef enum {
@@ -1026,6 +1027,7 @@ typedef enum {
   /* DEPRECATED, only used for versioning. */
   eMultiresModifierFlag_PlainUv_DEPRECATED = (1 << 1),
   eMultiresModifierFlag_UseCrease = (1 << 2),
+  eMultiresModifierFlag_UseCustomNormals = (1 << 3),
 } MultiresModifierFlag;
 
 /* DEPRECATED, only used for versioning. */
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 4d0d8cf1b6c..3d32e4695f5 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1818,6 +1818,12 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
       prop, "Use Creases", "Use mesh edge crease information to sharpen edges");
   RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
+  prop = RNA_def_property(srna, "use_custom_normals", PROP_BOOLEAN, PROP_NONE);
+  RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_UseCustomNormals);
+  RNA_def_property_ui_text(
+      prop, "Use Custom Normals", "Interpolates existing custom normals to resulting mesh");
+  RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
   RNA_define_lib_overridable(false);
 }
 
@@ -2019,6 +2025,12 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
       prop, "Use Creases", "Use mesh edge crease information to sharpen edges");
   RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
+  prop = RNA_def_property(srna, "use_custom_normals", PROP_BOOLEAN, PROP_NONE);
+  RNA_def_property_boolean_sdna(prop, NULL, "flags", eMultiresModifierFlag_UseCustomNormals);
+  RNA_def_property_ui_text(
+      prop, "Use Custom Normals", "Interpolates existing custom normals to resulting mesh");
+  RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
   RNA_define_lib_overridable(false);
 }
 
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index b05a42d2222..f091385ff8e 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -80,6 +80,26 @@ static void initData(ModifierData *md)
   md->ui_expand_flag = (1 << 0) | (1 << 1);
 }
 
+static void requiredDataMask(Object *UNUSED(ob),
+                             ModifierData *md,
+                             CustomData_MeshMasks *r_cddata_masks)
+{
+  MultiresModifierData *mmd = (MultiresModifierData *)md;
+  if (mmd->flags & eMultiresModifierFlag_UseCustomNormals) {
+    r_cddata_masks->lmask |= CD_MASK_NORMAL;
+    r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
+  }
+}
+
+static bool dependsOnNormals(ModifierData *md)
+{
+  MultiresModifierData *mmd = (MultiresModifierData *)md;
+  if (mmd->flags & eMultiresModifierFlag_UseCustomNormals) {
+    return true;
+  }
+  return false;
+}
+
 static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int flag)
 {
   BKE_modifier_copydata_generic(md_src, md_dst, flag);
@@ -208,6 +228,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
     /* Happens on bad topology, ut also on empty input mesh. */
     return result;
   }
+  const bool use_clnors = mmd->flags & eMultiresModifierFlag_UseCustomNormals &&
+                          mesh->flag & ME_AUTOSMOOTH &&
+                          CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
   /* NOTE: Orco needs final coordinates on CPU side, which are expected to be
    * accessible via MVert. For this reason we do not evaluate multires to
    * grids when orco is requested. */
@@ -243,7 +266,22 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
     // BKE_subdiv_stats_print(&subdiv->stats);
   }
   else {
+    if (use_clnors) {
+      /* If custom normals are present and the option is turned on calculate the split
+       * normals and clear flag so the normals get interpolated to the result mesh. */
+      BKE_mesh_calc_normals_split(mesh);
+      CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+    }
+
     result = multires_as_mesh(mmd, ctx, mesh, subdiv);
+
+    if (use_clnors) {
+      float(*lnors)[3] = CustomData_get_layer(&result->ldata, CD_NORMAL);
+      BLI_assert(lnors != NULL);
+      BKE_mesh_set_custom_normals(result, lnors);
+      CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+      CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+    }
     // BKE_subdiv_stats_print(&subdiv->stats);
     if (subdiv != runtime_data->subdiv) {
       BKE_subdiv_free(subdiv);
@@ -442,6 +480,7 @@ static void advanced_panel_draw(const bContext *C, Panel *panel)
   uiItemR(col, &ptr, "uv_smooth", 0, NULL, ICON_NONE);
 
   uiItemR(layout, &ptr, "use_creases", 0, NULL, ICON_NONE);
+  uiItemR(layout, &ptr, "use_custom_normals", 0, NULL, ICON_NONE);
 }
 
 static void panelRegister(ARegionType *region_type)
@@ -476,12 +515,12 @@ ModifierTypeInfo modifierType_Multires = {
     /* modifyVolume */ NULL,
 
     /* initData */ initData,
-    /* requiredDataMask */ NULL,
+    /* requiredDataMask */ requiredDataMask,
     /* freeData */ freeData,
     /* isDisabled */ NULL,
     /* updateDepsgraph */ NULL,
     /* dependsOnTime */ NULL,
-    /* dependsOnNormals */ NULL,
+    /* dependsOnNormals */ dependsOnNormals,
     /* foreachObjectLink */ NULL,
     /* foreachIDLink */ NULL,
     /* foreachTexLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index d5ff31bd3b1..8424b549f85 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -36,6 +36,7 @@
 #include "DNA_screen_types.h"
 
 #include "BKE_context.h"
+#include "BKE_mesh.h"
 #include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_subdiv.h"
@@ -77,6 +78,26 @@ static void initData(ModifierData *md)
   smd->flags |= (eSubsurfModifierFlag_UseCrease | eSubsurfModifierFlag_ControlEdges);
 }
 
+static void requiredDataMask(Object *UNUSED(ob),
+                             ModifierData *md,
+                             CustomData_MeshMasks *r_cddata_masks)
+{
+  SubsurfModifierData *smd = (SubsurfModifierData *)md;
+  if (smd->flags & eSubsurfModifierFlag_UseCustomNormals) {
+    r_cddata_masks->lmask |= CD_MASK_NORMAL;
+    r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
+  }
+}
+
+static bool dependsOnNormals(ModifierData *md)
+{
+  SubsurfModifierData *smd = (SubsurfModifierData *)md;
+  if (smd->flags & eSubsurfModifierFlag_UseCustomNormals) {
+    return true;
+  }
+  return false;
+}
+
 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
 {
 #if 0
@@ -242,6 +263,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
     /* Happens on bad topology, but also on empty input mesh. */
     return result;
   }
+  const bool use_clnors = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
+                          (mesh->flag & ME_AUTOSMOOTH) &&
+                          CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+  if (use_clnors) {
+    /* If custom normals are present and the option is turned on calculate the split
+     * normals and clear flag so the normals get interpolated to the result mesh. */
+    BKE_mesh_calc_normals_split(mesh);
+    CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+  }
   /* TODO(sergey): Decide whether we ever want to use CCG for subsurf,
    * maybe when it is a last modifier in the stack? */
   if (true) {
@@ -250,6 +280,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
   else {
     result = subdiv_as_ccg(smd, ctx, mesh, subdiv);
   }
+
+  if (use_clnors) {
+    float(*lnors)[3] = CustomData_get_layer(&result->ldata, CD_NORMAL);
+    BLI_assert(lnors != NULL);
+    BKE_mesh_set_custom_normals(result, lnors);
+    CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+    CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+  }
   // BKE_subdiv_stats_print(&subdiv->stats);
   if (subdiv != runtime_data->subdiv) {
     BKE_subdiv_free(subdiv);
@@ -416,6 +454,7 @@ static void advanced_panel_draw(const bContext *C, Panel *panel)
   uiItemR(layout, &ptr, "quality", 0, NULL, ICON_NONE);
   uiItemR(layout, &ptr, "uv_smooth", 0, NULL, ICON_NONE);
   uiItemR(layout, &ptr, "use_creases", 0, NULL, ICON_NONE);
+  uiItemR(layout, &ptr, "use_custom_normals", 0, NULL, ICON_NONE);
 }
 
 static void panelRegister(ARegionType *region_type)
@@ -453,12 +492,12 @@ ModifierTypeInfo modifierType_Subsurf = {
     /* modifyVolume */ NULL,
 
     /* initData */ initData,
-    /* requiredDataMask */ NULL,
+    /* requiredDataMask */ requiredDataMask,
     /* freeData */ freeData,
     /* isDisabled */ isDisabled,
     /* updateDepsgraph */ NULL,
     /* dependsOnTime */ NULL,
-    /* dependsOnNormals */ NULL,
+    /* dependsOnNormals */ dependsOnNormals,
     /* foreachObjectLink */ NULL,
     /* foreachIDLink */ NULL,
     /* foreachTexLink */ NULL,



More information about the Bf-blender-cvs mailing list