Blender V4.3
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
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
26#include "UI_interface.hh"
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, *l2;
71 if ((l1 = e->l) && (l2 = e->l->radial_next) != l1) {
72 if (/* 3+ faces on this edge, always split */
73 UNLIKELY(l1 != l2->radial_next) ||
74 /* O degree angle setting, we want to split on all edges. */
75 do_split_all ||
76 /* 2 face edge - check angle. */
77 (dot_v3v3(l1->f->no, l2->f->no) < threshold))
78 {
80 }
81 }
82 }
83 }
84
85 if (emd->flags & MOD_EDGESPLIT_FROMFLAG) {
87 /* check for 2 or more edge users */
88 if ((e->l) && (e->l->next != e->l)) {
91 }
92 }
93 }
94 }
95
96 BM_mesh_edgesplit(bm, false, true, false);
97
98 /* Uncomment for troubleshooting. */
99 // BM_mesh_validate(bm);
100
101 result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
103
105
106 return result;
107}
108
117
118static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext * /*ctx*/, Mesh *mesh)
119{
120 Mesh *result;
122
124 return mesh;
125 }
126
127 result = doEdgeSplit(mesh, emd);
128
129 return result;
130}
131
132static void panel_draw(const bContext * /*C*/, Panel *panel)
133{
134 uiLayout *row, *sub;
135 uiLayout *layout = panel->layout;
136
138
139 uiLayoutSetPropSep(layout, true);
140
141 row = uiLayoutRowWithHeading(layout, true, IFACE_("Edge Angle"));
142 uiItemR(row, ptr, "use_edge_angle", UI_ITEM_NONE, "", ICON_NONE);
143 sub = uiLayoutRow(row, true);
144 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_edge_angle"));
145 uiItemR(sub, ptr, "split_angle", UI_ITEM_NONE, "", ICON_NONE);
146
147 uiItemR(layout, ptr, "use_edge_sharp", UI_ITEM_NONE, IFACE_("Sharp Edges"), ICON_NONE);
148
149 modifier_panel_end(layout, ptr);
150}
151
152static void panel_register(ARegionType *region_type)
153{
155}
156
158 /*idname*/ "EdgeSplit",
159 /*name*/ N_("EdgeSplit"),
160 /*struct_name*/ "EdgeSplitModifierData",
161 /*struct_size*/ sizeof(EdgeSplitModifierData),
162 /*srna*/ &RNA_EdgeSplitModifier,
167 /*icon*/ ICON_MOD_EDGESPLIT,
168
169 /*copy_data*/ BKE_modifier_copydata_generic,
170
171 /*deform_verts*/ nullptr,
172 /*deform_matrices*/ nullptr,
173 /*deform_verts_EM*/ nullptr,
174 /*deform_matrices_EM*/ nullptr,
175 /*modify_mesh*/ modify_mesh,
176 /*modify_geometry_set*/ nullptr,
177
178 /*init_data*/ init_data,
179 /*required_data_mask*/ nullptr,
180 /*free_data*/ nullptr,
181 /*is_disabled*/ nullptr,
182 /*update_depsgraph*/ nullptr,
183 /*depends_on_time*/ nullptr,
184 /*depends_on_normals*/ nullptr,
185 /*foreach_ID_link*/ nullptr,
186 /*foreach_tex_link*/ nullptr,
187 /*free_runtime_data*/ nullptr,
188 /*panel_register*/ panel_register,
189 /*blend_write*/ nullptr,
190 /*blend_read*/ nullptr,
191 /*foreach_cache*/ nullptr,
192};
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:50
#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)
@ eModifierType_EdgeSplit
@ MOD_EDGESPLIT_FROMANGLE
@ MOD_EDGESPLIT_FROMFLAG
struct EdgeSplitModifierData EdgeSplitModifierData
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)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ 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
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
#define cosf(x)
void debug_randomize_mesh_order(Mesh *mesh)
Definition randomize.cc:220
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
float no[3]
struct BMLoop * radial_next
struct BMFace * f
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126