Revision: 15931
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15931
Author:   aligorith
Date:     2008-08-03 13:55:45 +0200 (Sun, 03 Aug 2008)

Log Message:
-----------
Grease Pencil Drawing:

Some WIP code for 'nicer' drawing of thick 2d-strokes that will hopefully 
result in smoother lines, particularly with abrupt direction changes. Currently 
the code is hidden behind the rt button (for rt != 0), as in some cases, it 
still looks rather bad.

Modified Paths:
--------------
    trunk/blender/source/blender/src/drawgpencil.c

Modified: trunk/blender/source/blender/src/drawgpencil.c
===================================================================
--- trunk/blender/source/blender/src/drawgpencil.c      2008-08-03 11:40:09 UTC 
(rev 15930)
+++ trunk/blender/source/blender/src/drawgpencil.c      2008-08-03 11:55:45 UTC 
(rev 15931)
@@ -310,6 +310,8 @@
 /* ************************************************** */
 /* GREASE PENCIL DRAWING */
 
+/* ----- General Defines ------ */
+
 /* flags for sflag */
 enum {
        GP_DRAWDATA_NOSTATUS    = (1<<0),       /* don't draw status info */
@@ -317,7 +319,9 @@
        GP_DRAWDATA_ONLYV2D             = (1<<2),       /* only draw 'canvas' 
strokes */
 };
 
-/* draw stroke in buffer */
+/* ----- Tool Buffer Drawing ------ */
+
+/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted 
lines) */
 static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short 
thickness, short dflag, short sflag)
 {
        tGPspoint *pt;
@@ -377,115 +381,232 @@
        }
 }
 
