Sculpt Branch:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 9 Dec 2009 13:37:19 +0000 (13:37 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 9 Dec 2009 13:37:19 +0000 (13:37 +0000)
* Smooth brush works again for multires.
* Optimal Display option for multires modifier, same as subsurf.

release/scripts/ui/properties_data_modifier.py
source/blender/blenkernel/BKE_multires.h
source/blender/blenkernel/intern/CCGSubSurf.c
source/blender/blenkernel/intern/multires.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenlib/BLI_pbvh.h
source/blender/blenlib/intern/pbvh.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_modifier.c

index 54a4def..8194027 100644 (file)
@@ -438,6 +438,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
         col.prop(md, "levels", text="Preview")
         col.prop(md, "sculpt_levels", text="Sculpt")
         col.prop(md, "render_levels", text="Render")
+        col.prop(md, "optimal_display")
 
         if wide_ui:
             col = split.column()
@@ -604,7 +605,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
         if wide_ui:
             col = split.column()
         col.label(text="Options:")
-        col.prop(md, "optimal_draw", text="Optimal Display")
+        col.prop(md, "optimal_display")
 
     def SURFACE(self, layout, ob, md, wide_ui):
         layout.label(text="See Fields panel.")
index 53ead3a..ff320bc 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */ 
 
+#ifndef BKE_MULTIRES_H
+#define BKE_MULTIRES_H
+
 struct DerivedMesh;
 struct Mesh;
 struct MFace;
+struct Multires;
 struct MultiresModifierData;
 struct Object;
 
-typedef struct MultiresSubsurf {
-       struct MultiresModifierData *mmd;
-       struct Object *ob;
-       int local_mmd;
-} MultiresSubsurf;
-
 void multires_mark_as_modified(struct Object *ob);
 
 void multires_force_update(struct Object *ob);
 
-struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, int local_mmd, struct DerivedMesh*,
-                                                   struct Object *, int, int);
+struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*,
+       int local_mmd, struct DerivedMesh*, struct Object *, int, int);
 
 struct MultiresModifierData *find_multires_modifier(struct Object *ob);
 void multiresModifier_join(struct Object *);
@@ -53,7 +51,11 @@ void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object
                                int updateblock, int simple);
 int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *dst, struct Object *src);
 
+void multires_stitch_grids(struct Object *);
+
 /* Related to the old multires */
-struct Multires;
 void multires_load_old(struct DerivedMesh *, struct Multires *);
 void multires_free(struct Multires*);
+
+#endif
+
index cc2bd53..4bd0586 100644 (file)
@@ -2228,8 +2228,9 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in
                VertDataZero(FACE_getCenterData(f));
 
                for (S=0; S<f->numVerts; S++)
-                       for (x=0; x<gridSize; x++)
-                               VertDataZero(FACE_getIECo(f, lvl, S, x));
+                       if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
+                               for (x=0; x<gridSize; x++)
+                                       VertDataZero(FACE_getIECo(f, lvl, S, x));
 
                for (S=0; S<f->numVerts; S++) {
                        int prevS = (S+f->numVerts-1)%f->numVerts;
@@ -2237,18 +2238,23 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in
                        CCGEdge *prevE = FACE_getEdges(f)[prevS];
 
                        VertDataAdd(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0));
-                       VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx));
+                       if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
+                               VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx));
 
                        for (x=1; x<gridSize-1; x++) {
-                               VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0));
-                               VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x));
+                               if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
+                                       VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0));
+                               if (FACE_getEdges(f)[prevS]->flags&Edge_eEffected)
+                                       VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x));
                        }
 
                        for (x=0; x<gridSize-1; x++) {
                                int eI = gridSize-1-x;
-                               VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x));
-                               if(x != 0)
-                                       VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx));
+                               if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
+                                       VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x));
+                               if (FACE_getEdges(f)[prevS]->flags&Edge_eEffected)
+                                       if(x != 0)
+                                               VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx));
                        }
                }
        }
