Mesh: Add "Set Sharpness by Angle" operator #117918

Merged
Hans Goudey merged 4 commits from HooglyBoogly/blender:mesh-set-sharpness-by-angle into blender-v4.1-release 2024-02-07 14:17:23 +01:00
5 changed files with 112 additions and 0 deletions

View File

@ -4466,6 +4466,7 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.operator("mesh.mark_sharp")
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
col.operator("mesh.set_sharpness_by_angle")
if with_freestyle:
col.separator()

View File

@ -49,6 +49,7 @@ set(SRC
editmesh_rip_edge.cc
editmesh_select.cc
editmesh_select_similar.cc
editmesh_set_sharpness_by_angle.cc
editmesh_tools.cc
editmesh_undo.cc
editmesh_utils.cc

View File

@ -0,0 +1,105 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
HooglyBoogly marked this conversation as resolved
Review

Missing

/** \file
 * \ingroup edmesh
 */
Missing ``` /** \file * \ingroup edmesh */ ```
/** \file
* \ingroup edmesh
*/
#include "BLI_math_angle_types.hh"
#include "BLI_math_vector.hh"
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "BKE_context.hh"
#include "BKE_editmesh.hh"
#include "BKE_layer.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "DEG_depsgraph.hh"
#include "WM_api.hh"
#include "ED_mesh.hh"
#include "ED_screen.hh"
#include "mesh_intern.hh"
namespace blender::ed::mesh {
static int set_sharpness_by_angle_exec(bContext *C, wmOperator *op)
{
const float angle_limit_cos = std::cos(RNA_float_get(op->ptr, "angle"));
const bool extend = RNA_boolean_get(op->ptr, "extend");
const Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
HooglyBoogly marked this conversation as resolved
Review

The changed state can be tracked, skip updates if no changes are made. Avoiding redundant updates when no changes are made.

The `changed` state can be tracked, skip updates if no changes are made. Avoiding redundant updates when no changes are made.
CTX_data_scene(C), CTX_data_view_layer(C), CTX_wm_view3d(C));
for (Object *object : objects) {
Mesh &mesh = *static_cast<Mesh *>(object->data);
BMEditMesh *em = mesh.edit_mesh;
bool changed = false;
BMIter iter;
BMEdge *e;
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
continue;
}
const bool prev_sharp = !BM_elem_flag_test(e, BM_ELEM_SMOOTH);
if (extend && prev_sharp) {
continue;
}
BMLoop *l1, *l2;
if (!BM_edge_loop_pair(e, &l1, &l2)) {
continue;
}
const float angle_cos = math::dot(float3(l1->f->no), float3(l2->f->no));
const bool sharp = angle_cos <= angle_limit_cos;
BM_elem_flag_set(e, BM_ELEM_SMOOTH, !sharp);
changed = changed || sharp != prev_sharp;
}
if (changed) {
BKE_editmesh_lnorspace_update(em);
DEG_id_tag_update(&mesh.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &mesh.id);
}
}
return OPERATOR_FINISHED;
}
void MESH_OT_set_sharpness_by_angle(wmOperatorType *ot)
{
ot->name = "Set Sharpness by Angle";
ot->description = "Set edge sharpness based on the angle between neighboring faces";
ot->idname = "MESH_OT_set_sharpness_by_angle";
ot->exec = set_sharpness_by_angle_exec;
ot->poll = ED_operator_editmesh;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
PropertyRNA *prop = RNA_def_float_rotation(ot->srna,
"angle",
0,
nullptr,
math::AngleRadian::from_degree(0.01f).radian(),
math::AngleRadian::from_degree(180.0f).radian(),
"Angle",
"",
math::AngleRadian::from_degree(1.0f).radian(),
math::AngleRadian::from_degree(180.0f).radian());
RNA_def_property_float_default(prop, math::AngleRadian::from_degree(30.0f).radian());
RNA_def_boolean(ot->srna,
"extend",
false,
"Extend",
"Add new sharp edges without clearing existing sharp edges");
}
} // namespace blender::ed::mesh

View File

@ -256,6 +256,9 @@ void MESH_OT_delete_loose(wmOperatorType *ot);
void MESH_OT_edge_collapse(wmOperatorType *ot);
void MESH_OT_faces_shade_smooth(wmOperatorType *ot);
void MESH_OT_faces_shade_flat(wmOperatorType *ot);
namespace blender::ed::mesh {
void MESH_OT_set_sharpness_by_angle(wmOperatorType *ot);
}
void MESH_OT_split(wmOperatorType *ot);
void MESH_OT_edge_rotate(wmOperatorType *ot);
void MESH_OT_hide(wmOperatorType *ot);

View File

@ -22,6 +22,7 @@
void ED_operatortypes_mesh()
{
using namespace blender::ed::mesh;
WM_operatortype_append(MESH_OT_select_all);
WM_operatortype_append(MESH_OT_select_interior_faces);
WM_operatortype_append(MESH_OT_select_more);
@ -98,6 +99,7 @@ void ED_operatortypes_mesh()
WM_operatortype_append(MESH_OT_delete_edgeloop);
WM_operatortype_append(MESH_OT_faces_shade_smooth);
WM_operatortype_append(MESH_OT_faces_shade_flat);
WM_operatortype_append(MESH_OT_set_sharpness_by_angle);
WM_operatortype_append(MESH_OT_sort_elements);
#ifdef WITH_FREESTYLE
WM_operatortype_append(MESH_OT_mark_freestyle_face);