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_tools.c')
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c218
1 files changed, 101 insertions, 117 deletions
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 891e1487781..a76d09827f0 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -153,22 +153,19 @@ void MESH_OT_subdivide(wmOperatorType *ot)
}
-void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
+void EMBM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, BMEditMesh *em)
{
- Object *obedit = em->ob;
BMIter iter;
BMVert *eve;
- ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
-
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- float mval[2], co_proj[3], no_dummy[3];
+ float mval[2], vec[3], no_dummy[3];
int dist_dummy;
- if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (snapObjectsContext(C, mval, &dist_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) {
- mul_v3_m4v3(eve->co, obedit->imat, co_proj);
- }
+ mul_v3_m4v3(vec, obedit->obmat, eve->co);
+ ED_view3d_project_float_noclip(ar, vec, mval);
+ if (snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) {
+ mul_v3_m4v3(eve->co, obedit->imat, vec);
}
}
}
@@ -442,17 +439,16 @@ static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOpe
zero_v3(nor);
- /* XXX If those popup menus were to be enabled again, please get rid of this "menu string" syntax! */
if (em->selectmode & SCE_SELECT_VERTEX) {
if (em->bm->totvertsel == 0) nr = 0;
else if (em->bm->totvertsel == 1) nr = 4;
else if (em->bm->totedgesel == 0) nr = 4;
else if (em->bm->totfacesel == 0)
- nr = 3; /* pupmenu("Extrude %t|Only Edges %x3|Only Vertices %x4"); */
+ nr = 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
else if (em->bm->totfacesel == 1)
- nr = 1; /* pupmenu("Extrude %t|Region %x1|Only Edges% x3|Only Vertices %x4"); */
+ nr = 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
else
- nr = 1; /* pupmenu("Extrude %t|Region %x1|Individual Faces %x2|Only Edges %x3|Only Vertices %x4"); */
+ nr = 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
}
else if (em->selectmode & SCE_SELECT_EDGE) {
if (em->bm->totedgesel == 0) nr = 0;
@@ -462,16 +458,16 @@ static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOpe
else if (em->totedgesel == 1) nr = 3;
else if (em->totfacesel == 0) nr = 3;
else if (em->totfacesel == 1)
- nr = 1; /* pupmenu("Extrude %t|Region %x1|Only Edges %x3"); */
+ nr = 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
else
- nr = 1; /* pupmenu("Extrude %t|Region %x1|Individual Faces %x2|Only Edges %x3"); */
+ nr = 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
#endif
}
else {
if (em->bm->totfacesel == 0) nr = 0;
else if (em->bm->totfacesel == 1) nr = 1;
else
- nr = 1; /* pupmenu("Extrude %t|Region %x1|Individual Faces %x2"); */
+ nr = 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
}
if (nr < 1) return 'g';
@@ -734,10 +730,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
short use_proj;
em_setup_viewcontext(C, &vc);
-
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
-
-
+
use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
(vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
@@ -765,27 +758,27 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
done = FALSE;
BM_ITER_MESH (eed, &iter, vc.em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- float co1[2], co2[2];
-
- if ((ED_view3d_project_float_object(vc.ar, eed->v1->co, co1, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
- {
- /* 2D rotate by 90d while adding.
- * (x, y) = (y, -x)
- *
- * accumulate the screenspace normal in 2D,
- * with screenspace edge length weighting the result. */
- if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
- nor[0] += (co1[1] - co2[1]);
- nor[1] += -(co1[0] - co2[0]);
- }
- else {
- nor[0] += (co2[1] - co1[1]);
- nor[1] += -(co2[0] - co1[0]);
- }
- done = TRUE;
+ float co1[3], co2[3];
+ mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
+ mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
+ ED_view3d_project_float_noclip(vc.ar, co1, co1);
+ ED_view3d_project_float_noclip(vc.ar, co2, co2);
+
+ /* 2D rotate by 90d while adding.
+ * (x, y) = (y, -x)
+ *
+ * accumulate the screenspace normal in 2D,
+ * with screenspace edge length weighting the result. */
+ if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
+ nor[0] += (co1[1] - co2[1]);
+ nor[1] += -(co1[0] - co2[0]);
+ }
+ else {
+ nor[0] += (co2[1] - co1[1]);
+ nor[1] += -(co2[0] - co1[0]);
}
}
+ done = TRUE;
}
if (done) {
@@ -842,7 +835,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
/* also project the source, for retopo workflow */
if (use_proj)
- EMBM_project_snap_verts(C, vc.ar, vc.em);
+ EMBM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
}
edbm_extrude_edge(vc.obedit, vc.em, BM_ELEM_SELECT, nor);
@@ -875,7 +868,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
}
if (use_proj)
- EMBM_project_snap_verts(C, vc.ar, vc.em);
+ EMBM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
/* This normally happens when pushing undo but modal operators
* like this one don't push undo data until after modal mode is
@@ -2147,7 +2140,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op)
}
/* if those are not found, because vertices where selected by e.g.
- * border or circle select, find two selected vertices */
+ border or circle select, find two selected vertices */
if (svert == NULL) {
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
@@ -2157,7 +2150,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op)
else if (evert == NULL) evert = eve;
else {
/* more than two vertices are selected,
- * show warning message and cancel operator */
+ show warning message and cancel operator */
svert = evert = NULL;
break;
}
@@ -2533,6 +2526,11 @@ void MESH_OT_solidify(wmOperatorType *ot)
RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
}
+typedef struct CutCurve {
+ float x;
+ float y;
+} CutCurve;
+
/* ******************************************************************** */
/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail
* drawn by user.
@@ -2566,14 +2564,15 @@ static EnumPropertyItem knife_items[] = {
/* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */
-static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
- float (*mouse_path)[2], int len, char mode, int *isected)
+static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode,
+ struct GHash *gh, int *isected)
{
#define MAXSLOPE 100000
float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max;
float y2min, dist, lastdist = 0, xdiff2, xdiff1;
float m1, b1, m2, b2, x21, x22, y21, y22, xi;
float yi, x1min, x1max, y1max, y1min, perc = 0;
+ float *scr;
float threshold = 0.0;
int i;
@@ -2581,11 +2580,13 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
// XXX threshold = scene->toolsettings->select_thresh / 100;
/* Get screen coords of verts */
- x21 = sco_a[0];
- y21 = sco_a[1];
+ scr = BLI_ghash_lookup(gh, e->v1);
+ x21 = scr[0];
+ y21 = scr[1];
- x22 = sco_b[0];
- y22 = sco_b[1];
+ scr = BLI_ghash_lookup(gh, e->v2);
+ x22 = scr[0];
+ y22 = scr[1];
xdiff2 = (x22 - x21);
if (xdiff2) {
@@ -2607,11 +2608,11 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
y11 = y12;
}
else {
- x11 = mouse_path[i][0];
- y11 = mouse_path[i][1];
+ x11 = c[i].x;
+ y11 = c[i].y;
}
- x12 = mouse_path[i][0];
- y12 = mouse_path[i][1];
+ x12 = c[i].x;
+ y12 = c[i].y;
/* test e->v1 */
if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) {
@@ -2635,11 +2636,11 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
y11 = y12;
}
else {
- x11 = mouse_path[i][0];
- y11 = mouse_path[i][1];
+ x11 = c[i].x;
+ y11 = c[i].y;
}
- x12 = mouse_path[i][0];
- y12 = mouse_path[i][1];
+ x12 = c[i].x;
+ y12 = c[i].y;
/* Perp. Distance from point to line */
if (m2 != MAXSLOPE) dist = (y12 - m2 * x12 - b2); /* /sqrt(m2 * m2 + 1); Only looking for */
@@ -2717,9 +2718,9 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
lastdist = dist;
}
return perc;
-}
+}
-#define ELE_EDGE_CUT 1
+#define MAX_CUTS 2048
static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
{
@@ -2731,93 +2732,76 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
BMIter iter;
BMEdge *be;
BMOperator bmop;
+ CutCurve curve[MAX_CUTS];
+ struct GHash *gh;
float isect = 0.0f;
- int len = 0, isected, i;
+ float *scr, co[4];
+ int len = 0, isected;
short numcuts = 1, mode = RNA_int_get(op->ptr, "type");
-
- /* allocd vars */
- float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2];
/* edit-object needed for matrix, and ar->regiondata for projections to work */
if (ELEM3(NULL, obedit, ar, ar->regiondata))
return OPERATOR_CANCELLED;
if (bm->totvertsel < 2) {
- BKE_report(op->reports, RPT_ERROR, "No edges are selected to operate on");
- return OPERATOR_CANCELLED;
- }
-
- len = RNA_collection_length(op->ptr, "path");
-
- if (len < 2) {
- BKE_report(op->reports, RPT_ERROR, "Mouse path too short");
+ //error("No edges are selected to operate on");
return OPERATOR_CANCELLED;
}
- mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__);
-
/* get the cut curve */
RNA_BEGIN(op->ptr, itemptr, "path")
{
- RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]);
+ RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]);
+ len++;
+ if (len >= MAX_CUTS) {
+ break;
+ }
}
RNA_END;
-
- /* for ED_view3d_project_float_object */
- ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
-
- /* TODO, investigate using index lookup for screen_vert_coords() rather then a hash table */
+
+ if (len < 2) {
+ return OPERATOR_CANCELLED;
+ }
/* the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer */
- screen_vert_coords = sco = MEM_mallocN(bm->totvert * sizeof(float) * 2, __func__);
-
- BM_ITER_MESH_INDEX (bv, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
- copy_v2_fl(*sco, FLT_MAX); /* set error value */
- }
- BM_elem_index_set(bv, i); /* set_ok */
- sco++;
-
+ gh = BLI_ghash_ptr_new("knife cut exec");
+ for (bv = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); bv; bv = BM_iter_step(&iter)) {
+ scr = MEM_mallocN(sizeof(float) * 2, "Vertex Screen Coordinates");
+ copy_v3_v3(co, bv->co);
+ co[3] = 1.0f;
+ mul_m4_v4(obedit->obmat, co);
+ ED_view3d_project_float(ar, co, scr);
+ BLI_ghash_insert(gh, bv, scr);
}
- bm->elem_index_dirty &= ~BM_VERT; /* clear dirty flag */
if (!EDBM_op_init(em, &bmop, op, "subdivide_edges")) {
- MEM_freeN(mouse_path);
- MEM_freeN(screen_vert_coords);
return OPERATOR_CANCELLED;
}
/* store percentage of edge cut for KNIFE_EXACT here.*/
for (be = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be = BM_iter_step(&iter)) {
- int is_cut = FALSE;
if (BM_elem_flag_test(be, BM_ELEM_SELECT)) {
- const float *sco_a = screen_vert_coords[BM_elem_index_get(be->v1)];
- const float *sco_b = screen_vert_coords[BM_elem_index_get(be->v2)];
-
- /* check for error value (vert cant be projected) */
- if ((sco_a[0] != FLT_MAX) && (sco_b[0] != FLT_MAX)) {
- isect = bm_edge_seg_isect(sco_a, sco_b, mouse_path, len, mode, &isected);
-
- if (isect != 0.0f) {
- if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
- BMO_slot_map_float_insert(bm, &bmop,
- "edgepercents",
- be, isect);
- }
+ isect = bm_edge_seg_isect(be, curve, len, mode, gh, &isected);
+
+ if (isect != 0.0f) {
+ if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
+ BMO_slot_map_float_insert(bm, &bmop,
+ "edgepercents",
+ be, isect);
+
}
+ BMO_elem_flag_enable(bm, be, 1);
+ }
+ else {
+ BMO_elem_flag_disable(bm, be, 1);
}
}
-
- BMO_elem_flag_set(bm, be, ELE_EDGE_CUT, is_cut);
+ else {
+ BMO_elem_flag_disable(bm, be, 1);
+ }
}
-
-
- /* free all allocs */
- MEM_freeN(screen_vert_coords);
- MEM_freeN(mouse_path);
-
-
- BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, ELE_EDGE_CUT);
+
+ BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, 1);
if (mode == KNIFE_MIDPOINT) numcuts = 1;
BMO_slot_int_set(&bmop, "numcuts", numcuts);
@@ -2832,14 +2816,14 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
return OPERATOR_CANCELLED;
}
+
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
EDBM_update_generic(C, em, TRUE);
return OPERATOR_FINISHED;
}
-#undef ELE_EDGE_CUT
-
void MESH_OT_knife_cut(wmOperatorType *ot)
{
PropertyRNA *prop;