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

Campbell Barton ideasman42 at gmail.com
Sun Sep 6 11:22:13 CEST 2009


from talking to ZanQdo and Martin the current method used to minimize
twist could be changed/improved
At the moment its not totally animation safe, since the minimum twist
can change when the point positions move (hooks or shape keys).
though is not likely to flicker, just rotate as the curve moves which
is noticeable if you have a bevel shape rather then a circle,
presumably if your using UV textures too.

Martin suggests the existing Z-up method could check for flipping and
correct for that but otherwise stay as it is.
I'll test some different methods and see if one can be used or maybe
it can be an option per curve since they give such different results.

On Sat, Sep 5, 2009 at 11:34 PM, Nathan Vegdahl<cessen at cessen.com> wrote:
> 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
>>
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers
>



-- 
- Campbell


More information about the Bf-committers mailing list