svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r22935:23022
authorCampbell Barton <ideasman42@gmail.com>
Mon, 7 Sep 2009 08:31:03 +0000 (08:31 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 7 Sep 2009 08:31:03 +0000 (08:31 +0000)
looks like 2 merges are needed to skip a commit.

source/blender/blenkernel/intern/curve.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/intern/arithb.c
source/blender/makesdna/DNA_curve_types.h

index 7dd868278f4c2f71716fcd8c7aec88d9aeb44a06..228523aa661c554201b30d07230d07cb76f911ee 100644 (file)
@@ -1550,7 +1550,7 @@ void makeBevelList(Object *ob)
        BPoint *bp;
        BevList *bl, *blnew, *blnext;
        BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
-       float min, inp, x1, x2, y1, y2, vec[3];
+       float min, inp, x1, x2, y1, y2, vec[3], vec_prev[3], q[4], quat[4], quat_prev[4], cross[3];
        float *coord_array, *tilt_array=NULL, *radius_array=NULL, *coord_fp, *tilt_fp=NULL, *radius_fp=NULL;
        float *v1, *v2;
        struct bevelsort *sortdata, *sd, *sd1;
@@ -1909,7 +1909,10 @@ void makeBevelList(Object *ob)
        bl= cu->bev.first;
        while(bl) {
        
-               if(bl->nr==2) { /* 2 pnt, treat separate */
+               if(bl->nr < 2) {
+                       /* do nothing */
+               }
+               else if(bl->nr==2) {    /* 2 pnt, treat separate */
                        bevp2= (BevPoint *)(bl+1);
                        bevp1= bevp2+1;
 
@@ -1923,68 +1926,169 @@ void makeBevelList(Object *ob)
                        if(cu->flag & CU_3D) {  /* 3D */
                                float quat[4], q[4];
                        
-                               vec[0]= bevp1->x - bevp2->x;
-                               vec[1]= bevp1->y - bevp2->y;
-                               vec[2]= bevp1->z - bevp2->z;
+                               VecSubf(vec, &bevp1->x, &bevp2->x);
                                
                                vectoquat(vec, 5, 1, quat);
                                
-                               Normalize(vec);
-                               q[0]= (float)cos(0.5*bevp1->alfa);
-                               x1= (float)sin(0.5*bevp1->alfa);
-                               q[1]= x1*vec[0];
-                               q[2]= x1*vec[1];
-                               q[3]= x1*vec[2];
+                               AxisAngleToQuat(q, vec, bevp1->alfa);
                                QuatMul(quat, q, quat);
                                
                                QuatToMat3(quat, bevp1->mat);
                                Mat3CpyMat3(bevp2->mat, bevp1->mat);
                        }
 
+               }       /* this has to be >2 points */
+               else if(cu->flag & CU_NO_TWIST && cu->flag & CU_3D && bl->poly != -1) {
+
+                       /* Special case, cyclic curve with no twisy. tricky... */
+
+                       float quat[4], q[4], cross[3];
+
+                       /* correcting a cyclic curve is more complicated, need to be corrected from both ends */
+                       float *quat_tmp1, *quat_tmp2; /* store a quat in the matrix temporarily */
+                       int iter_dir;
+                       BevPoint *bevp_start= (BevPoint *)(bl+1);
+
+                       /* loop over the points twice, once up, once back, accumulate the quat rotations
+                        * in both directions, then blend them in the 3rd loop and apply the tilt */
+                       for(iter_dir = 0; iter_dir < 2; iter_dir++) {
+
+                               bevp2= (BevPoint *)(bl+1);
+                               bevp1= bevp2+(bl->nr-1);
+                               bevp0= bevp1-1;
+
+                               nr= bl->nr;
+                               while(nr--) {
+       
+                                       /* Normalizes */
+                                       Vec3ToTangent(vec, &bevp0->x, &bevp1->x, &bevp2->x);
+
+                                       if(bl->nr==nr+1) { /* first time */
+                                               vectoquat(vec, 5, 1, quat);
+                                       }
+                                       else {
+                                               float angle = NormalizedVecAngle2(vec_prev, vec);
+                                       
+                                               if(angle > 0.0f) { /* otherwise we can keep as is */
+                                                       Crossf(cross, vec_prev, vec);
+                                                       AxisAngleToQuat(q, cross, angle);
+                                                       QuatMul(quat, q, quat_prev);
+                                               }
+                                               else {
+                                                       QUATCOPY(quat, quat_prev);
+                                               }
+                                       }
+                                       QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */
+                                       VECCOPY(vec_prev, vec);
+
+                                       if(iter_dir==0) { /* up, first time */
+                                               quat_tmp1= (float *)bevp1->mat;
+
+                                               bevp0= bevp1;
+                                               bevp1= bevp2;
+                                               bevp2++;
+                                       }
+                                       else { /* down second time */
+                                               quat_tmp1= ((float *)bevp1->mat)+4;
+
+                                               bevp2= bevp1;
+                                               bevp1= bevp0;
+                                               bevp0--;
+
+                                               /* wrap around */
+                                               if (bevp0 < bevp_start)
+                                                       bevp0= bevp_start+(bl->nr-1);
+                                       }
+
+                                       QUATCOPY(quat_tmp1, quat);
+                               }
+                       }
+
+                       /* Now interpolate the 2 quats and apply tilt */
+
+                       bevp2= (BevPoint *)(bl+1);
+                       bevp1= bevp2+(bl->nr-1);
+                       bevp0= bevp1-1;
+
+                       nr= bl->nr;
+                       while(nr--) {
+
+                               Vec3ToTangent(vec, &bevp0->x, &bevp1->x, &bevp2->x);
+
+                               quat_tmp1= (float *)bevp1->mat;
+                               quat_tmp2= quat_tmp1+4;
+
+                               /* blend the 2 rotations gathered from both directions */
+                               QuatInterpol(quat, quat_tmp1, quat_tmp2, 1.0 - (((float)nr)/bl->nr));
+
+                               AxisAngleToQuat(q, vec, bevp1->alfa);
+                               QuatMul(quat, q, quat);
+                               QuatToMat3(quat, bevp1->mat);
+                               
+                               /* generic */
+                               x1= bevp1->x- bevp0->x;
+                               x2= bevp1->x- bevp2->x;
+                               y1= bevp1->y- bevp0->y;
+                               y2= bevp1->y- bevp2->y;
+                       
+                               calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
+                               
+                               bevp0= bevp1;
+                               bevp1= bevp2;
+                               bevp2++;
+                       }
                }
-               else if(bl->nr>2) {
+               else {
+                       /* Any curve with 3 or more points */
+
                        bevp2= (BevPoint *)(bl+1);
                        bevp1= bevp2+(bl->nr-1);
                        bevp0= bevp1-1;
 
-               
                        nr= bl->nr;
-       
                        while(nr--) {
-       
+
                                if(cu->flag & CU_3D) {  /* 3D */
-                                       float quat[4], q[4];
-                               
-                                       vec[0]= bevp2->x - bevp0->x;
-                                       vec[1]= bevp2->y - bevp0->y;
-                                       vec[2]= bevp2->z - bevp0->z;
-                                       
-                                       Normalize(vec);
 
-                                       vectoquat(vec, 5, 1, quat);
-                                       
-                                       q[0]= (float)cos(0.5*bevp1->alfa);
-                                       x1= (float)sin(0.5*bevp1->alfa);
-                                       q[1]= x1*vec[0];
-                                       q[2]= x1*vec[1];
-                                       q[3]= x1*vec[2];
+                                       /* Normalizes */
+                                       Vec3ToTangent(vec, &bevp0->x, &bevp1->x, &bevp2->x);
+
+                                       if(bl->nr==nr+1 || !(cu->flag & CU_NO_TWIST)) { /* first time */
+                                               vectoquat(vec, 5, 1, quat);
+                                       }
+                                       else {
+                                               float angle = NormalizedVecAngle2(vec_prev, vec);
+
+                                               if(angle > 0.0f) { /* otherwise we can keep as is */
+                                                       Crossf(cross, vec_prev, vec);
+                                                       AxisAngleToQuat(q, cross, angle);
+                                                       QuatMul(quat, q, quat_prev);
+                                               }
+                                               else {
+                                                       QUATCOPY(quat, quat_prev);
+                                               }
+                                       }
+                                       QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */
+                                       VECCOPY(vec_prev, vec);
+
+                                       AxisAngleToQuat(q, vec, bevp1->alfa);
                                        QuatMul(quat, q, quat);
-                                       
                                        QuatToMat3(quat, bevp1->mat);
                                }
-                               
+
                                x1= bevp1->x- bevp0->x;
                                x2= bevp1->x- bevp2->x;
                                y1= bevp1->y- bevp0->y;
                                y2= bevp1->y- bevp2->y;
-                       
+
                                calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
-                               
-                               
+
+
                                bevp0= bevp1;
                                bevp1= bevp2;
                                bevp2++;
                        }
+
                        /* correct non-cyclic cases */
                        if(bl->poly== -1) {
                                if(bl->nr>2) {
index 2ab60c6a8d00356458a3347f3b8d39e362d1b042..2ce4e8e268c05532aea2208f3969e88933c12a8b 100644 (file)
@@ -380,6 +380,7 @@ void AxisAngleToQuat(float *q, float *axis, float angle);
 void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3]);
 void vectoquat(float *vec, short axis, short upflag, float *q);
 
+void Vec3ToTangent(float *v, float *v1, float *v2, float *v3);
 float VecAngle2(float *v1, float *v2);
 float VecAngle3(float *v1, float *v2, float *v3);
 float NormalizedVecAngle2(float *v1, float *v2);
index 2e60fbba4c90a3e24fca0ae8a1b94aec3eec8ccd..55bdc32c4e90198b166da38d54d1390a6dd9b038 100644 (file)
@@ -3374,6 +3374,19 @@ void VecRotToQuat(float *vec, float phi, float *quat)
        }
 }
 
+/* get a direction from 3 vectors that wont depend
+ * on the distance between the points */
+void Vec3ToTangent(float *v, float *v1, float *v2, float *v3)
+{
+       float d_12[3], d_23[3];
+       VecSubf(d_12, v2, v1);
+       VecSubf(d_23, v3, v2);
+       Normalize(d_12);
+       Normalize(d_23);
+       VecAddf(v, d_12, d_23);
+       Normalize(v);
+}
+
 /* Return the angle in degrees between vecs 1-2 and 2-3 in degrees
    If v1 is a shoulder, v2 is the elbow and v3 is the hand,
    this would return the angle at the elbow */
index 3bac2c73bcb28a2dee56bd7049467e009bc7814a..3655c57558a61d41a6806d89b7af85549cd791dc 100644 (file)
@@ -225,6 +225,8 @@ typedef struct Curve {
 #define CU_RETOPO               1024
 #define CU_DS_EXPAND   2048
 
+#define CU_NO_TWIST            4096
+
 /* spacemode */
 #define CU_LEFT                        0
 #define CU_MIDDLE              1