* Shrink/Fatten for bevelled curves

This is a much faster and easier way to give a bevelled curve a taper, without
using taper curves. Each point on a curve now has a 'radius' value that you can
shrink and fatten using Alt S, which will influence the taper when the curve is
bevelled (either with a bevob, or with front/back turned off and a bevel dept
set). Alt S shrinks and fattens the selected points in an interactive transform,
and you can set an absolute radius for selected points with 'Set Radius' in the
curve specials menu.

See demo: http://mke3.net/blender/etc/curve_shrinkfatten-h264.mov

This can be a quick way to create revolved surfaces (eg.
http://mke3.net/blender/etc/wineglass-h264.mov ) and it would be very
interesting to use this radius value in other tools, such as a 'freehand curve'
tool that would let you draw a curve freehand, with the radius affected by pen
pressure, or even using the radius at each point to control curve guides for
particles more precisely, rather than the continous maxdist.
This commit is contained in:
2006-08-13 07:37:51 +00:00
parent 515fe83f97
commit d3028ec70d
12 changed files with 315 additions and 37 deletions

View File

@@ -821,17 +821,17 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
/* count */ /* count */
len= 0; len= 0;
a= nu->pntsu-1; a= nu->pntsu-1;
if(nu->flagu & 1) a++; if(nu->flagu & CU_CYCLIC) a++;
prevbezt= nu->bezt; prevbezt= nu->bezt;
bezt= prevbezt+1; bezt= prevbezt+1;
while(a--) { while(a--) {
if(a==0 && (nu->flagu & 1)) bezt= nu->bezt; if(a==0 && (nu->flagu & CU_CYCLIC)) bezt= nu->bezt;
if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++; if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
else len+= resolu; else len+= resolu;
if(a==0 && (nu->flagu & 1)==0) len++; if(a==0 && (nu->flagu & CU_CYCLIC)==0) len++;
prevbezt= bezt; prevbezt= bezt;
bezt++; bezt++;
@@ -1119,6 +1119,133 @@ 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: /* taper rules:
- only 1 curve - only 1 curve
@@ -1389,7 +1516,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco)
makeBevelList(ob); makeBevelList(ob);
/* If curve has no bevel will return nothing */ /* If curve has no bevel will return nothing */
makebevelcurve(ob, &dlbev); makebevelcurve(ob, &dlbev);
/* no bevel or extrude, and no width correction? */ /* no bevel or extrude, and no width correction? */
@@ -1461,7 +1588,12 @@ void makeDispListCurveTypes(Object *ob, int forOrco)
/* for each point of poly make a bevel piece */ /* for each point of poly make a bevel piece */
bevp= (BevPoint *)(bl+1); bevp= (BevPoint *)(bl+1);
for(a=0; a<bl->nr; a++,bevp++) { for(a=0; a<bl->nr; a++,bevp++) {
float fac = calc_taper(cu->taperobj, a, bl->nr); float fac;
if (cu->taperobj==NULL) {
fac = calc_manual_taper(cu, nu, a);
} else {
fac = calc_taper(cu->taperobj, a, bl->nr);
}
if (bevp->f1) { if (bevp->f1) {
dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F); dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);

View File

@@ -52,6 +52,7 @@
#define TFM_MIRROR 14 #define TFM_MIRROR 14
#define TFM_BONESIZE 15 #define TFM_BONESIZE 15
#define TFM_BONE_ENVELOPE 16 #define TFM_BONE_ENVELOPE 16
#define TFM_CURVE_SHRINKFATTEN 17
/* TRANSFORM CONTEXTS */ /* TRANSFORM CONTEXTS */
#define CTX_NONE 0 #define CTX_NONE 0

View File

@@ -267,6 +267,9 @@ int ShrinkFatten(TransInfo *t, short mval[2]);
void initTilt(TransInfo *t); void initTilt(TransInfo *t);
int Tilt(TransInfo *t, short mval[2]); int Tilt(TransInfo *t, short mval[2]);
void initCurveShrinkFatten(TransInfo *t);
int CurveShrinkFatten(TransInfo *t, short mval[2]);
void initTrackball(TransInfo *t); void initTrackball(TransInfo *t);
int Trackball(TransInfo *t, short mval[2]); int Trackball(TransInfo *t, short mval[2]);

View File

@@ -89,7 +89,7 @@ typedef struct BevPoint {
*/ */
typedef struct BezTriple { typedef struct BezTriple {
float vec[3][3]; float vec[3][3];
float alfa, weight, pad; float alfa, weight, radius; /* alfa: tilt in 3D View, weight: used for softbody goal weight, radius: for bevel tapering */
short h1, h2; short h1, h2;
char f1, f2, f3, hide; char f1, f2, f3, hide;
} BezTriple; } BezTriple;
@@ -97,17 +97,18 @@ typedef struct BezTriple {
/* note; alfa location in struct is abused by Key system */ /* note; alfa location in struct is abused by Key system */
typedef struct BPoint { typedef struct BPoint {
float vec[4]; float vec[4];
float alfa, weight; float alfa, weight; /* alfa: tilt in 3D View, weight: used for softbody goal weight */
short f1, hide; short f1, hide;
float radius, pad; /* user-set radius per point for bevelling etc */
} BPoint; } BPoint;
typedef struct Nurb { typedef struct Nurb {
struct Nurb *next, *prev; struct Nurb *next, *prev; /* multiple nurbs per curve object are allowed */
short type; short type;
short mat_nr; /* index into material list */ short mat_nr; /* index into material list */
short hide, flag; short hide, flag;
short pntsu, pntsv; short pntsu, pntsv; /* number of points in the U or V directions */
short resolu, resolv; short resolu, resolv; /* tesselation resolution in the U or V directions */
short orderu, orderv; short orderu, orderv;
short flagu, flagv; short flagu, flagv;

View File

@@ -2412,7 +2412,7 @@ static void editing_panel_curve_type(Object *ob, Curve *cu)
uiDefButF(block, NUM, B_MAKEDISP, "Width:", 760,90,150,19, &cu->width, 0.0, 2.0, 1, 0, "Make interpolated result thinner or fatter"); uiDefButF(block, NUM, B_MAKEDISP, "Width:", 760,90,150,19, &cu->width, 0.0, 2.0, 1, 0, "Make interpolated result thinner or fatter");
uiDefButF(block, NUM, B_MAKEDISP, "Extrude:", 760,70,150,19, &cu->ext1, 0.0, 5.0, 10, 0, "Curve extrusion size when not using a bevel object"); uiDefButF(block, NUM, B_MAKEDISP, "Extrude:", 760,70,150,19, &cu->ext1, 0.0, 5.0, 10, 0, "Curve extrusion size when not using a bevel object");
uiDefButF(block, NUM, B_MAKEDISP, "Bevel Depth:", 760,50,150,19, &cu->ext2, 0.0, 2.0, 1, 0, "Bevel depth when not using a bevel object"); uiDefButF(block, NUM, B_MAKEDISP, "Bevel Depth:", 760,50,150,19, &cu->ext2, 0.0, 2.0, 1, 0, "Bevel depth when not using a bevel object");
uiDefButS(block, NUM, B_MAKEDISP, "BevResol:", 760,30,150,19, &cu->bevresol, 0.0, 10.0, 0, 0, "Bevel resolution when depth is non-zero and not using a bevel object"); uiDefButS(block, NUM, B_MAKEDISP, "BevResol:", 760,30,150,19, &cu->bevresol, 0.0, 32.0, 0, 0, "Bevel resolution when depth is non-zero and not using a bevel object");
uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "BevOb:", 760,10,150,19, &cu->bevobj, "Curve object name that defines the bevel shape"); uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "BevOb:", 760,10,150,19, &cu->bevobj, "Curve object name that defines the bevel shape");
uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "TaperOb:", 760,-10,150,19, &cu->taperobj, "Curve object name that defines the taper (width)"); uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "TaperOb:", 760,-10,150,19, &cu->taperobj, "Curve object name that defines the taper (width)");

View File

@@ -1573,7 +1573,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
nu= editNurb.first; nu= editNurb.first;
while(nu) { while(nu) {
if((nu->type & 7)==1) { if((nu->type & 7)==CU_BEZIER) {
bezt= nu->bezt; bezt= nu->bezt;
a= nu->pntsu; a= nu->pntsu;
while(a--) { while(a--) {
@@ -2388,17 +2388,6 @@ static void view3d_panel_background(short cntrl) // VIEW3D_HANDLER_BACKGROUND
uiDefButF(block, NUM, REDRAWVIEW3D, "X Offset:", 0, 6, 140, 19, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image"); uiDefButF(block, NUM, REDRAWVIEW3D, "X Offset:", 0, 6, 140, 19, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image");
uiDefButF(block, NUM, REDRAWVIEW3D, "Y Offset:", 150, 6, 140, 19, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image"); uiDefButF(block, NUM, REDRAWVIEW3D, "Y Offset:", 150, 6, 140, 19, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image");
// uiDefButF(block, NUM, REDRAWVIEW3D, "Size:", 160,160,150,20, &vd->bgpic->size, 0.1, 250.0, 100, 0, "Set the size for the width of the BackGroundPic");
// uiDefButF(block, NUMSLI, B_BLENDBGPIC, "Blend:", 120,100,190,20,&vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the BackGroundPic transparency");
// uiDefButF(block, NUM, B_DIFF, "Center X: ", 10,70,140,20,&vd->bgpic->xof, -20.0,20.0, 10, 2, "Set the BackGroundPic X Offset");
// uiDefButF(block, NUM, B_DIFF, "Center Y: ", 160,70,140,20,&vd->bgpic->yof, -20.0,20.0, 10, 2, "Set the BackGroundPic Y Offset");
} }
} }

View File

@@ -1367,6 +1367,9 @@ void subdivideNurb()
if(a==0 && (nu->flagu & 1)) {VECCOPY(beztnew->vec[0], vec+6);} if(a==0 && (nu->flagu & 1)) {VECCOPY(beztnew->vec[0], vec+6);}
else {VECCOPY(bezt->vec[0], vec+6);} else {VECCOPY(bezt->vec[0], vec+6);}
beztn->radius = (prevbezt->radius + bezt->radius)/2.0f;
beztn->weight = (prevbezt->weight + bezt->weight)/2.0f;
beztn++; beztn++;
} }
@@ -1801,6 +1804,8 @@ int convertspline(short type, Nurb *nu)
VECCOPY(bezt->vec[1], bp->vec); VECCOPY(bezt->vec[1], bp->vec);
bezt->f1=bezt->f2=bezt->f3= bp->f1; bezt->f1=bezt->f2=bezt->f3= bp->f1;
bezt->h1= bezt->h2= HD_VECT; bezt->h1= bezt->h2= HD_VECT;
bezt->weight= bp->weight;
bezt->radius= bp->radius;
bp++; bp++;
bezt++; bezt++;
} }
@@ -1840,6 +1845,8 @@ int convertspline(short type, Nurb *nu)
bp->vec[3]= 1.0; bp->vec[3]= 1.0;
bp->f1= bezt->f2; bp->f1= bezt->f2;
nr-= 2; nr-= 2;
bp->radius= bezt->radius;
bp->weight= bezt->weight;
bp++; bp++;
} }
else { else {
@@ -1849,6 +1856,8 @@ int convertspline(short type, Nurb *nu)
if(c==0) bp->f1= bezt->f1; if(c==0) bp->f1= bezt->f1;
else if(c==1) bp->f1= bezt->f2; else if(c==1) bp->f1= bezt->f2;
else bp->f1= bezt->f3; else bp->f1= bezt->f3;
bp->radius= bezt->radius;
bp->weight= bezt->weight;
bp++; bp++;
} }
} }
@@ -1898,6 +1907,8 @@ int convertspline(short type, Nurb *nu)
bp++; bp++;
VECCOPY(bezt->vec[2], bp->vec); VECCOPY(bezt->vec[2], bp->vec);
bezt->f3= bp->f1; bezt->f3= bp->f1;
bezt->radius= bp->radius;
bezt->weight= bp->weight;
bp++; bp++;
bezt++; bezt++;
} }
@@ -2769,7 +2780,7 @@ void makecyclicNurb()
bp= nu->bp; bp= nu->bp;
while(a--) { while(a--) {
if( bp->f1 & 1 ) { if( bp->f1 & 1 ) {
if(nu->flagu & 1) nu->flagu--; if(nu->flagu & CU_CYCLIC) nu->flagu--;
else nu->flagu++; else nu->flagu++;
break; break;
} }
@@ -2781,7 +2792,7 @@ void makecyclicNurb()
bezt= nu->bezt; bezt= nu->bezt;
while(a--) { while(a--) {
if( BEZSELECTED(bezt) ) { if( BEZSELECTED(bezt) ) {
if(nu->flagu & 1) nu->flagu--; if(nu->flagu & CU_CYCLIC) nu->flagu--;
else nu->flagu++; else nu->flagu++;
break; break;
} }
@@ -2794,7 +2805,7 @@ void makecyclicNurb()
bp= nu->bp; bp= nu->bp;
while(a--) { while(a--) {
if( bp->f1 & 1 ) { if( bp->f1 & 1 ) {
if(nu->flagu & 1) nu->flagu--; if(nu->flagu & CU_CYCLIC) nu->flagu--;
else { else {
nu->flagu++; nu->flagu++;
nu->flagu &= ~2; /* endpoint flag, fixme */ nu->flagu &= ~2; /* endpoint flag, fixme */
@@ -2823,7 +2834,7 @@ void makecyclicNurb()
if( bp->f1 & 1) { if( bp->f1 & 1) {
if(cyclmode==1 && nu->pntsu>1) { if(cyclmode==1 && nu->pntsu>1) {
if(nu->flagu & 1) nu->flagu--; if(nu->flagu & CU_CYCLIC) nu->flagu--;
else { else {
nu->flagu++; nu->flagu++;
fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN"); fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
@@ -3415,6 +3426,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
bezt= nu->bezt; bezt= nu->bezt;
bezt->h1= bezt->h2= HD_ALIGN; bezt->h1= bezt->h2= HD_ALIGN;
bezt->f1= bezt->f2= bezt->f3= 1; bezt->f1= bezt->f2= bezt->f3= 1;
bezt->radius = 1.0;
for(a=0;a<3;a++) { for(a=0;a<3;a++) {
VECCOPY(bezt->vec[a], cent); VECCOPY(bezt->vec[a], cent);
@@ -3429,6 +3441,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
bezt++; bezt++;
bezt->h1= bezt->h2= HD_ALIGN; bezt->h1= bezt->h2= HD_ALIGN;
bezt->f1= bezt->f2= bezt->f3= 1; bezt->f1= bezt->f2= bezt->f3= 1;
bezt->radius = bezt->weight = 1.0;
for(a=0;a<3;a++) { for(a=0;a<3;a++) {
VECCOPY(bezt->vec[a], cent); VECCOPY(bezt->vec[a], cent);
@@ -3449,6 +3462,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
VECCOPY(bp->vec, cent); VECCOPY(bp->vec, cent);
bp->vec[3]= 1.0; bp->vec[3]= 1.0;
bp->f1= 1; bp->f1= 1;
bp->radius = bp->weight = 1.0;
} }
bp= nu->bp; bp= nu->bp;
@@ -3472,7 +3486,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
} }
break; break;
case 6: /* 5 point pad */ case 6: /* 5 point path */
nu->pntsu= 5; nu->pntsu= 5;
nu->pntsv= 1; nu->pntsv= 1;
nu->orderu= 5; nu->orderu= 5;
@@ -3485,6 +3499,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
VECCOPY(bp->vec, cent); VECCOPY(bp->vec, cent);
bp->vec[3]= 1.0; bp->vec[3]= 1.0;
bp->f1= 1; bp->f1= 1;
bp->radius = bp->weight = 1.0;
} }
bp= nu->bp; bp= nu->bp;
@@ -3523,7 +3538,8 @@ Nurb *addNurbprim(int type, int stype, int newname)
bezt->f1= bezt->f2= bezt->f3= 1; bezt->f1= bezt->f2= bezt->f3= 1;
bezt->vec[1][0]+= -G.vd->grid; bezt->vec[1][0]+= -G.vd->grid;
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
bezt->radius = bezt->weight = 1.0;
bezt++; bezt++;
for(a=0;a<3;a++) { for(a=0;a<3;a++) {
VECCOPY(bezt->vec[a], cent); VECCOPY(bezt->vec[a], cent);
@@ -3532,6 +3548,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
bezt->f1= bezt->f2= bezt->f3= 1; bezt->f1= bezt->f2= bezt->f3= 1;
bezt->vec[1][1]+= G.vd->grid; bezt->vec[1][1]+= G.vd->grid;
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
bezt->radius = bezt->weight = 1.0;
bezt++; bezt++;
for(a=0;a<3;a++) { for(a=0;a<3;a++) {
@@ -3541,6 +3558,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
bezt->f1= bezt->f2= bezt->f3= 1; bezt->f1= bezt->f2= bezt->f3= 1;
bezt->vec[1][0]+= G.vd->grid; bezt->vec[1][0]+= G.vd->grid;
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
bezt->radius = bezt->weight = 1.0;
bezt++; bezt++;
for(a=0;a<3;a++) { for(a=0;a<3;a++) {
@@ -3550,6 +3568,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
bezt->f1= bezt->f2= bezt->f3= 1; bezt->f1= bezt->f2= bezt->f3= 1;
bezt->vec[1][1]+= -G.vd->grid; bezt->vec[1][1]+= -G.vd->grid;
for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]); for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
bezt->radius = bezt->weight = 1.0;
calchandlesNurb(nu); calchandlesNurb(nu);
} }
@@ -3576,6 +3595,8 @@ Nurb *addNurbprim(int type, int stype, int newname)
if(a & 1) bp->vec[3]= 0.25*sqrt(2.0); if(a & 1) bp->vec[3]= 0.25*sqrt(2.0);
else bp->vec[3]= 1.0; else bp->vec[3]= 1.0;
Mat3MulVecfl(imat,bp->vec); Mat3MulVecfl(imat,bp->vec);
bp->radius = bp->weight = 1.0;
bp++; bp++;
} }

View File

@@ -2174,7 +2174,7 @@ void special_editmenu(void)
} }
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) { else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight %x3"); nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight %x3|Set Radius %x4");
switch(nr) { switch(nr) {
case 1: case 1:
@@ -2210,6 +2210,39 @@ void special_editmenu(void)
} }
} }
break; break;
case 4:
{
static float radius= 1.0f;
extern ListBase editNurb;
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
if(fbutton(&radius, 0.0001f, 10.0f, 10, 10, "Set Radius")) {
for(nu= editNurb.first; nu; nu= nu->next) {
if(nu->bezt) {
for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) {
if(bezt->f2 & SELECT)
bezt->radius= radius;
}
}
else if(nu->bp) {
for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
if(bp->f1 & SELECT)
bp->radius= radius;
}
}
}
}
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSALL, 0);
allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
}
break;
} }
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);

View File

@@ -1737,8 +1737,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if(G.obedit->type==OB_ARMATURE) { if(G.obedit->type==OB_ARMATURE) {
initTransform(TFM_BONESIZE, CTX_NONE); initTransform(TFM_BONESIZE, CTX_NONE);
} }
else else if (G.obedit->type==OB_CURVE) {
initTransform(TFM_CURVE_SHRINKFATTEN, CTX_NONE);
} else {
initTransform(TFM_SHRINKFATTEN, CTX_NONE); initTransform(TFM_SHRINKFATTEN, CTX_NONE);
}
Transform(); Transform();
} }
else if(G.qual==LR_CTRLKEY) { else if(G.qual==LR_CTRLKEY) {

View File

@@ -786,6 +786,9 @@ void initTransform(int mode, int context) {
case TFM_TILT: case TFM_TILT:
initTilt(&Trans); initTilt(&Trans);
break; break;
case TFM_CURVE_SHRINKFATTEN:
initCurveShrinkFatten(&Trans);
break;
case TFM_TRACKBALL: case TFM_TRACKBALL:
initTrackball(&Trans); initTrackball(&Trans);
break; break;
@@ -2329,6 +2332,85 @@ int Tilt(TransInfo *t, short mval[2])
return 1; return 1;
} }
/* ******************** Curve Shrink/Fatten *************** */
int CurveShrinkFatten(TransInfo *t, short mval[2])
{
TransData *td = t->data;
float ratio;
int i;
char str[50];
if(t->flag & T_SHIFT_MOD) {
/* calculate ratio for shiftkey pos, and for total, and blend these for precision */
float dx= (float)(t->center2d[0] - t->shiftmval[0]);
float dy= (float)(t->center2d[1] - t->shiftmval[1]);
ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
dx= (float)(t->center2d[0] - mval[0]);
dy= (float)(t->center2d[1] - mval[1]);
ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
}
else {
float dx= (float)(t->center2d[0] - mval[0]);
float dy= (float)(t->center2d[1] - mval[1]);
ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
}
snapGrid(t, &ratio);
applyNumInput(&t->num, &ratio);
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[20];
outputNumInput(&(t->num), c);
sprintf(str, "Shrink/Fatten: %s", c);
}
else {
sprintf(str, "Shrink/Fatten: %3f", ratio);
}
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if(td->val) {
//*td->val= ratio;
*td->val= td->ival*ratio;
if (*td->val <= 0.0f) *td->val = 0.0001f;
}
}
recalcData(t);
headerprint(str);
viewRedrawForce(t);
if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
return 1;
}
void initCurveShrinkFatten(TransInfo *t)
{
t->idx_max = 0;
t->num.idx_max = 0;
t->snap[0] = 0.0f;
t->snap[1] = 0.1f;
t->snap[2] = t->snap[1] * 0.1f;
t->transform = CurveShrinkFatten;
t->fac = (float)sqrt( (
((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
+
((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
) );
}
/* ************************** PUSH/PULL *************************** */ /* ************************** PUSH/PULL *************************** */
void initPushPull(TransInfo *t) void initPushPull(TransInfo *t)

View File

@@ -1139,8 +1139,14 @@ static void createTransCurveVerts(TransInfo *t)
else td->flag= 0; else td->flag= 0;
td->ext = NULL; td->ext = NULL;
td->tdi = NULL; td->tdi = NULL;
td->val = &(bezt->alfa);
td->ival = bezt->alfa; if (t->mode==TFM_CURVE_SHRINKFATTEN) {
td->val = &(bezt->radius);
td->ival = bezt->radius;
} else {
td->val = &(bezt->alfa);
td->ival = bezt->alfa;
}
Mat3CpyMat3(td->smtx, smtx); Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx); Mat3CpyMat3(td->mtx, mtx);
@@ -1188,8 +1194,14 @@ static void createTransCurveVerts(TransInfo *t)
else td->flag= 0; else td->flag= 0;
td->ext = NULL; td->ext = NULL;
td->tdi = NULL; td->tdi = NULL;
td->val = &(bp->alfa);
td->ival = bp->alfa; if (t->mode==TFM_CURVE_SHRINKFATTEN) {
td->val = &(bp->radius);
td->ival = bp->radius;
} else {
td->val = &(bp->alfa);
td->ival = bp->alfa;
}
Mat3CpyMat3(td->smtx, smtx); Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx); Mat3CpyMat3(td->mtx, mtx);

View File

@@ -367,6 +367,7 @@ void initTransModeFlags(TransInfo *t, int mode)
case TFM_SHEAR: case TFM_SHEAR:
case TFM_CREASE: case TFM_CREASE:
case TFM_BONE_ENVELOPE: case TFM_BONE_ENVELOPE:
case TFM_CURVE_SHRINKFATTEN:
t->flag |= T_NO_CONSTRAINT; t->flag |= T_NO_CONSTRAINT;
break; break;
} }
@@ -499,7 +500,7 @@ static void apply_grid3(TransInfo *t, float *val, int max_index, float fac1, flo
if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL) if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL)
invert = U.flag & USER_AUTOROTGRID; invert = U.flag & USER_AUTOROTGRID;
else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN) else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN || t->mode==TFM_CURVE_SHRINKFATTEN)
invert = U.flag & USER_AUTOSIZEGRID; invert = U.flag & USER_AUTOSIZEGRID;
else else
invert = U.flag & USER_AUTOGRABGRID; invert = U.flag & USER_AUTOGRABGRID;