Fix #119446: Incorrect auto smooth versioning for subsurf modifier

Previously I misunderstood the subsurf modifier's handling of custom
normals. The "use custom normals" check in 4.0 checked if there were
custom normals and whether the auto smooth flag was checked. I wrongly
changed that to check the mesh normals domain instead of whether there
was custom normals. In 4.1, auto smooth isn't required to use custom
normals, but that should be the only change here.

In this PR, that change is done for CPU and GPU subdivision, and for
the versioning which adds a modifier. The versioning now only puts the
new modifier before the subsurf modifier if it would have used the
custom normals interpolation in 4.0.

The last change causes two test failures which I also misunderstood
before. The previous results were arguably incorrect, because the
Cycles experimental adaptive subdivision ignored the auto smooth
angle, which was 5 degrees. It should have been 180 degrees.
I will modify those test files to remove auto smooth from the meshes.

Pull Request: https://projects.blender.org/blender/blender/pulls/119485
This commit is contained in:
Hans Goudey 2024-03-15 11:29:46 -04:00
parent 52a8bea237
commit 1111903416
4 changed files with 15 additions and 8 deletions

@ -2289,7 +2289,8 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
/* Auto-smooth disabled sharp edge tagging when the evaluated mesh had custom normals.
* When the original mesh has custom normals, that's a good sign the evaluated mesh will
* have custom normals as well. */
if (CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL)) {
bool has_custom_normals = CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL);
if (has_custom_normals) {
continue;
}
@ -2297,6 +2298,9 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
* edge tags based on the mesh's smoothing angle. To keep the same behavior, a new modifier has
* to be added before that modifier when the option is on. */
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (ELEM(md->type, eModifierType_WeightedNormal, eModifierType_NormalEdit)) {
has_custom_normals = true;
}
if (md->type == eModifierType_WeightedNormal) {
WeightedNormalModifierData *nmd = reinterpret_cast<WeightedNormalModifierData *>(md);
if ((nmd->flag & MOD_WEIGHTEDNORMAL_KEEP_SHARP) != 0) {
@ -2317,10 +2321,12 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
}
ModifierData *new_md = create_auto_smooth_modifier(*object, add_node_group, angle);
if (last_md && last_md->type == eModifierType_Subsurf) {
if (last_md && last_md->type == eModifierType_Subsurf && has_custom_normals &&
(reinterpret_cast<SubsurfModifierData *>(last_md)->flags &
eSubsurfModifierFlag_UseCustomNormals) != 0)
{
/* Add the auto smooth node group before the last subdivision surface modifier if possible.
* Subdivision surface modifiers have special handling for interpolating face corner normals,
* and recalculating them afterwards isn't usually helpful and can be much slower. */
* Subdivision surface modifiers have special handling for interpolating custom normals. */
BLI_insertlinkbefore(&object->modifiers, object->modifiers.last, new_md);
}
else {

@ -13,6 +13,7 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "BKE_customdata.hh"
#include "BKE_mesh.hh"
#include "BKE_modifier.hh"
#include "BKE_subdiv.hh"
@ -87,7 +88,7 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene,
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
{
return smd->flags & eSubsurfModifierFlag_UseCustomNormals &&
mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner;
CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL);
}
static bool is_subdivision_evaluation_possible_on_gpu()

@ -2157,8 +2157,8 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
runtime_data->stats_totloop = draw_cache.num_subdiv_loops;
draw_cache.use_custom_loop_normals = (runtime_data->use_loop_normals) &&
mesh_eval->normals_domain() ==
bke::MeshNormalDomain::Corner;
CustomData_has_layer(&mesh_eval->corner_data,
CD_CUSTOMLOOPNORMAL);
if (DRW_ibo_requested(mbc.buff.ibo.tris)) {
draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache.mat_len);

@ -1 +1 @@
Subproject commit 6dd81d3f24ec18cec2ab70d1c4159be3900ccd55
Subproject commit 7e545568b056cfb3b03e38c9fec08e01d8761a77