[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [46526] trunk/blender: Add mask brush for sculpt mode.
Nicholas Bishop
nicholasbishop at gmail.com
Thu May 10 22:35:32 CEST 2012
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. @@
More information about the Bf-blender-cvs
mailing list