Blender V5.0
MOD_edgesplit.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
13
14#include "BLI_math_vector.h"
15#include "BLI_utildefines.h"
16
17#include "BLT_translation.hh"
18
19#include "DNA_defaults.h"
20#include "DNA_mesh_types.h"
21#include "DNA_screen_types.h"
22
23#include "BKE_mesh.hh"
24#include "BKE_modifier.hh"
25
27#include "UI_resources.hh"
28
29#include "RNA_access.hh"
30#include "RNA_prototypes.hh"
31
32#include "bmesh.hh"
33#include "bmesh_tools.hh"
34
35#include "MOD_ui_common.hh"
36
37#include "GEO_randomize.hh"
38
39/* For edge split modifier node. */
40Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd);
41
43{
44 Mesh *result;
45 BMesh *bm;
46 BMIter iter;
47 BMEdge *e;
48 const float threshold = cosf(emd->split_angle + 0.000000175f);
49 const bool do_split_angle = (emd->flags & MOD_EDGESPLIT_FROMANGLE) != 0 &&
50 emd->split_angle < float(M_PI);
51 const bool do_split_all = do_split_angle && emd->split_angle < FLT_EPSILON;
52 const bool calc_face_normals = do_split_angle && !do_split_all;
53
54 BMeshCreateParams create_params{};
55 BMeshFromMeshParams convert_params{};
56 convert_params.calc_face_normal = calc_face_normals;
57 convert_params.calc_vert_normal = false;
58 convert_params.add_key_index = false;
59 convert_params.use_shapekey = false;
60 convert_params.active_shapekey = 0;
61 convert_params.cd_mask_extra.vmask = CD_MASK_ORIGINDEX;
62 convert_params.cd_mask_extra.emask = CD_MASK_ORIGINDEX;
63 convert_params.cd_mask_extra.pmask = CD_MASK_ORIGINDEX;
64
65 bm = BKE_mesh_to_bmesh_ex(mesh, &create_params, &convert_params);
66
67 if (do_split_angle) {
69 /* check for 1 edge having 2 face users */
70 BMLoop *l1 = e->l;
71 BMLoop *l2 = (e->l) ? e->l->radial_next : nullptr;
72 if (l1 && l2 != l1) {
73 if (/* 3+ faces on this edge, always split */
74 UNLIKELY(l1 != l2->radial_next) ||
75 /* O degree angle setting, we want to split on all edges. */
76 do_split_all ||
77 /* 2 face edge - check angle. */
78 (dot_v3v3(l1->f->no, l2->f->no) < threshold))
79 {
81 }
82 }
83 }
84 }
85
86 if (emd->flags & MOD_EDGESPLIT_FROMFLAG) {
88 /* check for 2 or more edge users */
89 if ((e->l) && (e->l->next != e->l)) {
92 }
93 }
94 }
95 }
96
97 BM_mesh_edgesplit(bm, false, true, false);
98
99 /* Uncomment for troubleshooting. */
100 // BM_mesh_is_valid(bm);
101
104
106
107 return result;
108}
109
118
119static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext * /*ctx*/, Mesh *mesh)
120{
121 Mesh *result;
123
125 return mesh;
126 }
127
128 result = doEdgeSplit(mesh, emd);
129
130 return result;
131}
132
133static void panel_draw(const bContext * /*C*/, Panel *panel)
134{
135 uiLayout *row, *sub;
136 uiLayout *layout = panel->layout;
137
139
140 layout->use_property_split_set(true);
141
142 row = &layout->row(true, IFACE_("Edge Angle"));
143 row->prop(ptr, "use_edge_angle", UI_ITEM_NONE, "", ICON_NONE);
144 sub = &row->row(true);
145 sub->active_set(RNA_boolean_get(ptr, "use_edge_angle"));
146 sub->prop(ptr, "split_angle", UI_ITEM_NONE, "", ICON_NONE);
147
148 layout->prop(ptr, "use_edge_sharp", UI_ITEM_NONE, IFACE_("Sharp Edges"), ICON_NONE);
149
151}
152
153static void panel_register(ARegionType *region_type)
154{
156}
157
159 /*idname*/ "EdgeSplit",
160 /*name*/ N_("EdgeSplit"),
161 /*struct_name*/ "EdgeSplitModifierData",
162 /*struct_size*/ sizeof(EdgeSplitModifierData),
163 /*srna*/ &RNA_EdgeSplitModifier,
168 /*icon*/ ICON_MOD_EDGESPLIT,
169
170 /*copy_data*/ BKE_modifier_copydata_generic,
171
172 /*deform_verts*/ nullptr,
173 /*deform_matrices*/ nullptr,
174 /*deform_verts_EM*/ nullptr,
175 /*deform_matrices_EM*/ nullptr,
176 /*modify_mesh*/ modify_mesh,
177 /*modify_geometry_set*/ nullptr,
178
179 /*init_data*/ init_data,
180 /*required_data_mask*/ nullptr,
181 /*free_data*/ nullptr,
182 /*is_disabled*/ nullptr,
183 /*update_depsgraph*/ nullptr,
184 /*depends_on_time*/ nullptr,
185 /*depends_on_normals*/ nullptr,
186 /*foreach_ID_link*/ nullptr,
187 /*foreach_tex_link*/ nullptr,
188 /*free_runtime_data*/ nullptr,
189 /*panel_register*/ panel_register,
190 /*blend_write*/ nullptr,
191 /*blend_read*/ nullptr,
192 /*foreach_cache*/ nullptr,
193 /*foreach_working_space_color*/ nullptr,
194};
Mesh * BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const CustomData_MeshMasks *cd_mask_extra, const Mesh *me_settings)
BMesh * BKE_mesh_to_bmesh_ex(const Mesh *mesh, const BMeshCreateParams *create_params, const BMeshFromMeshParams *convert_params)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
#define BLI_assert(a)
Definition BLI_assert.h:46
#define M_PI
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
#define UNLIKELY(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
#define CD_MASK_ORIGINDEX
#define DNA_struct_default_get(struct_name)
@ MOD_EDGESPLIT_FROMANGLE
@ MOD_EDGESPLIT_FROMFLAG
@ eModifierType_EdgeSplit
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void panel_draw(const bContext *, Panel *panel)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
static void init_data(ModifierData *md)
Mesh * doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd)
static void panel_register(ARegionType *region_type)
ModifierTypeInfo modifierType_EdgeSplit
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *, Mesh *mesh)
static void panel_draw(const bContext *, Panel *panel)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
#define UI_ITEM_NONE
@ BM_ELEM_SMOOTH
@ BM_ELEM_TAG
void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
void debug_randomize_mesh_order(Mesh *mesh)
Definition randomize.cc:288
#define cosf
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
float no[3]
struct BMLoop * radial_next
struct BMFace * f
struct CustomData_MeshMasks cd_mask_extra
struct uiLayout * layout
void active_set(bool active)
uiLayout & row(bool align)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238