[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23019] trunk/blender/source/blender: Option to correct for 3D curve twist error.

Nathan Vegdahl cessen at cessen.com
Sun Sep 6 08:34:09 CEST 2009


Wootz!!!

On Sat, Sep 5, 2009 at 11:20 AM, joe<joeedh at gmail.com> wrote:
> Yay!
>
> Joe
>
> On Sat, Sep 5, 2009 at 3:54 AM, Campbell Barton<ideasman42 at gmail.com> wrote:
>> Revision: 23019
>>          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23019
>> Author:   campbellbarton
>> Date:     2009-09-05 11:54:01 +0200 (Sat, 05 Sep 2009)
>>
>> Log Message:
>> -----------
>> Option to correct for 3D curve twist error. example before and after.
>> http://www.graphicall.org/ftp/ideasman42/curve_auto_twist.png
>> Access next to the "3D" edit button.
>>
>> details...
>> - open curves use the first points orientation and minimize twist for each new segment.
>> - cyclic curves calculate the least twist in both directions and blend between them
>> - AxisAngleToQuat replaced inline code.
>> - Notice the model on the right now has more even corners. added Vec3ToTangent to arithb.c.
>>
>> Modified Paths:
>> --------------
>>    trunk/blender/source/blender/blenkernel/intern/curve.c
>>    trunk/blender/source/blender/blenlib/BLI_arithb.h
>>    trunk/blender/source/blender/blenlib/intern/arithb.c
>>    trunk/blender/source/blender/makesdna/DNA_curve_types.h
>>    trunk/blender/source/blender/src/buttons_editing.c
>>
>> Modified: trunk/blender/source/blender/blenkernel/intern/curve.c
>> ===================================================================
>> --- trunk/blender/source/blender/blenkernel/intern/curve.c      2009-09-05 06:10:30 UTC (rev 23018)
>> +++ trunk/blender/source/blender/blenkernel/intern/curve.c      2009-09-05 09:54:01 UTC (rev 23019)
>> @@ -1513,7 +1513,7 @@
>>        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;
>> @@ -1872,7 +1872,10 @@
>>        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;
>>
>> @@ -1886,68 +1889,169 @@
>>                        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) {
>>
>> Modified: trunk/blender/source/blender/blenlib/BLI_arithb.h
>> ===================================================================
>> --- trunk/blender/source/blender/blenlib/BLI_arithb.h   2009-09-05 06:10:30 UTC (rev 23018)
>> +++ trunk/blender/source/blender/blenlib/BLI_arithb.h   2009-09-05 09:54:01 UTC (rev 23019)
>> @@ -270,6 +270,7 @@
>>  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);
>>
>> Modified: trunk/blender/source/blender/blenlib/intern/arithb.c
>> ===================================================================
>> --- trunk/blender/source/blender/blenlib/intern/arithb.c        2009-09-05 06:10:30 UTC (rev 23018)
>> +++ trunk/blender/source/blender/blenlib/intern/arithb.c        2009-09-05 09:54:01 UTC (rev 23019)
>> @@ -2969,6 +2969,19 @@
>>        }
>>  }
>>
>> +/* 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 */
>>
>> Modified: trunk/blender/source/blender/makesdna/DNA_curve_types.h
>> ===================================================================
>> --- trunk/blender/source/blender/makesdna/DNA_curve_types.h     2009-09-05 06:10:30 UTC (rev 23018)
>> +++ trunk/blender/source/blender/makesdna/DNA_curve_types.h     2009-09-05 09:54:01 UTC (rev 23019)
>> @@ -205,6 +205,8 @@
>>  #define CU_FAST                        512 /* Font: no filling inside editmode */
>>  #define CU_RETOPO               1024
>>
>> +#define CU_NO_TWIST            4096
>> +
>>  /* spacemode */
>>  #define CU_LEFT                        0
>>  #define CU_MIDDLE              1
>>
>> Modified: trunk/blender/source/blender/src/buttons_editing.c
>> ===================================================================
>> --- trunk/blender/source/blender/src/buttons_editing.c  2009-09-05 06:10:30 UTC (rev 23018)
>> +++ trunk/blender/source/blender/src/buttons_editing.c  2009-09-05 09:54:01 UTC (rev 23019)
>> @@ -3671,7 +3671,8 @@
>>                uiBlockSetCol(block, TH_BUT_SETTING1);
>>                uiDefButBitS(block, TOG, CU_BACK, B_MAKEDISP, "Back",   760,115,50,19, &cu->flag, 0, 0, 0, 0, "Draw filled back for extruded/beveled curves");
>>                uiDefButBitS(block, TOG, CU_FRONT, B_MAKEDISP, "Front",810,115,50,19, &cu->flag, 0, 0, 0, 0, "Draw filled front for extruded/beveled curves");
>> -               uiDefButBitS(block, TOG, CU_3D, B_CU3D, "3D",           860,115,50,19, &cu->flag, 0, 0, 0, 0, "Allow Curve to be 3d, it doesn't fill then");
>> +               uiDefButBitS(block, TOG, CU_3D, B_CU3D, "3D",           860,115,30,19, &cu->flag, 0, 0, 0, 0, "Allow Curve to be 3d, it doesn't fill then");
>> +               uiDefIconButBitS(block, TOG, CU_NO_TWIST, B_MAKEDISP, ICON_AUTO,        890,115,20,19, &cu->flag, 0.0, 0.0, 0, 0, "Avoid twisting artifacts for 3D beveled/extruded curves");
>>        }
>>  }
>>
>>
>>
>> _______________________________________________
>> Bf-blender-cvs mailing list
>> Bf-blender-cvs at blender.org
>> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>>
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers
>


More information about the Bf-committers mailing list