Use curve twist for the CurveDeform modifier and bones (anything that uses curve_defo...
authorCampbell Barton <ideasman42@gmail.com>
Wed, 30 Sep 2009 23:31:10 +0000 (23:31 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 30 Sep 2009 23:31:10 +0000 (23:31 +0000)
So means minimum twist and twist smoothing are now used.

the Z up quaternion from the path is rotated to match the up axis given.

There was no logical rule for the up vector, some cases flipped the normals when used with the CurveDeform modifier.
Use the default X-Up behavior and match other settings with this. (comments explain this in detail).

- Interpolating quaternions didn't work in some cases, disabled for now.
- 'no_rot_axis' is different from in 2.4x since it now removes rotation from the tilt whereas before it edited the axis before calculating the tilt.

source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/lattice.c

index e943d92..bd77993 100644 (file)
@@ -280,17 +280,27 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat,
        if (quat) {
                float totfac, q1[4], q2[4];
 
+               /* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero
+                * to more then one index in data which can give divide by zero error */
+/*
                totfac= data[0]+data[1];
-               QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac);
+               if(totfac>0.000001)     QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac);
+               else                            QUATCOPY(q1, p1->quat);
+
                NormalQuat(q1);
 
                totfac= data[2]+data[3];
-               QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac);
+               if(totfac>0.000001)     QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac);
+               else                            QUATCOPY(q1, p3->quat);
                NormalQuat(q2);
 
                totfac = data[0]+data[1]+data[2]+data[3];
-               QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac);
+               if(totfac>0.000001)     QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac);
+               else                            QUATCOPY(quat, q2);
                NormalQuat(quat);
+               */
+               // XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases.
+               QUATCOPY(quat, p1->quat);
        }
 
        if(radius)
index 730a12b..a957be4 100644 (file)
@@ -524,30 +524,13 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir,
 static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp)
 {
        Curve *cu= par->data;
-       float fac, loc[4], dir[3], cent[3], radius;
-       short upflag, index;
-       
-       if(axis==MOD_CURVE_POSX || axis==MOD_CURVE_NEGX) {
-               upflag= OB_POSZ;
-               cent[0]= 0.0;
-               cent[1]= co[1];
-               cent[2]= co[2];
-               index= 0;
-       }
-       else if(axis==MOD_CURVE_POSY || axis==MOD_CURVE_NEGY) {
-               upflag= OB_POSZ;
-               cent[0]= co[0];
-               cent[1]= 0.0;
-               cent[2]= co[2];
-               index= 1;
-       }
-       else {
-               upflag= OB_POSY;
-               cent[0]= co[0];
-               cent[1]= co[1];
-               cent[2]= 0.0;
-               index= 2;
-       }
+       float fac, loc[4], dir[3], new_quat[4], radius;
+       short /*upflag, */ index;
+
+       index= axis-1;
+       if(index>2)
+               index -= 3; /* negative  */
+
        /* to be sure, mostly after file load */
        if(cu->path==NULL) {
                makeDispListCurveTypes(scene, par, 0);
@@ -555,7 +538,7 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
        }
        
        /* options */
-       if(ELEM3(axis, OB_NEGX, OB_NEGY, OB_NEGZ)) {
+       if(ELEM3(axis, OB_NEGX+1, OB_NEGY+1, OB_NEGZ+1)) { /* OB_NEG# 0-5, MOD_CURVE_POS# 1-6 */
                if(cu->flag & CU_STRETCH)
                        fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]);
                else
@@ -579,9 +562,10 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
        }
 #endif // XXX old animation system
        
-       if( where_on_path_deform(par, fac, loc, dir, NULL, &radius)) {  /* returns OK */
-               float q[4], mat[3][3], quat[4];
-               
+       if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) {      /* returns OK */
+               float quat[4], cent[3];
+
+#if 0  // XXX - 2.4x Z-Up, Now use bevel tilt.
                if(cd->no_rot_axis)     /* set by caller */
                        dir[cd->no_rot_axis-1]= 0.0f;
                
@@ -597,22 +581,104 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
                        q[2]= -fac*dir[1];
                        q[3]= -fac*dir[2];
                        QuatMul(quat, q, quat);
-               }               
-               QuatToMat3(quat, mat);
-
-               if(cu->flag & CU_PATH_RADIUS) {
-                       float tmat[3][3], rmat[3][3];
-                       Mat3Scale(tmat, radius);
-                       Mat3MulMat3(rmat, mat, tmat);
-                       Mat3CpyMat3(mat, rmat);
                }
+#endif
 
-               /* local rotation */
-               Mat3MulVecfl(mat, cent);
+
+               static float q_x90d[4] = {0.70710676908493, 0.70710676908493, 0.0, 0.0};        // float rot_axis[3]= {1,0,0}; AxisAngleToQuat(q, rot_axis, 90 * (M_PI / 180));
+               static float q_y90d[4] = {0.70710676908493, 0.0, 0.70710676908493, 0.0};        // float rot_axis[3]= {0,1,0}; AxisAngleToQuat(q, rot_axis, 90 * (M_PI / 180));
+               static float q_z90d[4] = {0.70710676908493, 0.0, 0.0, 0.70710676908493};        // float rot_axis[3]= {0,0,2}; AxisAngleToQuat(q, rot_axis, 90 * (M_PI / 180));
+
+               static float q_nx90d[4] = {0.70710676908493, -0.70710676908493, 0.0, 0.0};      // float rot_axis[3]= {1,0,0}; AxisAngleToQuat(q, rot_axis, -90 * (M_PI / 180));
+               static float q_ny90d[4] = {0.70710676908493, 0.0, -0.70710676908493, 0.0};      // float rot_axis[3]= {0,1,0}; AxisAngleToQuat(q, rot_axis, -90 * (M_PI / 180));
+               static float q_nz90d[4] = {0.70710676908493, 0.0, 0.0, -0.70710676908493};      // float rot_axis[3]= {0,0,2}; AxisAngleToQuat(q, rot_axis, -90 * (M_PI / 180));
+
+
+               if(cd->no_rot_axis) {   /* set by caller */
+
+                       /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather then
+                        * changing the axis before calculating the tilt but serves much the same purpose */
+                       float dir_flat[3]={0,0,0}, q[4];
+                       VECCOPY(dir_flat, dir);
+                       dir_flat[cd->no_rot_axis-1]= 0.0f;
+
+                       Normalize(dir);
+                       Normalize(dir_flat);
+
+                       RotationBetweenVectorsToQuat(q, dir, dir_flat); /* Could this be done faster? */
+
+                       QuatMul(new_quat, q, new_quat);
+               }
+
+
+               /* Logic for 'cent' orientation *
+                *
+                * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
+                *
+                * Use a curve modifier to stretch a cube out, color each side RGB, positive side light, negative dark.
+                * view with X up (default), from the angle that you can see 3 faces RGB colors (light), anti-clockwise
+                * Notice X,Y,Z Up all have light colors and each ordered CCW.
+                *
+                * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
+                * */
+
+               switch(axis) {
+               case MOD_CURVE_POSX:
+                       QuatMul(quat, new_quat, q_y90d);
+
+                       cent[0]=  0.0;
+                       cent[1]=  co[2];
+                       cent[2]=  co[1];
+                       break;
+               case MOD_CURVE_NEGX:
+                       QuatMul(quat, new_quat, q_ny90d);
+
+                       cent[0]=  0.0;
+                       cent[1]= -co[1];
+                       cent[2]=  co[2];
+
+                       break;
+               case MOD_CURVE_POSY:
+                       QuatMul(quat, new_quat, q_x90d);
+
+                       cent[0]=  co[2];
+                       cent[1]=  0.0;
+                       cent[2]= -co[0];
+                       break;
+               case MOD_CURVE_NEGY:
+                       QuatMul(quat, new_quat, q_nx90d);
+
+                       cent[0]= -co[0];
+                       cent[1]=  0.0;
+                       cent[2]= -co[2];
+                       break;
+               case MOD_CURVE_POSZ:
+                       QuatMul(quat, new_quat, q_z90d);
+
+                       cent[0]=  co[1];
+                       cent[1]= -co[0];
+                       cent[2]=  0.0;
+                       break;
+               case MOD_CURVE_NEGZ:
+                       QuatMul(quat, new_quat, q_nz90d);
+
+                       cent[0]=  co[0];
+                       cent[1]= -co[1];
+                       cent[2]=  0.0;
+                       break;
+               }
+
+               /* scale if enabled */
+               if(cu->flag & CU_PATH_RADIUS)
+                       VecMulf(cent, radius);
                
+               /* local rotation */
+               NormalQuat(quat);
+               QuatMulVecf(quat, cent);
+
                /* translation */
                VECADD(co, cent, loc);
-               
+
                if(quatp)
                        QUATCOPY(quatp, quat);