Modifiers: option to preserve custom normals for subsurf & multires
This commit is contained in:
parent
a197b81090
commit
5c28955d3a
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue