* Fix: Disabled radius tapering on 2d curves with filled front or back. It would be
authorMatt Ebb <matt@mke3.net>
Sun, 13 Aug 2006 08:31:59 +0000 (08:31 +0000)
committerMatt Ebb <matt@mke3.net>
Sun, 13 Aug 2006 08:31:59 +0000 (08:31 +0000)
really cool to get this working solidly, but there are many potential problems with the
triangle face creation across the flat surfaces, especially when there are holes inside
the curves. Maybe this could be a fun project for someone better at this than I? :)
Taper object curves still cause similar problems...

* Made the curve radius affect the 'Nsize' curve normal drawing too, so you don't need a
bevel to see the value.

source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/displist.c
source/blender/src/drawobject.c

index c05e1e729f3f63ee4f4824dd3ca2b2b8bde83e5d..c3a7cdcd8dd3d1835dd69401e597f71e80d90356 100644 (file)
@@ -71,6 +71,8 @@ float *make_orco_surf( struct Object *ob);
 void makebevelcurve( struct Object *ob,  struct ListBase *disp);
 
 void makeBevelList( struct Object *ob);
+float calc_curve_subdiv_radius( struct Curve *cu, struct Nurb *nu, int cursubdiv);
+
 void calchandleNurb( struct BezTriple *bezt, struct BezTriple *prev,  struct BezTriple *next, int mode);
 void calchandlesNurb( struct Nurb *nu);
 void testhandlesNurb( struct Nurb *nu);
index a419fceeb433b1618074612e6266cd9261efd65b..c3c7704da85a013b2c76e871e35e08bb12dd65a7 100644 (file)
@@ -1863,6 +1863,134 @@ void makeBevelList(Object *ob)
        }
 }
 
