* Fix: Disabled radius tapering on 2d curves with filled front or back. It would be

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.
This commit is contained in:
Matt Ebb
2006-08-13 08:31:59 +00:00
parent d3028ec70d
commit e3d78dd4e1
4 changed files with 137 additions and 133 deletions

View 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);

View 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 ************** */
/*

View 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);
}

View 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);