Sculpt: memory fixes
* Removed a pointer from a sculpt cloth struct. Due to padding this doubled the size of the struct. Hopefully this will be nicer on the L3 cache. * Fixed a nasty memory leak in the smoothing code with multires.
This commit is contained in:
parent
87c6d95603
commit
04d1bdbf36
|
@ -302,6 +302,8 @@ typedef enum eSculptClothConstraintType {
|
|||
SCULPT_CLOTH_CONSTRAINT_PIN = 3,
|
||||
} eSculptClothConstraintType;
|
||||
|
||||
#define CLOTH_NO_POS_PTR
|
||||
|
||||
typedef struct SculptClothConstraint {
|
||||
signed char ctype, thread_nr;
|
||||
|
||||
|
@ -328,18 +330,30 @@ typedef struct SculptClothConstraint {
|
|||
|
||||
struct {
|
||||
int index;
|
||||
float *co;
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
float *position;
|
||||
#endif
|
||||
} elems[];
|
||||
} SculptClothConstraint;
|
||||
|
||||
#define MAKE_CONSTRAINT_STRUCT(totelem) \
|
||||
signed char ctype, thread_nr; \
|
||||
short node; \
|
||||
float strength; \
|
||||
struct { \
|
||||
int index; \
|
||||
float *position; \
|
||||
} elems[totelem]
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
# define MAKE_CONSTRAINT_STRUCT(totelem) \
|
||||
signed char ctype, thread_nr; \
|
||||
short node; \
|
||||
float strength; \
|
||||
struct { \
|
||||
int index; \
|
||||
float *position; \
|
||||
} elems[totelem]
|
||||
#else
|
||||
# define MAKE_CONSTRAINT_STRUCT(totelem) \
|
||||
signed char ctype, thread_nr; \
|
||||
short node; \
|
||||
float strength; \
|
||||
struct { \
|
||||
int index; \
|
||||
} elems[totelem]
|
||||
#endif
|
||||
|
||||
typedef struct SculptClothLengthConstraint {
|
||||
MAKE_CONSTRAINT_STRUCT(2);
|
||||
|
@ -375,12 +389,6 @@ typedef struct SculptClothSimulation {
|
|||
*/
|
||||
int tot_constraint_tasks;
|
||||
|
||||
/* Position anchors for deformation brushes. These positions are modified by the brush and the
|
||||
* final positions of the simulated vertices are updated with constraints that use these points
|
||||
* as targets. */
|
||||
float (*deformation_pos)[3];
|
||||
float *deformation_strength;
|
||||
|
||||
float mass;
|
||||
float damping;
|
||||
float softbody_strength;
|
||||
|
@ -392,9 +400,17 @@ typedef struct SculptClothSimulation {
|
|||
float sim_falloff;
|
||||
|
||||
float (*acceleration)[3];
|
||||
|
||||
float (*pos)[3];
|
||||
float (*init_pos)[3];
|
||||
float (*softbody_pos)[3];
|
||||
|
||||
/* Position anchors for deformation brushes. These positions are modified by the brush and the
|
||||
* final positions of the simulated vertices are updated with constraints that use these points
|
||||
* as targets. */
|
||||
float (*deformation_pos)[3];
|
||||
float *deformation_strength;
|
||||
|
||||
float (*prev_pos)[3];
|
||||
float (*last_iteration_pos)[3];
|
||||
float (*init_normal)[3];
|
||||
|
@ -602,7 +618,9 @@ enum {
|
|||
SCULPT_SCL_LAYER_DISP,
|
||||
SCULPT_SCL_LAYER_STROKE_ID,
|
||||
SCULPT_SCL_ORIG_FSETS,
|
||||
SCULPT_SCL_LAYER_MAX
|
||||
SCULPT_SCL_SMOOTH_VEL,
|
||||
SCULPT_SCL_SMOOTH_BDIS,
|
||||
SCULPT_SCL_LAYER_MAX,
|
||||
};
|
||||
|
||||
typedef struct SculptSession {
|
||||
|
|
|
@ -6945,6 +6945,22 @@ void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache)
|
|||
MEM_freeN(cache);
|
||||
}
|
||||
|
||||
void SCULPT_release_customlayers(SculptSession *ss, bool non_customdata_only)
|
||||
{
|
||||
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
|
||||
if (ss->custom_layers[i]) {
|
||||
if (non_customdata_only && !ss->custom_layers[i]->params.simple_array) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SCULPT_temp_customlayer_release(ss, ss->custom_layers[i]);
|
||||
|
||||
MEM_freeN(ss->custom_layers[i]);
|
||||
ss->custom_layers[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SCULPT_clear_scl_pointers(SculptSession *ss)
|
||||
{
|
||||
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
|
||||
|
|
|
@ -127,6 +127,26 @@ struct {
|
|||
#endif
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
enum {
|
||||
CLOTH_POS_POS,
|
||||
CLOTH_POS_INIT,
|
||||
CLOTH_POS_SOFT,
|
||||
CLOTH_POS_DEF
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef CLOTH_NO_POS_PTR
|
||||
# define PACK_POS_TYPE(index, type) ((index) | ((type) << 26))
|
||||
# define UNPACK_POS_TYPE(index) ((index) >> 26)
|
||||
# define UNPACK_POS_INDEX(index) ((index) & ~(3 << 26))
|
||||
# define GET_POS_PTR(index) (&cloth_sim->pos)[UNPACK_POS_TYPE(index)][UNPACK_POS_INDEX(index)]
|
||||
//# define GET_POS_PTR_TYPE(index, type) (&cloth_sim->pos)[type][index]
|
||||
#else
|
||||
# define PACK_POS_TYPE(index, type) index
|
||||
# define UNPACK_POS_INDEX(index) index
|
||||
#endif
|
||||
|
||||
/* C port of:
|
||||
https://github.com/InteractiveComputerGraphics/PositionBasedDynamics/blob/master/PositionBasedDynamics/PositionBasedDynamics.cpp
|
||||
MIT license
|
||||
|
@ -254,17 +274,25 @@ static bool calc_bending_gradients(const SculptClothBendConstraint *constraint,
|
|||
return true;
|
||||
}
|
||||
# else
|
||||
static bool calc_bending_gradients(const SculptClothBendConstraint *constraint,
|
||||
static bool calc_bending_gradients(const SculptClothSimulation *cloth_sim,
|
||||
const SculptClothBendConstraint *constraint,
|
||||
float gradients[4][3])
|
||||
{
|
||||
// derivatives from Bridson, Simulation of Clothing with Folds and Wrinkles
|
||||
// his modes correspond to the derivatives of the bending angle arccos(n1 dot n2) with correct
|
||||
// scaling
|
||||
const float invMass0 = 1.0f, invMass1 = 1.0f, invMass2 = 1.0f, invMass3 = 1.0f;
|
||||
# ifndef CLOTH_NO_POS_PTR
|
||||
float *p0 = constraint->elems[0].position;
|
||||
float *p1 = constraint->elems[1].position;
|
||||
float *p2 = constraint->elems[2].position;
|
||||
float *p3 = constraint->elems[3].position;
|
||||
# else
|
||||
float *p0 = GET_POS_PTR(constraint->elems[0].index);
|
||||
float *p1 = GET_POS_PTR(constraint->elems[1].index);
|
||||
float *p2 = GET_POS_PTR(constraint->elems[2].index);
|
||||
float *p3 = GET_POS_PTR(constraint->elems[3].index);
|
||||
# endif
|
||||
|
||||
float *d0 = gradients[0];
|
||||
float *d1 = gradients[1];
|
||||
|
@ -602,17 +630,19 @@ static void cloth_brush_add_bend_constraint(SculptSession *ss,
|
|||
v3 = BKE_pbvh_table_index_to_vertex(ss->pbvh, v3i);
|
||||
v4 = BKE_pbvh_table_index_to_vertex(ss->pbvh, v4i);
|
||||
|
||||
bend_constraint->elems[0].index = v1i;
|
||||
bend_constraint->elems[1].index = v2i;
|
||||
bend_constraint->elems[2].index = v3i;
|
||||
bend_constraint->elems[3].index = v4i;
|
||||
bend_constraint->elems[0].index = PACK_POS_TYPE(v1i, CLOTH_POS_POS);
|
||||
bend_constraint->elems[1].index = PACK_POS_TYPE(v2i, CLOTH_POS_POS);
|
||||
bend_constraint->elems[2].index = PACK_POS_TYPE(v3i, CLOTH_POS_POS);
|
||||
bend_constraint->elems[3].index = PACK_POS_TYPE(v4i, CLOTH_POS_POS);
|
||||
|
||||
bend_constraint->node = node_index;
|
||||
|
||||
# ifndef CLOTH_NO_POS_PTR
|
||||
bend_constraint->elems[0].position = cloth_sim->pos[v1i];
|
||||
bend_constraint->elems[1].position = cloth_sim->pos[v2i];
|
||||
bend_constraint->elems[2].position = cloth_sim->pos[v3i];
|
||||
bend_constraint->elems[3].position = cloth_sim->pos[v4i];
|
||||
# endif
|
||||
|
||||
const float *co1, *co2, *co3, *co4;
|
||||
|
||||
|
@ -642,12 +672,12 @@ static void cloth_brush_add_bend_constraint(SculptSession *ss,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void cloth_brush_add_length_constraint(SculptSession *ss,
|
||||
SculptClothSimulation *cloth_sim,
|
||||
const int node_index,
|
||||
const int v1i,
|
||||
const int v2i,
|
||||
const bool use_persistent)
|
||||
ATTR_NO_OPT static void cloth_brush_add_length_constraint(SculptSession *ss,
|
||||
SculptClothSimulation *cloth_sim,
|
||||
const int node_index,
|
||||
const int v1i,
|
||||
const int v2i,
|
||||
const bool use_persistent)
|
||||
{
|
||||
SculptClothLengthConstraint *length_constraint = cloth_add_constraint(cloth_sim, CON_LENGTH);
|
||||
SculptVertRef v1, v2;
|
||||
|
@ -655,13 +685,15 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
|
|||
v1 = BKE_pbvh_table_index_to_vertex(ss->pbvh, v1i);
|
||||
v2 = BKE_pbvh_table_index_to_vertex(ss->pbvh, v2i);
|
||||
|
||||
length_constraint->elems[0].index = v1i;
|
||||
length_constraint->elems[1].index = v2i;
|
||||
length_constraint->elems[0].index = PACK_POS_TYPE(v1i, CLOTH_POS_POS);
|
||||
length_constraint->elems[1].index = PACK_POS_TYPE(v2i, CLOTH_POS_POS);
|
||||
|
||||
length_constraint->node = node_index;
|
||||
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
length_constraint->elems[0].position = cloth_sim->pos[v1i];
|
||||
length_constraint->elems[1].position = cloth_sim->pos[v2i];
|
||||
#endif
|
||||
|
||||
length_constraint->type = SCULPT_CLOTH_CONSTRAINT_STRUCTURAL;
|
||||
|
||||
|
@ -689,13 +721,15 @@ static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim
|
|||
{
|
||||
SculptClothLengthConstraint *length_constraint = cloth_add_constraint(cloth_sim, CON_LENGTH);
|
||||
|
||||
length_constraint->elems[0].index = v;
|
||||
length_constraint->elems[1].index = v;
|
||||
length_constraint->elems[0].index = PACK_POS_TYPE(v, CLOTH_POS_POS);
|
||||
length_constraint->elems[1].index = PACK_POS_TYPE(v, CLOTH_POS_SOFT);
|
||||
|
||||
length_constraint->node = node_index;
|
||||
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
length_constraint->elems[0].position = cloth_sim->pos[v];
|
||||
length_constraint->elems[1].position = cloth_sim->softbody_pos[v];
|
||||
#endif
|
||||
|
||||
length_constraint->type = SCULPT_CLOTH_CONSTRAINT_SOFTBODY;
|
||||
|
||||
|
@ -713,13 +747,15 @@ static void cloth_brush_add_pin_constraint(SculptClothSimulation *cloth_sim,
|
|||
{
|
||||
SculptClothLengthConstraint *length_constraint = cloth_add_constraint(cloth_sim, CON_LENGTH);
|
||||
|
||||
length_constraint->elems[0].index = v;
|
||||
length_constraint->elems[1].index = v;
|
||||
length_constraint->elems[0].index = PACK_POS_TYPE(v, CLOTH_POS_POS);
|
||||
length_constraint->elems[1].index = PACK_POS_TYPE(v, CLOTH_POS_INIT);
|
||||
|
||||
length_constraint->node = node_index;
|
||||
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
length_constraint->elems[0].position = cloth_sim->pos[v];
|
||||
length_constraint->elems[1].position = cloth_sim->init_pos[v];
|
||||
#endif
|
||||
|
||||
length_constraint->type = SCULPT_CLOTH_CONSTRAINT_PIN;
|
||||
|
||||
|
@ -730,22 +766,24 @@ static void cloth_brush_add_pin_constraint(SculptClothSimulation *cloth_sim,
|
|||
cloth_brush_reallocate_constraints(cloth_sim);
|
||||
}
|
||||
|
||||
static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_sim,
|
||||
const int node_index,
|
||||
const int v,
|
||||
const float strength)
|
||||
ATTR_NO_OPT static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_sim,
|
||||
const int node_index,
|
||||
const int v,
|
||||
const float strength)
|
||||
{
|
||||
SculptClothLengthConstraint *length_constraint = cloth_add_constraint(cloth_sim, CON_LENGTH);
|
||||
|
||||
length_constraint->elems[0].index = v;
|
||||
length_constraint->elems[1].index = v;
|
||||
length_constraint->elems[0].index = PACK_POS_TYPE(v, CLOTH_POS_POS);
|
||||
length_constraint->elems[1].index = PACK_POS_TYPE(v, CLOTH_POS_DEF);
|
||||
|
||||
length_constraint->node = node_index;
|
||||
|
||||
length_constraint->type = SCULPT_CLOTH_CONSTRAINT_DEFORMATION;
|
||||
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
length_constraint->elems[0].position = cloth_sim->pos[v];
|
||||
length_constraint->elems[1].position = cloth_sim->deformation_pos[v];
|
||||
#endif
|
||||
|
||||
length_constraint->length = 0.0f;
|
||||
length_constraint->strength = strength;
|
||||
|
@ -814,6 +852,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
|
|||
|
||||
build_indices[tot_indices] = vd.index;
|
||||
tot_indices++;
|
||||
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
|
||||
build_indices[tot_indices] = ni.index;
|
||||
|
||||
|
@ -1630,10 +1669,10 @@ static void cloth_free_tasks(SculptClothSimulation *cloth_sim)
|
|||
cloth_sim->tot_constraint_tasks = 0;
|
||||
}
|
||||
|
||||
static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
||||
Brush *brush,
|
||||
SculptClothSimulation *cloth_sim,
|
||||
int totthread)
|
||||
ATTR_NO_OPT static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
||||
Brush *brush,
|
||||
SculptClothSimulation *cloth_sim,
|
||||
int totthread)
|
||||
{
|
||||
SculptClothTaskData *tasks = MEM_calloc_arrayN(
|
||||
totthread + 1, sizeof(SculptClothTaskData), "SculptClothTaskData");
|
||||
|
@ -1675,7 +1714,7 @@ static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
|||
int last = 0, same = true;
|
||||
|
||||
for (int j = 0; j < totelem; j++) {
|
||||
int threadnr = vthreads[con->elems[j].index];
|
||||
int threadnr = vthreads[UNPACK_POS_INDEX(con->elems[j].index)];
|
||||
|
||||
if (threadnr) {
|
||||
ok = false;
|
||||
|
@ -1695,14 +1734,14 @@ static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
|||
tasknr = BLI_rng_get_int(rng) % totthread;
|
||||
|
||||
for (int j = 0; j < totelem; j++) {
|
||||
vthreads[con->elems[j].index] = tasknr + 1;
|
||||
vthreads[UNPACK_POS_INDEX(con->elems[j].index)] = tasknr + 1;
|
||||
}
|
||||
}
|
||||
else if (same) {
|
||||
tasknr = last - 1;
|
||||
|
||||
for (int j = 0; j < totelem; j++) {
|
||||
vthreads[con->elems[j].index] = tasknr + 1;
|
||||
vthreads[UNPACK_POS_INDEX(con->elems[j].index)] = tasknr + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1719,7 +1758,7 @@ static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
|||
dynamic mode where the performance benefits are
|
||||
not worth it*/
|
||||
for (int step = 0; not_dynamic && step < totelem; step++) {
|
||||
int v = con->elems[step].index;
|
||||
int v = UNPACK_POS_INDEX(con->elems[step].index);
|
||||
|
||||
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, v);
|
||||
SculptVertexNeighborIter ni;
|
||||
|
@ -1764,6 +1803,11 @@ static void cloth_sort_constraints_for_tasks(SculptSession *ss,
|
|||
cloth_sim->tot_constraint_tasks = totthread + 1;
|
||||
|
||||
#if 1
|
||||
unsigned int size = sizeof(SculptClothLengthConstraint) * cloth_sim->tot_constraints[0];
|
||||
size += sizeof(SculptClothBendConstraint) * cloth_sim->tot_constraints[1];
|
||||
|
||||
printf("%.2fmb", (float)size / 1024.0f / 1024.0f);
|
||||
|
||||
for (int i = 0; i < totthread + 1; i++) {
|
||||
printf("%d: ", i);
|
||||
|
||||
|
@ -1802,10 +1846,13 @@ static void cloth_brush_satisfy_constraints_intern(SculptSession *ss,
|
|||
continue;
|
||||
}
|
||||
|
||||
# ifndef CLOTH_NO_POS_PTR
|
||||
for (int j = 0; j < 4; j++) {
|
||||
constraint->elems[j].position = cloth_sim->pos[constraint->elems[j].index];
|
||||
}
|
||||
if (!calc_bending_gradients(constraint, gradients)) {
|
||||
# endif
|
||||
|
||||
if (!calc_bending_gradients(cloth_sim, constraint, gradients)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1813,9 +1860,14 @@ static void cloth_brush_satisfy_constraints_intern(SculptSession *ss,
|
|||
cloth_brush_simulation_location_get(ss, brush, sim_location);
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
int vi = constraint->elems[j].index;
|
||||
int vi = UNPACK_POS_INDEX(constraint->elems[j].index);
|
||||
|
||||
# ifndef CLOTH_NO_POS_PTR
|
||||
float *pos = constraint->elems[j].position;
|
||||
# else
|
||||
float *pos = GET_POS_PTR(constraint->elems[j].index);
|
||||
# endif
|
||||
|
||||
# if 1
|
||||
float sim_factor = ss->cache ? cloth_brush_simulation_falloff_get(cloth_sim,
|
||||
brush,
|
||||
ss->cache->radius,
|
||||
|
@ -1823,11 +1875,8 @@ static void cloth_brush_satisfy_constraints_intern(SculptSession *ss,
|
|||
cloth_sim->init_pos[vi]) :
|
||||
1.0f;
|
||||
|
||||
/*increase strength of bending constraints*/
|
||||
/* increase strength of bending constraints */
|
||||
sim_factor = sqrtf(sim_factor);
|
||||
# else
|
||||
float sim_factor = 0.9f;
|
||||
# endif
|
||||
|
||||
if (sim_factor == 0.0f) {
|
||||
continue;
|
||||
|
@ -1838,7 +1887,7 @@ static void cloth_brush_satisfy_constraints_intern(SculptSession *ss,
|
|||
sim_factor *= SCULPT_automasking_factor_get(automasking, ss, vref) * 1.0f -
|
||||
SCULPT_vertex_mask_get(ss, vref);
|
||||
|
||||
madd_v3_v3fl(constraint->elems[j].position, gradients[j], sim_factor);
|
||||
madd_v3_v3fl(pos, gradients[j], sim_factor);
|
||||
|
||||
if (USE_SOLVER_RIPPLE_CONSTRAINT) {
|
||||
cloth_brush_constraint_pos_to_line(cloth_sim, vi);
|
||||
|
@ -1855,14 +1904,23 @@ static void cloth_brush_satisfy_constraints_intern(SculptSession *ss,
|
|||
continue;
|
||||
}
|
||||
|
||||
const int v1 = constraint->elems[0].index;
|
||||
const int v2 = constraint->elems[1].index;
|
||||
#ifndef CLOTH_NO_POS_PTR
|
||||
float *pos1 = constraint->elems[0].position;
|
||||
float *pos2 = constraint->elems[1].position;
|
||||
#else
|
||||
float *pos1 = GET_POS_PTR(constraint->elems[0].index);
|
||||
float *pos2 = GET_POS_PTR(constraint->elems[1].index);
|
||||
#endif
|
||||
|
||||
const int v1 = UNPACK_POS_INDEX(constraint->elems[0].index);
|
||||
const int v2 = UNPACK_POS_INDEX(constraint->elems[1].index);
|
||||
|
||||
const SculptVertRef v1ref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v1);
|
||||
const SculptVertRef v2ref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v2);
|
||||
|
||||
float v1_to_v2[3];
|
||||
sub_v3_v3v3(v1_to_v2, constraint->elems[1].position, constraint->elems[0].position);
|
||||
sub_v3_v3v3(v1_to_v2, pos2, pos1);
|
||||
|
||||
const float current_distance = len_v3(v1_to_v2);
|
||||
float correction_vector[3];
|
||||
float correction_vector_half[3];
|
||||
|
|
|
@ -777,6 +777,12 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
|
|||
}
|
||||
}
|
||||
|
||||
/* destroy non-customdata temporary layers (which are rarely used) */
|
||||
SCULPT_release_customlayers(ss, true);
|
||||
|
||||
/* clear all the other temporary layer references, that point to customdata layers*/
|
||||
SCULPT_clear_scl_pointers(ss);
|
||||
|
||||
if (!ss->bm || !ss->pbvh || BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
|
||||
SCULPT_pbvh_clear(ob);
|
||||
}
|
||||
|
@ -923,6 +929,11 @@ static void SCULPT_dynamic_topology_disable_ex(
|
|||
Mesh *me = ob->data;
|
||||
|
||||
SCULPT_pbvh_clear(ob);
|
||||
|
||||
/* destroy non-customdata temporary layers (which are rarely used) */
|
||||
SCULPT_release_customlayers(ss, true);
|
||||
|
||||
/* free all the other pointers in ss->custom_layers*/
|
||||
SCULPT_clear_scl_pointers(ss);
|
||||
|
||||
BKE_sculptsession_bm_to_me(ob, true);
|
||||
|
|
|
@ -395,14 +395,14 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
|||
ss,
|
||||
avg,
|
||||
vd.vertex,
|
||||
&((SculptSmoothArgs){.projection = 0.0f,
|
||||
.slide_fset = slide_fset, // 1.0f - hard_edge_fac,
|
||||
.bound_smooth = bsmooth,
|
||||
.preserve_fset_boundaries = preserve_fset_boundaries,
|
||||
.do_weighted_smooth = weighted,
|
||||
.bound_smooth_radius = bound_smooth_radius,
|
||||
.bound_scl = bsmooth > 0.0f ? &ss->filter_cache->bound_scl :
|
||||
NULL}));
|
||||
&((SculptSmoothArgs){
|
||||
.projection = 0.0f,
|
||||
.slide_fset = slide_fset, // 1.0f - hard_edge_fac,
|
||||
.bound_smooth = bsmooth,
|
||||
.preserve_fset_boundaries = preserve_fset_boundaries,
|
||||
.do_weighted_smooth = weighted,
|
||||
.bound_smooth_radius = bound_smooth_radius,
|
||||
.bound_scl = bsmooth > 0.0f ? ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] : NULL}));
|
||||
|
||||
sub_v3_v3v3(val, avg, orig_co);
|
||||
madd_v3_v3v3fl(val, orig_co, val, fade);
|
||||
|
@ -910,7 +910,8 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
|
|||
ss->filter_cache->bound_smooth_radius = RNA_float_get(op->ptr, "bound_smooth_radius");
|
||||
|
||||
if (filter_type == MESH_FILTER_SMOOTH && ss->filter_cache->bound_smooth_radius != 0.0f) {
|
||||
SCULPT_bound_smooth_init(ss, &ss->filter_cache->bound_scl);
|
||||
/*ensure ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] exists*/
|
||||
SCULPT_bound_smooth_ensure(ss);
|
||||
}
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
|
|
@ -1722,8 +1722,6 @@ typedef struct FilterCache {
|
|||
float hard_edge_fac;
|
||||
bool hard_edge_mode;
|
||||
float bound_smooth_radius;
|
||||
|
||||
struct SculptCustomLayer bound_scl;
|
||||
} FilterCache;
|
||||
|
||||
void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
|
||||
|
@ -1959,6 +1957,7 @@ bool SCULPT_temp_customlayer_has(SculptSession *ss,
|
|||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name);
|
||||
void SCULPT_release_customlayers(SculptSession *ss, bool non_customdata_only);
|
||||
|
||||
bool SCULPT_dyntopo_automasking_init(const SculptSession *ss,
|
||||
Sculpt *sd,
|
||||
|
@ -2037,7 +2036,7 @@ struct BMesh *SCULPT_dyntopo_empty_bmesh();
|
|||
|
||||
/* initializes customdata layer used by SCULPT_neighbor_coords_average_interior when bound_smooth >
|
||||
* 0.0f*/
|
||||
void SCULPT_bound_smooth_init(SculptSession *ss, SculptCustomLayer *r_bound_scl);
|
||||
void SCULPT_bound_smooth_ensure(SculptSession *ss);
|
||||
|
||||
#define SCULPT_stroke_needs_original(brush) \
|
||||
ELEM(brush->sculpt_tool, \
|
||||
|
|
|
@ -1540,11 +1540,21 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
|
|||
}
|
||||
#endif
|
||||
|
||||
void SCULPT_bound_smooth_init(SculptSession *ss, SculptCustomLayer *r_bound_scl)
|
||||
void SCULPT_bound_smooth_ensure(SculptSession *ss)
|
||||
{
|
||||
SculptLayerParams params = {.permanent = true, .simple_array = false};
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "t__smooth_bdist", r_bound_scl, ¶ms);
|
||||
|
||||
if (!ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS]) {
|
||||
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] = MEM_callocN(sizeof(SculptCustomLayer),
|
||||
"bound_scl");
|
||||
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_COLOR,
|
||||
"t__smooth_bdist",
|
||||
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS],
|
||||
¶ms);
|
||||
}
|
||||
}
|
||||
|
||||
void SCULPT_smooth(Sculpt *sd,
|
||||
|
@ -1575,13 +1585,19 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
}
|
||||
|
||||
SculptLayerParams params = {.permanent = false, .simple_array = false};
|
||||
SculptCustomLayer vel_scl;
|
||||
|
||||
if (do_vel_smooth) {
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__scl_smooth_vel", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__scl_smooth_vel", &vel_scl, ¶ms);
|
||||
if (!ss->custom_layers[SCULPT_SCL_SMOOTH_VEL]) {
|
||||
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL] = MEM_callocN(sizeof(SculptCustomLayer),
|
||||
"vel_smooth_scl");
|
||||
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_FLOAT3,
|
||||
"__scl_smooth_vel",
|
||||
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL],
|
||||
¶ms);
|
||||
}
|
||||
}
|
||||
|
||||
float bstrength2 = bstrength;
|
||||
|
@ -1618,8 +1634,6 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
SCULPT_vertex_random_access_ensure(ss);
|
||||
SCULPT_boundary_info_ensure(ob);
|
||||
|
||||
SculptCustomLayer _scl, *bound_scl = NULL;
|
||||
|
||||
float bound_smooth = SCULPT_get_float(ss, boundary_smooth, sd, brush);
|
||||
float fset_slide = SCULPT_get_float(ss, fset_slide, sd, brush);
|
||||
|
||||
|
@ -1627,13 +1641,8 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
if (bound_smooth > 0.0f) {
|
||||
bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
|
||||
|
||||
bound_scl = &_scl;
|
||||
SCULPT_bound_smooth_init(ss, bound_scl);
|
||||
|
||||
if (do_vel_smooth) {
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__scl_smooth_vel", &vel_scl, ¶ms);
|
||||
}
|
||||
/* ensure ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] exists */
|
||||
SCULPT_bound_smooth_ensure(ss);
|
||||
}
|
||||
|
||||
#ifdef PROXY_ADVANCED
|
||||
|
@ -1672,8 +1681,8 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
.smooth_projection = projection,
|
||||
.fset_slide = fset_slide,
|
||||
.bound_smooth = bound_smooth,
|
||||
.scl = do_vel ? &vel_scl : NULL,
|
||||
.scl2 = bound_scl,
|
||||
.scl = do_vel ? ss->custom_layers[SCULPT_SCL_SMOOTH_VEL] : NULL,
|
||||
.scl2 = ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS],
|
||||
.vel_smooth_fac = vel_fac,
|
||||
.do_origco = do_origco,
|
||||
.iterations = count + 1,
|
||||
|
|
Loading…
Reference in New Issue