Fix #114244: Smooth operators destroy sharp edge tags #117069

Merged
Hans Goudey merged 1 commits from HooglyBoogly/blender:shade-keep-sharp-edges into main 2024-01-15 14:05:34 +01:00
3 changed files with 41 additions and 23 deletions

View File

@ -319,8 +319,8 @@ void mesh_vert_normals_assign(Mesh &mesh, Span<float3> vert_normals);
/** Set mesh vertex normals to known-correct values, avoiding future lazy computation. */
void mesh_vert_normals_assign(Mesh &mesh, Vector<float3> vert_normals);
void mesh_smooth_set(Mesh &mesh, bool use_smooth);
void mesh_sharp_edges_set_from_angle(Mesh &mesh, float angle);
void mesh_smooth_set(Mesh &mesh, bool use_smooth, bool keep_sharp_edges = false);
void mesh_sharp_edges_set_from_angle(Mesh &mesh, float angle, bool keep_sharp_edges = false);
/** Make edge and face visibility consistent with vertices. */
void mesh_hide_vert_flush(Mesh &mesh);

View File

@ -1128,34 +1128,34 @@ void BKE_mesh_material_remap(Mesh *mesh, const uint *remap, uint remap_len)
namespace blender::bke {
void mesh_smooth_set(Mesh &mesh, const bool use_smooth)
void mesh_smooth_set(Mesh &mesh, const bool use_smooth, const bool keep_sharp_edges)
{
MutableAttributeAccessor attributes = mesh.attributes_for_write();
if (use_smooth) {
if (!keep_sharp_edges) {
attributes.remove("sharp_edge");
attributes.remove("sharp_face");
}
else {
attributes.remove("sharp_edge");
SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_only_span<bool>(
"sharp_face", AttrDomain::Face);
sharp_faces.span.fill(true);
sharp_faces.finish();
attributes.remove("sharp_face");
if (!use_smooth) {
attributes.add<bool>("sharp_face",
AttrDomain::Face,
AttributeInitVArray(VArray<bool>::ForSingle(true, mesh.faces_num)));
}
}
void mesh_sharp_edges_set_from_angle(Mesh &mesh, const float angle)
void mesh_sharp_edges_set_from_angle(Mesh &mesh, const float angle, const bool keep_sharp_edges)
{
MutableAttributeAccessor attributes = mesh.attributes_for_write();
if (angle >= M_PI) {
attributes.remove("sharp_edge");
attributes.remove("sharp_face");
mesh_smooth_set(mesh, true, keep_sharp_edges);
return;
}
if (angle == 0.0f) {
mesh_smooth_set(mesh, false);
mesh_smooth_set(mesh, false, keep_sharp_edges);
return;
}
if (!keep_sharp_edges) {
attributes.remove("sharp_edge");
}
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", AttrDomain::Edge);
const VArraySpan<bool> sharp_faces = *attributes.lookup<bool>("sharp_face", AttrDomain::Face);

View File

@ -1616,12 +1616,12 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
bool changed = false;
if (ob->type == OB_MESH) {
bke::mesh_smooth_set(*static_cast<Mesh *>(ob->data), use_smooth || use_smooth_by_angle);
if (use_smooth || use_smooth_by_angle) {
if (use_smooth_by_angle) {
const float angle = RNA_float_get(op->ptr, "angle");
bke::mesh_sharp_edges_set_from_angle(*static_cast<Mesh *>(ob->data), angle);
}
Mesh &mesh = *static_cast<Mesh *>(ob->data);
const bool keep_sharp_edges = RNA_boolean_get(op->ptr, "keep_sharp_edges");
bke::mesh_smooth_set(mesh, use_smooth || use_smooth_by_angle, keep_sharp_edges);
if (use_smooth_by_angle) {
const float angle = RNA_float_get(op->ptr, "angle");
bke::mesh_sharp_edges_set_from_angle(mesh, angle, keep_sharp_edges);
}
BKE_mesh_batch_cache_dirty_tag(static_cast<Mesh *>(ob->data), BKE_MESH_BATCH_DIRTY_ALL);
changed = true;
@ -1671,7 +1671,7 @@ void OBJECT_OT_shade_flat(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Shade Flat";
ot->description = "Render and display faces uniform, using Face Normals";
ot->description = "Render and display faces uniform, using face normals";
ot->idname = "OBJECT_OT_shade_flat";
/* api callbacks */
@ -1680,13 +1680,19 @@ void OBJECT_OT_shade_flat(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna,
"keep_sharp_edges",
true,
"Keep Sharp Edges",
"Don't remove sharp edges, which are redundant with faces shaded smooth");
}
void OBJECT_OT_shade_smooth(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Shade Smooth";
ot->description = "Render and display faces smooth, using interpolated Vertex Normals";
ot->description = "Render and display faces smooth, using interpolated vertex normals";
ot->idname = "OBJECT_OT_shade_smooth";
/* api callbacks */
@ -1695,6 +1701,12 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna,
"keep_sharp_edges",
true,
"Keep Sharp Edges",
"Don't remove sharp edges. Tagged edges will remain sharp");
}
void OBJECT_OT_shade_smooth_by_angle(wmOperatorType *ot)
@ -1714,6 +1726,12 @@ void OBJECT_OT_shade_smooth_by_angle(wmOperatorType *ot)
RNA_def_property_float_default(prop, DEG2RADF(30.0f));
RNA_def_property_ui_text(
prop, "Angle", "Maximum angle between face normals that will be considered as smooth");
RNA_def_boolean(ot->srna,
"keep_sharp_edges",
true,
"Keep Sharp Edges",
"Only add sharp edges instead of clearing existing tags first");
}
/** \} */