Revision: 46526
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=46526
Author:   nicholasbishop
Date:     2012-05-10 20:35:32 +0000 (Thu, 10 May 2012)
Log Message:
-----------
Add mask brush for sculpt mode.

The mask brush currently has two modes, 'draw' and 'smooth'.

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
    trunk/blender/source/blender/editors/sculpt_paint/sculpt.c
    trunk/blender/source/blender/makesdna/DNA_brush_types.h
    trunk/blender/source/blender/makesrna/intern/rna_brush.c

Modified: trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py 
2012-05-10 20:35:12 UTC (rev 46525)
+++ trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py 
2012-05-10 20:35:32 UTC (rev 46526)
@@ -575,6 +575,9 @@
 
                 row.prop(brush, "sculpt_plane", text="")
 
+            if brush.sculpt_tool == 'MASK':
+                col.prop(brush, "mask_tool", text="")
+
             # plane_offset, use_offset_pressure, use_plane_trim, plane_trim
             if capabilities.has_plane_offset:
                 row = col.row(align=True)

Modified: trunk/blender/source/blender/editors/sculpt_paint/sculpt.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/sculpt.c  2012-05-10 
20:35:12 UTC (rev 46525)
+++ trunk/blender/source/blender/editors/sculpt_paint/sculpt.c  2012-05-10 
20:35:32 UTC (rev 46526)
@@ -291,10 +291,14 @@
                        PBVHVertexIter vd;
 
                        BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, 
PBVH_ITER_UNIQUE) {
-                               copy_v3_v3(vd.co, unode->co[vd.i]);
-                               if (vd.no) copy_v3_v3_short(vd.no, 
unode->no[vd.i]);
-                               else normal_short_to_float_v3(vd.fno, 
unode->no[vd.i]);
-
+                               if (unode->type == SCULPT_UNDO_COORDS) {
+                                       copy_v3_v3(vd.co, unode->co[vd.i]);
+                                       if (vd.no) copy_v3_v3_short(vd.no, 
unode->no[vd.i]);
+                                       else normal_short_to_float_v3(vd.fno, 
unode->no[vd.i]);
+                               }
+                               else if (unode->type == SCULPT_UNDO_MASK) {
+                                       *vd.mask = unode->mask[vd.i];
+                               }
                                if (vd.mvert) vd.mvert->flag |= 
ME_VERT_PBVH_UPDATE;
                        }
                        BLI_pbvh_vertex_iter_end;
@@ -640,6 +644,15 @@
                case SCULPT_TOOL_DRAW:
                case SCULPT_TOOL_LAYER:
                        return alpha * flip * pressure * overlap * feather;
+                       
+               case SCULPT_TOOL_MASK:
+                       overlap = (1 + overlap) / 2;
+                       switch ((BrushMaskTool)brush->mask_tool) {
+                       case BRUSH_MASK_DRAW:
+                               return alpha * flip * pressure * overlap * 
feather;
+                       case BRUSH_MASK_SMOOTH:
+                               return alpha * pressure * feather;
+                       }
 
                case SCULPT_TOOL_CREASE:
                case SCULPT_TOOL_BLOB:
@@ -1019,8 +1032,37 @@
        copy_v3_v3(avg, deform_co ? deform_co[vert] : mvert[vert].co);
 }
 
-static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode 
*node, float bstrength)
+/* Similar to neighbor_average(), but returns an averaged mask value
+   instead of coordinate. Also does not restrict based on border or
+   corner vertices. */
+static float neighbor_average_mask(SculptSession *ss, unsigned vert)
 {
+       const float *vmask = ss->vmask;
+       float avg = 0;
+       int i, total = 0;
+
+       for (i = 0; i < ss->pmap[vert].count; i++) {
+               const MPoly *p = &ss->mpoly[ss->pmap[vert].indices[i]];
+               unsigned f_adj_v[3];
+
+               if (poly_get_adj_loops_from_vert(f_adj_v, p, ss->mloop, vert) 
!= -1) {
+                       int j;
+                       
+                       for (j = 0; j < 3; j++) {
+                               avg += vmask[f_adj_v[j]];
+                               total++;
+                       }
+               }
+       }
+
+       if (total > 0)
+               return avg / (float)total;
+       else
+               return vmask[vert];
+}
+
+static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode 
*node, float bstrength, int smooth_mask)
+{
        Brush *brush = paint_brush(&sd->paint);
        PBVHVertexIter vd;
        SculptBrushTest test;
@@ -1032,16 +1074,25 @@
        BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
                if (sculpt_brush_test(&test, vd.co)) {
                        const float fade = bstrength*tex_strength(ss, brush, 
vd.co, test.dist,
-                                                                               
                          ss->cache->view_normal, vd.no, vd.fno, *vd.mask);
-                       float avg[3], val[3];
+                                                                               
                          ss->cache->view_normal, vd.no, vd.fno,
+                                                                               
                          smooth_mask ? 0 : *vd.mask);
+                       if (smooth_mask) {
+                               float val = neighbor_average_mask(ss, 
vd.vert_indices[vd.i]) - *vd.mask;
+                               val *= fade * bstrength;
+                               *vd.mask += val;
+                               CLAMP(*vd.mask, 0, 1);
+                       }
+                       else {
+                               float avg[3], val[3];
 
-                       neighbor_average(ss, avg, vd.vert_indices[vd.i]);
-                       sub_v3_v3v3(val, avg, vd.co);
-                       mul_v3_fl(val, fade);
+                               neighbor_average(ss, avg, 
vd.vert_indices[vd.i]);
+                               sub_v3_v3v3(val, avg, vd.co);
+                               mul_v3_fl(val, fade);
 
-                       add_v3_v3(val, vd.co);
+                               add_v3_v3(val, vd.co);
 
-                       sculpt_clip(sd, ss, vd.co, val);
+                               sculpt_clip(sd, ss, vd.co, val);
+                       }
 
                        if (vd.mvert)
                                vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -1050,14 +1101,16 @@
        BLI_pbvh_vertex_iter_end;
 }
 