@@ -2276,8 +2282,9 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in
                VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
 
                for (S=0; S<f->numVerts; S++)
-                       for (x=1; x<gridSize-1; x++)
-                               VertDataMulN(FACE_getIECo(f, lvl, S, x), 0.5f);
+                       if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
+                               for (x=1; x<gridSize-1; x++)
+                                       VertDataMulN(FACE_getIECo(f, lvl, S, x), 0.5f);
 
                for (S=0; S<f->numVerts; S++) {
                        int prevS = (S+f->numVerts-1)%f->numVerts;
index 69659db..8a76d65 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_pbvh.h"
 
 #include "BKE_btex.h"
 #include "BKE_cdderivedmesh.h"
@@ -60,8 +61,8 @@
 
 /* MULTIRES MODIFIER */
 static const int multires_max_levels = 13;
-static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
-static const int multires_side_tot[] = {1, 2, 3, 5,  9,  17,  33,   65,   129,   257,   513,    1025,    2049,    4097};
+static const int multires_grid_tot[] = {0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
+static const int multires_side_tot[] = {0, 2, 3, 5,  9,  17,  33,   65,   129,   257,   513,    1025,    2049,    4097};
 
 static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl);
 
@@ -307,7 +308,7 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv
        return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0);
 }
 
-static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple)
+static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal)
 {
        SubsurfModifierData smd;
 
@@ -316,6 +317,8 @@ static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl
        smd.flags |= eSubsurfModifierFlag_SubsurfUv;
        if(simple)
                smd.subdivType = ME_SIMPLE_SUBSURF;
+       if(optimal)
+               smd.flags |= eSubsurfModifierFlag_ControlEdges;
 
        return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0);
 }
@@ -363,7 +366,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat
 
                /* create subsurf DM from original mesh at high level */
                cddm = CDDM_from_mesh(me, NULL);
-               highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple);
+               highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0);
 
                /* create multires DM from original mesh at low level */
                lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple);
@@ -551,7 +554,7 @@ static void multiresModifier_update(DerivedMesh *dm)
 
                        /* create subsurf DM from original mesh at high level */
                        cddm = CDDM_from_mesh(me, NULL);
-                       highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple);
+                       highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0);
 
                        /* create multires DM from original mesh and displacements */
                        lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple);
@@ -602,7 +605,7 @@ static void multiresModifier_update(DerivedMesh *dm)
                        DerivedMesh *cddm, *subdm;
 
                        cddm = CDDM_from_mesh(me, NULL);
-                       subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple);
+                       subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0);
                        cddm->release(cddm);
 
                        multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl);
@@ -629,6 +632,25 @@ void multires_force_update(Object *ob)
        }
 }
 
