forked from bartvdbraak/blender
New Curves Widget option: curves can get extrapolated extension.
Especially for Compositing it was annoying that colors always got clipped in the 0.0-1.0 range. For this reason, extrapolated Curves now is the default. Old saved files still have horizontal extrapolation. Set the option with 'Tools' menu (wrench icon). This is a setting per curve, so you might need to set all 4 curves for an RGBA curves widget.
This commit is contained in:
parent
a7d3a58ba9
commit
129cab4137
@ -73,6 +73,7 @@ CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, floa
|
||||
cumap->bwmul[0]= cumap->bwmul[1]= cumap->bwmul[2]= 1.0f;
|
||||
|
||||
for(a=0; a<tot; a++) {
|
||||
cumap->cm[a].flag= CUMA_EXTEND_EXTRAPOLATE;
|
||||
cumap->cm[a].totpoint= 2;
|
||||
cumap->cm[a].curve= MEM_callocN(2*sizeof(CurveMapPoint), "curve points");
|
||||
|
||||
@ -278,6 +279,37 @@ static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *nex
|
||||
}
|
||||
}
|
||||
|
||||
/* in X, out Y.
|
||||
X is presumed to be outside first or last */
|
||||
static float curvemap_calc_extend(CurveMap *cuma, float x, float *first, float *last)
|
||||
{
|
||||
if(x <= first[0]) {
|
||||
if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) {
|
||||
/* no extrapolate */
|
||||
return first[1];
|
||||
}
|
||||
else {
|
||||
if(cuma->ext_in[0]==0.0f)
|
||||
return first[1] + cuma->ext_in[1]*10000.0f;
|
||||
else
|
||||
return first[1] + cuma->ext_in[1]*(x - first[0])/cuma->ext_in[0];
|
||||
}
|
||||
}
|
||||
else if(x >= last[0]) {
|
||||
if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) {
|
||||
/* no extrapolate */
|
||||
return last[1];
|
||||
}
|
||||
else {
|
||||
if(cuma->ext_out[0]==0.0f)
|
||||
return last[1] - cuma->ext_out[1]*10000.0f;
|
||||
else
|
||||
return last[1] + cuma->ext_out[1]*(x - last[0])/cuma->ext_out[0];
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* only creates a table for a single channel in CurveMapping */
|
||||
static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
{
|
||||
@ -333,6 +365,7 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
if(nlen>FLT_EPSILON) {
|
||||
VecMulf(vec, hlen/nlen);
|
||||
VecAddf(bezt[0].vec[2], vec, bezt[0].vec[1]);
|
||||
VecSubf(bezt[0].vec[0], bezt[0].vec[1], vec);
|
||||
}
|
||||
}
|
||||
a= cuma->totpoint-1;
|
||||
@ -349,6 +382,7 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
if(nlen>FLT_EPSILON) {
|
||||
VecMulf(vec, hlen/nlen);
|
||||
VecAddf(bezt[a].vec[0], vec, bezt[a].vec[1]);
|
||||
VecSubf(bezt[a].vec[2], bezt[a].vec[1], vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -364,8 +398,23 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2);
|
||||
}
|
||||
|
||||
MEM_freeN(bezt);
|
||||
/* store first and last handle for extrapolation, unit length */
|
||||
cuma->ext_in[0]= bezt[0].vec[0][0] - bezt[0].vec[1][0];
|
||||
cuma->ext_in[1]= bezt[0].vec[0][1] - bezt[0].vec[1][1];
|
||||
range= sqrt(cuma->ext_in[0]*cuma->ext_in[0] + cuma->ext_in[1]*cuma->ext_in[1]);
|
||||
cuma->ext_in[0]/= range;
|
||||
cuma->ext_in[1]/= range;
|
||||
|
||||
a= cuma->totpoint-1;
|
||||
cuma->ext_out[0]= bezt[a].vec[1][0] - bezt[a].vec[2][0];
|
||||
cuma->ext_out[1]= bezt[a].vec[1][1] - bezt[a].vec[2][1];
|
||||
range= sqrt(cuma->ext_out[0]*cuma->ext_out[0] + cuma->ext_out[1]*cuma->ext_out[1]);
|
||||
cuma->ext_out[0]/= range;
|
||||
cuma->ext_out[1]/= range;
|
||||
|
||||
/* cleanup */
|
||||
MEM_freeN(bezt);
|
||||
|
||||
range= CM_TABLEDIV*(cuma->maxtable - cuma->mintable);
|
||||
cuma->range= 1.0f/range;
|
||||
|
||||
@ -373,10 +422,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
fp= allpoints;
|
||||
lastpoint= allpoints + 2*(totpoint-1);
|
||||
cmp= MEM_callocN((CM_TABLE+1)*sizeof(CurveMapPoint), "dist table");
|
||||
cmp[0].x= cuma->mintable;
|
||||
cmp[0].y= allpoints[1];
|
||||
|
||||
for(a=1; a<CM_TABLE; a++) {
|
||||
for(a=0; a<=CM_TABLE; a++) {
|
||||
curf= cuma->mintable + range*(float)a;
|
||||
cmp[a].x= curf;
|
||||
|
||||
@ -384,8 +431,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
while(curf >= fp[0] && fp!=lastpoint) {
|
||||
fp+=2;
|
||||
}
|
||||
if(curf >= fp[0] && fp==lastpoint)
|
||||
cmp[a].y= fp[1];
|
||||
if(fp==allpoints || (curf >= fp[0] && fp==lastpoint))
|
||||
cmp[a].y= curvemap_calc_extend(cuma, curf, allpoints, lastpoint);
|
||||
else {
|
||||
float fac1= fp[0] - fp[-2];
|
||||
float fac2= fp[0] - curf;
|
||||
@ -396,8 +443,6 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
|
||||
cmp[a].y= fac1*fp[-1] + (1.0f-fac1)*fp[1];
|
||||
}
|
||||
}
|
||||
cmp[CM_TABLE].x= cuma->maxtable;
|
||||
cmp[CM_TABLE].y= allpoints[2*totpoint-1];
|
||||
|
||||
MEM_freeN(allpoints);
|
||||
cuma->table= cmp;
|
||||
@ -518,11 +563,16 @@ float curvemap_evaluateF(CurveMap *cuma, float value)
|
||||
/* index in table */
|
||||
fi= (value-cuma->mintable)*cuma->range;
|
||||
i= (int)fi;
|
||||
if(i<0) return cuma->table[0].y;
|
||||
if(i>=CM_TABLE) return cuma->table[CM_TABLE].y;
|
||||
|
||||
fi= fi-(float)i;
|
||||
return (1.0f-fi)*cuma->table[i].y + (fi)*cuma->table[i+1].y;
|
||||
if(fi<0.0f || fi>cuma->range)
|
||||
return curvemap_calc_extend(cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x);
|
||||
else {
|
||||
if(i<0) return cuma->table[0].y;
|
||||
if(i>=CM_TABLE) return cuma->table[CM_TABLE].y;
|
||||
|
||||
fi= fi-(float)i;
|
||||
return (1.0f-fi)*cuma->table[i].y + (fi)*cuma->table[i+1].y;
|
||||
}
|
||||
}
|
||||
|
||||
/* works with curve 'cur' */
|
||||
|
@ -53,11 +53,15 @@ typedef struct CurveMap {
|
||||
|
||||
float range; /* quick multiply value for reading table */
|
||||
float mintable, maxtable; /* the x-axis range for the table */
|
||||
float ext_in[2], ext_out[2]; /* for extrapolated curves, the direction vector */
|
||||
CurveMapPoint *curve; /* actual curve */
|
||||
CurveMapPoint *table; /* display and evaluate table */
|
||||
CurveMapPoint *premultable; /* for RGB curves, premulled table */
|
||||
} CurveMap;
|
||||
|
||||
/* cuma->flag */
|
||||
#define CUMA_EXTEND_EXTRAPOLATE 1
|
||||
|
||||
typedef struct CurveMapping {
|
||||
int flag, cur; /* cur; for buttons, to show active curve */
|
||||
|
||||
@ -68,7 +72,7 @@ typedef struct CurveMapping {
|
||||
float bwmul[3], padf; /* black/white point multiply value, for speed */
|
||||
} CurveMapping;
|
||||
|
||||
/* cumap->flag */
|
||||
/* cumapping->flag */
|
||||
#define CUMA_DO_CLIP 1
|
||||
#define CUMA_PREMULLED 2
|
||||
|
||||
|
@ -403,6 +403,14 @@ static void curvemap_tools_dofunc(void *cumap_v, int event)
|
||||
curvemap_sethandle(cuma, 0);
|
||||
curvemapping_changed(cumap, 0);
|
||||
break;
|
||||
case 4: /* extend horiz */
|
||||
cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
|
||||
curvemapping_changed(cumap, 0);
|
||||
break;
|
||||
case 5: /* extend extrapolate */
|
||||
cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
|
||||
curvemapping_changed(cumap, 0);
|
||||
break;
|
||||
}
|
||||
addqueue(curarea->win, REDRAW, 1);
|
||||
}
|
||||
@ -418,6 +426,8 @@ static uiBlock *curvemap_tools_func(void *cumap_v)
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
|
@ -2187,13 +2187,27 @@ static void ui_draw_but_CURVE(uiBut *but)
|
||||
curvemapping_changed(cumap, 0); /* 0 = no remove doubles */
|
||||
cmp= cuma->table;
|
||||
|
||||
glVertex2f(but->x1, but->y1 + zoomy*(cmp[0].y-offsy)); /* first point */
|
||||
/* first point */
|
||||
if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
|
||||
glVertex2f(but->x1, but->y1 + zoomy*(cmp[0].y-offsy));
|
||||
else {
|
||||
fx= but->x1 + zoomx*(cmp[0].x-offsx + cuma->ext_in[0]);
|
||||
fy= but->y1 + zoomy*(cmp[0].y-offsy + cuma->ext_in[1]);
|
||||
glVertex2f(fx, fy);
|
||||
}
|
||||
for(a=0; a<=CM_TABLE; a++) {
|
||||
fx= but->x1 + zoomx*(cmp[a].x-offsx);
|
||||
fy= but->y1 + zoomy*(cmp[a].y-offsy);
|
||||
glVertex2f(fx, fy);
|
||||
}
|
||||
glVertex2f(but->x2, but->y1 + zoomy*(cmp[CM_TABLE].y-offsy)); /* last point */
|
||||
/* last point */
|
||||
if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0)
|
||||
glVertex2f(but->x2, but->y1 + zoomy*(cmp[CM_TABLE].y-offsy));
|
||||
else {
|
||||
fx= but->x1 + zoomx*(cmp[CM_TABLE].x-offsx - cuma->ext_out[0]);
|
||||
fy= but->y1 + zoomy*(cmp[CM_TABLE].y-offsy - cuma->ext_out[1]);
|
||||
glVertex2f(fx, fy);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* the points, use aspect to make them visible on edges */
|
||||
|
Loading…
Reference in New Issue
Block a user