forked from bartvdbraak/blender
Sculpt Branch:
* Smooth brush works again for multires. * Optimal Display option for multires modifier, same as subsurf.
This commit is contained in:
parent
abae1e2ccf
commit
9ea765e5d3
@ -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.")
|
||||
|
@ -27,24 +27,22 @@
|
||||
* ***** 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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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_brush_test_init(ss, &test);
|
||||
|
||||
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;
|
||||
|
||||
sculpt_clip(sd, ss, data[x + y*gridsize].co, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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++) {
|
||||
PBVHVertexIter vd;
|
||||
SculptBrushTest test;
|
||||
|
||||
sculpt_undo_push_node(ss, nodes[n]);
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user