-/* draw a given stroke */
-static void gp_draw_stroke (bGPDspoint *points, int totpoints, short 
thickness, short dflag, short sflag, short debug, int winx, int winy)
+/* ----- Existing Strokes Drawing (3D and Point) ------ */
+
+/* draw a given stroke - just a single dot (only one point) */
+static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, 
int winy)
 {
+       /* draw point */
+       if (sflag & GP_STROKE_3DSPACE) {
+               glBegin(GL_POINTS);
+                       glVertex3f(points->x, points->y, points->z);
+               glEnd();
+       }
+       else if (sflag & GP_STROKE_2DSPACE) {
+               glBegin(GL_POINTS);
+                       glVertex2f(points->x, points->y);
+               glEnd();
+       }
+       else {
+               const float x= (points->x / 1000 * winx);
+               const float y= (points->y / 1000 * winy);
+               
+               glBegin(GL_POINTS);
+                       glVertex2f(x, y);
+               glEnd();
+       }
+}
+
+/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
+static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short 
thickness, short dflag, short sflag, short debug, int winx, int winy)
+{
        bGPDspoint *pt;
+       float oldpressure = 0.0f;
        int i;
        
-       /* error checking */
-       if ((points == NULL) || (totpoints <= 0))
-               return;
-       
-       /* check if stroke can be drawn */
-       if ((dflag & GP_DRAWDATA_ONLY3D) && !(sflag & GP_STROKE_3DSPACE))
-               return;
-       if (!(dflag & GP_DRAWDATA_ONLY3D) && (sflag & GP_STROKE_3DSPACE))
-               return;
-       if ((dflag & GP_DRAWDATA_ONLYV2D) && !(sflag & GP_STROKE_2DSPACE))
-               return;
-       if (!(dflag & GP_DRAWDATA_ONLYV2D) && (sflag & GP_STROKE_2DSPACE))
-               return;
-       
-       /* if drawing a single point, draw it larger */
-       if (totpoints == 1) {           
-               /* draw point */
-               if (sflag & GP_STROKE_3DSPACE) {
-                       glBegin(GL_POINTS);
-                               glVertex3f(points->x, points->y, points->z);
+       /* draw stroke curve */
+       glBegin(GL_LINE_STRIP);
+       for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+               if (fabs(pt->pressure - oldpressure) > 0.2f) {
                        glEnd();
-               }
-               else if (sflag & GP_STROKE_2DSPACE) {
-                       glBegin(GL_POINTS);
-                               glVertex2f(points->x, points->y);
-                       glEnd();
-               }
-               else {
-                       const float x= (points->x / 1000 * winx);
-                       const float y= (points->y / 1000 * winy);
+                       glLineWidth(pt->pressure * thickness);
+                       glBegin(GL_LINE_STRIP);
                        
-                       glBegin(GL_POINTS);
-                               glVertex2f(x, y);
-                       glEnd();
+                       glVertex3f(pt->x, pt->y, pt->z);
+                       
+                       oldpressure = pt->pressure;
                }
+               else
+                       glVertex3f(pt->x, pt->y, pt->z);
        }
-       else {
-               float oldpressure = 0.0f;
+       glEnd();
+       
+       /* draw debug points of curve on top? */
+       if (debug) {
+               glBegin(GL_POINTS);
+               for (i=0, pt=points; i < totpoints && pt; i++, pt++)
+                       glVertex3f(pt->x, pt->y, pt->z);
+               glEnd();
+       }
+}
+
+/* ----- Fancy 2D-Stroke Drawing ------ */
+
+/* draw a given stroke in 2d */
+static void gp_draw_stroke (bGPDspoint *points, int totpoints, short 
thickness, short dflag, short sflag, short debug, int winx, int winy)
+{      
+       /* if thickness is less than 3, 'smooth' opengl lines look better */
+       if ((thickness < 3) || (G.rt==0)) {
+               bGPDspoint *pt;
+               int i;
                
-               /* draw stroke curve */
                glBegin(GL_LINE_STRIP);
                for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
-                       float x, y, z;
+                       if (sflag & GP_STROKE_2DSPACE) {
+                               glVertex2f(pt->x, pt->y);
+                       }
+                       else {
+                               const float x= (pt->x / 1000 * winx);
+                               const float y= (pt->y / 1000 * winy);
+                               
+                               glVertex2f(x, y);
+                       }
+               }
+               glEnd();
+       }
+       else { /* tesselation code: currently only enabled with rt != 0 */
+               bGPDspoint *pt1, *pt2;
+               float p0[2], p1[2], pm[2];
+               int i;
+               
+               glShadeModel(GL_FLAT);
+               glBegin(GL_QUAD_STRIP);
+               
+               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 */
                        
-                       if (sflag & GP_STROKE_3DSPACE) {
-                               x= pt->x;
-                               y= pt->y;
-                               z= pt->z;
+                       /* get x and y coordinates from points */
+                       if (sflag & GP_STROKE_2DSPACE) {
+                               s0[0]= pt1->x;          s0[1]= pt1->y;
+                               s1[0]= pt2->x;          s1[1]= pt2->y;
                        }
-                       else if (sflag & GP_STROKE_2DSPACE) {
-                               x= pt->x;
-                               y= pt->y;
-                               z= 0;
-                       }
                        else {
-                               x= (pt->x / 1000 * winx);
-                               y= (pt->y / 1000 * winy);
-                               z= 0;
+                               s0[0]= (pt1->x / 1000 * winx);
+                               s0[1]= (pt1->y / 1000 * winy);
+                               s1[0]= (pt2->x / 1000 * winx);
+                               s1[1]= (pt2->y / 1000 * winy);
+                       }               
+                       
+                       /* 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;
+                       
+                       /* if the first segment, initialise the first segment 
using segment's normal */
+                       if (i == 0) {   
+                               pthick= (pt1->pressure * thickness);
+                               
+                               // 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]);
+                               
+                               Vec2Copyf(pm, m1);
                        }
                        
-                       if (fabs(pt->pressure - oldpressure) > 0.2f) {
-                               glEnd();
-                               glLineWidth(pt->pressure * thickness);
-                               glBegin(GL_LINE_STRIP);
+                       /* 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];
                                
-                               if (sflag & GP_STROKE_3DSPACE) 
-                                       glVertex3f(x, y, z);
+                               /* 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
-                                       glVertex2f(x, y);
+                                       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]);
+                               }
                                
-                               oldpressure = pt->pressure;
+                               /* reset gl-states! */
+                               glEnd();
+                               glBegin(GL_QUAD_STRIP);                         
                        }
-                       else {
-                               if (sflag & GP_STROKE_3DSPACE) 
-                                       glVertex3f(x, y, z);
-                               else
-                                       glVertex2f(x, y);
+                       
+                       /* do the end of this segment */
+                       pthick= (pt2->pressure * thickness);
+                       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) {
+                       
                        }
+                       
+                       /* store current points for next segment to use */
+                       Vec2Copyf(p0, t0);
+                       Vec2Copyf(p1, t1);
+                       Vec2Copyf(pm, m1);
                }
+               
                glEnd();
+       }
+       
+       /* draw debug points of curve on top? (original stroke points) */
+       if (debug) {
+               bGPDspoint *pt;
+               int i;
                
-               /* draw debug points of curve on top? */
-               if (debug) {
-                       glBegin(GL_POINTS);
-                       for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
-                               if (sflag & GP_STROKE_3DSPACE) {
-                                       glVertex3f(pt->x, pt->y, pt->z);
-                               }
-                               else if (sflag & GP_STROKE_2DSPACE) {
-                                       glVertex2f(pt->x, pt->y);
-                               }
-                               else {
-                                       const float x= (pt->x / 1000 * winx);
-                                       const float y= (pt->y / 1000 * winy);
-                                       
-                                       glVertex2f(x, y);
-                               }
+               glBegin(GL_POINTS);
+               for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+                       if (sflag & GP_STROKE_2DSPACE) {
+                               glVertex2f(pt->x, pt->y);
                        }
-                       glEnd();
+                       else {
+                               const float x= (pt->x / 1000 * winx);
+                               const float y= (pt->y / 1000 * winy);
+                               
+                               glVertex2f(x, y);
+                       }
                }
+               glEnd();
        }
 }
 
+/* ----- General Drawing ------ */
+
 /* draw a set of strokes */
 static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, 
short debug, 
                                                         short lthick, float 
color[4])
@@ -495,9 +616,26 @@
        /* set color first (may need to reset it again later too) */
        glColor4f(color[0], color[1], color[2], color[3]);
        
-       for (gps= gpf->strokes.first; gps; gps= gps->next) {    
-               /* just draw the stroke once */
-               gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, 
gps->flag, debug, winx, winy);
+       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+               /* check if stroke can be drawn */
+               if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & 
GP_STROKE_3DSPACE))
+                       continue;
+               if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & 
GP_STROKE_3DSPACE))
+                       continue;
+               if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & 
GP_STROKE_2DSPACE))
+                       continue;

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to