+/* calculates a bevel width (radius) for a particular subdivided curve part,
+ * based on the radius value of the surrounding CVs */
+float calc_curve_subdiv_radius(Curve *cu, Nurb *nu, int cursubdiv)
+{
+       BezTriple *bezt, *beztfirst, *beztlast, *beztnext, *beztprev;
+       BPoint *bp, *bpfirst, *bplast;
+       int resolu;
+       float prevrad=0.0, nextrad=0.0, rad=0.0, ratio=0.0;
+       int vectseg=0, subdivs=0;
+       
+       if((nu==NULL) || (nu->pntsu<=1)) return 1.0; 
+       bezt= nu->bezt;
+       bp = nu->bp;
+       
+       if(G.rendering && cu->resolu_ren!=0) resolu= cu->resolu_ren;
+       else resolu= nu->resolu;
+       
+       if(((nu->type & 7)==CU_BEZIER) && (bezt != NULL)) {
+               beztfirst = nu->bezt;
+               beztlast = nu->bezt + (nu->pntsu - 1);
+               
+               /* loop through the CVs to end up with a pointer to the CV before the subdiv in question, and a ratio
+                * of how far that subdiv is between this CV and the next */
+               while(bezt<=beztlast) {
+                       beztnext = bezt+1;
+                       beztprev = bezt-1;
+                       vectseg=0;
+                       
+                       if (subdivs==cursubdiv) {
+                               ratio= 0.0;
+                               break;
+                       }
+
+                       /* check to see if we're looking at a vector segment (no subdivisions) */
+                       if (nu->flagu & CU_CYCLIC) {
+                               if (bezt == beztfirst) {
+                                       if ((beztlast->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1;
+                               } else {
+                                       if ((beztprev->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1;
+                               }
+                       } else if ((bezt->h2==HD_VECT) && (beztnext->h1==HD_VECT)) vectseg = 1;
+                       
+                       
+                       if (vectseg==0) {
+                               /* if it's NOT a vector segment, check to see if the subdiv falls within the segment */
+                               subdivs += resolu;
+                               
+                               if (cursubdiv < subdivs) {
+                                       ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu);
+                                       break;
+                               }
+                       } else {
+                               /* must be a vector segment.. loop again! */
+                               subdivs += 1;
+                       } 
+                       
+                       bezt++;
+               }
+               
+               /* Now we have a nice bezt pointer to the CV that we want. But cyclic messes it up, so must correct for that..
+                * (cyclic goes last-> first -> first+1 -> first+2 -> ...) */
+               if (nu->flagu & CU_CYCLIC) {
+                       if (bezt == beztfirst) bezt = beztlast;
+                       else bezt--;
+               }
+                
+               /* find the radii at the bounding CVs and interpolate between them based on ratio */
+               rad = prevrad = bezt->radius;
+               
+               if ((bezt == beztlast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
+                       bezt= beztfirst;
+               } else if (bezt != beztlast) {
+                       bezt++;
+               }
+               nextrad = bezt->radius;
+               
+       }
+       else if( ( ((nu->type & 7)==CU_NURBS) || ((nu->type & 7)==CU_POLY)) && (bp != NULL)) {
+               /* follows similar algo as for bezt above */
+               bpfirst = nu->bp;
+               bplast = nu->bp + (nu->pntsu - 1);
+               
+               if ((nu->type & 7)==CU_POLY) resolu=1;
+               
+               while(bp<=bplast) {
+                       if (subdivs==cursubdiv) {
+                               ratio= 0.0;
+                               break;
+                       }
+                       
+                       subdivs += resolu;
+
+                       if (cursubdiv < subdivs) {
+                               ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu);
+                               break;
+                       }
+
+                       bp++;
+               }
+               
+               if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) {
+                       if (bp == bplast) bp = bpfirst;
+                       else bp++;
+               }
+               
+               rad = prevrad = bp->radius;
+               
+               if ((bp == bplast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
+                       bp= bpfirst;
+               } else if (bp != bplast) {
+                       bp++;
+               }
+               nextrad = bp->radius;
+               
+       }
+       
+       
+       if (nextrad != prevrad) {
+               /* smooth interpolation */
+               rad = prevrad + (nextrad-prevrad)*(3.0f*ratio*ratio - 2.0f*ratio*ratio*ratio);
+       }
+
+       if (rad > 0.0) 
+               return rad;
+       else
+               return 1.0;
+}
+
 /* ****************** HANDLES ************** */
 
 /*
index 5ae7ffa6b3638330cd163f50eff255fd1c5fbda9..acabd2ac0babaf49ce5d85ceeca17a456d1868ae 100644 (file)
@@ -1119,134 +1119,6 @@ void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
        }
 }
 
-/* calculates a bevel width (radius) for a particular subdivided curve part,
- * based on the radius value of the surrounding CVs */
-static float calc_manual_taper(Curve *cu, Nurb *nu, int cursubdiv)
-{
-       BezTriple *bezt, *beztfirst, *beztlast, *beztnext, *beztprev;
-       BPoint *bp, *bpfirst, *bplast;
-       int resolu;
-       float prevrad=0.0, nextrad=0.0, rad=0.0, ratio=0.0;
-       int vectseg=0, subdivs=0;
-       
-       if((nu==NULL) || (nu->pntsu<=1)) return 1.0; 
-       bezt= nu->bezt;
-       bp = nu->bp;
-       
-       if(G.rendering && cu->resolu_ren!=0) resolu= cu->resolu_ren;
-       else resolu= nu->resolu;
-       
-       if(((nu->type & 7)==CU_BEZIER) && (bezt != NULL)) {
-               beztfirst = nu->bezt;
-               beztlast = nu->bezt + (nu->pntsu - 1);
-               
-               /* loop through the CVs to end up with a pointer to the CV before the subdiv in question, and a ratio
-                * of how far that subdiv is between this CV and the next */
-               while(bezt<=beztlast) {
-                       beztnext = bezt+1;
-                       beztprev = bezt-1;
-                       vectseg=0;
-                       
-                       if (subdivs==cursubdiv) {
-                               ratio= 0.0;
-                               break;
-                       }
-
-                       /* check to see if we're looking at a vector segment (no subdivisions) */
-                       if (nu->flagu & CU_CYCLIC) {
-                               if (bezt == beztfirst) {
-                                       if ((beztlast->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1;
-                               } else {
-                                       if ((beztprev->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1;
-                               }
-                       } else if ((bezt->h2==HD_VECT) && (beztnext->h1==HD_VECT)) vectseg = 1;
-                       
-                       
-                       if (vectseg==0) {
-                               /* if it's NOT a vector segment, check to see if the subdiv falls within the segment */
-                               subdivs += resolu;
-                               
-                               if (cursubdiv < subdivs) {
-                                       ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu);
-                                       break;
-                               }
-                       } else {
-                               /* must be a vector segment.. loop again! */
-                               subdivs += 1;
-                       } 
-                       
-                       bezt++;
-               }
-               
-               /* Now we have a nice bezt pointer to the CV that we want. But cyclic messes it up, so must correct for that..
-                * (cyclic goes last-> first -> first+1 -> first+2 -> ...) */
-               if (nu->flagu & CU_CYCLIC) {
-                       if (bezt == beztfirst) bezt = beztlast;
-                       else bezt--;
-               }
-                
-               /* find the radii at the bounding CVs and interpolate between them based on ratio */
-               rad = prevrad = bezt->radius;
-               
-               if ((bezt == beztlast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
-                       bezt= beztfirst;
-               } else if (bezt != beztlast) {
-                       bezt++;
-               }
-               nextrad = bezt->radius;
-               
-       }
-       else if( ( ((nu->type & 7)==CU_NURBS) || ((nu->type & 7)==CU_POLY)) && (bp != NULL)) {
-               /* follows similar algo as for bezt above */
-               bpfirst = nu->bp;
-               bplast = nu->bp + (nu->pntsu - 1);
-               
-               if ((nu->type & 7)==CU_POLY) resolu=1;
-               
-               while(bp<=bplast) {
-                       if (subdivs==cursubdiv) {
-                               ratio= 0.0;
-                               break;
-                       }
-                       
-                       subdivs += resolu;
-
-                       if (cursubdiv < subdivs) {
-                               ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu);
-                               break;
-                       }
-
-                       bp++;
-               }
-               
-               if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) {
-                       if (bp == bplast) bp = bpfirst;
-                       else bp++;
-               }
-               
-               rad = prevrad = bp->radius;
-               
-               if ((bp == bplast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
-                       bp= bpfirst;
-               } else if (bp != bplast) {
-                       bp++;
-               }
-               nextrad = bp->radius;
-               
-       }
-       
-       
-       if (nextrad != prevrad) {
-               /* smooth interpolation */
-               rad = prevrad + (nextrad-prevrad)*(3.0f*ratio*ratio - 2.0f*ratio*ratio*ratio);
-       }
-
-       if (rad > 0.0) 
-               return rad;
-       else
-               return 1.0;
-}
-
 /* taper rules:
   - only 1 curve
   - first point left, last point right
@@ -1589,8 +1461,8 @@ void makeDispListCurveTypes(Object *ob, int forOrco)
                                                bevp= (BevPoint *)(bl+1);
                                                for(a=0; a<bl->nr; a++,bevp++) {
                                                        float fac;
-                                                       if (cu->taperobj==NULL) {
-                                                               fac = calc_manual_taper(cu, nu, a);
+                                                       if ((cu->taperobj==NULL) && !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK))) {
+                                                               fac = calc_curve_subdiv_radius(cu, nu, a);
                                                        } else {
                                                                fac = calc_taper(cu->taperobj, a, bl->nr);
                                                        }
index c1b599a71ba6198dd52382a0f85054e540b3b62a..70f3c4e095e4781a1ba0f197c2773783e1a12ad7 100644 (file)
@@ -2913,11 +2913,13 @@ static void drawnurb(Base *base, Nurb *nurb, int dt)
                        BevPoint *bevp= (BevPoint *)(bl+1);             
                        int nr= bl->nr;
                        int skip= nu->resolu/16;
+                       float fac;
                        
                        while (nr-->0) {
-                               float ox = G.scene->editbutsize*bevp->mat[0][0];
-                               float oy = G.scene->editbutsize*bevp->mat[0][1];
-                               float oz = G.scene->editbutsize*bevp->mat[0][2];
+                               fac = calc_curve_subdiv_radius(cu, nu, (bl->nr - nr));
+                               float ox = G.scene->editbutsize*fac*bevp->mat[0][0];
+                               float oy = G.scene->editbutsize*fac*bevp->mat[0][1];
+                               float oz = G.scene->editbutsize*fac*bevp->mat[0][2];
 
                                glVertex3f(bevp->x - ox, bevp->y - oy, bevp->z - oz);
                                glVertex3f(bevp->x + ox, bevp->y + oy, bevp->z + oz);