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_knife.c')
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c258
1 files changed, 118 insertions, 140 deletions
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 787b79f0d6e..621155bc696 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -209,6 +209,8 @@ typedef struct KnifeTool_OpData {
bool is_ortho;
float ortho_extent;
+ float ortho_extent_center[3];
+
float clipsta, clipend;
enum {
@@ -226,14 +228,8 @@ typedef struct KnifeTool_OpData {
/* use to check if we're currently dragging an angle snapped line */
bool is_angle_snapping;
-
- enum {
- ANGLE_FREE,
- ANGLE_0,
- ANGLE_45,
- ANGLE_90,
- ANGLE_135
- } angle_snapping;
+ bool angle_snapping;
+ float angle;
const float (*cagecos)[3];
} KnifeTool_OpData;
@@ -941,98 +937,66 @@ static void knife_finish_cut(KnifeTool_OpData *kcd)
static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
{
- bglMats mats;
- double u[3], u1[2], u2[2], v1[3], v2[3], dx, dy;
- double wminx, wminy, wmaxx, wmaxy;
-
- /* make u the window coords of prevcage */
- view3d_get_transformation(kcd->ar, kcd->vc.rv3d, kcd->ob, &mats);
- gluProject(kcd->prev.cage[0], kcd->prev.cage[1], kcd->prev.cage[2],
- mats.modelview, mats.projection, mats.viewport,
- &u[0], &u[1], &u[2]);
-
- /* make u1, u2 the points on window going through u at snap angle */
- wminx = kcd->ar->winrct.xmin;
- wmaxx = kcd->ar->winrct.xmin + kcd->ar->winx;
- wminy = kcd->ar->winrct.ymin;
- wmaxy = kcd->ar->winrct.ymin + kcd->ar->winy;
-
- switch (kcd->angle_snapping) {
- case ANGLE_0:
- u1[0] = wminx;
- u2[0] = wmaxx;
- u1[1] = u2[1] = u[1];
- break;
- case ANGLE_90:
- u1[0] = u2[0] = u[0];
- u1[1] = wminy;
- u2[1] = wmaxy;
- break;
- case ANGLE_45:
- /* clip against left or bottom */
- dx = u[0] - wminx;
- dy = u[1] - wminy;
- if (dy > dx) {
- u1[0] = wminx;
- u1[1] = u[1] - dx;
- }
- else {
- u1[0] = u[0] - dy;
- u1[1] = wminy;
- }
- /* clip against right or top */
- dx = wmaxx - u[0];
- dy = wmaxy - u[1];
- if (dy > dx) {
- u2[0] = wmaxx;
- u2[1] = u[1] + dx;
- }
- else {
- u2[0] = u[0] + dy;
- u2[1] = wmaxy;
- }
- break;
- case ANGLE_135:
- /* clip against right or bottom */
- dx = wmaxx - u[0];
- dy = u[1] - wminy;
- if (dy > dx) {
- u1[0] = wmaxx;
- u1[1] = u[1] - dx;
- }
- else {
- u1[0] = u[0] + dy;
- u1[1] = wminy;
- }
- /* clip against left or top */
- dx = u[0] - wminx;
- dy = wmaxy - u[1];
- if (dy > dx) {
- u2[0] = wminx;
- u2[1] = u[1] + dx;
- }
- else {
- u2[0] = u[0] - dy;
- u2[1] = wmaxy;
+ float v1[3], v2[3];
+ float planes[4][4];
+
+ planes_from_projmat(
+ (float (*)[4])kcd->projmat,
+ planes[2], planes[0], planes[3], planes[1], NULL, NULL);
+
+ /* ray-cast all planes */
+ {
+ float ray_dir[3];
+ float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
+ float lambda_best[2] = {-FLT_MAX, FLT_MAX};
+ int i;
+
+ /* we (sometimes) need the lines to be at the same depth before projecting */
+#if 0
+ sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
+#else
+ {
+ float curr_cage_adjust[3];
+ float co_depth[3];
+
+ copy_v3_v3(co_depth, kcd->prev.cage);
+ mul_m4_v3(kcd->ob->obmat, co_depth);
+ ED_view3d_win_to_3d(kcd->ar, co_depth, kcd->curr.mval, curr_cage_adjust);
+ mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
+
+ sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
+ }
+#endif
+
+ for (i = 0; i < 4; i++) {
+ float ray_hit[3];
+ float lambda_test;
+ if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
+ madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
+ if (lambda_test < 0.0f) {
+ if (lambda_test > lambda_best[0]) {
+ copy_v3_v3(ray_hit_best[0], ray_hit);
+ lambda_best[0] = lambda_test;
+ }
+ }
+ else {
+ if (lambda_test < lambda_best[1]) {
+ copy_v3_v3(ray_hit_best[1], ray_hit);
+ lambda_best[1] = lambda_test;
+ }
+ }
}
- break;
- default:
- return;
- }
+ }
- /* unproject u1 and u2 back into object space */
- gluUnProject(u1[0], u1[1], 0.0,
- mats.modelview, mats.projection, mats.viewport,
- &v1[0], &v1[1], &v1[2]);
- gluUnProject(u2[0], u2[1], 0.0,
- mats.modelview, mats.projection, mats.viewport,
- &v2[0], &v2[1], &v2[2]);
+ copy_v3_v3(v1, ray_hit_best[0]);
+ copy_v3_v3(v2, ray_hit_best[1]);
+ }
UI_ThemeColor(TH_TRANSFORM);
glLineWidth(2.0);
glBegin(GL_LINES);
- glVertex3dv(v1);
- glVertex3dv(v2);
+ glVertex3fv(v1);
+ glVertex3fv(v2);
glEnd();
}
@@ -1065,7 +1029,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glMultMatrixf(kcd->ob->obmat);
if (kcd->mode == MODE_DRAGGING) {
- if (kcd->angle_snapping != ANGLE_FREE)
+ if (kcd->is_angle_snapping)
knifetool_draw_angle_snapping(kcd);
glColor3ubv(kcd->colors.line);
@@ -1281,20 +1245,29 @@ static bool knife_ray_intersect_face(
return false;
}
-/* Calculate maximum excursion from (0,0,0) of mesh */
+/**
+ * Calculate the center and maximum excursion of mesh.
+ */
static void calc_ortho_extent(KnifeTool_OpData *kcd)
{
BMIter iter;
BMVert *v;
BMesh *bm = kcd->em->bm;
- float max_xyz = 0.0f;
- int i;
+ float min[3], max[3];
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- for (i = 0; i < 3; i++)
- max_xyz = max_ff(max_xyz, fabsf(v->co[i]));
+ INIT_MINMAX(min, max);
+
+ if (kcd->cagecos) {
+ minmax_v3v3_v3_array(min, max, kcd->cagecos, bm->totvert);
+ }
+ else {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, v->co);
+ }
}
- kcd->ortho_extent = max_xyz;
+
+ kcd->ortho_extent = len_v3v3(min, max) / 2;
+ mid_v3_v3v3(kcd->ortho_extent_center, min, max);
}
static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
@@ -1482,14 +1455,20 @@ static bool point_is_visible(
/* Clip the line (v1, v2) to planes perpendicular to it and distances d from
* the closest point on the line to the origin */
-static void clip_to_ortho_planes(float v1[3], float v2[3], float d)
+static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3], const float d)
{
- float closest[3];
- const float origin[3] = {0.0f, 0.0f, 0.0f};
+ float closest[3], dir[3];
+
+ sub_v3_v3v3(dir, v1, v2);
+ normalize_v3(dir);
+
+ /* could be v1 or v2 */
+ sub_v3_v3(v1, center);
+ project_plane_v3_v3v3(closest, v1, dir);
+ add_v3_v3(closest, center);
- closest_to_line_v3(closest, origin, v1, v2);
- dist_ensure_v3_v3fl(v1, closest, d);
- dist_ensure_v3_v3fl(v2, closest, d);
+ madd_v3_v3v3fl(v1, closest, dir, d);
+ madd_v3_v3v3fl(v2, closest, dir, -d);
}
static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
@@ -1573,8 +1552,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
if (kcd->ortho_extent == 0.0f)
calc_ortho_extent(kcd);
- clip_to_ortho_planes(v1, v3, kcd->ortho_extent + 10.0f);
- clip_to_ortho_planes(v2, v4, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v1, v3, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v2, v4, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
}
/* First use bvh tree to find faces, knife edges, and knife verts that might
@@ -2124,42 +2103,41 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
return NULL;
}
+/**
+ * Snaps a 2d vector to an angle, relative to \a v_ref.
+ */
+static float snap_v2_angle(float r[2], const float v[2], const float v_ref[2], float angle_snap)
+{
+ float m2[2][2];
+ float v_unit[2];
+ float angle, angle_delta;
+
+ BLI_ASSERT_UNIT_V2(v_ref);
+
+ normalize_v2_v2(v_unit, v);
+ angle = angle_signed_v2v2(v_unit, v_ref);
+ angle_delta = (roundf(angle / angle_snap) * angle_snap) - angle;
+ rotate_m2(m2, angle_delta);
+
+ mul_v2_m2v2(r, m2, v);
+ return angle + angle_delta;
+}
+
/* update both kcd->curr.mval and kcd->mval to snap to required angle */
static bool knife_snap_angle(KnifeTool_OpData *kcd)
{
- float dx, dy;
- float w, abs_tan;
+ const float dvec_ref[2] = {0.0f, 1.0f};
+ float dvec[2], dvec_snap[2];
+ float snap_step = DEG2RADF(45);
- dx = kcd->curr.mval[0] - kcd->prev.mval[0];
- dy = kcd->curr.mval[1] - kcd->prev.mval[1];
- if (dx == 0.0f && dy == 0.0f)
+ sub_v2_v2v2(dvec, kcd->curr.mval, kcd->prev.mval);
+ if (is_zero_v2(dvec)) {
return false;
-
- if (dx == 0.0f) {
- kcd->angle_snapping = ANGLE_90;
- kcd->curr.mval[0] = kcd->prev.mval[0];
}
- w = dy / dx;
- abs_tan = fabsf(w);
- if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */
- kcd->angle_snapping = ANGLE_0;
- kcd->curr.mval[1] = kcd->prev.mval[1];
- }
- else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */
- if (w > 0) {
- kcd->angle_snapping = ANGLE_45;
- kcd->curr.mval[1] = kcd->prev.mval[1] + dx;
- }
- else {
- kcd->angle_snapping = ANGLE_135;
- kcd->curr.mval[1] = kcd->prev.mval[1] - dx;
- }
- }
- else {
- kcd->angle_snapping = ANGLE_90;
- kcd->curr.mval[0] = kcd->prev.mval[0];
- }
+ kcd->angle = snap_v2_angle(dvec_snap, dvec, dvec_ref, snap_step);
+
+ add_v2_v2v2(kcd->curr.mval, kcd->prev.mval, dvec_snap);
copy_v2_v2(kcd->mval, kcd->curr.mval);
@@ -2175,7 +2153,7 @@ static int knife_update_active(KnifeTool_OpData *kcd)
/* view matrix may have changed, reproject */
knife_project_v2(kcd, kcd->prev.cage, kcd->prev.mval);
- if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) {
+ if (kcd->angle_snapping && (kcd->mode == MODE_DRAGGING)) {
kcd->is_angle_snapping = knife_snap_angle(kcd);
}
else {