Sculpt dyntopo:
* Fixed noise on using autosmooth with tools that use original coorinates. While this was most prominent with DynTopo, it did happen with other tools. * The solution is to smooth the original coordinates as well as the explicit coordinates if the active tool requires original data. * I decided to replace the original coordinates system for PBVH_FACES and PBVH_GRIDS with the same MDynTopoVert structure DynTopo uses. The alternative would have been extremely messy code. * Todo: Rename MDynTopoVert to. . .SculptInfoVert? * Todo: Cache boundary flag and corner info in MDynTopoVert->flag for PBVH_FACES/GRIDS similar to PBVH_BMESH.
This commit is contained in:
parent
0676928408
commit
3df335d330
|
@ -34,6 +34,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct MDynTopoVert;
|
||||
struct BMFace;
|
||||
struct BMesh;
|
||||
struct BlendDataReader;
|
||||
|
@ -658,6 +659,8 @@ typedef struct SculptSession {
|
|||
int stroke_id, boundary_symmetry;
|
||||
|
||||
bool fast_draw; // hides facesets/masks and forces smooth to save GPU bandwidth
|
||||
struct MDynTopoVert *mdyntopo_verts; // for non-bmesh
|
||||
int mdyntopo_verts_size;
|
||||
} SculptSession;
|
||||
|
||||
void BKE_sculptsession_free(struct Object *ob);
|
||||
|
@ -665,6 +668,7 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
|
|||
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
|
||||
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
|
||||
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
|
||||
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert);
|
||||
|
||||
/* Create new color layer on object if it doesn't have one and if experimental feature set has
|
||||
* sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */
|
||||
|
|
|
@ -269,6 +269,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
|||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
struct MVert *verts,
|
||||
struct MDynTopoVert *mdyntopo_verts,
|
||||
int totvert,
|
||||
struct CustomData *vdata,
|
||||
struct CustomData *ldata,
|
||||
|
|
|
@ -1552,7 +1552,8 @@ static void layerDynTopoVert_interp(
|
|||
float mul = 1.0f / totweight;
|
||||
|
||||
mul_v3_fl(co, mul);
|
||||
mul_v3_fl(no, mul);
|
||||
normalize_v3(no);
|
||||
|
||||
mul_v4_fl(color, mul);
|
||||
origmask *= mul;
|
||||
|
||||
|
|
|
@ -560,10 +560,26 @@ static BMEdge *bmesh_edge_create_log(PBVH *pbvh, BMVert *v1, BMVert *v2, BMEdge
|
|||
BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
|
||||
{
|
||||
float co[3];
|
||||
float origco[3], origco1[3];
|
||||
float origno1[3];
|
||||
float tan[3];
|
||||
float tot = 0.0;
|
||||
|
||||
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
|
||||
|
||||
if (mv1->stroke_id != pbvh->stroke_id) {
|
||||
copy_v3_v3(origco1, v->co);
|
||||
copy_v3_v3(origno1, v->no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(origco1, mv1->origco);
|
||||
copy_v3_v3(origno1, dot_v3v3(mv1->origno, mv1->origno) == 0.0f ? v->no : mv1->origno);
|
||||
}
|
||||
|
||||
// BKE_pbvh_bmesh_check_origdata(pbvh, v, pbvh->stroke_id);
|
||||
|
||||
zero_v3(co);
|
||||
zero_v3(origco);
|
||||
|
||||
// this is a manual edge walk
|
||||
|
||||
|
@ -572,11 +588,14 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
|
|||
return;
|
||||
}
|
||||
|
||||
pbvh_check_vert_boundary(pbvh, v);
|
||||
if (mv1->flag & DYNVERT_NEED_BOUNDARY) {
|
||||
return; // can't update boundary in thread
|
||||
}
|
||||
|
||||
// pbvh_check_vert_boundary(pbvh, v);
|
||||
|
||||
const int cd_dyn_vert = pbvh->cd_dyn_vert;
|
||||
|
||||
MDynTopoVert *mv1 = BKE_PBVH_DYNVERT(cd_dyn_vert, v);
|
||||
const bool bound1 = mv1->flag & DYNVERT_SMOOTH_BOUNDARY;
|
||||
|
||||
if (mv1->flag & DYNVERT_SMOOTH_CORNER) {
|
||||
|
@ -601,6 +620,18 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
|
|||
|
||||
madd_v3_v3fl(tan, v->no, -d * 0.99f);
|
||||
add_v3_v3(co, tan);
|
||||
|
||||
if (mv2->stroke_id == pbvh->stroke_id) {
|
||||
sub_v3_v3v3(tan, mv2->origco, origco1);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(tan, v2->co, origco1);
|
||||
}
|
||||
|
||||
d = dot_v3v3(tan, origno1);
|
||||
madd_v3_v3fl(tan, origno1, -d * 0.99f);
|
||||
add_v3_v3(origco, tan);
|
||||
|
||||
tot += 1.0f;
|
||||
|
||||
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
|
||||
|
@ -610,12 +641,32 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
|
|||
}
|
||||
|
||||
mul_v3_fl(co, 1.0f / tot);
|
||||
float x = v->co[0], y = v->co[1], z = v->co[2];
|
||||
mul_v3_fl(origco, 1.0f / tot);
|
||||
|
||||
volatile float x = v->co[0], y = v->co[1], z = v->co[2];
|
||||
volatile float nx = x + co[0] * fac, ny = y + co[1] * fac, nz = z + co[2] * fac;
|
||||
|
||||
// conflicts here should be pretty rare.
|
||||
atomic_cas_float(&v->co[0], x, x + co[0] * fac);
|
||||
atomic_cas_float(&v->co[1], y, y + co[1] * fac);
|
||||
atomic_cas_float(&v->co[2], z, z + co[2] * fac);
|
||||
atomic_cas_float(&v->co[0], x, nx);
|
||||
atomic_cas_float(&v->co[1], y, ny);
|
||||
atomic_cas_float(&v->co[2], z, nz);
|
||||
|
||||
// conflicts here should be pretty rare.
|
||||
x = mv1->origco[0];
|
||||
y = mv1->origco[1];
|
||||
z = mv1->origco[2];
|
||||
|
||||
nx = x + origco[0] * fac;
|
||||
ny = y + origco[1] * fac;
|
||||
nz = z + origco[2] * fac;
|
||||
|
||||
atomic_cas_float(&mv1->origco[0], x, nx);
|
||||
atomic_cas_float(&mv1->origco[1], y, ny);
|
||||
atomic_cas_float(&mv1->origco[2], z, nz);
|
||||
|
||||
volatile int stroke_id = mv1->stroke_id;
|
||||
|
||||
// atomic_cas_int32(&mv1->stroke_id, stroke_id, pbvh->stroke_id);
|
||||
}
|
||||
|
||||
static void pbvh_kill_vert(PBVH *pbvh, BMVert *v)
|
||||
|
@ -3624,8 +3675,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
// snap customdata
|
||||
if (snap) {
|
||||
int ni_conn = BM_ELEM_CD_GET_INT(v_conn, pbvh->cd_vert_node_offset);
|
||||
|
||||
const float v_ws[2] = {0.5f, 0.5f};
|
||||
const void *v_blocks[2] = {v_del->head.data, v_conn->head.data};
|
||||
|
||||
CustomData_bmesh_interp(&pbvh->bm->vdata, v_blocks, v_ws, NULL, 2, v_conn->head.data);
|
||||
BM_ELEM_CD_SET_INT(v_conn, pbvh->cd_vert_node_offset, ni_conn);
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
|
|||
void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
|
||||
BMesh *SCULPT_dyntopo_empty_bmesh();
|
||||
|
||||
static void init_mdyntopo_layer(SculptSession *ss, int totvert);
|
||||
|
||||
static void palette_init_data(ID *id)
|
||||
{
|
||||
Palette *palette = (Palette *)id;
|
||||
|
@ -1483,6 +1485,11 @@ void BKE_sculptsession_free(Object *ob)
|
|||
if (ob && ob->sculpt) {
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (ss->mdyntopo_verts) {
|
||||
MEM_freeN(ss->mdyntopo_verts);
|
||||
ss->mdyntopo_verts = NULL;
|
||||
}
|
||||
|
||||
if (ss->bm_log && BM_log_free(ss->bm_log, true)) {
|
||||
ss->bm_log = NULL;
|
||||
}
|
||||
|
@ -1671,7 +1678,6 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
}
|
||||
|
||||
ss->shapekey_active = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
|
||||
|
||||
ss->boundary_symmetry = (int)BKE_get_fset_boundary_symflag(ob);
|
||||
|
||||
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
|
||||
|
@ -1724,6 +1730,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
ss->fast_draw = (scene->toolsettings->sculpt->flags & SCULPT_FAST_DRAW) != 0;
|
||||
|
||||
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
|
||||
|
||||
BLI_assert(pbvh == ss->pbvh);
|
||||
UNUSED_VARS_NDEBUG(pbvh);
|
||||
|
||||
|
@ -2190,11 +2197,14 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
|
|||
|
||||
BKE_sculpt_sync_face_set_visibility(me, NULL);
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, me->totvert);
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh,
|
||||
me,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->mvert,
|
||||
ob->sculpt->mdyntopo_verts,
|
||||
me->totvert,
|
||||
&me->vdata,
|
||||
&me->ldata,
|
||||
|
@ -2235,11 +2245,40 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
|
|||
subdiv_ccg->grid_flag_mats,
|
||||
subdiv_ccg->grid_hidden,
|
||||
ob->sculpt->fast_draw);
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, BKE_pbvh_get_grid_num_vertices(pbvh));
|
||||
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert)
|
||||
{
|
||||
if (!ss->bm && (!ss->mdyntopo_verts || totvert != ss->mdyntopo_verts_size)) {
|
||||
init_mdyntopo_layer(ss, totvert);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void init_mdyntopo_layer(SculptSession *ss, int totvert)
|
||||
{
|
||||
if (ss->mdyntopo_verts) {
|
||||
MEM_freeN(ss->mdyntopo_verts);
|
||||
}
|
||||
|
||||
ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
|
||||
ss->mdyntopo_verts_size = totvert;
|
||||
|
||||
MDynTopoVert *mv = ss->mdyntopo_verts;
|
||||
|
||||
for (int i = 0; i < totvert; i++, mv++) {
|
||||
mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
|
||||
mv->stroke_id = -1;
|
||||
}
|
||||
}
|
||||
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
{
|
||||
if (ob == NULL || ob->sculpt == NULL) {
|
||||
|
@ -2331,6 +2370,9 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, me_eval_deform->totvert);
|
||||
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -607,6 +607,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
|||
const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
MVert *verts,
|
||||
MDynTopoVert *mdyntopo_verts,
|
||||
|
||||
int totvert,
|
||||
struct CustomData *vdata,
|
||||
struct CustomData *ldata,
|
||||
|
@ -624,6 +626,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
|||
pbvh->mloop = mloop;
|
||||
pbvh->looptri = looptri;
|
||||
pbvh->verts = verts;
|
||||
pbvh->mdyntopo_verts = mdyntopo_verts;
|
||||
pbvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
|
||||
pbvh->totvert = totvert;
|
||||
pbvh->leaf_limit = LEAF_LIMIT;
|
||||
|
|
|
@ -833,6 +833,8 @@ void BKE_pbvh_bmesh_update_origvert(
|
|||
|
||||
bool BKE_pbvh_bmesh_check_origdata(PBVH *pbvh, BMVert *v, int stroke_id)
|
||||
{
|
||||
// keep this up to date with surface_smooth_v_safe in dyntopo.c
|
||||
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
|
||||
|
||||
if (mv->stroke_id != stroke_id) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
struct MDynTopoVert;
|
||||
|
||||
/* Axis-aligned bounding box */
|
||||
typedef struct {
|
||||
|
@ -217,6 +218,7 @@ struct PBVH {
|
|||
|
||||
int balance_counter;
|
||||
int stroke_id; // used to keep origdata up to date in PBVH_BMESH
|
||||
struct MDynTopoVert *mdyntopo_verts;
|
||||
};
|
||||
|
||||
/* pbvh.c */
|
||||
|
|
|
@ -158,15 +158,40 @@ int SCULPT_vertex_count_get(SculptSession *ss)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex)
|
||||
MDynTopoVert *SCULPT_vertex_get_mdyntopo(SculptSession *ss, SculptVertRef vertex)
|
||||
{
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
|
||||
BMVert *v = (BMVert *)vertex.i;
|
||||
return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v)->origco;
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
BMVert *v = (BMVert *)vertex.i;
|
||||
return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v);
|
||||
}
|
||||
|
||||
case PBVH_GRIDS:
|
||||
case PBVH_FACES: {
|
||||
return ss->mdyntopo_verts + vertex.i;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX implement me
|
||||
return SCULPT_vertex_co_get(ss, vertex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex)
|
||||
{
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
BMVert *v = (BMVert *)vertex.i;
|
||||
return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v)->origco;
|
||||
}
|
||||
|
||||
case PBVH_GRIDS:
|
||||
case PBVH_FACES: {
|
||||
MDynTopoVert *mv = ss->mdyntopo_verts + vertex.i;
|
||||
|
||||
return ss->mdyntopo_verts[vertex.i].origco;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const float *SCULPT_vertex_co_get(SculptSession *ss, SculptVertRef index)
|
||||
|
@ -2284,6 +2309,9 @@ typedef enum StrokeFlags {
|
|||
void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, SculptUndoNode *unode)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
// do nothing
|
||||
|
||||
BMesh *bm = ss->bm;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
@ -2295,12 +2323,9 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
|
|||
if (bm) {
|
||||
data->bm_log = ss->bm_log;
|
||||
}
|
||||
|
||||
else {
|
||||
data->datatype = data->unode->type;
|
||||
data->coords = data->unode->co;
|
||||
data->normals = data->unode->no;
|
||||
data->vmasks = data->unode->mask;
|
||||
data->colors = data->unode->col;
|
||||
// data->datatype = data->unode->type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2316,75 +2341,58 @@ void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
|
|||
SculptUndoNode *unode = NULL;
|
||||
data->ss = ob->sculpt;
|
||||
|
||||
/*do not allocate an undo node for bmesh pbvh*/
|
||||
// don't need undo node here anymore
|
||||
if (!ob->sculpt->bm) {
|
||||
unode = SCULPT_undo_push_node(ob, node, type);
|
||||
// unode = SCULPT_undo_push_node(ob, node, type);
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_unode_init(data, ob, unode);
|
||||
data->datatype = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a #SculptOrigVertData for a particular vertex from the PBVH iterator.
|
||||
*/
|
||||
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
|
||||
void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex)
|
||||
{
|
||||
// check if we need to update original data for current stroke
|
||||
if (orig_data->bm_log) {
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert);
|
||||
if (mv->stroke_id != orig_data->ss->stroke_id) {
|
||||
mv->stroke_id = orig_data->ss->stroke_id;
|
||||
MDynTopoVert *mv = ss->bm ? BKE_PBVH_DYNVERT(ss->cd_dyn_vert, (BMVert *)vertex.i) :
|
||||
ss->mdyntopo_verts + vertex.i;
|
||||
|
||||
copy_v3_v3(mv->origco, iter->bm_vert->co);
|
||||
copy_v3_v3(mv->origno, iter->bm_vert->no);
|
||||
if (mv->stroke_id != ss->stroke_id) {
|
||||
mv->stroke_id = ss->stroke_id;
|
||||
|
||||
const int cd_vcol = iter->cd_vcol_offset;
|
||||
const int cd_mask = iter->cd_vert_mask_offset;
|
||||
copy_v3_v3(mv->origco, SCULPT_vertex_co_get(ss, vertex));
|
||||
SCULPT_vertex_normal_get(ss, vertex, mv->origno);
|
||||
|
||||
if (cd_vcol >= 0) {
|
||||
MPropCol *col = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, cd_vcol);
|
||||
copy_v4_v4(mv->origcolor, col->color);
|
||||
}
|
||||
|
||||
if (cd_mask >= 0) {
|
||||
mv->origmask = BM_ELEM_CD_GET_FLOAT(iter->bm_vert, cd_mask);
|
||||
}
|
||||
const float *color = SCULPT_vertex_color_get(ss, vertex);
|
||||
if (color) {
|
||||
copy_v4_v4(mv->origcolor, color);
|
||||
}
|
||||
|
||||
mv->origmask = SCULPT_vertex_mask_get(ss, vertex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED use Update a #SculptOrigVertData for a particular vertex from the PBVH iterator.
|
||||
*/
|
||||
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, SculptVertRef vertex)
|
||||
{
|
||||
// check if we need to update original data for current stroke
|
||||
MDynTopoVert *mv = SCULPT_vertex_get_mdyntopo(orig_data->ss, vertex);
|
||||
|
||||
SCULPT_vertex_check_origdata(orig_data->ss, vertex);
|
||||
|
||||
if (orig_data->datatype == SCULPT_UNDO_COORDS) {
|
||||
if (orig_data->bm_log) {
|
||||
orig_data->co = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origco;
|
||||
float *no = mv->origno;
|
||||
normal_float_to_short_v3(orig_data->_no, no);
|
||||
|
||||
float *no = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origno;
|
||||
normal_float_to_short_v3(orig_data->_no, no);
|
||||
orig_data->no = orig_data->_no;
|
||||
|
||||
orig_data->col = iter->cd_vcol_offset >= 0 ?
|
||||
BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origcolor :
|
||||
NULL;
|
||||
}
|
||||
else {
|
||||
orig_data->co = orig_data->coords[iter->i];
|
||||
orig_data->no = orig_data->normals[iter->i];
|
||||
}
|
||||
orig_data->no = orig_data->_no;
|
||||
orig_data->co = mv->origco;
|
||||
}
|
||||
else if (orig_data->datatype == SCULPT_UNDO_COLOR) {
|
||||
if (orig_data->bm_log) {
|
||||
orig_data->col = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origcolor;
|
||||
}
|
||||
else {
|
||||
orig_data->col = orig_data->colors[iter->i];
|
||||
}
|
||||
orig_data->col = mv->origcolor;
|
||||
}
|
||||
else if (orig_data->datatype == SCULPT_UNDO_MASK) {
|
||||
if (orig_data->bm_log) {
|
||||
orig_data->mask = BKE_PBVH_DYNVERT(iter->cd_dyn_vert, iter->bm_vert)->origmask;
|
||||
}
|
||||
else {
|
||||
orig_data->mask = orig_data->vmasks[iter->i];
|
||||
}
|
||||
orig_data->mask = mv->origmask;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2547,7 +2555,7 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
|
|||
SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
|
||||
copy_v3_v3(vd.co, orig_data.co);
|
||||
|
@ -4050,20 +4058,25 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
|
|||
}
|
||||
#endif
|
||||
|
||||
SCULPT_bmesh_four_neighbor_average(ss,
|
||||
avg,
|
||||
direction2,
|
||||
vd.bm_vert,
|
||||
data->rake_projection,
|
||||
check_fsets,
|
||||
data->cd_temp,
|
||||
data->cd_dyn_vert);
|
||||
int steps = data->do_origco ? 2 : 1;
|
||||
|
||||
sub_v3_v3v3(val, avg, vd.co);
|
||||
for (int step = 0; step < steps; step++) {
|
||||
float *co = step ? (float *)SCULPT_vertex_origco_get(ss, vd.vertex) : vd.co;
|
||||
|
||||
madd_v3_v3v3fl(val, vd.co, val, fade);
|
||||
SCULPT_bmesh_four_neighbor_average(ss,
|
||||
avg,
|
||||
direction2,
|
||||
vd.bm_vert,
|
||||
data->rake_projection,
|
||||
check_fsets,
|
||||
data->cd_temp,
|
||||
data->cd_dyn_vert,
|
||||
step);
|
||||
|
||||
SCULPT_clip(sd, ss, vd.co, val);
|
||||
sub_v3_v3v3(val, avg, co);
|
||||
madd_v3_v3v3fl(val, co, val, fade);
|
||||
SCULPT_clip(sd, ss, co, val);
|
||||
}
|
||||
|
||||
if (vd.mvert) {
|
||||
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
|
||||
|
@ -4146,7 +4159,8 @@ static void bmesh_topology_rake(
|
|||
.strength = factor,
|
||||
.cd_temp = cd_temp,
|
||||
.cd_dyn_vert = ss->cd_dyn_vert,
|
||||
.rake_projection = brush->topology_rake_projection};
|
||||
.rake_projection = brush->topology_rake_projection,
|
||||
.do_origco = SCULPT_stroke_needs_original(brush)};
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
|
||||
|
||||
|
@ -4220,7 +4234,7 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
|||
do_mask_brush_draw(sd, ob, nodes, totnode);
|
||||
break;
|
||||
case BRUSH_MASK_SMOOTH:
|
||||
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true, 0.0f);
|
||||
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true, 0.0f, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4537,7 +4551,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
|
|||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -4620,7 +4634,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
|
|||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -4789,7 +4803,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
|
|||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -5188,7 +5202,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
|
|||
const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE;
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -5289,7 +5303,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
|
|||
¶ms, ss->cache->radius, force, 1.0f, brush->elastic_deform_volume_preservation);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
float final_disp[3];
|
||||
switch (brush->elastic_deform_type) {
|
||||
case BRUSH_ELASTIC_DEFORM_GRAB:
|
||||
|
@ -5740,7 +5754,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
|
|||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -5813,7 +5827,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
|
|||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -5916,7 +5930,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
|
|||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
|
||||
continue;
|
||||
|
@ -7710,11 +7724,18 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
|
|||
totnode,
|
||||
brush->autosmooth_factor * (1.0f - ss->cache->pressure),
|
||||
false,
|
||||
brush->autosmooth_projection);
|
||||
brush->autosmooth_projection,
|
||||
false);
|
||||
}
|
||||
else {
|
||||
SCULPT_smooth(
|
||||
sd, ob, nodes, totnode, brush->autosmooth_factor, false, brush->autosmooth_projection);
|
||||
SCULPT_smooth(sd,
|
||||
ob,
|
||||
nodes,
|
||||
totnode,
|
||||
brush->autosmooth_factor,
|
||||
false,
|
||||
brush->autosmooth_projection,
|
||||
false);
|
||||
}
|
||||
|
||||
if (brush->autosmooth_radius_factor != 1.0f) {
|
||||
|
|
|
@ -1589,7 +1589,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
if (!SCULPT_check_vertex_pivot_symmetry(
|
||||
orig_data.co, boundary->initial_vertex_position, symm)) {
|
||||
continue;
|
||||
|
@ -1638,7 +1638,7 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
if (!SCULPT_check_vertex_pivot_symmetry(
|
||||
orig_data.co, boundary->initial_vertex_position, symm)) {
|
||||
continue;
|
||||
|
@ -1684,7 +1684,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
if (!SCULPT_check_vertex_pivot_symmetry(
|
||||
orig_data.co, boundary->initial_vertex_position, symm)) {
|
||||
continue;
|
||||
|
@ -1730,7 +1730,7 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
if (!SCULPT_check_vertex_pivot_symmetry(
|
||||
orig_data.co, boundary->initial_vertex_position, symm)) {
|
||||
continue;
|
||||
|
@ -1781,7 +1781,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
if (!SCULPT_check_vertex_pivot_symmetry(
|
||||
orig_data.co, boundary->initial_vertex_position, symm)) {
|
||||
continue;
|
||||
|
@ -1827,7 +1827,7 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata,
|
|||
continue;
|
||||
}
|
||||
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
if (!SCULPT_check_vertex_pivot_symmetry(
|
||||
orig_data.co, boundary->initial_vertex_position, symm)) {
|
||||
continue;
|
||||
|
@ -1913,7 +1913,7 @@ static void SCULPT_boundary_autosmooth(SculptSession *ss, SculptBoundary *bounda
|
|||
float sco[3];
|
||||
|
||||
SCULPT_neighbor_coords_average_interior(
|
||||
ss, sco, vd.vertex, ss->cache->brush->autosmooth_projection, NULL);
|
||||
ss, sco, vd.vertex, ss->cache->brush->autosmooth_projection, NULL, false);
|
||||
|
||||
float *co = SCULPT_brush_deform_target_vertex_co_get(
|
||||
ss, ss->cache->brush->deform_target, &vd);
|
||||
|
@ -1952,7 +1952,7 @@ static void SCULPT_boundary_build_smoothco(SculptSession *ss, SculptBoundary *bo
|
|||
|
||||
float sco[3];
|
||||
|
||||
SCULPT_neighbor_coords_average_interior(ss, sco, vd.vertex, projection, NULL);
|
||||
SCULPT_neighbor_coords_average_interior(ss, sco, vd.vertex, projection, NULL, false);
|
||||
|
||||
float *co = SCULPT_brush_deform_target_vertex_co_get(
|
||||
ss, ss->cache->brush->deform_target, &vd);
|
||||
|
|
|
@ -768,6 +768,11 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
|
|||
|
||||
SCULPT_pbvh_clear(ob);
|
||||
|
||||
if (ss->mdyntopo_verts) {
|
||||
MEM_freeN(ss->mdyntopo_verts);
|
||||
ss->mdyntopo_verts = NULL;
|
||||
}
|
||||
|
||||
ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) !=
|
||||
0;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ static void color_filter_task_cb(void *__restrict userdata,
|
|||
|
||||
PBVHVertexIter vd;
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
float orig_color[3], final_color[4], hsv_color[3];
|
||||
int hue;
|
||||
float brightness, contrast, gain, delta, offset;
|
||||
|
|
|
@ -303,7 +303,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
|||
|
||||
PBVHVertexIter vd;
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3];
|
||||
float fade = vd.mask ? *vd.mask : 0.0f;
|
||||
fade = 1.0f - fade;
|
||||
|
@ -334,7 +334,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
|||
switch (filter_type) {
|
||||
case MESH_FILTER_SMOOTH:
|
||||
fade = clamp_f(fade, -1.0f, 1.0f);
|
||||
SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, 0.0f, NULL);
|
||||
SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, 0.0f, NULL, false);
|
||||
sub_v3_v3v3(val, avg, orig_co);
|
||||
madd_v3_v3v3fl(val, orig_co, val, fade);
|
||||
sub_v3_v3v3(disp, val, orig_co);
|
||||
|
|
|
@ -217,8 +217,9 @@ void SCULPT_vertex_neighbors_get(const struct SculptSession *ss,
|
|||
|
||||
SculptVertRef SCULPT_active_vertex_get(SculptSession *ss);
|
||||
const float *SCULPT_active_vertex_co_get(SculptSession *ss);
|
||||
const float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex);
|
||||
float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex);
|
||||
void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3]);
|
||||
MDynTopoVert *SCULPT_vertex_get_mdyntopo(SculptSession *ss, SculptVertRef vertex);
|
||||
|
||||
/* Returns PBVH deformed vertices array if shape keys or deform modifiers are used, otherwise
|
||||
* returns mesh original vertices array. */
|
||||
|
@ -646,7 +647,8 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
float projection,
|
||||
bool check_fsets,
|
||||
int cd_temp,
|
||||
int cd_dyn_vert);
|
||||
int cd_dyn_vert,
|
||||
bool do_origco);
|
||||
|
||||
/* Smoothing api */
|
||||
void SCULPT_neighbor_coords_average(
|
||||
|
@ -659,7 +661,8 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
float result[3],
|
||||
SculptVertRef index,
|
||||
float projection,
|
||||
SculptCustomLayer *bound_scl);
|
||||
SculptCustomLayer *bound_scl,
|
||||
bool do_origco);
|
||||
|
||||
void SCULPT_smooth_vcol_boundary(
|
||||
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength);
|
||||
|
@ -670,7 +673,8 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
const int totnode,
|
||||
float bstrength,
|
||||
const bool smooth_mask,
|
||||
float projection);
|
||||
float projection,
|
||||
bool do_origco);
|
||||
|
||||
void SCULPT_do_smooth_brush(
|
||||
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float projection);
|
||||
|
@ -923,6 +927,7 @@ typedef struct SculptThreadedTaskData {
|
|||
float smooth_projection;
|
||||
float rake_projection;
|
||||
SculptCustomLayer *scl, *scl2;
|
||||
bool do_origco;
|
||||
} SculptThreadedTaskData;
|
||||
|
||||
/*************** Brush testing declarations ****************/
|
||||
|
@ -1446,11 +1451,13 @@ void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
|
|||
const float angle);
|
||||
void SCULPT_cache_free(StrokeCache *cache);
|
||||
|
||||
void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex);
|
||||
|
||||
void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
|
||||
Object *ob,
|
||||
PBVHNode *node,
|
||||
SculptUndoType type);
|
||||
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter);
|
||||
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, SculptVertRef vertex);
|
||||
void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data,
|
||||
Object *ob,
|
||||
struct SculptUndoNode *unode);
|
||||
|
@ -1692,3 +1699,13 @@ void SCULPT_replay_log_append(struct Sculpt *sd, struct SculptSession *ss, struc
|
|||
void SCULPT_replay_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
#define SCULPT_stroke_needs_original(brush) \
|
||||
ELEM(brush->sculpt_tool, \
|
||||
SCULPT_TOOL_DRAW_SHARP, \
|
||||
SCULPT_TOOL_GRAB, \
|
||||
SCULPT_TOOL_ROTATE, \
|
||||
SCULPT_TOOL_THUMB, \
|
||||
SCULPT_TOOL_ELASTIC_DEFORM, \
|
||||
SCULPT_TOOL_BOUNDARY, \
|
||||
SCULPT_TOOL_POSE)
|
||||
|
|
|
@ -140,7 +140,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
IMB_colormanagement_srgb_to_scene_linear_v3(brush_color);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
bool affect_vertex = false;
|
||||
float distance_to_stroke_location = 0.0f;
|
||||
|
|
|
@ -175,7 +175,7 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata,
|
|||
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
float total_disp[3];
|
||||
zero_v3(total_disp);
|
||||
|
|
|
@ -78,9 +78,17 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
float result[3],
|
||||
SculptVertRef vertex,
|
||||
float projection,
|
||||
SculptCustomLayer *bound_scl)
|
||||
SculptCustomLayer *bound_scl,
|
||||
bool do_origco)
|
||||
{
|
||||
float avg[3] = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
MDynTopoVert *mv = SCULPT_vertex_get_mdyntopo(ss, vertex);
|
||||
|
||||
if (do_origco) {
|
||||
SCULPT_vertex_check_origdata(ss, vertex);
|
||||
}
|
||||
|
||||
float total = 0.0f;
|
||||
int neighbor_count = 0;
|
||||
bool check_fsets = ss->cache->brush->flag2 & BRUSH_SMOOTH_PRESERVE_FACE_SETS;
|
||||
|
@ -97,11 +105,16 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
const SculptBoundaryType is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag);
|
||||
|
||||
const float *co = SCULPT_vertex_co_get(ss, vertex);
|
||||
const float *co = do_origco ? mv->origco : SCULPT_vertex_co_get(ss, vertex);
|
||||
float no[3];
|
||||
|
||||
if (true || projection > 0.0f) {
|
||||
SCULPT_vertex_normal_get(ss, vertex, no);
|
||||
if (do_origco) {
|
||||
copy_v3_v3(no, mv->origno);
|
||||
}
|
||||
else {
|
||||
SCULPT_vertex_normal_get(ss, vertex, no);
|
||||
}
|
||||
}
|
||||
|
||||
const bool weighted = (ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT) && !is_boundary;
|
||||
|
@ -131,6 +144,16 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
SculptVertexNeighborIter ni;
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
|
||||
MDynTopoVert *mv2 = SCULPT_vertex_get_mdyntopo(ss, ni.vertex);
|
||||
const float *co2;
|
||||
|
||||
if (!do_origco || mv2->stroke_id != ss->stroke_id) {
|
||||
co2 = SCULPT_vertex_co_get(ss, ni.vertex);
|
||||
}
|
||||
else {
|
||||
co2 = mv2->origco;
|
||||
}
|
||||
|
||||
neighbor_count++;
|
||||
|
||||
float tmp[3], w;
|
||||
|
@ -186,12 +209,12 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
w *= slide_fset;
|
||||
|
||||
sub_v3_v3v3(t, SCULPT_vertex_co_get(ss, ni.vertex), co);
|
||||
sub_v3_v3v3(t, co2, co);
|
||||
madd_v3_v3v3fl(tmp, co, no, dot_v3v3(t, no));
|
||||
ok = true;
|
||||
}
|
||||
else if (final_boundary) {
|
||||
copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex));
|
||||
copy_v3_v3(tmp, co2);
|
||||
ok = true;
|
||||
do_diffuse = false;
|
||||
}
|
||||
|
@ -200,7 +223,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
}
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex));
|
||||
copy_v3_v3(tmp, co2);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
|
@ -210,7 +233,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
makes more rounded edges.
|
||||
*/
|
||||
copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex));
|
||||
copy_v3_v3(tmp, co2);
|
||||
ok = true;
|
||||
|
||||
float len = len_v3v3(co, tmp);
|
||||
|
@ -228,7 +251,13 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
btot += w2;
|
||||
|
||||
float no2[3];
|
||||
SCULPT_vertex_normal_get(ss, ni.vertex, no2);
|
||||
|
||||
if (!do_origco || mv2->stroke_id != ss->stroke_id) {
|
||||
SCULPT_vertex_normal_get(ss, ni.vertex, no2);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(no2, mv2->origno);
|
||||
}
|
||||
|
||||
float radius = ss->cache->radius * 10.0f;
|
||||
|
||||
|
@ -280,13 +309,13 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
/* Do not modify corner vertices. */
|
||||
if (neighbor_count <= 2 && is_boundary) {
|
||||
copy_v3_v3(result, SCULPT_vertex_co_get(ss, vertex));
|
||||
copy_v3_v3(result, co);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Avoid division by 0 when there are no neighbors. */
|
||||
if (total == 0.0f) {
|
||||
copy_v3_v3(result, SCULPT_vertex_co_get(ss, vertex));
|
||||
copy_v3_v3(result, co);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -475,11 +504,12 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
float projection,
|
||||
bool check_fsets,
|
||||
int cd_temp,
|
||||
int cd_dyn_vert)
|
||||
int cd_dyn_vert,
|
||||
bool do_origco)
|
||||
{
|
||||
|
||||
float avg_co[3] = {0.0f, 0.0f, 0.0f};
|
||||
float tot_co = 0.0f;
|
||||
|
||||
float buckets[8] = {0};
|
||||
|
||||
// zero_v3(direction);
|
||||
|
@ -493,6 +523,17 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
const bool weighted = (ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT);
|
||||
float *areas;
|
||||
|
||||
SCULPT_vertex_check_origdata(ss, (SculptVertRef){.i = (intptr_t)v});
|
||||
|
||||
if (do_origco) {
|
||||
// SCULPT_vertex_check_origdata(ss, (SculptVertRef){.i = (intptr_t)v});
|
||||
madd_v3_v3fl(direction, mv->origno, -dot_v3v3(mv->origno, direction));
|
||||
normalize_v3(direction);
|
||||
}
|
||||
|
||||
float *co1 = do_origco ? mv->origco : v->co;
|
||||
float *no1 = do_origco ? mv->origno : v->no;
|
||||
|
||||
if (weighted) {
|
||||
SculptVertRef vertex = {.i = (intptr_t)v};
|
||||
|
||||
|
@ -508,12 +549,12 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
copy_v3_v3(dir, direction);
|
||||
}
|
||||
else {
|
||||
closest_vec_to_perp(dir, direction, v->no, buckets, 1.0f); // col[3]);
|
||||
closest_vec_to_perp(dir, direction, no1, buckets, 1.0f); // col[3]);
|
||||
}
|
||||
|
||||
float totdir3 = 0.0f;
|
||||
|
||||
const float selfw = (float)mv->valence * 0.25f;
|
||||
const float selfw = (float)mv->valence * 0.0025f;
|
||||
madd_v3_v3fl(dir3, direction, selfw);
|
||||
totdir3 += selfw;
|
||||
|
||||
|
@ -538,6 +579,18 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
//}
|
||||
|
||||
MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v_other);
|
||||
float *co2;
|
||||
float *no2;
|
||||
|
||||
if (!do_origco || mv2->stroke_id != ss->stroke_id) {
|
||||
co2 = v_other->co;
|
||||
no2 = v_other->no;
|
||||
}
|
||||
else {
|
||||
co2 = mv2->origco;
|
||||
no2 = mv2->origno;
|
||||
}
|
||||
|
||||
// bool bound = (mv2->flag &
|
||||
// (DYNVERT_BOUNDARY)); // | DYNVERT_FSET_BOUNDARY | DYNVERT_SHARP_BOUNDARY));
|
||||
// bool bound2 = (mv2->flag &
|
||||
|
@ -552,8 +605,8 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
if (bound) {
|
||||
had_bound = true;
|
||||
|
||||
sub_v3_v3v3(dir2, v_other->co, v->co);
|
||||
madd_v3_v3fl(dir2, v->no, -dot_v3v3(v->no, dir2));
|
||||
sub_v3_v3v3(dir2, co2, co1);
|
||||
madd_v3_v3fl(dir2, no1, -dot_v3v3(no1, dir2));
|
||||
normalize_v3(dir2);
|
||||
dirw = 100000.0f;
|
||||
}
|
||||
|
@ -566,7 +619,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
}
|
||||
}
|
||||
|
||||
closest_vec_to_perp(dir, dir2, v->no, buckets, bucketw); // col2[3]);
|
||||
closest_vec_to_perp(dir, dir2, no1, buckets, bucketw); // col2[3]);
|
||||
|
||||
madd_v3_v3fl(dir3, dir2, dirw);
|
||||
totdir3 += dirw;
|
||||
|
@ -577,9 +630,9 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
}
|
||||
|
||||
float vec[3];
|
||||
sub_v3_v3v3(vec, v_other->co, v->co);
|
||||
sub_v3_v3v3(vec, co2, co1);
|
||||
|
||||
madd_v3_v3fl(vec, v->no, -dot_v3v3(vec, v->no) * projection);
|
||||
madd_v3_v3fl(vec, no1, -dot_v3v3(vec, no1) * projection);
|
||||
normalize_v3(vec);
|
||||
|
||||
/* fac is a measure of how orthogonal or parallel the edge is
|
||||
|
@ -610,7 +663,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
fac *= areas[area_i];
|
||||
}
|
||||
|
||||
madd_v3_v3fl(avg_co, v_other->co, fac);
|
||||
madd_v3_v3fl(avg_co, co2, fac);
|
||||
tot_co += fac;
|
||||
}
|
||||
|
||||
|
@ -620,14 +673,19 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
|
||||
/* Preserve volume. */
|
||||
float vec[3];
|
||||
sub_v3_v3(avg, v->co);
|
||||
mul_v3_v3fl(vec, v->no, dot_v3v3(avg, v->no) * projection);
|
||||
sub_v3_v3(avg, co1);
|
||||
mul_v3_v3fl(vec, no1, dot_v3v3(avg, no1) * projection);
|
||||
sub_v3_v3(avg, vec);
|
||||
add_v3_v3(avg, v->co);
|
||||
add_v3_v3(avg, co1);
|
||||
}
|
||||
else {
|
||||
// zero_v3(avg);
|
||||
copy_v3_v3(avg, v->co);
|
||||
copy_v3_v3(avg, co1);
|
||||
}
|
||||
|
||||
// do not update in do_origco
|
||||
if (do_origco) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (totdir3 > 0.0f) {
|
||||
|
@ -658,7 +716,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
}
|
||||
|
||||
// negate_v3(col);
|
||||
vec_transform(col, v->no, bi);
|
||||
vec_transform(col, no1, bi);
|
||||
// negate_v3(col);
|
||||
}
|
||||
}
|
||||
|
@ -1077,10 +1135,16 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
|
|||
// continue;
|
||||
//}
|
||||
|
||||
SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, projection, bound_scl);
|
||||
sub_v3_v3v3(val, avg, vd.co);
|
||||
madd_v3_v3v3fl(val, vd.co, val, fade);
|
||||
SCULPT_clip(sd, ss, vd.co, val);
|
||||
int steps = data->do_origco ? 2 : 1;
|
||||
for (int step = 0; step < steps; step++) {
|
||||
float *co = step ? (float *)SCULPT_vertex_origco_get(ss, vd.vertex) : vd.co;
|
||||
|
||||
SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, projection, bound_scl, step);
|
||||
|
||||
sub_v3_v3v3(val, avg, co);
|
||||
madd_v3_v3v3fl(val, co, val, fade);
|
||||
SCULPT_clip(sd, ss, co, val);
|
||||
}
|
||||
}
|
||||
if (vd.mvert) {
|
||||
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
|
||||
|
@ -1159,7 +1223,8 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
const int totnode,
|
||||
float bstrength,
|
||||
const bool smooth_mask,
|
||||
float projection)
|
||||
float projection,
|
||||
bool do_origco)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
@ -1221,15 +1286,18 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
for (iteration = 0; iteration <= count; iteration++) {
|
||||
const float strength = (iteration != count) ? 1.0f : last;
|
||||
|
||||
SculptThreadedTaskData data = {.sd = sd,
|
||||
.ob = ob,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
.smooth_mask = smooth_mask,
|
||||
.strength = strength,
|
||||
.smooth_projection = projection,
|
||||
.scl = have_scl ? &scl : NULL,
|
||||
.scl2 = bound_scl};
|
||||
SculptThreadedTaskData data = {
|
||||
.sd = sd,
|
||||
.ob = ob,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
.smooth_mask = smooth_mask,
|
||||
.strength = strength,
|
||||
.smooth_projection = projection,
|
||||
.scl = have_scl ? &scl : NULL,
|
||||
.scl2 = bound_scl,
|
||||
.do_origco = SCULPT_stroke_needs_original(ss->cache->brush),
|
||||
};
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
|
||||
|
@ -1263,7 +1331,7 @@ void SCULPT_do_smooth_brush(
|
|||
}
|
||||
else {
|
||||
/* Regular mode, smooth. */
|
||||
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false, projection);
|
||||
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false, projection, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1350,7 +1418,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
|
|||
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
|
||||
continue;
|
||||
|
|
|
@ -165,7 +165,7 @@ static void sculpt_transform_task_cb(void *__restrict userdata,
|
|||
|
||||
SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
float transformed_co[3], orig_co[3], disp[3];
|
||||
float *start_co;
|
||||
float fade = vd.mask ? *vd.mask : 0.0f;
|
||||
|
|
|
@ -1602,7 +1602,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
|
|||
}
|
||||
|
||||
if (ss->deform_modifiers_active) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, unode->index[vd.i]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue