Code Cleanups: A bunch of tweaks to tidy up things from the GPencil Fill patch
authorJoshua Leung <aligorith@gmail.com>
Thu, 28 Apr 2016 15:12:53 +0000 (03:12 +1200)
committerJoshua Leung <aligorith@gmail.com>
Sun, 8 May 2016 12:53:48 +0000 (00:53 +1200)
source/blender/blenloader/intern/readfile.c
source/blender/editors/gpencil/drawgpencil.c
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesrna/intern/rna_gpencil.c

index 9c3091f186bb8aed1af82b5d22e18a445243a154..678fd84de9406af1a49f023a58aabf27e413c5c2 100644 (file)
@@ -6159,9 +6159,11 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
                        
                        for (gps = gpf->strokes.first; gps; gps = gps->next) {
                                gps->points = newdataadr(fd, gps->points);
+                               
                                /* the triangulation is not saved, so need to be recalculated */
-                               gps->triangles = NULL;
                                gps->flag |= GP_STROKE_RECALC_CACHES;
+                               gps->triangles = NULL;
+                               gps->tot_triangles = 0;
                        }
                }
        }
index 3f7805fa2c42f0b8d0e0a7c1d92859d2ad47d05e..c885842e756ed7395f232d1f7dc20a730de5497d 100644 (file)
@@ -328,128 +328,134 @@ static void gp_draw_stroke_volumetric_3d(bGPDspoint *points, int totpoints, shor
 
 
 /* --------------- Stroke Fills ----------------- */
-/* get points of stroke always flat to view not affected by camera view or view position
- */
+
+/* Get points of stroke always flat to view not affected by camera view or view position */
 static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
 {
        bGPDspoint *pt0 = &points[0];
        bGPDspoint *pt1 = &points[1];
-       bGPDspoint *pt3 = &points[(int) (totpoints * 0.75)];
-       bGPDspoint *pt;
+       bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+       
        float locx[3];
        float locy[3];
        float loc3[3];
        float normal[3];
-
+       
        /* local X axis (p0-p1) */
        sub_v3_v3v3(locx, &pt1->x, &pt0->x);
-
+       
        /* point vector at 3/4 */
        sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
-
+       
        /* vector orthogonal to polygon plane */
        cross_v3_v3v3(normal, locx, loc3);
-
+       
        /* local Y axis (cross to normal/x axis) */
        cross_v3_v3v3(locy, normal, locx);
-
+       
        /* Normalize vectors */
        normalize_v3(locx);
        normalize_v3(locy);
-
+       
        /* Get all points in local space */
-       for (int i = 0; i < totpoints; i++)     {
-
+       for (int i = 0; i < totpoints; i++) {
+               bGPDspoint *pt = &points[i];
                float loc[3];
+               
                /* Get local space using first point as origin */
-               pt = &points[i];
                sub_v3_v3v3(loc, &pt->x, &pt0->x);
-
-               float co[2];
-               co[0] = dot_v3v3(loc, locx);
-               co[1] = dot_v3v3(loc, locy);
-               points2d[i][0] = co[0];
-               points2d[i][1] = co[1];
+               
+               points2d[i][0] = dot_v3v3(loc, locx);
+               points2d[i][1] = dot_v3v3(loc, locy);
        }
-
+       
        *r_direction = (int)locy[2];
 }
 
 
-/* triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
+/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */
 static void gp_triangulate_stroke_fill(bGPDstroke *gps)
 {
        BLI_assert(gps->totpoints >= 3);
-
-       bGPDtriangle *stroke_triangle;
-       int i;
-
+       
        /* allocate memory for temporary areas */
-       unsigned int(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->totpoints, "GP Stroke temp triangulation");
-       float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
-
+       unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->totpoints, "GP Stroke temp triangulation");
+       float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
+       
        int direction;
-
+       
        /* convert to 2d and triangulate */
        gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
        BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)gps->totpoints, direction, (unsigned int(*)[3])tmp_triangles);
-
+       
        /* count number of valid triangles */
        gps->tot_triangles = 0;
