Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/mesh/editmesh_bevel.c')
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c154
1 files changed, 145 insertions, 9 deletions
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index b73ce410626..e87abc6adf7 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -30,6 +30,7 @@
#include "BLI_string.h"
#include "BLI_math.h"
+#include "BLI_linklist_stack.h"
#include "BLT_translation.h"
@@ -38,6 +39,7 @@
#include "BKE_editmesh.h"
#include "BKE_unit.h"
#include "BKE_layer.h"
+#include "BKE_mesh.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -95,7 +97,7 @@ typedef struct {
/* modal only */
float mcenter[2];
void *draw_handle_pixel;
- short mpr_flag;
+ short gizmo_flag;
short value_mode; /* Which value does mouse movement and numeric input affect? */
float segments; /* Segments as float so smooth mouse pan works in small increments */
} BevelData;
@@ -134,6 +136,98 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
}
}
+static void bevel_harden_normals(BMEditMesh *em, BMOperator *bmop, float face_strength)
+{
+ BKE_editmesh_lnorspace_update(em);
+ BM_normals_loops_edges_tag(em->bm, true);
+ const int cd_clnors_offset = CustomData_get_offset(&em->bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *l_cur, *l_first;
+ BMIter fiter;
+
+ BMOpSlot *nslot = BMO_slot_get(bmop->slots_out, "normals.out"); /* Per vertex normals depending on hn_mode */
+
+ /* Similar functionality to bm_mesh_loops_calc_normals... Edges that can be smoothed are tagged */
+ BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_cur = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if ((BM_elem_flag_test(l_cur->v, BM_ELEM_SELECT)) &&
+ ((!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG)) ||
+ (!BM_elem_flag_test(l_cur, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_cur))))
+ {
+ /* Both adjacent loops are sharp, set clnor to face normal */
+ if (!BM_elem_flag_test(l_cur->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_cur->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_cur);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_cur, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ /* Find next corresponding sharp edge in this smooth fan */
+ BMVert *v_pivot = l_cur->v;
+ float *calc_n = BLI_ghash_lookup(nslot->data.ghash, v_pivot);
+
+ BMEdge *e_next;
+ const BMEdge *e_org = l_cur->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_cur;
+ e_next = lfan_pivot->e;
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float cn_wght[3] = { 0.0f, 0.0f, 0.0f }, cn_unwght[3] = { 0.0f, 0.0f, 0.0f };
+
+ /* Fan through current vert and accumulate normals and loops */
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
+ float cur[3];
+ mul_v3_v3fl(cur, lfan_pivot->f->no, BM_face_calc_area(lfan_pivot->f));
+ add_v3_v3(cn_wght, cur);
+
+ if (BM_elem_flag_test(lfan_pivot->f, BM_ELEM_SELECT))
+ add_v3_v3(cn_unwght, cur);
+
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
+ }
+
+ normalize_v3(cn_wght);
+ normalize_v3(cn_unwght);
+ if (calc_n) {
+ mul_v3_fl(cn_wght, face_strength);
+ mul_v3_fl(calc_n, 1.0f - face_strength);
+ add_v3_v3(calc_n, cn_wght);
+ normalize_v3(calc_n);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ if (calc_n) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], calc_n, clnors);
+ }
+ else {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], cn_unwght, clnors);
+ }
+ }
+ BLI_ghash_remove(nslot->data.ghash, v_pivot, NULL, MEM_freeN);
+ }
+ }
+ } while ((l_cur = l_cur->next) != l_first);
+ }
+}
+
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
Scene *scene = CTX_data_scene(C);
@@ -201,8 +295,8 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
- opdata->mpr_flag = v3d->mpr_flag;
- v3d->mpr_flag = V3D_GIZMO_HIDE;
+ opdata->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
}
}
@@ -224,6 +318,10 @@ static bool edbm_bevel_calc(wmOperator *op)
const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
int material = RNA_int_get(op->ptr, "material");
const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
+ const bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
+ const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ const float hn_strength = RNA_float_get(op->ptr, "strength");
+ const int hnmode = RNA_enum_get(op->ptr, "hnmode");
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
@@ -238,11 +336,12 @@ static bool edbm_bevel_calc(wmOperator *op)
material = CLAMPIS(material, -1, em->ob->totcol - 1);
}
- EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
- "material=%i loop_slide=%b",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
- clamp_overlap, material, loop_slide);
+ EDBM_op_init(
+ em, &bmop, op,
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
+ "material=%i loop_slide=%b mark_seam=%b mark_sharp=%b strength=%f hnmode=%i",
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
+ clamp_overlap, material, loop_slide, mark_seam, mark_sharp, hn_strength, hnmode);
BMO_op_exec(em->bm, &bmop);
@@ -253,6 +352,10 @@ static bool edbm_bevel_calc(wmOperator *op)
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
+ if (hnmode != BEVEL_HN_NONE) {
+ bevel_harden_normals(em, &bmop, hn_strength);
+ }
+
/* no need to de-select existing geometry */
if (!EDBM_op_finish(em, &bmop, op, true)) {
continue;
@@ -284,7 +387,7 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
}
ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
if (v3d) {
- v3d->mpr_flag = opdata->mpr_flag;
+ v3d->gizmo_flag = opdata->gizmo_flag;
}
G.moving = 0;
}
@@ -603,6 +706,26 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
edbm_bevel_update_header(C, op);
handled = true;
break;
+ case UKEY:
+ if (event->val == KM_RELEASE)
+ break;
+ else {
+ bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
+ RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
+ edbm_bevel_calc(op);
+ handled = true;
+ break;
+ }
+ case KKEY:
+ if (event->val == KM_RELEASE)
+ break;
+ else {
+ bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
+ edbm_bevel_calc(op);
+ handled = true;
+ break;
+ }
}
@@ -641,6 +764,13 @@ void MESH_OT_bevel(wmOperatorType *ot)
{0, NULL, 0, NULL, NULL},
};
+ static EnumPropertyItem harden_normals_items[] = {
+ { BEVEL_HN_NONE, "HN_NONE", 0, "Off", "Do not use Harden Normals" },
+ { BEVEL_HN_FACE, "HN_FACE", 0, "Face Area", "Use faces as weight" },
+ { BEVEL_HN_ADJ, "HN_ADJ", 0, "Vertex average", "Use adjacent vertices as weight" },
+ { 0, NULL, 0, NULL, NULL },
+ };
+
/* identifiers */
ot->name = "Bevel";
ot->description = "Edge Bevel";
@@ -666,6 +796,12 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap",
"Do not allow beveled edges/vertices to overlap each other");
RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
+ RNA_def_boolean(ot->srna, "mark_seam", false, "Mark Seams", "Mark Seams along beveled edges");
+ RNA_def_boolean(ot->srna, "mark_sharp", false, "Mark Sharp", "Mark beveled edges as sharp");
RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material",
"Material for bevel faces (-1 means use adjacent faces)", -1, 100);
+ RNA_def_float(ot->srna, "strength", 0.5f, 0.0f, 1.0f, "Normal Strength",
+ "Strength of calculated normal", 0.0f, 1.0f);
+ RNA_def_enum(ot->srna, "hnmode", harden_normals_items, BEVEL_HN_NONE, "Normal Mode",
+ "Weighting mode for Harden Normals");
}