Merged changes in the trunk up to revision 28536.
[blender.git] / source / blender / editors / transform / transform.c
index df024a4b3d9cbbec6efa93674e9cd6825812c370..bdf9203961900073ec54f33a907f5ed7a0105dae 100644 (file)
 #include <math.h>
 #include <float.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #ifndef WIN32
 #include <unistd.h>
 #else
@@ -1925,39 +1921,50 @@ static void constraintTransLim(TransInfo *t, TransData *td)
        }
 }
 
+static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
+{
+       /* Make a temporary bConstraintOb for use by limit constraints
+        *      - they only care that cob->matrix is correctly set ;-)
+        *      - current space should be local
+        */
+       memset(cob, 0, sizeof(bConstraintOb));
+       if (td->rotOrder == ROT_MODE_QUAT) {
+               /* quats */
+               if (td->ext) {
+                       /* objects and bones do normalization first too, otherwise
+                          we don't necessarily end up with a rotation matrix, and
+                          then conversion back to quat gives a different result */
+                       float quat[4];
+                       copy_qt_qt(quat, td->ext->quat);
+                       normalize_qt(quat);
+                       quat_to_mat4(cob->matrix, quat);
+               }
+               else
+                       return;
+       }
+       else if (td->rotOrder == ROT_MODE_AXISANGLE) {
+               /* axis angle */
+               if (td->ext)
+                       axis_angle_to_mat4(cob->matrix, &td->ext->quat[1], td->ext->quat[0]);
+               else
+                       return;
+       }
+       else {
+               /* eulers */
+               if (td->ext)
+                       eulO_to_mat4(cob->matrix, td->ext->rot, td->rotOrder);
+               else
+                       return;
+       }
+}
+
 static void constraintRotLim(TransInfo *t, TransData *td)
 {
        if (td->con) {
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
                bConstraintOb cob;
                bConstraint *con;
-
-               /* Make a temporary bConstraintOb for using these limit constraints
-                *      - they only care that cob->matrix is correctly set ;-)
-                *      - current space should be local
-                */
-               memset(&cob, 0, sizeof(bConstraintOb));
-               if (td->rotOrder == ROT_MODE_QUAT) {
-                       /* quats */
-                       if (td->ext)
-                               quat_to_mat4( cob.matrix,td->ext->quat);
-                       else
-                               return;
-               }
-               else if (td->rotOrder == ROT_MODE_AXISANGLE) {
-                       /* axis angle */
-                       if (td->ext)
-                               axis_angle_to_mat4( cob.matrix,&td->ext->quat[1], td->ext->quat[0]);
-                       else
-                               return;
-               }
-               else {
-                       /* eulers */
-                       if (td->ext)
-                               eulO_to_mat4( cob.matrix,td->ext->rot, td->rotOrder);
-                       else
-                               return;
-               }
+               int dolimit = 0;
                
                /* Evaluate valid constraints */
                for (con= td->con; con; con= con->next) {
@@ -1973,6 +1980,16 @@ static void constraintRotLim(TransInfo *t, TransData *td)
                                /* only use it if it's tagged for this purpose */
                                if ((data->flag2 & LIMIT_TRANSFORM)==0)
                                        continue;
+
+                               /* skip incompatable spacetypes */
+                               if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL))
+                                       continue;
+
+                               /* only do conversion if necessary, to preserve quats and eulers */
+                               if(!dolimit) {
+                                       constraintob_from_transdata(&cob, td);
+                                       dolimit= 1;
+                               }
                                
                                /* do space conversions */
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
@@ -1980,10 +1997,6 @@ static void constraintRotLim(TransInfo *t, TransData *td)
                                        copy_m4_m4(tmat, cob.matrix);
                                        mul_m4_m3m4(cob.matrix, td->mtx, tmat);
                                }
-                               else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
-                                       /* skip... incompatable spacetype */
-                                       continue;
-                               }
                                
                                /* do constraint */
                                cti->evaluate_constraint(con, &cob, NULL);
@@ -1997,18 +2010,20 @@ static void constraintRotLim(TransInfo *t, TransData *td)
                        }
                }
                
-               /* copy results from cob->matrix */
-               if (td->rotOrder == ROT_MODE_QUAT) {
-                       /* quats */
-                       mat4_to_quat( td->ext->quat,cob.matrix);
-               }
-               else if (td->rotOrder == ROT_MODE_AXISANGLE) {
-                       /* axis angle */
-                       mat4_to_axis_angle( &td->ext->quat[1], &td->ext->quat[0],cob.matrix);
-               }
-               else {
-                       /* eulers */
-                       mat4_to_eulO( td->ext->rot, td->rotOrder,cob.matrix);
+               if(dolimit) {
+                       /* copy results from cob->matrix */
+                       if (td->rotOrder == ROT_MODE_QUAT) {
+                               /* quats */
+                               mat4_to_quat( td->ext->quat,cob.matrix);
+                       }
+                       else if (td->rotOrder == ROT_MODE_AXISANGLE) {
+                               /* axis angle */
+                               mat4_to_axis_angle( &td->ext->quat[1], &td->ext->quat[0],cob.matrix);
+                       }
+                       else {
+                               /* eulers */
+                               mat4_to_eulO( td->ext->rot, td->rotOrder,cob.matrix);
+                       }
                }
        }
 }
@@ -2130,7 +2145,7 @@ void initWarp(TransInfo *t)
                VECCOPY(center, t->data[i].center);
                mul_m3_v3(t->data[i].mtx, center);
                mul_m4_v3(t->viewmat, center);
