diff options
-rw-r--r-- | source/blender/blenkernel/BKE_curve.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 128 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/displist.c | 132 | ||||
-rw-r--r-- | source/blender/src/drawobject.c | 8 |
4 files changed, 137 insertions, 133 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index c05e1e729f3..c3a7cdcd8dd 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -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); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index a419fceeb43..c3c7704da85 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -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 ************** */ /* diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 5ae7ffa6b36..acabd2ac0ba 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -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); } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index c1b599a71ba..70f3c4e095e 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -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); |