fix [#36282] Spin error with non uniform scale
authorCampbell Barton <ideasman42@gmail.com>
Fri, 26 Jul 2013 11:15:22 +0000 (11:15 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 26 Jul 2013 11:15:22 +0000 (11:15 +0000)
add support for passing object matrix to bmesh transform operators.

source/blender/blenlib/BLI_math_matrix.h
source/blender/blenlib/intern/math_matrix.c
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/operators/bmo_dupe.c
source/blender/bmesh/operators/bmo_utils.c
source/blender/editors/mesh/editmesh_extrude.c

index 1d877be67bd689e4c2580ea628d3798476e5a3b6..a4b0f449dc3242a62e2298d5d8ecee33c37b3102 100644 (file)
@@ -133,12 +133,12 @@ void normalize_m4_m4(float R[4][4], float A[4][4]);
 void orthogonalize_m3(float R[3][3], int axis);
 void orthogonalize_m4(float R[4][4], int axis);
 
-int is_orthogonal_m3(float mat[3][3]);
-int is_orthogonal_m4(float mat[4][4]);
-int is_orthonormal_m3(float mat[3][3]);
-int is_orthonormal_m4(float mat[4][4]);
+bool is_orthogonal_m3(float mat[3][3]);
+bool is_orthogonal_m4(float mat[4][4]);
+bool is_orthonormal_m3(float mat[3][3]);
+bool is_orthonormal_m4(float mat[4][4]);
 
-int is_uniform_scaled_m3(float mat[3][3]);
+bool is_uniform_scaled_m3(float mat[3][3]);
 
 void adjoint_m2_m2(float R[2][2], float A[2][2]);
 void adjoint_m3_m3(float R[3][3], float A[3][3]);
@@ -194,8 +194,11 @@ void loc_axisangle_size_to_mat4(float R[4][4],
 void blend_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
 void blend_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
 
-int is_negative_m3(float mat[3][3]);
-int is_negative_m4(float mat[4][4]);
+bool is_negative_m3(float mat[3][3]);
+bool is_negative_m4(float mat[4][4]);
+
+bool is_zero_m3(float mat[3][3]);
+bool is_zero_m4(float mat[4][4]);
 
 /*********************************** Other ***********************************/
 
index 3f635f97ec0ae62e71fc63d5d96b09bd55902fba..8565698110e26fc6fe396431465ba9f9ab354d4e 100644 (file)
@@ -930,7 +930,7 @@ void orthogonalize_m4(float mat[4][4], int axis)
        mul_v3_fl(mat[2], size[2]);
 }
 
-int is_orthogonal_m3(float m[3][3])
+bool is_orthogonal_m3(float m[3][3])
 {
        int i, j;
 
@@ -944,7 +944,7 @@ int is_orthogonal_m3(float m[3][3])
        return 1;
 }
 
-int is_orthogonal_m4(float m[4][4])
+bool is_orthogonal_m4(float m[4][4])
 {
        int i, j;
 
@@ -959,7 +959,7 @@ int is_orthogonal_m4(float m[4][4])
        return 1;
 }
 
-int is_orthonormal_m3(float m[3][3])
+bool is_orthonormal_m3(float m[3][3])
 {
        if (is_orthogonal_m3(m)) {
                int i;
@@ -974,7 +974,7 @@ int is_orthonormal_m3(float m[3][3])
        return 0;
 }
 
-int is_orthonormal_m4(float m[4][4])
+bool is_orthonormal_m4(float m[4][4])
 {
        if (is_orthogonal_m4(m)) {
                int i;
@@ -989,7 +989,7 @@ int is_orthonormal_m4(float m[4][4])
        return 0;
 }
 
-int is_uniform_scaled_m3(float m[3][3])
+bool is_uniform_scaled_m3(float m[3][3])
 {
        const float eps = 1e-7;
        float t[3][3];
@@ -1434,20 +1434,34 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
        loc_quat_size_to_mat4(out, floc, fquat, fsize);
 }
 
-int is_negative_m3(float mat[3][3])
+bool is_negative_m3(float mat[3][3])
 {
        float vec[3];
        cross_v3_v3v3(vec, mat[0], mat[1]);
        return (dot_v3v3(vec, mat[2]) < 0.0f);
 }
 
-int is_negative_m4(float mat[4][4])
+bool is_negative_m4(float mat[4][4])
 {
        float vec[3];
        cross_v3_v3v3(vec, mat[0], mat[1]);
        return (dot_v3v3(vec, mat[2]) < 0.0f);
 }
 
+bool is_zero_m3(float mat[3][3])
+{
+       return (is_zero_v3(mat[0]) &&
+               is_zero_v3(mat[1]) &&
+               is_zero_v3(mat[2]));
+}
+bool is_zero_m4(float mat[4][4])
+{
+       return (is_zero_v4(mat[0]) &&
+               is_zero_v4(mat[1]) &&
+               is_zero_v4(mat[2]) &&
+               is_zero_v4(mat[3]));
+}
+
 /* make a 4x4 matrix out of 3 transform components */
 /* matrices are made in the order: scale * rot * loc */
 /* TODO: need to have a version that allows for rotation order... */
index 451d4a37a00c97f79cfe880cf1c08a4542bc93dc..b56ed15b901d58026d0947d23bf208695ffb5f1e 100644 (file)
@@ -663,6 +663,7 @@ static BMOpDefine bmo_rotate_def = {
        {{"cent",            BMO_OP_SLOT_VEC},  /* center of rotation */
         {"matrix",          BMO_OP_SLOT_MAT},  /* matrix defining rotation */
         {"verts",           BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
+        {"space",           BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
         {{'\0'}},
        },
        {{{'\0'}}},  /* no output */
@@ -679,6 +680,7 @@ static BMOpDefine bmo_translate_def = {
        "translate",
        /* slots_in */
        {{"vec", BMO_OP_SLOT_VEC},  /* translation offset */
+        {"space", BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
         {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
         {{'\0'}},
        },
@@ -696,6 +698,7 @@ static BMOpDefine bmo_scale_def = {
        "scale",
        /* slots_in */
        {{"vec", BMO_OP_SLOT_VEC},  /* scale factor */
+        {"space", BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
         {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
         {{'\0'}},
        },
@@ -715,6 +718,7 @@ static BMOpDefine bmo_transform_def = {
        "transform",
        /* slots_in */
        {{"matrix",          BMO_OP_SLOT_MAT},  /* transform matrix */
+        {"space",           BMO_OP_SLOT_MAT},  /* matrix to define the space (typically object matrix) */
         {"verts",           BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},  /* input vertices */
         {{'\0'}},
        },
@@ -1159,6 +1163,7 @@ static BMOpDefine bmo_spin_def = {
         {"axis", BMO_OP_SLOT_VEC},             /* rotation axis */
         {"dvec", BMO_OP_SLOT_VEC},             /* translation delta per step */
         {"angle", BMO_OP_SLOT_FLT},            /* total rotation angle (radians) */
+        {"space", BMO_OP_SLOT_MAT},            /* matrix to define the space (typically object matrix) */
         {"steps", BMO_OP_SLOT_INT},            /* number of steps */
         {"use_duplicate", BMO_OP_SLOT_BOOL},   /* duplicate or extrude? */
         {{'\0'}},
index 481039694740db1a535a2f5b165289d5346512bf..59e018eccf136c22a7fd086fe79eae5649b50920 100644 (file)
@@ -489,8 +489,8 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
                        BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out");
                        BMO_op_exec(bm, &dupop);
                        BMO_op_callf(bm, op->flag,
-                                    "rotate cent=%v matrix=%m3 verts=%S",
-                                    cent, rmat, &dupop, "geom.out");
+                                    "rotate cent=%v matrix=%m3 space=%s verts=%S",
+                                    cent, rmat, op, "space", &dupop, "geom.out");
                        BMO_slot_copy(&dupop, slots_out, "geom.out",
                                      op,     slots_out, "geom_last.out");
                        BMO_op_finish(bm, &dupop);
@@ -500,8 +500,8 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
                                     op, "geom_last.out");
                        BMO_op_exec(bm, &extop);
                        BMO_op_callf(bm, op->flag,
-                                    "rotate cent=%v matrix=%m3 verts=%S",
-                                    cent, rmat, &extop, "geom.out");
+                                    "rotate cent=%v matrix=%m3 space=%s verts=%S",
+                                    cent, rmat, op, "space", &extop, "geom.out");
                        BMO_slot_copy(&extop, slots_out, "geom.out",
                                      op,     slots_out, "geom_last.out");
                        BMO_op_finish(bm, &extop);
@@ -510,8 +510,8 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
                if (usedvec) {
                        mul_m3_v3(rmat, dvec);
                        BMO_op_callf(bm, op->flag,
-                                    "translate vec=%v verts=%S",
-                                    dvec, op, "geom_last.out");
+                                    "translate vec=%v space=%s verts=%S",
+                                    dvec, op, "space", op, "geom_last.out");
                }
        }
 }
index 053e4da6e022e546b62e62ca1d930271d0e5662d..85bd8a853765e900b8438bbcf8cb2d3d88b1bdbc 100644 (file)
@@ -55,9 +55,15 @@ void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op)
 {
        BMOIter iter;
        BMVert *v;
-       float mat[4][4];
+       float mat[4][4], mat_space[4][4], imat_space[4][4];
 
        BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+       BMO_slot_mat4_get(op->slots_in, "space", mat_space);
+
+       if (!is_zero_m4(mat_space)) {
+               invert_m4_m4(imat_space, mat_space);
+               mul_serie_m4(mat, imat_space, mat, mat_space, NULL, NULL, NULL, NULL, NULL);
+       }
 
        BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) {
                mul_m4_v3(mat, v->co);
@@ -73,7 +79,7 @@ void bmo_translate_exec(BMesh *bm, BMOperator *op)
        unit_m4(mat);
        copy_v3_v3(mat[3], vec);
 
-       BMO_op_callf(bm, op->flag, "transform matrix=%m4 verts=%s", mat, op, "verts");
+       BMO_op_callf(bm, op->flag, "transform matrix=%m4 space=%s verts=%s", mat, op, "space", op, "verts");
 }
 
 void bmo_scale_exec(BMesh *bm, BMOperator *op)
@@ -87,7 +93,7 @@ void bmo_scale_exec(BMesh *bm, BMOperator *op)
        mat[1][1] = vec[1];
        mat[2][2] = vec[2];
 
-       BMO_op_callf(bm, op->flag, "transform matrix=%m3 verts=%s", mat, op, "verts");
+       BMO_op_callf(bm, op->flag, "transform matrix=%m3 space=%s verts=%s", mat, op, "space", op, "verts");
 }
 
 void bmo_rotate_exec(BMesh *bm, BMOperator *op)
@@ -99,7 +105,7 @@ void bmo_rotate_exec(BMesh *bm, BMOperator *op)
        BMO_slot_mat4_get(op->slots_in, "matrix", mat);
        pivot_m4(mat, center);
 
-       BMO_op_callf(bm, op->flag, "transform matrix=%m4 verts=%s", mat, op, "verts");
+       BMO_op_callf(bm, op->flag, "transform matrix=%m4 space=%s verts=%s", mat, op, "space", op, "verts");
 }
 
 void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op)
index 65c528dbe03738b517177485ad7939828dffc906..b38f09b1dec7cf5e05528644d54121ee7926a0fb 100644 (file)
@@ -713,7 +713,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op)
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
        BMesh *bm = em->bm;
        BMOperator spinop;
-       float cent[3], axis[3], imat[3][3];
+       float cent[3], axis[3];
        float d[3] = {0.0f, 0.0f, 0.0f};
        int steps, dupli;
        float angle;
@@ -726,15 +726,10 @@ static int edbm_spin_exec(bContext *C, wmOperator *op)
        angle = -angle;
        dupli = RNA_boolean_get(op->ptr, "dupli");
 
-       /* undo object transformation */
-       copy_m3_m4(imat, obedit->imat);
-       sub_v3_v3(cent, obedit->obmat[3]);
-       mul_m3_v3(imat, cent);
-       mul_m3_v3(imat, axis);
-
+       /* keep the values in worldspace since we're passing the obmat */
        if (!EDBM_op_init(em, &spinop, op,
-                         "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b",
-                         BM_ELEM_SELECT, cent, axis, d, steps, angle, dupli))
+                         "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 use_duplicate=%b",
+                         BM_ELEM_SELECT, cent, axis, d, steps, angle, obedit->obmat, dupli))
        {
                return OPERATOR_CANCELLED;
        }
@@ -800,8 +795,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
        BMVert *eve, *v1, *v2;
        BMIter iter, eiter;
        BMOperator spinop;
-       float dvec[3], nor[3], cent[3], axis[3];
-       float imat[3][3];
+       float dvec[3], nor[3], cent[3], axis[3], v1_co_global[3], v2_co_global[3];
        int steps, turns;
        int valence;
 
@@ -811,13 +805,6 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
        RNA_float_get_array(op->ptr, "center", cent);
        RNA_float_get_array(op->ptr, "axis", axis);
 
-       /* undo object transformation */
-       copy_m3_m4(imat, obedit->imat);
-       sub_v3_v3(cent, obedit->obmat[3]);
-       mul_m3_v3(imat, cent);
-       mul_m3_v3(imat, axis);
-
-
        /* find two vertices with valence count == 1, more or less is wrong */
        v1 = NULL;
        v2 = NULL;
@@ -850,15 +837,17 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
        }
 
        /* calculate dvec */
-       sub_v3_v3v3(dvec, v1->co, v2->co);
+       mul_v3_m4v3(v1_co_global, obedit->obmat, v1->co);
+       mul_v3_m4v3(v2_co_global, obedit->obmat, v2->co);
+       sub_v3_v3v3(dvec, v1_co_global, v2_co_global);
        mul_v3_fl(dvec, 1.0f / steps);
 
-       if (dot_v3v3(nor, dvec) > 0.000f)
+       if (dot_v3v3(nor, dvec) > 0.0f)
                negate_v3(dvec);
 
        if (!EDBM_op_init(em, &spinop, op,
-                         "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b",
-                         BM_ELEM_SELECT, cent, axis, dvec, turns * steps, DEG2RADF(360.0f * turns), false))
+                         "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f space=%m4 use_duplicate=%b",
+                         BM_ELEM_SELECT, cent, axis, dvec, turns * steps, DEG2RADF(360.0f * turns), obedit->obmat, false))
        {
                return OPERATOR_CANCELLED;
        }