-static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode 
*node, float bstrength)
+static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode 
*node,
+                                                                        float 
bstrength, int smooth_mask)
 {
        Brush *brush = paint_brush(&sd->paint);
        SculptBrushTest test;
        CCGElem **griddata, *data;
        CCGKey key;
        DMGridAdjacency *gridadj, *adj;
-       float (*tmpgrid)[3], (*tmprow)[3];
+       float (*tmpgrid_co)[3], (*tmprow_co)[3];
+       float *tmpgrid_mask, *tmprow_mask;
        int v1, v2, v3, v4;
        int *grid_indices, totgrid, gridsize, i, x, y;
 
@@ -1071,39 +1124,68 @@
 
        #pragma omp critical
        {
-               tmpgrid = MEM_mallocN(sizeof(float) * 3 * gridsize * gridsize, 
"tmpgrid");
-               tmprow =  MEM_mallocN(sizeof(float) * 3 * gridsize, "tmprow");
+               if (smooth_mask) {
+                       tmpgrid_mask = 
MEM_mallocN(sizeof(float)*gridsize*gridsize, "tmpgrid_mask");
+                       tmprow_mask = MEM_mallocN(sizeof(float)*gridsize, 
"tmprow_mask");
+               }
+               else {
+                       tmpgrid_co = 
MEM_mallocN(sizeof(float)*3*gridsize*gridsize, "tmpgrid_co");
+                       tmprow_co = MEM_mallocN(sizeof(float)*3*gridsize, 
"tmprow_co");
+               }
        }
 
        for (i = 0; i < totgrid; ++i) {
                data = griddata[grid_indices[i]];
                adj = &gridadj[grid_indices[i]];
 
-               memset(tmpgrid, 0, sizeof(float) * 3 * gridsize * gridsize);
+               if (smooth_mask)
+                       memset(tmpgrid_mask, 0, 
sizeof(float)*gridsize*gridsize);
+               else
+                       memset(tmpgrid_co, 0, 
sizeof(float)*3*gridsize*gridsize);
 
                for (y = 0; y < gridsize - 1; y++) {
-                       float tmp[3];
+                       v1 = y*gridsize;
+                       if (smooth_mask) {
+                               tmprow_mask[0] = (*CCG_elem_offset_mask(&key, 
data, v1) +
+                                                                 
*CCG_elem_offset_mask(&key, data, v1 + gridsize));
+                       }
+                       else {
+                               add_v3_v3v3(tmprow_co[0],
+                                                       
CCG_elem_offset_co(&key, data, v1),
+                                                       
CCG_elem_offset_co(&key, data, v1 + gridsize));
+                       }
 
-                       v1 = y * gridsize;
-                       add_v3_v3v3(tmprow[0],
-                                               CCG_elem_offset_co(&key, data, 
v1),
-                                               CCG_elem_offset_co(&key, data, 
v1 + gridsize));
-
                        for (x = 0; x < gridsize - 1; x++) {
                                v1 = x + y * gridsize;
                                v2 = v1 + 1;
                                v3 = v1 + gridsize;
                                v4 = v3 + 1;
 
-                               add_v3_v3v3(tmprow[x + 1],
-                                                       
CCG_elem_offset_co(&key, data, v2),
-                                                       
CCG_elem_offset_co(&key, data, v4));
-                               add_v3_v3v3(tmp, tmprow[x + 1], tmprow[x]);
+                               if (smooth_mask) {
+                                       float tmp;
 
-                               add_v3_v3(tmpgrid[v1], tmp);
-                               add_v3_v3(tmpgrid[v2], tmp);
-                               add_v3_v3(tmpgrid[v3], tmp);
-                               add_v3_v3(tmpgrid[v4], tmp);
+                                       tmprow_mask[x + 1] = 
(*CCG_elem_offset_mask(&key, data, v2) +
+                                                                               
  *CCG_elem_offset_mask(&key, data, v4));
+                                       tmp = tmprow_mask[x + 1] + 
tmprow_mask[x];
+
+                                       tmpgrid_mask[v1] += tmp;
+                                       tmpgrid_mask[v2] += tmp;
+                                       tmpgrid_mask[v3] += tmp;
+                                       tmpgrid_mask[v4] += tmp;
+                               }
+                               else {
+                                       float tmp[3];
+
+                                       add_v3_v3v3(tmprow_co[x + 1],
+                                                               
CCG_elem_offset_co(&key, data, v2),
+                                                               
CCG_elem_offset_co(&key, data, v4));
+                                       add_v3_v3v3(tmp, tmprow_co[x + 1], 
tmprow_co[x]);
+
+                                       add_v3_v3(tmpgrid_co[v1], tmp);
+                                       add_v3_v3(tmpgrid_co[v2], tmp);
+                                       add_v3_v3(tmpgrid_co[v3], tmp);
+                                       add_v3_v3(tmpgrid_co[v4], tmp);
+                               }
                        }
                }
 
@@ -1130,32 +1212,38 @@
                                index = x + y*gridsize;
                                co = CCG_elem_offset_co(&key, data, index);
                                fno = CCG_elem_offset_no(&key, data, index);
-                               mask = CCG_elem_offset_no(&key, data, index);
+                               mask = CCG_elem_offset_mask(&key, data, index);
 
                                if (sculpt_brush_test(&test, co)) {
+                                       const float strength_mask = 
(smooth_mask ? 0 : *mask);
                                        const float fade = 
bstrength*tex_strength(ss, brush, co, test.dist,
-                                                                               
  ss->cache->view_normal, NULL, fno, *mask);
-                                       float *avg, val[3];
-                                       float n;
-
-                                       avg = tmpgrid[x + y * gridsize];
-
-                                       n = 1 / 16.0f;
-
+                                                                               
                                          ss->cache->view_normal,
+                                                                               
                                          NULL, fno, strength_mask);
+                                       float n = 1.0f / 16.0f;
+                                       
                                        if (x == 0 || x == gridsize - 1)
                                                n *= 2;
-
+                                       
                                        if (y == 0 || y == gridsize - 1)
                                                n *= 2;
+                                       
+                                       if (smooth_mask) {
+                                               *mask += ((tmpgrid_mask[x + 
y*gridsize] * n) - *mask) * fade;
+                                       }
+                                       else {
+                                               float *avg, val[3];
 
-                                       mul_v3_fl(avg, n);
+                                               avg = tmpgrid_co[x + 
y*gridsize];
 
-                                       sub_v3_v3v3(val, avg, co);
-                                       mul_v3_fl(val, fade);
+                                               mul_v3_fl(avg, n);
 
-                                       add_v3_v3(val, co);
+                                               sub_v3_v3v3(val, avg, co);
+                                               mul_v3_fl(val, fade);
 
-                                       sculpt_clip(sd, ss, co, val);
+                                               add_v3_v3(val, co);
+
+                                               sculpt_clip(sd, ss, co, val);
+                                       }
                                }
                        }
                }
