Grease Pencil: WIP commit (nothing new)
Just a little commit so that I can transfer some changes back over to laptop. * Line drawing should now be improved for most cases, but acute angles still need more work to reduce 'shrinking' artifacts. As such, this is still hidden behind 'rt' setting * Preparation work for Grease-Pencil in Image Editor, and also 'Stick to View' for Image/Sequence editors.
This commit is contained in:
parent
9b29810912
commit
eab746fc5f
@ -43,7 +43,6 @@ struct bGPDframe;
|
||||
/* Temporary 'Stroke Point' data */
|
||||
typedef struct tGPspoint {
|
||||
short x, y; /* x and y coordinates of cursor (in relative to area) */
|
||||
float xf, yf; /* same as x and y, but as floats */
|
||||
float pressure; /* pressure of tablet at this point */
|
||||
} tGPspoint;
|
||||
|
||||
|
@ -28,15 +28,18 @@
|
||||
#ifndef BIF_DRAWGPENCIL_H
|
||||
#define BIF_DRAWGPENCIL_H
|
||||
|
||||
|
||||
struct bGPdata;
|
||||
struct ScrArea;
|
||||
struct View3D;
|
||||
struct SpaceNode;
|
||||
struct SpaceSeq;
|
||||
struct bGPdata;
|
||||
struct uiBlock;
|
||||
struct ImBuf;
|
||||
|
||||
short draw_gpencil_panel(struct uiBlock *block, struct bGPdata *gpd, struct ScrArea *sa);
|
||||
|
||||
void draw_gpencil_2dimage(struct ScrArea *sa, struct ImBuf *ibuf);
|
||||
void draw_gpencil_2dview(struct ScrArea *sa, short onlyv2d);
|
||||
void draw_gpencil_3dview(struct ScrArea *sa, short only3d);
|
||||
void draw_gpencil_oglrender(struct View3D *v3d, int winx, int winy);
|
||||
|
@ -59,8 +59,10 @@ typedef struct bGPDstroke {
|
||||
#define GP_STROKE_3DSPACE (1<<0)
|
||||
/* stroke is in 2d-space */
|
||||
#define GP_STROKE_2DSPACE (1<<1)
|
||||
/* stroke is in 2d-space (but with special 'image' scaling) */
|
||||
#define GP_STROKE_2DIMAGE (1<<2)
|
||||
/* stroke is an "eraser" stroke */
|
||||
#define GP_STROKE_ERASER (1<<2)
|
||||
#define GP_STROKE_ERASER (1<<15)
|
||||
|
||||
|
||||
/* Grease-Pencil Annotations - 'Frame'
|
||||
|
@ -247,6 +247,7 @@ typedef struct SpaceImage {
|
||||
float xof, yof; /* user defined offset, image is centered */
|
||||
float centx, centy; /* storage for offset while render drawing */
|
||||
|
||||
struct bGPdata *gpd; /* grease pencil data */
|
||||
} SpaceImage;
|
||||
|
||||
typedef struct SpaceNla {
|
||||
|
@ -37,6 +37,9 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "BMF_Api.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
@ -317,6 +320,7 @@ enum {
|
||||
GP_DRAWDATA_NOSTATUS = (1<<0), /* don't draw status info */
|
||||
GP_DRAWDATA_ONLY3D = (1<<1), /* only draw 3d-strokes */
|
||||
GP_DRAWDATA_ONLYV2D = (1<<2), /* only draw 'canvas' strokes */
|
||||
GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */
|
||||
};
|
||||
|
||||
/* ----- Tool Buffer Drawing ------ */
|
||||
@ -466,18 +470,22 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
|
||||
}
|
||||
else { /* tesselation code: currently only enabled with rt != 0 */
|
||||
bGPDspoint *pt1, *pt2;
|
||||
float p0[2], p1[2], pm[2];
|
||||
float pm[2];
|
||||
int i;
|
||||
short n;
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
|
||||
glPointSize(3.0f); // temp
|
||||
|
||||
for (n= 0; n < 2; n++) { // temp
|
||||
glBegin((n)?GL_POINTS:GL_QUADS);
|
||||
|
||||
for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) {
|
||||
float s0[2], s1[2]; /* segment 'center' points */
|
||||
float t0[2], t1[2]; /* tesselated coordinates */
|
||||
float m1[2], m2[2]; /* gradient and normal */
|
||||
float pthick, dist; /* thickness at segment point, and length of segment */
|
||||
float sminorang; /* minor angle between strokes */
|
||||
float pthick; /* thickness at segment point */
|
||||
|
||||
/* get x and y coordinates from points */
|
||||
if (sflag & GP_STROKE_2DSPACE) {
|
||||
@ -494,95 +502,75 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
|
||||
/* calculate gradient and normal - 'angle'=(ny/nx) */
|
||||
m1[1]= s1[1] - s0[1];
|
||||
m1[0]= s1[0] - s0[0];
|
||||
dist = Vec2Lenf(s0, s1);
|
||||
m2[1]= -(m1[0]) / dist;
|
||||
m2[0]= m1[1] / dist;
|
||||
m2[1]= -m1[0];
|
||||
m2[0]= m1[1];
|
||||
Normalize2(m2);
|
||||
|
||||
/* if the first segment, initialise the first segment using segment's normal */
|
||||
if (i == 0) {
|
||||
/* always use pressure from first point here */
|
||||
pthick= (pt1->pressure * thickness);
|
||||
|
||||
/* if the first segment, start of segment is segment's normal */
|
||||
if (i == 0) {
|
||||
// TODO: also draw/do a round end-cap first
|
||||
|
||||
p0[0]= s0[0] - (pthick * m2[0]);
|
||||
p0[1]= s0[1] - (pthick * m2[1]);
|
||||
p1[0]= s1[0] + (pthick * m2[0]);
|
||||
p1[1]= s1[1] + (pthick * m2[1]);
|
||||
/* calculate points for start of segment */
|
||||
t0[0]= s0[0] - (pthick * m2[0]);
|
||||
t0[1]= s0[1] - (pthick * m2[1]);
|
||||
t1[0]= s0[0] + (pthick * m2[0]);
|
||||
t1[1]= s0[1] + (pthick * m2[1]);
|
||||
|
||||
Vec2Copyf(pm, m1);
|
||||
/* draw this line only once */
|
||||
glVertex2fv(t0);
|
||||
glVertex2fv(t1);
|
||||
}
|
||||
/* if not the first segment, use bisector of angle between segments */
|
||||
else {
|
||||
float mb[2]; /* bisector normal */
|
||||
|
||||
/* calculate gradient of bisector (as average of normals) */
|
||||
mb[0]= (pm[0] + m2[0]) / 2;
|
||||
mb[1]= (pm[1] + m2[1]) / 2;
|
||||
Normalize2(mb);
|
||||
|
||||
/* calculate points for start of segment */
|
||||
// FIXME: do we need extra padding for acute angles?
|
||||
t0[0]= s0[0] - (pthick * mb[0]);
|
||||
t0[1]= s0[1] - (pthick * mb[1]);
|
||||
t1[0]= s0[0] + (pthick * mb[0]);
|
||||
t1[1]= s0[1] + (pthick * mb[1]);
|
||||
|
||||
/* draw this line twice (once for end of current segment, and once for start of next) */
|
||||
glVertex2fv(t1);
|
||||
glVertex2fv(t0);
|
||||
glVertex2fv(t0);
|
||||
glVertex2fv(t1);
|
||||
}
|
||||
|
||||
/* if the minor angle between the current segment and the previous one is less than 90 degrees */
|
||||
if (i)
|
||||
sminorang= NormalizedVecAngle2_2D(pm, m1);
|
||||
else
|
||||
sminorang= 0.0f;
|
||||
|
||||
if ((IS_EQ(sminorang, 0)==0) && (abs(sminorang) < M_PI_2) )
|
||||
{
|
||||
float closep[2];
|
||||
|
||||
/* recalculate startpoint of segment, where the new start-line:
|
||||
* - starts a new gl-quad-strip
|
||||
* - uses the vert of old startpoint closer to our endpoint
|
||||
* - distance between new startpoints = distance between old startpoints
|
||||
* - new startpoints occur on same gradient as old segment does (has potential for some 'minor' overlap, but ok)
|
||||
*/
|
||||
|
||||
/* find the closer vertex, and distance between startpoints */
|
||||
if (Vec2Lenf(p0, s1) > Vec2Lenf(p1, s1))
|
||||
Vec2Copyf(closep, p1);
|
||||
else
|
||||
Vec2Copyf(closep, p0);
|
||||
|
||||
/* determine which side this closer vertex should be on */
|
||||
pthick= (pt1->pressure * thickness * 2);
|
||||
if ( ((closep[0] - s0[0]) > 0) || ((closep[1] - s0[1]) > 0) ) {
|
||||
/* assumes this is the 'second' point, (i.e. the 'plus' one), so the other is subtracting */
|
||||
p0[0]= closep[0] - (pthick * pm[0]);
|
||||
p0[1]= closep[1] - (pthick * pm[1]);
|
||||
p1[0]= closep[0];
|
||||
p1[1]= closep[1];
|
||||
}
|
||||
else if ( ((closep[0] - s0[0]) < 0) || ((closep[1] - s0[1]) < 0) ) {
|
||||
/* assumes this is the 'first' point, (i.e. the 'minus' one), so the other is adding */
|
||||
p0[0]= closep[0];
|
||||
p0[1]= closep[1];
|
||||
p1[0]= closep[0] + (pthick * pm[0]);
|
||||
p1[1]= closep[1] + (pthick * pm[1]);
|
||||
}
|
||||
|
||||
/* reset gl-states! */
|
||||
glEnd();
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
}
|
||||
|
||||
/* do the end of this segment */
|
||||
/* if last segment, also draw end of segment (defined as segment's normal) */
|
||||
if (i == totpoints-2) {
|
||||
/* for once, we use second point's pressure (otherwise it won't be drawn) */
|
||||
pthick= (pt2->pressure * thickness);
|
||||
|
||||
/* calculate points for end of segment */
|
||||
t0[0]= s1[0] - (pthick * m2[0]);
|
||||
t0[1]= s1[1] - (pthick * m2[1]);
|
||||
t1[0]= s1[0] + (pthick * m2[0]);
|
||||
t1[1]= s1[1] + (pthick * m2[1]);
|
||||
|
||||
/* draw this segment */
|
||||
glVertex2f(p0[0], p0[1]);
|
||||
glVertex2f(p1[0], p1[1]);
|
||||
glVertex2f(t0[0], t0[1]);
|
||||
glVertex2f(t1[0], t1[1]);
|
||||
|
||||
// TODO: draw end cap if last segment
|
||||
if (i == totpoints-2) {
|
||||
/* draw this line only once */
|
||||
glVertex2fv(t1);
|
||||
glVertex2fv(t0);
|
||||
|
||||
// TODO: draw end cap as last step
|
||||
}
|
||||
|
||||
/* store current points for next segment to use */
|
||||
Vec2Copyf(p0, t0);
|
||||
Vec2Copyf(p1, t1);
|
||||
Vec2Copyf(pm, m1);
|
||||
/* store stroke's 'natural' normal for next stroke to use */
|
||||
Vec2Copyf(pm, m2);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/* draw debug points of curve on top? (original stroke points) */
|
||||
if (debug) {
|
||||
@ -626,6 +614,10 @@ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, shor
|
||||
continue;
|
||||
if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
|
||||
continue;
|
||||
if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
|
||||
continue;
|
||||
if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
|
||||
continue;
|
||||
if ((gps->points == 0) || (gps->totpoints < 1))
|
||||
continue;
|
||||
|
||||
@ -796,6 +788,22 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
|
||||
|
||||
/* ----- Grease Pencil Sketches Drawing API ------ */
|
||||
|
||||
/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
|
||||
void draw_gpencil_2dimage (ScrArea *sa, ImBuf *ibuf)
|
||||
{
|
||||
bGPdata *gpd;
|
||||
int dflag = 0;
|
||||
|
||||
/* check that we have grease-pencil stuff to draw */
|
||||
if (ELEM(NULL, sa, ibuf)) return;
|
||||
gpd= gpencil_data_getactive(sa);
|
||||
if (gpd == NULL) return;
|
||||
|
||||
/* draw it! */
|
||||
dflag = (GP_DRAWDATA_ONLYI2D|GP_DRAWDATA_NOSTATUS);
|
||||
gp_draw_data(gpd, sa->winx, sa->winy, dflag);
|
||||
}
|
||||
|
||||
/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
|
||||
* Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes
|
||||
*/
|
||||
|
@ -39,6 +39,9 @@
|
||||
|
||||
#include "BMF_Api.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
@ -312,11 +315,17 @@ bGPdata *gpencil_data_getactive (ScrArea *sa)
|
||||
{
|
||||
SpaceSeq *sseq= sa->spacedata.first;
|
||||
|
||||
/* only applicable for "Image Preview" mode */
|
||||
/* only applicable for image modes */
|
||||
if (sseq->mainb)
|
||||
return sseq->gpd;
|
||||
}
|
||||
break;
|
||||
case SPACE_IMAGE:
|
||||
{
|
||||
SpaceImage *sima= sa->spacedata.first;
|
||||
return sima->gpd;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* nothing found */
|
||||
@ -379,6 +388,17 @@ short gpencil_data_setactive (ScrArea *sa, bGPdata *gpd)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPACE_IMAGE:
|
||||
{
|
||||
SpaceImage *sima= sa->spacedata.first;
|
||||
|
||||
if (sima->gpd)
|
||||
free_gpencil_data(sima->gpd);
|
||||
sima->gpd= gpd;
|
||||
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* failed to add */
|
||||
@ -589,7 +609,7 @@ void gpencil_layer_delactive (bGPdata *gpd)
|
||||
}
|
||||
|
||||
/* ************************************************** */
|
||||
/* GREASE-PENCIL EDITING MODE - Tools */
|
||||
/* GREASE-PENCIL EDITING - Tools */
|
||||
|
||||
/* --------- Data Deletion ---------- */
|
||||
|
||||
@ -679,6 +699,7 @@ void gpencil_delete_menu (void)
|
||||
typedef struct tGPsdata {
|
||||
ScrArea *sa; /* area where painting originated */
|
||||
View2D *v2d; /* needed for GP_STROKE_2DSPACE */
|
||||
ImBuf *ibuf; /* needed for GP_STROKE_2DIMAGE */
|
||||
|
||||
bGPdata *gpd; /* gp-datablock layer comes from */
|
||||
bGPDlayer *gpl; /* layer we're working on */
|
||||
@ -800,6 +821,16 @@ static void gp_session_initpaint (tGPsdata *p)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPACE_IMAGE:
|
||||
{
|
||||
SpaceImage *sima= curarea->spacedata.first;
|
||||
|
||||
/* set the current area */
|
||||
p->sa= curarea;
|
||||
p->v2d= &sima->v2d;
|
||||
//p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
|
||||
}
|
||||
break;
|
||||
/* unsupported views */
|
||||
default:
|
||||
{
|
||||
@ -869,6 +900,7 @@ static short gp_stroke_filtermval (tGPsdata *p, short mval[2], short pmval[2])
|
||||
return 1;
|
||||
|
||||
/* check if the distance since the last point is significant enough */
|
||||
// future optimisation: sqrt here may be too slow?
|
||||
else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX)
|
||||
return 1;
|
||||
|
||||
@ -884,7 +916,7 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[])
|
||||
|
||||
/* in 3d-space - pt->x/y/z are 3 side-by-side floats */
|
||||
if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) {
|
||||
short mx=mval[0], my=mval[1];
|
||||
const short mx=mval[0], my=mval[1];
|
||||
float *fp= give_cursor();
|
||||
float dvec[3];
|
||||
|
||||
@ -904,6 +936,26 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[])
|
||||
out[1]= y;
|
||||
}
|
||||
|
||||
/* 2d - on image 'canvas' (asume that p->v2d is set) */
|
||||
else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) &&
|
||||
(p->v2d) && (p->ibuf) )
|
||||
{
|
||||
ImBuf *ibuf= p->ibuf;
|
||||
float x, y;
|
||||
|
||||
/* convert to 'canvas' coordinates, then adjust for view */
|
||||
areamouseco_to_ipoco(p->v2d, mval, &x, &y);
|
||||
|
||||
if (ibuf) {
|
||||
out[0]= x*ibuf->x;
|
||||
out[1]= y*ibuf->y;
|
||||
}
|
||||
else {
|
||||
out[0]= x;
|
||||
out[1]= y;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2d - relative to screen (viewport area) */
|
||||
else {
|
||||
out[0] = (float)(mval[0]) / (float)(p->sa->winx) * 1000;
|
||||
@ -927,8 +979,6 @@ static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure)
|
||||
/* store settings */
|
||||
pt->x= mval[0];
|
||||
pt->y= mval[1];
|
||||
pt->xf= (float)mval[0];
|
||||
pt->yf= (float)mval[0];
|
||||
pt->pressure= pressure;
|
||||
|
||||
/* increment counters */
|
||||
|
Loading…
Reference in New Issue
Block a user