-       for (i = 0; i < gps->totpoints; i++) {
+       for (int i = 0; i < gps->totpoints; i++) {
                if ((tmp_triangles[i][0] >= 0) && (tmp_triangles[i][0] < gps->totpoints) &&
                        (tmp_triangles[i][1] >= 0) && (tmp_triangles[i][1] < gps->totpoints) &&
                        (tmp_triangles[i][2] >= 0) && (tmp_triangles[i][2] < gps->totpoints))
                {
-                       gps->tot_triangles += 1;
+                       gps->tot_triangles++;
                }
        }
-
+       
        /* save triangulation data in stroke cache */
-       if (gps->triangles == NULL) {
-               gps->triangles = MEM_callocN(sizeof(bGPDtriangle) * gps->tot_triangles, "GP Stroke triangulation");
+       if (gps->tot_triangles > 0) {
+               if (gps->triangles == NULL) {
+                       gps->triangles = MEM_callocN(sizeof(bGPDtriangle) * gps->tot_triangles, "GP Stroke triangulation");
+               }
+               else {
+                       gps->triangles = MEM_recallocN(gps->triangles, sizeof(bGPDtriangle) * gps->tot_triangles);
+               }
+               
+               for (int i = 0; i < gps->tot_triangles; i++) {
+                       if ((tmp_triangles[i][0] >= 0) && (tmp_triangles[i][0] < gps->totpoints) &&
+                           (tmp_triangles[i][1] >= 0) && (tmp_triangles[i][1] < gps->totpoints) &&
+                           (tmp_triangles[i][2] >= 0) && (tmp_triangles[i][2] < gps->totpoints))
+                       {
+                               bGPDtriangle *stroke_triangle = &gps->triangles[i];
+                               
+                               stroke_triangle->v1 = tmp_triangles[i][0];
+                               stroke_triangle->v2 = tmp_triangles[i][1];
+                               stroke_triangle->v3 = tmp_triangles[i][2];
+                       }
+               }
        }
        else {
-               gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
-       }
-
-       for (i = 0; i < gps->tot_triangles; i++) {
-               if ((tmp_triangles[i][0] >= 0) && (tmp_triangles[i][0] < gps->totpoints) &&
-                       (tmp_triangles[i][1] >= 0) && (tmp_triangles[i][1] < gps->totpoints) &&
-                       (tmp_triangles[i][2] >= 0) && (tmp_triangles[i][2] < gps->totpoints))
-               {
-                       stroke_triangle = &gps->triangles[i];
-                       stroke_triangle->v1 = tmp_triangles[i][0];
-                       stroke_triangle->v2 = tmp_triangles[i][1];
-                       stroke_triangle->v3 = tmp_triangles[i][2];
-               }
+               /* No triangles needed - Free anything allocated previously */
+               if (gps->triangles)
+                       MEM_freeN(gps->triangles);
+                       
+               gps->triangles = NULL;
        }
-       /* disable recalculation flag (False)*/
+       
+       /* disable recalculation flag */
        if (gps->flag & GP_STROKE_RECALC_CACHES) {
-               gps->flag ^= GP_STROKE_RECALC_CACHES;
+               gps->flag &= ~GP_STROKE_RECALC_CACHES;
        }
+       
        /* clear memory */
        if (tmp_triangles) MEM_freeN(tmp_triangles);
        if (points2d) MEM_freeN(points2d);
-
 }
 
 
 /* draw fills for shapes */
 static void gp_draw_stroke_fill(bGPDstroke *gps, short UNUSED(thickness), short dflag, int offsx, int offsy, int winx, int winy)
 {
-       int i;
-
        BLI_assert(gps->totpoints >= 3);
+       
        /* Triangulation fill if high quality flag is enabled */
        if (dflag & GP_DRAWDATA_HQ_FILL) {
                bGPDtriangle *stroke_triangle;
                bGPDspoint *pt;
-
+               int i;
+               
                /* Calculate triangles cache for filling area (must be done only after changes) */
                if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
                        gp_triangulate_stroke_fill(gps);
                }
+               
                /* Draw all triangles for filling the polygon (cache must be calculated before) */
                BLI_assert(gps->tot_triangles >= 1);
                glBegin(GL_TRIANGLES);
@@ -458,23 +464,28 @@ static void gp_draw_stroke_fill(bGPDstroke *gps, short UNUSED(thickness), short
                                /* vertex 1 */
                                pt = &gps->points[stroke_triangle->v1];
                                glVertex3fv(&pt->x);
+                               
                                /* vertex 2 */
                                pt = &gps->points[stroke_triangle->v2];
                                glVertex3fv(&pt->x);
+                               
                                /* vertex 3 */
                                pt = &gps->points[stroke_triangle->v3];
                                glVertex3fv(&pt->x);
                        }
                        else {
                                float co[2];
+                               
                                /* vertex 1 */
                                pt = &gps->points[stroke_triangle->v1];
                                gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
                                glVertex2fv(co);
+                               
                                /* vertex 2 */
                                pt = &gps->points[stroke_triangle->v2];
                                gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
                                glVertex2fv(co);
+                               
                                /* vertex 3 */
                                pt = &gps->points[stroke_triangle->v3];
                                gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
@@ -486,11 +497,17 @@ static void gp_draw_stroke_fill(bGPDstroke *gps, short UNUSED(thickness), short
        else {
                /* As an initial implementation, we use the OpenGL filled polygon drawing
                 * here since it's the easiest option to implement for this case. It does
-                * come with limitations (notably for concave shapes), though it shouldn't
-                * be much of an issue in most cases.
+                * come with limitations (notably for concave shapes), though it works well
+                * enough for many simple situations.
+                *
+                * We keep this legacy implementation around despite now having the high quality
+                * fills, as this is necessary for keeping everything working nicely for files
+                * created using old versions of Blender which may have depended on the artifacts
+                * the old fills created.
                 */
                bGPDspoint *pt;
-
+               int i;
+               
                glBegin(GL_POLYGON);
                for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
                        if (gps->flag & GP_STROKE_3DSPACE) {
@@ -498,12 +515,11 @@ static void gp_draw_stroke_fill(bGPDstroke *gps, short UNUSED(thickness), short
                        }
                        else {
                                float co[2];
-
+                               
                                gp_calc_2d_stroke_xy(pt, gps->flag, offsx, offsy, winx, winy, co);
                                glVertex2fv(co);
                        }
                }
-
                glEnd();
        }
 }
index e1f9a99c61098de8bdefe746807acc981f4d7307..ab0fcb81379321f0c93e5aa4036caf948ec3a950 100644 (file)
@@ -59,7 +59,7 @@ typedef enum eGPDspoint_Flag {
 
 /* Grease-Pencil Annotations - 'Triangle'
  *     -> A triangle contains the index of three vertices for filling the stroke
- *        this is only used if high quality fill is enabled
+ *        This is only used if high quality fill is enabled
  */
 typedef struct bGPDtriangle {
        int v1, v2, v3;         /* indices for tesselated triangle used for GP Fill */
@@ -77,6 +77,7 @@ typedef struct bGPDstroke {
        
        short thickness;                /* thickness of stroke (currently not used) */
        short flag;                             /* various settings about this stroke */
+       
        bGPDtriangle *triangles;/* tesselated triangles for GP Fill */
        int tot_triangles;      /* number of triangles in array */
        short  pad2[2];         /* avoid compiler align error */
@@ -94,7 +95,7 @@ typedef enum eGPDstroke_Flag {
        GP_STROKE_2DIMAGE               = (1 << 2),
        /* stroke is selected */
        GP_STROKE_SELECT                = (1 << 3),
-       /* Recalculate triangulation for high quality fill (true force a new recalc) */
+       /* Recalculate triangulation for high quality fill (when true, force a new recalc) */
        GP_STROKE_RECALC_CACHES = (1 << 4),
        /* only for use with stroke-buffer (while drawing eraser) */
        GP_STROKE_ERASER                = (1 << 15)
@@ -173,7 +174,7 @@ typedef enum eGPDlayer_Flag {
        GP_LAYER_GHOST_NEXTCOL  = (1 << 9),
        /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
        GP_LAYER_VOLUMETRIC             = (1 << 10),
-       /* Use High quality fill using stencil */
+       /* Use high quality fill (instead of buggy legacy OpenGL Fill) */
        GP_LAYER_HQ_FILL        = (1 << 11)
 } eGPDlayer_Flag;
 
index 6f67a4c992f231ee3eb7c98bf6a242281fcd2595..10d7efe93740705a1b3f1e3e62b94eda98ca744c 100644 (file)
@@ -721,10 +721,10 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect");
        RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
        
-       /* Use High quality fill */
+       /* Use High Quality Fill */
        prop = RNA_def_property(srna, "use_hq_fill", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HQ_FILL);
-       RNA_def_property_ui_text(prop, "High Quality Fill", "Fill strokes using high quality to avoid glitches (slower fps during animation play)");
+       RNA_def_property_ui_text(prop, "High Quality Fill", "Fill strokes using high quality method to avoid glitches (slower fps during animation playback)");
        RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
 
        /* Stroke Drawing Color */