+void multires_stitch_grids(Object *ob)
+{
+       /* utility for smooth brush */
+       if(ob && ob->derivedFinal) {
+               CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)ob->derivedFinal;
+               CCGFace **faces;
+               int totface;
+
+               if(ccgdm->pbvh) {
+                       BLI_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void***)&faces, &totface);
+
+                       if(totface) {
+                               ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface);
+                               MEM_freeN(faces);
+                       }
+               }
+       }
+}
+
 struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob,
                                                    int useRenderParams, int isFinalCalc)
 {
@@ -642,7 +664,8 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i
        if(lvl == 0)
                return dm;
 
-       result = subsurf_dm_create_local(ob, dm, lvl, 0);
+       result = subsurf_dm_create_local(ob, dm, lvl,
+               mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges);
 
        if(!local_mmd) {
                ccgdm = (CCGDerivedMesh*)result;
@@ -680,6 +703,36 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i
 /**** Old Multires code ****
 ***************************/
 
+#if 0
+static void mdisp_copy_grid(float (*new)[3], int newstride, float (*old)[3], int oldstride, int xoff, int yoff, int xsize, int ysize)
+{
+       int x, y;
+
+       for(y = 0; y < ysize; ++y)
+               for(x = 0; x < xsize; ++x)
+                       copy_v3_v3(disps[x + y*side], mdisp->disps[(x + xoffs) + (y + yoffs)*oldside]);
+
+}
+
+static void mdisps_convert(MFace *mface, MDisps *mdisp, int lvl)
+{
+       int side = multires_side_tot[lvl];
+       int nvert = (mface->v4)? 4: 3;
+       int totdisp = multires_grid_tot[lvl]*nvert;
+       int x, y;
+       float (*disps)[3];
+
+       disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps");
+
+
+
+static const int multires_max_levels = 13;
+static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
+static const int multires_side_tot[] = {1, 2, 3, 5,  9,  17,  33,   65,   129,   257,   513,    1025,    2049,    4097};
+
+}
+#endif
+
 /* Does not actually free lvl itself */
 static void multires_free_level(MultiresLevel *lvl)
 {
index c9d8467..f6abedd 100644 (file)
@@ -1235,7 +1235,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
                CCGFace **faces;
                int totface;
 
-               BLI_pbvh_get_grid_updates(ccgdm->pbvh, (void***)&faces, &totface);
+               BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface);
                if(totface) {
                        ccgSubSurf_updateFromFaces(ss, 0, faces, totface);
                        ccgSubSurf_updateNormals(ss, faces, totface);
@@ -2155,8 +2155,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
                numGrids = ccgDM_getNumGrids(dm);
 
                ccgdm->pbvh = BLI_pbvh_new();
-               BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, numGrids, gridSize,
-                       (void**)ccgdm->gridFaces);
+               BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
+                       numGrids, gridSize, (void**)ccgdm->gridFaces);
        }
        else if(ob->type == OB_MESH) {
                Mesh *me= ob->data;
index 5c5277d..e1e733c 100644 (file)
@@ -27,6 +27,7 @@
 
 struct MFace;
 struct MVert;
+struct DMGridAdjacency;
 struct DMGridData;
 struct PBVH;
 struct PBVHNode;
@@ -47,7 +48,8 @@ typedef void (*BLI_pbvh_HitCallback)(PBVHNode *node, void *data);
 PBVH *BLI_pbvh_new(void);
 void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
                    int totface, int totvert);
-void BLI_pbvh_build_grids(PBVH *bvh, struct DMGridData **grids, int totgrid,
+void BLI_pbvh_build_grids(PBVH *bvh, struct DMGridData **grids,
+       struct DMGridAdjacency *gridadj, int totgrid,
        int gridsize, void **gridfaces);
 void BLI_pbvh_free(PBVH *bvh);
 
@@ -94,7 +96,8 @@ typedef enum {
 void BLI_pbvh_node_mark_update(PBVHNode *node);
 
 void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
-       int **grid_indices, int *totgrid, int *maxgrid, int *gridsize);
+       int **grid_indices, int *totgrid, int *maxgrid, int *gridsize,
+       struct DMGridData ***griddata, struct DMGridAdjacency **gridadj);
 void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
        int *uniquevert, int *totvert);
 
@@ -105,7 +108,7 @@ void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max
 
 void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
 void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
-void BLI_pbvh_get_grid_updates(PBVH *bvh, void ***gridfaces, int *totface);
+void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface);
 
 /* Vertex Iterator */
 
index 3aa0f43..9608882 100644 (file)
@@ -114,6 +114,7 @@ struct PBVH {
 
        /* Grid Data */
        DMGridData **grids;
+       DMGridAdjacency *gridadj;
        void **gridfaces;
        int totgrid;
        int gridsize;
@@ -510,14 +511,15 @@ void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
 }
 
 /* Do a full rebuild with on Grids data structure */
-void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, int totgrid,
-       int gridsize, void **gridfaces)
+void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj,
+       int totgrid, int gridsize, void **gridfaces)
 {
        BBC *prim_bbc = NULL;
        BB cb;
        int i, j;
 
        bvh->grids= grids;
+       bvh->gridadj= gridadj;
        bvh->gridfaces= gridfaces;
        bvh->totgrid= totgrid;
        bvh->gridsize= gridsize;
@@ -948,7 +950,7 @@ void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
        copy_v3_v3(bb_max, bb.bmax);
 }
 