@@ -1163,12 +1251,19 @@
 
        #pragma omp critical
        {
-               MEM_freeN(tmpgrid);
-               MEM_freeN(tmprow);
+               if (smooth_mask) {
+                       MEM_freeN(tmpgrid_mask);
+                       MEM_freeN(tmprow_mask);
+               }
+               else {
+                       MEM_freeN(tmpgrid_co);
+                       MEM_freeN(tmprow_co);
+               }
        }
 }
 
-static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, 
float bstrength)
+static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
+                                  float bstrength, int smooth_mask)
 {
        SculptSession *ss = ob->sculpt;
        const int max_iterations = 4;
@@ -1185,10 +1280,13 @@
                #pragma omp parallel for schedule(guided) if (sd->flags & 
SCULPT_USE_OPENMP)
                for (n = 0; n < totnode; n++) {
                        if (ss->multires) {
-                               do_multires_smooth_brush(sd, ss, nodes[n], 
iteration != count ? 1.0f : last);
+                               do_multires_smooth_brush(sd, ss, nodes[n],
+                                       iteration != count ? 1.0f : last, 
smooth_mask);
                        }
-                       else if (ss->pmap)
-                               do_mesh_smooth_brush(sd, ss, nodes[n], 
iteration != count ? 1.0f : last);
+                       else if (ss->pmap) {
+                               do_mesh_smooth_brush(sd, ss, nodes[n],
+                                       iteration != count ? 1.0f : last, 
smooth_mask);
+                       }
                }
 
                if (ss->multires)
@@ -1199,9 +1297,55 @@
 static void do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int 
totnode)
 {
        SculptSession *ss = ob->sculpt;
-       smooth(sd, ob, nodes, totnode, ss->cache->bstrength);
+       smooth(sd, ob, nodes, totnode, ss->cache->bstrength, FALSE);
 }
 
+static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int 
totnode)
+{
+       SculptSession *ss = ob->sculpt;
+       Brush *brush = paint_brush(&sd->paint);
+       float bstrength = ss->cache->bstrength;
+       int n;
+

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to