-               sub_v3_v3v3(center, center, t->viewmat[3]);
+               sub_v3_v3(center, t->viewmat[3]);
                if (i)
                        minmax_v3_v3v3(min, max, center);
                else {
@@ -2186,12 +2201,12 @@ int Warp(TransInfo *t, short mval[2])
        VECCOPY(cursor, curs);
        VECCOPY(gcursor, cursor);
        if (t->flag & T_EDIT) {
-               sub_v3_v3v3(cursor, cursor, t->obedit->obmat[3]);
-               sub_v3_v3v3(gcursor, gcursor, t->obedit->obmat[3]);
+               sub_v3_v3(cursor, t->obedit->obmat[3]);
+               sub_v3_v3(gcursor, t->obedit->obmat[3]);
                mul_m3_v3(t->data->smtx, gcursor);
        }
        mul_m4_v3(t->viewmat, cursor);
-       sub_v3_v3v3(cursor, cursor, t->viewmat[3]);
+       sub_v3_v3(cursor, t->viewmat[3]);
        
        /* amount of radians for warp */
        circumfac = t->values[0];
@@ -2230,7 +2245,7 @@ int Warp(TransInfo *t, short mval[2])
                VECCOPY(vec, td->iloc);
                mul_m3_v3(td->mtx, vec);
                mul_m4_v3(t->viewmat, vec);
-               sub_v3_v3v3(vec, vec, t->viewmat[3]);
+               sub_v3_v3(vec, t->viewmat[3]);
                
                dist= vec[0]-cursor[0];
                
@@ -2246,10 +2261,10 @@ int Warp(TransInfo *t, short mval[2])
                loc[2]= vec[2];
                
                mul_m4_v3(t->viewinv, loc);
-               sub_v3_v3v3(loc, loc, t->viewinv[3]);
+               sub_v3_v3(loc, t->viewinv[3]);
                mul_m3_v3(td->smtx, loc);
                
-               sub_v3_v3v3(loc, loc, td->iloc);
+               sub_v3_v3(loc, td->iloc);
                mul_v3_fl(loc, td->factor);
                add_v3_v3v3(td->loc, td->iloc, loc);
        }
@@ -2374,8 +2389,8 @@ int Shear(TransInfo *t, short mval[2])
                
                mul_m3_v3(tmat, vec);
                
-               add_v3_v3v3(vec, vec, t->center);
-               sub_v3_v3v3(vec, vec, td->center);
+               add_v3_v3(vec, t->center);
+               sub_v3_v3(vec, td->center);
                
                mul_v3_fl(vec, td->factor);
                
@@ -2554,11 +2569,11 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
        
        mul_m3_v3(tmat, vec);
        
-       add_v3_v3v3(vec, vec, center);
+       add_v3_v3(vec, center);
        if (t->flag & T_POINTS)
-               sub_v3_v3v3(vec, vec, td->iloc);
+               sub_v3_v3(vec, td->iloc);
        else
-               sub_v3_v3v3(vec, vec, td->center);
+               sub_v3_v3(vec, td->center);
        
        mul_v3_fl(vec, td->factor);
        
@@ -2846,7 +2861,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                        mul_m3_v3(mat, vec);            // Applying rotation
                        mul_m3_v3(imtx, vec);   // To Local space
                        
-                       add_v3_v3v3(vec, vec, center);
+                       add_v3_v3(vec, center);
                        /* vec now is the location where the object has to be */
                        
                        sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
@@ -2918,9 +2933,9 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
                        /* translation */
                        sub_v3_v3v3(vec, td->center, center);
                        mul_m3_v3(mat, vec);
-                       add_v3_v3v3(vec, vec, center);
+                       add_v3_v3(vec, center);
                        /* vec now is the location where the object has to be */
-                       sub_v3_v3v3(vec, vec, td->center);
+                       sub_v3_v3(vec, td->center);
                        mul_m3_v3(td->smtx, vec);
                        
                        protectedTransBits(td->protectflag, vec);
@@ -3672,7 +3687,7 @@ int PushPull(TransInfo *t, short mval[2])
                        if (isLockConstraint(t)) {
                                float dvec[3];
                                project_v3_v3v3(dvec, vec, axis);
-                               sub_v3_v3v3(vec, vec, dvec);
+                               sub_v3_v3(vec, dvec);
                        }
                        else {
                                project_v3_v3v3(vec, vec, axis);
@@ -4467,7 +4482,7 @@ static int createSlideVerts(TransInfo *t)
                                        sub_v3_v3v3(vec, co2, co);
                                }
 
-                               add_v3_v3v3(start, start, vec);
+                               add_v3_v3(start, vec);
 
                                if (v3d) {
                                        view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat);
@@ -4480,7 +4495,7 @@ static int createSlideVerts(TransInfo *t)
                                        sub_v3_v3v3(vec, co, co2);
                                }
 
-                               add_v3_v3v3(end, end, vec);
+                               add_v3_v3(end, vec);
 
                                totvec += 1.0f;
                                nearest = (EditVert*)look->link;
@@ -4492,7 +4507,7 @@ static int createSlideVerts(TransInfo *t)
                look = look->next;
        }
 
-       add_v3_v3v3(start, start, end);
+       add_v3_v3(start, end);
        mul_v3_fl(start, 0.5*(1.0/totvec));
        VECCOPY(vec, start);
        start[0] = t->mval[0];