-void BLI_pbvh_get_grid_updates(PBVH *bvh, void ***gridfaces, int *totface)
+void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface)
 {
        PBVHIter iter;
        PBVHNode *node;
@@ -965,10 +967,12 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, void ***gridfaces, int *totface)
                if(node->flag & PBVH_UpdateNormals) {
                        for(i = 0; i < node->totprim; ++i) {
                                face= bvh->gridfaces[node->prim_indices[i]];
-                               BLI_ghash_insert(map, face, face);
+                               if(!BLI_ghash_lookup(map, face))
+                                       BLI_ghash_insert(map, face, face);
                        }
 
-                       node->flag &= ~PBVH_UpdateNormals;
+                       if(clear)
+                               node->flag &= ~PBVH_UpdateNormals;
                }
        }
 
@@ -1021,19 +1025,23 @@ void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to
        }
 }
 
-void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize)
+void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, DMGridData ***griddata, DMGridAdjacency **gridadj)
 {
        if(bvh->grids) {
                if(grid_indices) *grid_indices= node->prim_indices;
                if(totgrid) *totgrid= node->totprim;
                if(maxgrid) *maxgrid= bvh->totgrid;
                if(gridsize) *gridsize= bvh->gridsize;
+               if(griddata) *griddata= bvh->grids;
+               if(gridadj) *gridadj= bvh->gridadj;
        }
        else {
                if(grid_indices) *grid_indices= NULL;
                if(totgrid) *totgrid= 0;
                if(maxgrid) *maxgrid= 0;
                if(gridsize) *gridsize= 0;
+               if(griddata) *griddata= NULL;
+               if(gridadj) *gridadj= NULL;
        }
 }
 
index d67f13f..c715dc9 100644 (file)
@@ -415,7 +415,8 @@ static SculptUndoNode *sculpt_undo_push_node(SculptSession *ss, PBVHNode *node)
        unode->node= node;
 
        BLI_pbvh_node_num_verts(ss->tree, node, &totvert, &allvert);
-       BLI_pbvh_node_get_grids(ss->tree, node, &grids, &totgrid, &maxgrid, &gridsize);
+       BLI_pbvh_node_get_grids(ss->tree, node, &grids, &totgrid,
+               &maxgrid, &gridsize, NULL, NULL);
 
        unode->totvert= totvert;
        /* we will use this while sculpting, is mapalloc slow to access then? */
@@ -795,9 +796,9 @@ static void calc_area_normal(Sculpt *sd, SculptSession *ss, float area_normal[3]
                        BLI_pbvh_vertex_iter_end;
                }
 
+               #pragma omp critical
                {
                        /* we sum per node and add together later for threads */
-                       #pragma omp critical
                        add_v3_v3v3(out, out, nout);
                        add_v3_v3v3(out_flip, out_flip, nout_flip);
                }
@@ -903,43 +904,128 @@ static void neighbor_average(SculptSession *ss, float avg[3], const int vert)
                copy_v3_v3(avg, ss->mvert[vert].co);
 }
 
-static void do_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode **nodes, int totnode)
+static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node)
 {
        Brush *brush = paint_brush(&sd->paint);
        float bstrength= ss->cache->bstrength;
-       int iteration, n;
+       PBVHVertexIter vd;
+       SculptBrushTest test;
+       
+       sculpt_brush_test_init(ss, &test);
 
-       /* XXX not working for multires yet */
-       if(!ss->fmap)
-               return;
+       BLI_pbvh_vertex_iter_begin(ss->tree, node, vd, PBVH_ITER_UNIQUE) {
+               if(sculpt_brush_test(&test, vd.co)) {
+                       float fade = tex_strength(ss, brush, vd.co, test.dist)*bstrength;
+                       float avg[3], val[3];
+                       
+                       neighbor_average(ss, avg, vd.vert_indices[vd.i]);
+                       val[0] = vd.co[0]+(avg[0]-vd.co[0])*fade;
+                       val[1] = vd.co[1]+(avg[1]-vd.co[1])*fade;
+                       val[2] = vd.co[2]+(avg[2]-vd.co[2])*fade;
+                       
+                       sculpt_clip(sd, ss, vd.co, val);                        
+                       if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+               }
+       }
+       BLI_pbvh_vertex_iter_end;
+}
 
