Feature for Curve objects in Blender; 'tapering'.
Next to the "BevOb" button you now have a "TaperOb" button to give a name of a curve object which defines the width of extrusion of the 'BevObj' along the curve. The TaperOb curve typically is horizontal, where the height denotes the width. Important rules; - Only the firste curve in TaperObj is evaluated - the first width is left, last width is right - it scales the width of normal extrusions based on evaluating the taper curve; which means sharp corners in taper curve won't be easily visible (That latter feature could be improved by extrusing based on the points in the taper curve; this is a *lot* more work)
This commit is contained in:
@@ -1666,6 +1666,54 @@ void set_displist_onlyzero(int val)
|
||||
dl_onlyzero= val;
|
||||
}
|
||||
|
||||
/* taper rules:
|
||||
- only 1 curve
|
||||
- first point left, last point right
|
||||
- based on subdivided points in original curve, not on points in taper curve (still)
|
||||
*/
|
||||
static float calc_taper(Object *taperobj, int cur, int tot)
|
||||
{
|
||||
Curve *cu;
|
||||
DispList *dl;
|
||||
|
||||
if(taperobj==NULL) return 1.0;
|
||||
|
||||
cu= taperobj->data;
|
||||
dl= cu->disp.first;
|
||||
if(dl==NULL) {
|
||||
makeDispList(taperobj);
|
||||
dl= cu->disp.first;
|
||||
}
|
||||
if(dl) {
|
||||
float fac= ((float)cur)/(float)(tot-1);
|
||||
float minx, dx, *fp;
|
||||
int a;
|
||||
|
||||
/* horizontal size */
|
||||
minx= dl->verts[0];
|
||||
dx= dl->verts[3*(dl->nr-1)] - minx;
|
||||
if(dx>0.0) {
|
||||
|
||||
fp= dl->verts;
|
||||
for(a=0; a<dl->nr; a++, fp+=3) {
|
||||
if( (fp[0]-minx)/dx >= fac) {
|
||||
/* interpolate with prev */
|
||||
if(a>0) {
|
||||
float fac1= (fp[-3]-minx)/dx;
|
||||
float fac2= (fp[0]-minx)/dx;
|
||||
if(fac1!=fac2)
|
||||
return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
|
||||
}
|
||||
return fp[1];
|
||||
}
|
||||
}
|
||||
return fp[-2]; // last y coord
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void makeDispList(Object *ob)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
@@ -1888,14 +1936,18 @@ void makeDispList(Object *ob)
|
||||
|
||||
data= dl->verts;
|
||||
bevp= (BevPoint *)(bl+1);
|
||||
a= bl->nr;
|
||||
while(a--) { /* for each point of poly make a bevel piece */
|
||||
|
||||
for(a=0; a<bl->nr; a++) { /* for each point of poly make a bevel piece */
|
||||
float fac;
|
||||
|
||||
/* returns 1.0 if no taper, of course */
|
||||
fac= calc_taper(cu->taperobj, a, bl->nr);
|
||||
|
||||
/* rotate bevel piece and write in data */
|
||||
fp1= dlb->verts;
|
||||
b= dlb->nr;
|
||||
|
||||
while(b--) {
|
||||
|
||||
if(cu->flag & CU_3D) {
|
||||
|
||||
vec[0]= fp1[1]+widfac;
|
||||
@@ -1904,14 +1956,14 @@ void makeDispList(Object *ob)
|
||||
|
||||
Mat3MulVecfl(bevp->mat, vec);
|
||||
|
||||
data[0]= bevp->x+ vec[0];
|
||||
data[1]= bevp->y+ vec[1];
|
||||
data[2]= bevp->z+ vec[2];
|
||||
data[0]= bevp->x+ fac*vec[0];
|
||||
data[1]= bevp->y+ fac*vec[1];
|
||||
data[2]= bevp->z+ fac*vec[2];
|
||||
}
|
||||
else {
|
||||
data[0]= bevp->x+ (fp1[1]+widfac)*bevp->sina;
|
||||
data[1]= bevp->y+ (fp1[1]+widfac)*bevp->cosa;
|
||||
data[2]= bevp->z+ fp1[2];
|
||||
data[0]= bevp->x+ fac*(fp1[1]+widfac)*bevp->sina;
|
||||
data[1]= bevp->y+ fac*(fp1[1]+widfac)*bevp->cosa;
|
||||
data[2]= bevp->z+ fac*fp1[2];
|
||||
}
|
||||
|
||||
data+=3;
|
||||
|
||||
@@ -218,28 +218,29 @@ void unlink_object(Object *ob)
|
||||
/* check all objects: parents en bevels */
|
||||
obt= G.main->object.first;
|
||||
while(obt) {
|
||||
if(obt->id.lib==0) {
|
||||
if(obt->id.lib==NULL) {
|
||||
if(obt->parent==ob) {
|
||||
obt->parent= 0;
|
||||
obt->parent= NULL;
|
||||
if(ob->type==OB_LATTICE) freedisplist(&obt->disp);
|
||||
}
|
||||
if(obt->track==ob) obt->track= 0;
|
||||
if(obt->track==ob) obt->track= NULL;
|
||||
if ELEM(obt->type, OB_CURVE, OB_FONT) {
|
||||
cu= obt->data;
|
||||
if(cu->bevobj==ob) cu->bevobj= 0;
|
||||
if(cu->textoncurve==ob) cu->textoncurve= 0;
|
||||
if(cu->bevobj==ob) cu->bevobj= NULL;
|
||||
if(cu->taperobj==ob) cu->taperobj= NULL;
|
||||
if(cu->textoncurve==ob) cu->textoncurve= NULL;
|
||||
}
|
||||
if(obt->type==OB_IKA) {
|
||||
Ika *ika= obt->data;
|
||||
Deform *def= ika->def;
|
||||
|
||||
if(ika->parent==ob) ika->parent= 0;
|
||||
if(ika->parent==ob) ika->parent= NULL;
|
||||
a= ika->totdef;
|
||||
while(a--) {
|
||||
if(def->ob==ob) {
|
||||
ika->totdef= 0;
|
||||
MEM_freeN(ika->def);
|
||||
ika->def= 0;
|
||||
ika->def= NULL;
|
||||
break;
|
||||
}
|
||||
def++;
|
||||
|
||||
@@ -1781,6 +1781,7 @@ static void lib_link_curve(FileData *fd, Main *main)
|
||||
for(a=0; a<cu->totcol; a++) cu->mat[a]= newlibadr_us(fd, cu->id.lib, cu->mat[a]);
|
||||
|
||||
cu->bevobj= newlibadr(fd, cu->id.lib, cu->bevobj);
|
||||
cu->taperobj= newlibadr(fd, cu->id.lib, cu->taperobj);
|
||||
cu->textoncurve= newlibadr(fd, cu->id.lib, cu->textoncurve);
|
||||
cu->vfont= newlibadr_us(fd, cu->id.lib, cu->vfont);
|
||||
|
||||
@@ -4535,6 +4536,7 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
|
||||
expand_doit(fd, mainvar, cu->key);
|
||||
expand_doit(fd, mainvar, cu->ipo);
|
||||
expand_doit(fd, mainvar, cu->bevobj);
|
||||
expand_doit(fd, mainvar, cu->taperobj);
|
||||
expand_doit(fd, mainvar, cu->textoncurve);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ typedef struct Curve {
|
||||
|
||||
ListBase nurb;
|
||||
ListBase disp;
|
||||
struct Object *bevobj, *textoncurve;
|
||||
struct Object *bevobj, *taperobj, *textoncurve;
|
||||
struct Ipo *ipo;
|
||||
Path *path;
|
||||
struct Key *key;
|
||||
|
||||
@@ -1270,7 +1270,8 @@ static void editing_panel_curve_type(Object *ob, Curve *cu)
|
||||
uiDefButF(block, NUM, B_MAKEDISP, "Ext1:", 760,70,150,19, &cu->ext1, 0.0, 5.0, 10, 0, "");
|
||||
uiDefButF(block, NUM, B_MAKEDISP, "Ext2:", 760,50,150,19, &cu->ext2, 0.0, 2.0, 1, 0, "");
|
||||
uiDefButS(block, NUM, B_MAKEDISP, "BevResol:", 760,30,150,19, &cu->bevresol, 0.0, 10.0, 0, 0, "");
|
||||
uiDefIDPoinBut(block, test_obcurpoin_but, B_MAKEDISP, "BevOb:", 760,10,150,19, &cu->bevobj, "");
|
||||
uiDefIDPoinBut(block, test_obcurpoin_but, B_MAKEDISP, "BevOb:", 760,10,150,19, &cu->bevobj, "Curve object name that defines the bevel shape");
|
||||
uiDefIDPoinBut(block, test_obcurpoin_but, B_MAKEDISP, "TaperOb:", 760,-10,150,19, &cu->taperobj, "Curve object name that defines the taper (width)");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiBlockSetCol(block, TH_BUT_SETTING1);
|
||||
|
||||
@@ -1175,7 +1175,7 @@ void exit_editmode(int freedata) /* freedata==0 at render */
|
||||
text_to_curve(base->object, 0);
|
||||
makeDispList(base->object);
|
||||
}
|
||||
if(cu->bevobj== ob) {
|
||||
if(cu->bevobj==ob || cu->taperobj==ob) {
|
||||
makeDispList(base->object);
|
||||
}
|
||||
}
|
||||
@@ -2142,6 +2142,7 @@ void copy_attr(short event)
|
||||
cu1= base->object->data;
|
||||
|
||||
cu1->bevobj= cu->bevobj;
|
||||
cu1->taperobj= cu->taperobj;
|
||||
cu1->width= cu->width;
|
||||
cu1->bevresol= cu->bevresol;
|
||||
cu1->ext1= cu->ext1;
|
||||
@@ -3931,6 +3932,7 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
|
||||
cu= ob->data;
|
||||
|
||||
if(cu->bevobj && (cu->bevobj->flag & SELECT) ) doit= 1;
|
||||
else if(cu->taperobj && (cu->taperobj->flag & SELECT) ) doit= 1;
|
||||
else if(cu->textoncurve) {
|
||||
if(cu->textoncurve->flag & SELECT) doit= 1;
|
||||
else if(ob->flag & SELECT) doit= 1;
|
||||
@@ -3947,6 +3949,8 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
|
||||
|
||||
if(cu->bevobj && (cu->bevobj->flag & SELECT) )
|
||||
makeDispList(ob);
|
||||
else if(cu->taperobj && (cu->taperobj->flag & SELECT) )
|
||||
makeDispList(ob);
|
||||
}
|
||||
|
||||
where_is_object(ob); /* always do, for track etc. */
|
||||
@@ -4561,8 +4565,8 @@ void transform(int mode)
|
||||
if(mode=='w' && G.obedit==0) return;
|
||||
|
||||
if (G.obedit && G.obedit->type == OB_MESH) {
|
||||
undo_push_mesh(transform_mode_to_string(mode));
|
||||
}
|
||||
undo_push_mesh(transform_mode_to_string(mode));
|
||||
}
|
||||
|
||||
/* what data will be involved? */
|
||||
if(G.obedit) {
|
||||
@@ -6142,6 +6146,10 @@ void transform(int mode)
|
||||
if(edge_creases) MEM_freeN(edge_creases);
|
||||
|
||||
tottrans= 0;
|
||||
|
||||
/* undo after transform, since it's storing current situations */
|
||||
//if(canceled==0 && G.obedit==NULL)
|
||||
// BIF_write_undo(transform_mode_to_string(mode));
|
||||
}
|
||||
|
||||
void std_rmouse_transform(void (*xf_func)(int))
|
||||
@@ -6300,6 +6308,7 @@ void single_obdata_users(int flag)
|
||||
case OB_FONT:
|
||||
ob->data= cu= copy_curve(ob->data);
|
||||
ID_NEW(cu->bevobj);
|
||||
ID_NEW(cu->taperobj);
|
||||
makeDispList(ob);
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
|
||||
Reference in New Issue
Block a user