-       for(iteration = 0; iteration < 2; ++iteration) {
-               #pragma omp parallel for private(n) schedule(static)
-               for(n=0; n<totnode; n++) {
-                       PBVHVertexIter vd;
-                       SculptBrushTest test;
+static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node)
+{
+       Brush *brush = paint_brush(&sd->paint);
+       SculptBrushTest test;
+       DMGridData **griddata, *data;
+       DMGridAdjacency *gridadj, *adj;
+       float bstrength= ss->cache->bstrength;
+       float co[3], (*tmpgrid)[3];
+       int v1, v2, v3, v4;
+       int *grid_indices, totgrid, gridsize, i, x, y;
                        
-                       sculpt_undo_push_node(ss, nodes[n]);
-                       sculpt_brush_test_init(ss, &test);
+       sculpt_brush_test_init(ss, &test);
 
-                       BLI_pbvh_vertex_iter_begin(ss->tree, nodes[n], vd, PBVH_ITER_UNIQUE) {
-                               if(sculpt_brush_test(&test, vd.co)) {
-                                       float fade = tex_strength(ss, brush, vd.co, test.dist)*bstrength;
+       BLI_pbvh_node_get_grids(ss->tree, node, &grid_indices, &totgrid,
+               NULL, &gridsize, &griddata, &gridadj);
+
+       #pragma omp critical
+       tmpgrid= MEM_mallocN(sizeof(float)*3*gridsize*gridsize, "tmpgrid");
+
+       for(i = 0; i < totgrid; ++i) {
+               data = griddata[grid_indices[i]];
+               adj = &gridadj[grid_indices[i]];
+
+               memset(tmpgrid, 0, sizeof(float)*3*gridsize*gridsize);
+
+               /* average grid values */
+               for(y = 0; y < gridsize-1; ++y)  {
+                       for(x = 0; x < gridsize-1; ++x)  {
+                               v1 = x + y*gridsize;
+                               v2 = (x + 1) + y*gridsize;
+                               v3 = (x + 1) + (y + 1)*gridsize;
+                               v4 = x + (y + 1)*gridsize;
+
+                               cent_quad_v3(co, data[v1].co, data[v2].co, data[v3].co, data[v4].co);
+                               mul_v3_fl(co, 0.25f);
+
+                               add_v3_v3(tmpgrid[v1], co);
+                               add_v3_v3(tmpgrid[v2], co);
+                               add_v3_v3(tmpgrid[v3], co);
+                               add_v3_v3(tmpgrid[v4], co);
+                       }
+               }
+
+               /* blend with existing coordinates */
+               for(y = 0; y < gridsize; ++y)  {
+                       for(x = 0; x < gridsize; ++x)  {
+                               if(x == 0 && adj->index[0] == -1) continue;
+                               if(x == gridsize - 1 && adj->index[2] == -1) continue;
+                               if(y == 0 && adj->index[3] == -1) continue;
+                               if(y == gridsize - 1 && adj->index[1] == -1) continue;
+
+                               copy_v3_v3(co, data[x + y*gridsize].co);
+
+                               if(sculpt_brush_test(&test, co)) {
+                                       float fade = tex_strength(ss, brush, co, test.dist)*bstrength;
                                        float avg[3], val[3];
+
+                                       copy_v3_v3(avg, tmpgrid[x + y*gridsize]);
+                                       if(x == 0 || x == gridsize - 1)
+                                               mul_v3_fl(avg, 2.0f);
+                                       if(y == 0 || y == gridsize - 1)
+                                               mul_v3_fl(avg, 2.0f);
+
+                                       val[0] = co[0]+(avg[0]-co[0])*fade;
+                                       val[1] = co[1]+(avg[1]-co[1])*fade;
+                                       val[2] = co[2]+(avg[2]-co[2])*fade;
                                        
-                                       neighbor_average(ss, avg, vd.vert_indices[vd.i]);
-                                       val[0] = vd.co[0]+(avg[0]-vd.co[0])*fade;
-                                       val[1] = vd.co[1]+(avg[1]-vd.co[1])*fade;
-                                       val[2] = vd.co[2]+(avg[2]-vd.co[2])*fade;
-                                       
-                                       sculpt_clip(sd, ss, vd.co, val);                        
-                                       if(vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+                                       sculpt_clip(sd, ss, data[x + y*gridsize].co, val);
                                }
                        }
-                       BLI_pbvh_vertex_iter_end;
+               }
+       }
+
+       #pragma omp critical
+       MEM_freeN(tmpgrid);
+}
+
+static void do_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode **nodes, int totnode)
+{
+       int iteration, n;
+
+       for(iteration = 0; iteration < 2; ++iteration) {
+               #pragma omp parallel for private(n) schedule(static)
+               for(n=0; n<totnode; n++) {
+                       sculpt_undo_push_node(ss, nodes[n]);
+
+                       if(ss->fmap)
+                               do_mesh_smooth_brush(sd, ss, nodes[n]);
+                       else
+                               do_multires_smooth_brush(sd, ss, nodes[n]);
 
                        BLI_pbvh_node_mark_update(nodes[n]);
                }
+
+               if(!ss->fmap)
+                       multires_stitch_grids(ss->ob);
        }
 }
 
index 33130c6..c599c8a 100644 (file)
@@ -586,9 +586,13 @@ typedef struct MultiresModifierData {
        ModifierData modifier;
 
        char lvl, sculptlvl, renderlvl, totlvl;
-       char simple, pad[3];
+       char simple, flags, pad[2];
 } MultiresModifierData;
 
+typedef enum {
+       eMultiresModifierFlag_ControlEdges = (1<<0),
+} MultiresModifierFlag;
+
 typedef struct FluidsimModifierData {
        ModifierData modifier;
        
index dedd072..cefaf2d 100644 (file)
@@ -534,9 +534,9 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
        RNA_def_property_ui_range(prop, 0, 6, 1, 0);
        RNA_def_property_ui_text(prop, "Render Levels", "Number of subdivisions to perform when rendering.");
 
-       prop= RNA_def_property(srna, "optimal_draw", PROP_BOOLEAN, PROP_NONE);
+       prop= RNA_def_property(srna, "optimal_display", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_ControlEdges);
-       RNA_def_property_ui_text(prop, "Optimal Draw", "Skip drawing/rendering of interior subdivided edges");
+       RNA_def_property_ui_text(prop, "Optimal Display", "Skip drawing/rendering of interior subdivided edges");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
        
        prop= RNA_def_property(srna, "subsurf_uv", PROP_BOOLEAN, PROP_NONE);
@@ -583,6 +583,11 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
        RNA_def_property_boolean_funcs(prop, "rna_MultiresModifier_external_get", "rna_MultiresModifier_external_set");
        RNA_def_property_editable_func(prop, "rna_MultiresModifier_external_editable");
        RNA_def_property_ui_text(prop, "External", "Store multires displacements outside the .blend file, to save memory.");
+
+       prop= RNA_def_property(srna, "optimal_display", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flags", eMultiresModifierFlag_ControlEdges);
+       RNA_def_property_ui_text(prop, "Optimal Display", "Skip drawing/rendering of interior subdivided edges");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
 }
 
 static void rna_def_modifier_lattice(BlenderRNA *brna)