Sculpt-dev: clean up sculpt custom attribute API

* Cleaned up naming.
  - SCULPT_temp_customlayer_ensure is now
    SCULPT_attr_ensure_layer.
  - SCULPT_temp_cdata_get is now
    SCULPT_attr_vertex_data.
  - SCULPT_temp_cdata_get_f is now
    SCULPT_attr_face_data
  - SCULPT_temp_customlayer_get is now
    SCULPT_attr_get_layer.
* Replaced with ss->limit_surface with an
  entry in ss->custom_layers.
This commit is contained in:
Joseph Eagar 2022-01-12 01:13:15 -08:00
parent 15cb3130c3
commit 5e27ed5f0e
13 changed files with 386 additions and 321 deletions

View File

@ -660,7 +660,7 @@ typedef struct SculptCustomLayer {
int proptype;
SculptLayerParams params;
char name[512];
char name[MAX_CUSTOMDATA_LAYER_NAME];
bool is_cdlayer; // false for multires data
void *data; // only valid for multires and face
@ -676,7 +676,7 @@ typedef struct SculptCustomLayer {
(SculptCustomLayer pointers) inside of ss->custom_layers
that are kept up to date with SCULPT_update_customdata_refs.
*/
enum {
typedef enum {
SCULPT_SCL_FAIRING_MASK,
SCULPT_SCL_FAIRING_FADE,
SCULPT_SCL_PREFAIRING_CO,
@ -688,8 +688,13 @@ enum {
SCULPT_SCL_ORIG_FSETS,
SCULPT_SCL_SMOOTH_VEL,
SCULPT_SCL_SMOOTH_BDIS,
SCULPT_SCL_AUTOMASKING,
SCULPT_SCL_LIMIT_SURFACE,
SCULPT_SCL_LAYER_MAX,
};
} SculptStandardAttr;
#define SCULPT_SCL_GET_NAME(stdattr) ("__" #stdattr)
typedef struct SculptSession {
/* Mesh data (not copied) can come either directly from a Mesh, or from a MultiresDM */
@ -842,9 +847,6 @@ typedef struct SculptSession {
/* Boundary Brush Preview */
SculptBoundary *boundary_preview;
// float (*limit_surface)[3];
struct SculptCustomLayer *limit_surface;
SculptVertexInfo vertex_info;
SculptFakeNeighbors fake_neighbors;
@ -922,25 +924,32 @@ typedef struct SculptSession {
void BKE_sculptsession_free(struct Object *ob);
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, struct PBVH *pbvh, int totvert);
void BKE_sculptsession_sync_attributes(struct Object *ob, struct Mesh *me);
bool BKE_sculptsession_check_sculptverts(SculptSession *ss, struct PBVH *pbvh, int totvert);
struct BMesh *BKE_sculptsession_empty_bmesh_create(void);
void BKE_sculptsession_bmesh_attr_update_internal(struct Object *ob);
void BKE_sculptsession_sync_attributes(struct Object *ob, struct Mesh *me);
void BKE_sculptsession_bmesh_add_layers(struct Object *ob);
bool BKE_sculptsession_customlayer_get(struct Object *ob,
bool BKE_sculptsession_attr_get_layer(struct Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params);
bool BKE_sculptsession_customlayer_release(struct Object *ob, SculptCustomLayer *scl);
void BKE_sculptsession_bmesh_attr_update_internal(struct Object *ob);
bool BKE_sculptsession_attr_release_layer(struct Object *ob, SculptCustomLayer *scl);
void BKE_sculptsession_update_attr_refs(struct Object *ob);
int BKE_sculptsession_get_totvert(const SculptSession *ss);
void BKE_sculptsession_ignore_uvs_set(struct Object *ob, bool value);
/**
/**
* 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.
*/

View File

@ -1452,8 +1452,6 @@ static void sculptsession_free_pbvh(Object *object)
MEM_SAFE_FREE(ss->vemap);
MEM_SAFE_FREE(ss->vemap_mem);
MEM_SAFE_FREE(ss->limit_surface);
MEM_SAFE_FREE(ss->preview_vert_index_list);
ss->preview_vert_index_count = 0;
@ -1530,14 +1528,14 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->texcache);
bool SCULPT_temp_customlayer_release(
bool SCULPT_attr_release_layer(
SculptSession * ss, Object * ob, struct SculptCustomLayer * scl);
if (ss->layers_to_free) {
for (int i = 0; i < ss->tot_layers_to_free; i++) {
if (ss->layers_to_free[i]) {
SCULPT_temp_customlayer_release(ss, ob, ss->layers_to_free[i]);
// SCULPT_temp_customlayer_release frees layers_to_free[i] itself
SCULPT_attr_release_layer(ss, ob, ss->layers_to_free[i]);
// SCULPT_attr_release_layer frees layers_to_free[i] itself
}
}
@ -1552,8 +1550,6 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->deform_cos);
MEM_SAFE_FREE(ss->deform_imats);
MEM_SAFE_FREE(ss->limit_surface);
if (ss->pose_ik_chain_preview) {
for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights);
@ -1884,7 +1880,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
break;
}
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, totvert);
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, totvert);
if (ss->bm && me->key && ob->shapenr != ss->bm->shapenr) {
KeyBlock *actkey = BLI_findlink(&me->key->block, ss->bm->shapenr - 1);
@ -2432,7 +2428,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
false);
}
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, me->totvert);
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, me->totvert);
MEM_SAFE_FREE(ss->face_areas);
ss->face_areas = MEM_calloc_arrayN(me->totpoly, sizeof(float) * 2, "ss->face_areas");
@ -2500,7 +2496,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
ss->temp_vdata_elems = BKE_pbvh_get_grid_num_vertices(pbvh);
ss->temp_pdata_elems = ss->totfaces;
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, BKE_pbvh_get_grid_num_vertices(pbvh));
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, 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);
@ -2508,7 +2504,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
return pbvh;
}
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, PBVH *pbvh, int totvert)
bool BKE_sculptsession_check_sculptverts(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (!ss->bm && (!ss->mdyntopo_verts || totvert != ss->mdyntopo_verts_size)) {
init_mdyntopo_layer(ss, pbvh, totvert);
@ -2684,7 +2680,7 @@ 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);
BKE_sculptsession_check_sculptverts(ob->sculpt, me_eval_deform->totvert);
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
}
@ -2986,14 +2982,14 @@ void BKE_sculptsession_bmesh_add_layers(Object *ob)
}
}
static bool sculpt_temp_customlayer_get(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *out,
bool autocreate,
SculptLayerParams *params)
static bool sculpt_attr_get_layer(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *out,
bool autocreate,
SculptLayerParams *params)
{
if (ss->save_temp_layers && !params->simple_array) {
params->permanent = true;
@ -3270,7 +3266,7 @@ static bool sculpt_temp_customlayer_get(SculptSession *ss,
return true;
}
bool BKE_sculptsession_customlayer_get(Object *ob,
bool BKE_sculptsession_attr_get_layer(Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
@ -3279,7 +3275,7 @@ bool BKE_sculptsession_customlayer_get(Object *ob,
{
SculptSession *ss = ob->sculpt;
bool ret = sculpt_temp_customlayer_get(ss, ob, domain, proptype, name, scl, true, params);
bool ret = sculpt_attr_get_layer(ss, ob, domain, proptype, name, scl, true, params);
BKE_sculptsession_update_attr_refs(ob);
return ret;
@ -3307,14 +3303,14 @@ void BKE_sculptsession_update_attr_refs(Object *ob)
{
SculptSession *ss = ob->sculpt;
/* run twice, in case sculpt_temp_customlayer_get had to recreate a layer and
/* run twice, in case SCULPT_attr_get_layer had to recreate a layer and
messed up the ordering. */
for (int i = 0; i < 2; i++) {
for (int j = 0; j < SCULPT_SCL_LAYER_MAX; j++) {
SculptCustomLayer *scl = ss->custom_layers[j];
if (scl && !scl->released && !scl->params.simple_array) {
sculpt_temp_customlayer_get(
sculpt_attr_get_layer(
ss, ob, scl->domain, scl->proptype, scl->name, scl, true, &scl->params);
}
}
@ -3363,7 +3359,7 @@ bool BKE_paint_uses_channels(ePaintMode mode)
return mode == PAINT_MODE_SCULPT;
}
bool BKE_sculptsession_customlayer_release(Object *ob, SculptCustomLayer *scl)
bool BKE_sculptsession_attr_release_layer(Object *ob, SculptCustomLayer *scl)
{
SculptSession *ss = ob->sculpt;
AttributeDomain domain = scl->domain;

View File

@ -59,6 +59,11 @@ static std::vector<AttributeRef> get_vcol_refs(const CustomData *cd_vdata,
AttributeDomain domain = domains[step2];
int i = cdata->typemap[(int)type];
if (i == -1) {
continue;
}
for (; i < cdata->totlayer && (CustomDataType)cdata->layers[i].type == type; i++, layeri++) {
const CustomDataLayer *layer = cdata->layers + i;

View File

@ -736,7 +736,7 @@ bool SCULPT_has_persistent_base(SculptSession *ss)
const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, SculptVertRef index)
{
if (ss->custom_layers[SCULPT_SCL_PERS_CO]) {
return (float *)SCULPT_temp_cdata_get(index, ss->custom_layers[SCULPT_SCL_PERS_CO]);
return (float *)SCULPT_attr_vertex_data(index, ss->custom_layers[SCULPT_SCL_PERS_CO]);
}
return SCULPT_vertex_co_get(ss, index);
@ -762,8 +762,8 @@ const float *SCULPT_vertex_co_for_grab_active_get(SculptSession *ss, SculptVertR
void SCULPT_vertex_limit_surface_get(SculptSession *ss, SculptVertRef vertex, float r_co[3])
{
if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
if (ss->limit_surface) {
float *f = SCULPT_temp_cdata_get(vertex, ss->limit_surface);
if (ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE]) {
float *f = SCULPT_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE]);
copy_v3_v3(r_co, f);
}
else {
@ -786,7 +786,7 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, SculptVertRef vertex, fl
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, SculptVertRef vertex, float no[3])
{
if (ss->custom_layers[SCULPT_SCL_PERS_NO]) {
float *no2 = SCULPT_temp_cdata_get(vertex, ss->custom_layers[SCULPT_SCL_PERS_NO]);
float *no2 = SCULPT_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_PERS_NO]);
copy_v3_v3(no, no2);
}
else {
@ -822,7 +822,7 @@ float SCULPT_vertex_mask_get(SculptSession *ss, SculptVertRef index)
return 0.0f;
}
bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
bool SCULPT_attr_ensure_layer(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
@ -835,7 +835,7 @@ bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
// thoeretically it can allocate new layers
SCULPT_update_customdata_refs(ss, ob);
bool ret = SCULPT_temp_customlayer_get(ss, ob, domain, proptype, name, &scl, params);
bool ret = SCULPT_attr_get_layer(ss, ob, domain, proptype, name, &scl, params);
SCULPT_update_customdata_refs(ss, ob);
@ -843,7 +843,7 @@ bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
}
/* TODO: thoroughly test this function */
bool SCULPT_temp_customlayer_has(SculptSession *ss,
bool SCULPT_attr_has_layer(SculptSession *ss,
AttributeDomain domain,
int proptype,
const char *name)
@ -882,12 +882,12 @@ bool SCULPT_temp_customlayer_has(SculptSession *ss,
return false;
}
bool SCULPT_temp_customlayer_release(SculptSession *ss, Object *ob, SculptCustomLayer *scl)
bool SCULPT_attr_release_layer(SculptSession *ss, Object *ob, SculptCustomLayer *scl)
{
return BKE_sculptsession_customlayer_release(ob, scl);
return BKE_sculptsession_attr_release_layer(ob, scl);
}
bool SCULPT_temp_customlayer_get(SculptSession *ss,
bool SCULPT_attr_get_layer(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
@ -895,7 +895,7 @@ bool SCULPT_temp_customlayer_get(SculptSession *ss,
SculptCustomLayer *scl,
SculptLayerParams *params)
{
return BKE_sculptsession_customlayer_get(ob, domain, proptype, name, scl, params);
return BKE_sculptsession_attr_get_layer(ob, domain, proptype, name, scl, params);
}
SculptVertRef SCULPT_active_vertex_get(SculptSession *ss)
@ -6887,13 +6887,13 @@ void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
#endif
if (ss->custom_layers[SCULPT_SCL_LAYER_DISP]) {
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_LAYER_DISP]);
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[SCULPT_SCL_LAYER_DISP]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_LAYER_DISP]);
ss->custom_layers[SCULPT_SCL_LAYER_DISP] = NULL;
}
if (ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]) {
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]);
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]);
ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID] = NULL;
}
@ -6906,20 +6906,20 @@ void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
}
if (ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) {
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
ss->custom_layers[SCULPT_SCL_FAIRING_MASK] = NULL;
}
if (ss->custom_layers[SCULPT_SCL_FAIRING_FADE]) {
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
ss->custom_layers[SCULPT_SCL_FAIRING_FADE] = NULL;
}
if (ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]) {
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO] = NULL;
@ -6965,7 +6965,7 @@ void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
MEM_freeN(cache);
}
void SCULPT_release_customlayers(SculptSession *ss, Object *ob, bool non_customdata_only)
void SCULPT_release_attributes(SculptSession *ss, Object *ob, bool non_customdata_only)
{
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
if (ss->custom_layers[i]) {
@ -6973,7 +6973,7 @@ void SCULPT_release_customlayers(SculptSession *ss, Object *ob, bool non_customd
continue;
}
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[i]);
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[i]);
MEM_freeN(ss->custom_layers[i]);
ss->custom_layers[i] = NULL;

View File

@ -94,14 +94,14 @@ static void sculpt_array_datalayers_init(Object *ob, SculptArray *array, SculptS
array->scl_sym = MEM_callocN(sizeof(SculptCustomLayer), __func__);
}
SCULPT_temp_customlayer_ensure(
SCULPT_attr_ensure_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, &params);
SCULPT_temp_customlayer_ensure(
SCULPT_attr_ensure_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, &params);
SCULPT_temp_customlayer_get(
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_get(ss,
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
@ -121,8 +121,8 @@ static void sculpt_array_datalayers_add(SculptArray *array, SculptSession *ss, M
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
*(int *)SCULPT_temp_cdata_get(vertex, scl) = ARRAY_INSTANCE_ORIGINAL;
*(int *)SCULPT_temp_cdata_get(vertex, array->scl_sym) = 0;
*(int *)SCULPT_attr_vertex_data(vertex, scl) = ARRAY_INSTANCE_ORIGINAL;
*(int *)SCULPT_attr_vertex_data(vertex, array->scl_sym) = 0;
}
}
@ -133,7 +133,7 @@ void SCULPT_array_datalayers_free(SculptArray *array, Object *ob)
#if 0
Mesh *mesh = BKE_object_get_original_mesh(ob);
// update cdata pointers for SCULPT_temp_customlayer_release
// update cdata pointers for SCULPT_attr_release_layer
if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
ss->vdata = &mesh->vdata;
ss->edata = &mesh->edata;
@ -154,32 +154,32 @@ void SCULPT_array_datalayers_free(SculptArray *array, Object *ob)
ss->totvert = mesh->totvert;
}
BKE_sculptsession_check_mdyntopo(ss, ss->pbvh, SCULPT_vertex_count_get(ss));
BKE_sculptsession_check_sculptverts(ss, ss->pbvh, SCULPT_vertex_count_get(ss));
}
#endif
SculptLayerParams params = {.permanent = true, .simple_array = false};
if (array->scl_inst) {
SCULPT_temp_customlayer_get(ss,
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_instance_cd_name,
array->scl_inst,
&params);
SCULPT_temp_customlayer_release(ss, ob, array->scl_inst);
SCULPT_attr_release_layer(ss, ob, array->scl_inst);
}
if (array->scl_sym) {
SCULPT_temp_customlayer_get(ss,
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
SCULPT_temp_customlayer_release(ss, ob, array->scl_sym);
SCULPT_attr_release_layer(ss, ob, array->scl_sym);
}
SCULPT_update_customdata_refs(ss, ob);
@ -353,9 +353,9 @@ static void sculpt_array_ensure_geometry_indices(Object *ob, SculptArray *array)
SculptLayerParams params = {.permanent = true, .simple_array = false};
SCULPT_temp_customlayer_get(
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_get(ss,
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
@ -369,8 +369,8 @@ static void sculpt_array_ensure_geometry_indices(Object *ob, SculptArray *array)
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
array->copy_index[i] = *(int *)SCULPT_temp_cdata_get(vertex, array->scl_inst);
array->symmetry_pass[i] = *(int *)SCULPT_temp_cdata_get(vertex, array->scl_sym);
array->copy_index[i] = *(int *)SCULPT_attr_vertex_data(vertex, array->scl_inst);
array->symmetry_pass[i] = *(int *)SCULPT_attr_vertex_data(vertex, array->scl_sym);
}
SCULPT_array_datalayers_free(array, ob);

View File

@ -206,25 +206,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
* automasking information can't be computed in real time per vertex and needs to be
* initialized for the whole mesh when the stroke starts. */
if (automasking->factorlayer) {
mask = *(float *)SCULPT_temp_cdata_get(vert, automasking->factorlayer);
}
// don't used cached automasking factors for facesets or concave in
// dyntopo
if (automasking->factorlayer && !ss->bm) {
return mask;
}
if (do_concave) {
float fac = SCULPT_calc_concavity(ss, vert);
mask *= sculpt_concavity_factor(automasking, fac);
}
if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
return 0.0f;
}
mask = *(float *)SCULPT_attr_vertex_data(vert, automasking->factorlayer);
}
if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
@ -265,6 +247,24 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
automasking->settings.view_normal_falloff);
}
// don't used cached automasking factors for facesets or concave in
// dyntopo
if (automasking->factorlayer && !ss->bm) {
return mask;
}
if (do_concave) {
float fac = SCULPT_calc_concavity(ss, vert);
mask *= sculpt_concavity_factor(automasking, fac);
}
if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
return 0.0f;
}
}
return mask;
}
@ -274,9 +274,11 @@ void SCULPT_automasking_cache_free(SculptSession *ss, Object *ob, AutomaskingCac
return;
}
if (automasking->factorlayer) {
SCULPT_temp_customlayer_release(ss, ob, automasking->factorlayer);
MEM_SAFE_FREE(automasking->factorlayer);
if (ss->custom_layers[SCULPT_SCL_AUTOMASKING]) {
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[SCULPT_SCL_AUTOMASKING]);
MEM_SAFE_FREE(ss->custom_layers[SCULPT_SCL_AUTOMASKING]);
ss->custom_layers[SCULPT_SCL_AUTOMASKING] = NULL;
}
MEM_SAFE_FREE(automasking);
@ -311,8 +313,8 @@ static bool automask_floodfill_cb(SculptSession *ss,
{
AutomaskFloodFillData *data = userdata;
*(float *)SCULPT_temp_cdata_get(to_vref, data->factorlayer) = 1.0f;
*(float *)SCULPT_temp_cdata_get(from_vref, data->factorlayer) = 1.0f;
*(float *)SCULPT_attr_vertex_data(to_vref, data->factorlayer) = 1.0f;
*(float *)SCULPT_attr_vertex_data(from_vref, data->factorlayer) = 1.0f;
return (!data->use_radius ||
SCULPT_is_vertex_inside_brush_radius_symm(
@ -335,7 +337,7 @@ static void SCULPT_topology_automasking_init(Sculpt *sd,
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *fac = SCULPT_temp_cdata_get(vertex, factorlayer);
float *fac = SCULPT_attr_vertex_data(vertex, factorlayer);
*fac = 0.0f;
}
@ -387,7 +389,7 @@ static void sculpt_face_sets_automasking_init(Sculpt *sd,
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
if (!SCULPT_vertex_has_face_set(ss, vertex, active_face_set)) {
*(float *)SCULPT_temp_cdata_get(vertex, factorlayer) = 0.0f;
*(float *)SCULPT_attr_vertex_data(vertex, factorlayer) = 0.0f;
}
}
}
@ -449,7 +451,7 @@ void SCULPT_boundary_automasking_init(Object *ob,
const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps);
const float edge_boundary_automask = pow2f(p);
*(float *)SCULPT_temp_cdata_get(vertex, factorlayer) *= (1.0f - edge_boundary_automask);
*(float *)SCULPT_attr_vertex_data(vertex, factorlayer) *= (1.0f - edge_boundary_automask);
}
MEM_SAFE_FREE(edge_distance);
@ -538,7 +540,7 @@ static void SCULPT_concavity_automasking_init(Object *ob,
float f = SCULPT_calc_concavity(ss, vref);
f = sculpt_concavity_factor(automasking, f);
*(float *)SCULPT_temp_cdata_get(vref, factorlayer) *= f;
*(float *)SCULPT_attr_vertex_data(vref, factorlayer) *= f;
}
// BKE_pbvh_vertex_iter_begin
}
@ -564,26 +566,35 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
SCULPT_vertex_random_access_ensure(ss);
SCULPT_face_random_access_ensure(ss);
automasking->factorlayer = MEM_callocN(sizeof(SculptCustomLayer), "automasking->factorlayer");
SculptLayerParams params = {.permanent = false, .simple_array = false};
if (ss->custom_layers[SCULPT_SCL_AUTOMASKING]) {
automasking->factorlayer = ss->custom_layers[SCULPT_SCL_AUTOMASKING];
}
else {
ss->custom_layers[SCULPT_SCL_AUTOMASKING] = MEM_callocN(sizeof(SculptCustomLayer),
"automasking->factorlayer");
if (!SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
"__sculpt_mask_factor",
automasking->factorlayer,
&params)) {
// failed
MEM_freeN(automasking->factorlayer);
return automasking;
SculptLayerParams params = {.permanent = false, .simple_array = false};
if (!SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_SCL_GET_NAME(SCULPT_SCL_AUTOMASKING),
automasking->factorlayer,
&params)) {
// failed
MEM_freeN(ss->custom_layers[SCULPT_SCL_AUTOMASKING]);
ss->custom_layers[SCULPT_SCL_AUTOMASKING] = NULL;
return automasking;
}
}
// automasking->factorlayer = SCULPT_temp_customlayer_ensure()
// automasking->factorlayer = SCULPT_attr_ensure_layer()
// automasking->factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *f = SCULPT_temp_cdata_get(vertex, automasking->factorlayer);
float *f = SCULPT_attr_vertex_data(vertex, automasking->factorlayer);
*f = 1.0f;
}

View File

@ -1851,10 +1851,10 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
}
if (!use_persistent_base) {
int *stroke_id = SCULPT_temp_cdata_get(vd.vertex, scl_stroke_id);
int *stroke_id = SCULPT_attr_vertex_data(vd.vertex, scl_stroke_id);
if (*stroke_id != ss->stroke_id) {
*((float *)SCULPT_temp_cdata_get(vd.vertex, scl_disp)) = 0.0f;
*((float *)SCULPT_attr_vertex_data(vd.vertex, scl_disp)) = 0.0f;
*stroke_id = ss->stroke_id;
}
}
@ -1872,11 +1872,11 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
float *disp_factor;
if (use_persistent_base) {
disp_factor = (float *)SCULPT_temp_cdata_get(vd.vertex,
ss->custom_layers[SCULPT_SCL_PERS_DISP]);
disp_factor = (float *)SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_PERS_DISP]);
}
else {
disp_factor = (float *)SCULPT_temp_cdata_get(vd.vertex, scl_disp);
disp_factor = (float *)SCULPT_attr_vertex_data(vd.vertex, scl_disp);
}
/* When using persistent base, the layer brush (holding Control) invert mode resets the
@ -2007,32 +2007,32 @@ void SCULPT_ensure_persistent_layers(SculptSession *ss, Object *ob)
SculptLayerParams params = {.permanent = true, .simple_array = false};
ss->custom_layers[SCULPT_SCL_PERS_CO] = MEM_callocN(sizeof(SculptCustomLayer), "scl_pers_co");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_LAYER_PERS_CO,
ss->custom_layers[SCULPT_SCL_PERS_CO],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_LAYER_PERS_CO,
ss->custom_layers[SCULPT_SCL_PERS_CO],
&params);
ss->custom_layers[SCULPT_SCL_PERS_NO] = MEM_callocN(sizeof(SculptCustomLayer), "scl_pers_no");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_LAYER_PERS_NO,
ss->custom_layers[SCULPT_SCL_PERS_NO],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_LAYER_PERS_NO,
ss->custom_layers[SCULPT_SCL_PERS_NO],
&params);
ss->custom_layers[SCULPT_SCL_PERS_DISP] = MEM_callocN(sizeof(SculptCustomLayer),
"scl_pers_disp");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_PERS_DISP,
ss->custom_layers[SCULPT_SCL_PERS_DISP],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_PERS_DISP,
ss->custom_layers[SCULPT_SCL_PERS_DISP],
&params);
}
}
@ -2056,25 +2056,25 @@ void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
if (!ss->custom_layers[SCULPT_SCL_LAYER_DISP]) {
ss->custom_layers[SCULPT_SCL_LAYER_DISP] = MEM_callocN(sizeof(SculptCustomLayer),
"layer disp scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_DISP,
ss->custom_layers[SCULPT_SCL_LAYER_DISP],
&((SculptLayerParams){.permanent = false, .simple_array = false}));
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_DISP,
ss->custom_layers[SCULPT_SCL_LAYER_DISP],
&((SculptLayerParams){.permanent = false, .simple_array = false}));
}
if (!ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]) {
ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID] = MEM_callocN(sizeof(SculptCustomLayer),
"layer disp scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_LAYER_STROKE_ID,
ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID],
&((SculptLayerParams){.permanent = false, .simple_array = false}));
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID],
&((SculptLayerParams){.permanent = false, .simple_array = false}));
}
if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
@ -3436,7 +3436,8 @@ static void do_fairing_brush_tag_store_task_cb_ex(void *__restrict userdata,
continue;
}
float *prefair = SCULPT_temp_cdata_get(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
float *prefair = SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
@ -3452,10 +3453,10 @@ static void do_fairing_brush_tag_store_task_cb_ex(void *__restrict userdata,
continue;
}
float *fairing_fade = SCULPT_temp_cdata_get(vd.vertex,
ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
bool *fairing_mask = SCULPT_temp_cdata_get(vd.vertex,
ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
float *fairing_fade = SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
uchar *fairing_mask = SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
*fairing_fade = max_ff(fade, *fairing_fade);
*fairing_mask = true;
@ -3469,6 +3470,8 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
Brush *brush = BKE_paint_brush(&sd->paint);
const int totvert = SCULPT_vertex_count_get(ss);
printf("sizeof(bool): %d\n", (int)(sizeof(bool)));
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
return;
}
@ -3477,9 +3480,9 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SCULPT_face_random_access_ensure(ss);
if (!ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) {
// SCULPT_temp_customlayer_ensure(ss, ATTR_DOMAIN_POINT, CD_PROP_BOOL, "fairing_mask");
// SCULPT_temp_customlayer_ensure(ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "fairing_fade");
// SCULPT_temp_customlayer_ensure(ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "prefairing_co");
// SCULPT_attr_ensure_layer(ss, ATTR_DOMAIN_POINT, CD_PROP_BOOL, "fairing_mask");
// SCULPT_attr_ensure_layer(ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "fairing_fade");
// SCULPT_attr_ensure_layer(ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "prefairing_co");
ss->custom_layers[SCULPT_SCL_FAIRING_MASK] = MEM_callocN(sizeof(SculptCustomLayer),
"ss->Cache->fairing_mask");
@ -3490,29 +3493,29 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SculptLayerParams params = {.permanent = false, .simple_array = true};
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_BOOL,
"fairing_mask",
ss->custom_layers[SCULPT_SCL_FAIRING_MASK],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_BOOL,
SCULPT_SCL_GET_NAME(SCULPT_SCL_FAIRING_MASK),
ss->custom_layers[SCULPT_SCL_FAIRING_MASK],
&params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
"fairing_fade",
ss->custom_layers[SCULPT_SCL_FAIRING_FADE],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_SCL_GET_NAME(SCULPT_SCL_FAIRING_FADE),
ss->custom_layers[SCULPT_SCL_FAIRING_FADE],
&params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"prefairing_co",
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_SCL_GET_NAME(SCULPT_SCL_PREFAIRING_CO),
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO],
&params);
SCULPT_update_customdata_refs(ss, ob);
}
@ -3521,10 +3524,10 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
*(bool *)SCULPT_temp_cdata_get(vertex, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) = false;
*(float *)SCULPT_temp_cdata_get(vertex, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]) = 0.0f;
*(uchar *)SCULPT_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) = false;
*(float *)SCULPT_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]) = 0.0f;
copy_v3_v3(
(float *)SCULPT_temp_cdata_get(vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]),
(float *)SCULPT_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]),
SCULPT_vertex_co_get(ss, vertex));
}
}
@ -3552,18 +3555,18 @@ static void do_fairing_brush_displace_task_cb_ex(void *__restrict userdata,
SculptSession *ss = data->ob->sculpt;
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!*(bool *)SCULPT_temp_cdata_get(vd.vertex, ss->custom_layers[SCULPT_SCL_FAIRING_MASK])) {
if (!*(uchar *)SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_FAIRING_MASK])) {
continue;
}
float disp[3];
sub_v3_v3v3(disp,
vd.co,
SCULPT_temp_cdata_get(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]));
SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]));
mul_v3_fl(
disp,
*(float *)SCULPT_temp_cdata_get(vd.vertex, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]));
*(float *)SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]));
copy_v3_v3(vd.co,
SCULPT_temp_cdata_get(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]));
SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]));
add_v3_v3(vd.co, disp);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;

View File

@ -609,7 +609,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
}
/* destroy non-customdata temporary layers (which are rarely used) */
SCULPT_release_customlayers(ss, ob, true);
SCULPT_release_attributes(ss, ob, true);
/* clear all the other temporary layer references, that point to customdata layers*/
SCULPT_clear_scl_pointers(ss);
@ -740,7 +740,7 @@ static void SCULPT_dynamic_topology_disable_ex(
SCULPT_pbvh_clear(ob);
/* destroy non-customdata temporary layers (which are rarely (never?) used for PBVH_BMESH) */
SCULPT_release_customlayers(ss, ob, true);
SCULPT_release_attributes(ss, ob, true);
/* free all the other pointers in ss->custom_layers*/
SCULPT_clear_scl_pointers(ss);

View File

@ -136,7 +136,7 @@ void SCULPT_face_check_origdata(SculptSession *ss, SculptFaceRef face)
return;
}
short *s = (short *)SCULPT_temp_cdata_get_f(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
short *s = (short *)SCULPT_attr_face_data(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
// pack ss->stroke_id in higher 16 bits
if (s[1] != ss->stroke_id) {
@ -151,7 +151,7 @@ int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face)
return SCULPT_face_set_get(ss, face);
}
short *s = (short *)SCULPT_temp_cdata_get_f(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
short *s = (short *)SCULPT_attr_face_data(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
if (s[1] != ss->stroke_id) {
s[0] = SCULPT_face_set_get(ss, face);
@ -169,11 +169,11 @@ void SCULPT_face_ensure_original(SculptSession *ss, Object *ob)
SculptCustomLayer *scl = MEM_callocN(sizeof(*scl), "orig fset scl");
SCULPT_temp_customlayer_get(ss,
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_FACE,
CD_PROP_INT32,
"orig_faceset_attr_name",
SCULPT_SCL_GET_NAME(SCULPT_SCL_ORIG_FSETS),
scl,
&((SculptLayerParams){.permanent = false, .simple_array = false}));

View File

@ -579,7 +579,7 @@ float SCULPT_automasking_factor_get(struct AutomaskingCache *automasking,
SculptVertRef vert);
bool SCULPT_automasking_needs_normal(const SculptSession *ss, const Brush *brush);
/* Returns the automasking cache depending on the active tool. Used for code that can run both for
/* Returns the automasking cache depending on the active tool. Used for code that can run both for
* brushes and filter. */
struct AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss);
@ -1973,7 +1973,7 @@ void SCULPT_curvature_dir_get(SculptSession *ss,
/*
DEPRECATED in favor of SCULPT_temp_customlayer_ensure
DEPRECATED in favor of SCULPT_attr_ensure_layer
which works with all three PBVH types
Ensure a named temporary layer exists, creating it if necassary.
@ -1994,7 +1994,6 @@ void SCULPT_ensure_persistent_layers(SculptSession *ss, struct Object *ob);
#define SCULPT_LAYER_PERS_NO "Persistent Base No"
#define SCULPT_LAYER_PERS_DISP "Persistent Base Height"
#define SCULPT_LAYER_DISP "__temp_layer_disp"
#define SCULPT_LAYER_STROKE_ID "__temp_layer_strokeid"
// these tools don't support dynamic pbvh splitting during the stroke
#define DYNTOPO_HAS_DYNAMIC_SPLIT(tool) true
@ -2008,29 +2007,68 @@ int SCULPT_get_symmetry_pass(const SculptSession *ss);
void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
void SCULPT_reorder_bmesh(SculptSession *ss);
static inline void *SCULPT_temp_cdata_get(const SculptVertRef vertex, const SculptCustomLayer *scl)
{
if (scl->data) {
char *p = (char *)scl->data;
int idx = (int)vertex.i;
/*
API for custom (usually temporary) attributes.
Vertices and faces are supported.
if (scl->from_bmesh) {
BMElem *v = (BMElem *)vertex.i;
idx = v->head.index;
Note that attributes must be created at once,
*then* loaded into SculptCustomLayer structures, e.g.:
SCULPT_attr_ensure_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "attr1", params);
SCULPT_attr_ensure_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "attr2", params);
SCULPT_attr_ensure_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "attr3", params);
SculptCustomLayer scl1, scl2, scl3;
SCULPT_attr_get_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "attr1", &scl1, params);
SCULPT_attr_get_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "attr2", &scl2, params);
SCULPT_attr_get_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "attr3", &scl3, params);
Access per element data with SCULPT_attr_vertex_data and SCULPT_attr_face_data:.
float *f = SCULPT_attr_vertex_data(sculpt_vertex, &scl1);
Layers that are reused by different parts of the sculpt code
should be cached in SculptSession->custom_layers, the entries of which
map to the SculptStandardAttr enum in BKE_paint.h.
These layers will not be created for you, though once they exist they won't
be pruned until the user exits sculpt mode. To use:
if (!ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) {
ss->custom_layers[SCULPT_SCL_FAIRING_MASK] = MEM_callocN(sizeof(SculptLayerRef), "SculptLayerRef");
SCULPT_attr_get_layer(ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "_sculpt_fairing_mask", ss->custom_layers[SCULPT_SCL_FAIRING_MASK], params);
}
return p + scl->elemsize * (int)idx;
}
else {
BMElem *v = (BMElem *)vertex.i;
return BM_ELEM_CD_GET_VOID_P(v, scl->cd_offset);
}
Note that SCULPT_attr_get_layer will automatically update the customdata
offsets for all non-NULL entries in ss->custom_layers automatically.
return NULL;
}
TODO: prune CD_TEMPORARY layers on sculpt mode exit if PBVH_FACES is active;
in this case the layers are stored in the original meshes's CustomData
structs and will remain there until the user saves/loads the file.
*/
// arg, duplicate functions!
static inline void *SCULPT_temp_cdata_get_f(const SculptFaceRef vertex,
/** returns true if layer was successfully created */
bool SCULPT_attr_ensure_layer(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptLayerParams *params);
bool SCULPT_attr_get_layer(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params);
bool SCULPT_attr_release_layer(SculptSession *ss, struct Object *ob, SculptCustomLayer *scl);
bool SCULPT_attr_has_layer(SculptSession *ss,
AttributeDomain domain,
int proptype,
const char *name);
static inline void *SCULPT_attr_vertex_data(const SculptVertRef vertex,
const SculptCustomLayer *scl)
{
if (scl->data) {
@ -2052,37 +2090,29 @@ static inline void *SCULPT_temp_cdata_get_f(const SculptFaceRef vertex,
return NULL;
}
/*
create a custom vertex or face attribute.
always create all of your attributes together with SCULPT_temp_customlayer_ensure,
// arg, duplicate functions!
static inline void *SCULPT_attr_face_data(const SculptFaceRef vertex, const SculptCustomLayer *scl)
{
if (scl->data) {
char *p = (char *)scl->data;
int idx = (int)vertex.i;
then initialize their SculptCustomLayer's with SCULPT_temp_customlayer_get
afterwards. Otherwise customdata offsets might be wrong (for PBVH_BMESH).
if (scl->from_bmesh) {
BMElem *v = (BMElem *)vertex.i;
idx = v->head.index;
}
return true on success. if false, layer was not created.
return p + scl->elemsize * (int)idx;
}
else {
BMElem *v = (BMElem *)vertex.i;
return BM_ELEM_CD_GET_VOID_P(v, scl->cd_offset);
}
Access per element data with SCULPT_temp_cdata_get.
*/
return NULL;
}
bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptLayerParams *params);
bool SCULPT_temp_customlayer_get(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params);
bool SCULPT_temp_customlayer_release(SculptSession *ss, struct Object *ob, SculptCustomLayer *scl);
bool SCULPT_temp_customlayer_has(SculptSession *ss,
AttributeDomain domain,
int proptype,
const char *name);
void SCULPT_release_customlayers(SculptSession *ss, struct Object *ob, bool non_customdata_only);
void SCULPT_release_attributes(SculptSession *ss, struct Object *ob, bool non_customdata_only);
bool SCULPT_dyntopo_automasking_init(const SculptSession *ss,
Sculpt *sd,

View File

@ -149,9 +149,9 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *co = SCULPT_temp_cdata_get(vertex, scl_co);
float *no = SCULPT_temp_cdata_get(vertex, scl_no);
float *disp = SCULPT_temp_cdata_get(vertex, scl_disp);
float *co = SCULPT_attr_vertex_data(vertex, scl_co);
float *no = SCULPT_attr_vertex_data(vertex, scl_no);
float *disp = SCULPT_attr_vertex_data(vertex, scl_disp);
copy_v3_v3(co, SCULPT_vertex_co_get(ss, vertex));
SCULPT_vertex_normal_get(ss, vertex, no);
@ -1132,30 +1132,28 @@ static int sculpt_set_limit_surface_exec(bContext *C, wmOperator *UNUSED(op))
SCULPT_vertex_random_access_ensure(ss);
if (ss->limit_surface) {
SCULPT_temp_customlayer_release(ss, ob, ss->limit_surface);
if (!ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE]) {
ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE] = MEM_callocN(sizeof(SculptCustomLayer),
"SculptCustomLayer");
}
MEM_SAFE_FREE(ss->limit_surface);
ss->limit_surface = MEM_callocN(sizeof(SculptCustomLayer), "ss->limit_surface");
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_temp_customlayer_ensure(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "_sculpt_limit_surface", &params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"_sculpt_limit_surface",
ss->limit_surface,
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LIMIT_SURFACE),
ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE],
&params);
const SculptCustomLayer *scl = ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE];
const int totvert = SCULPT_vertex_count_get(ss);
const bool weighted = false;
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *f = SCULPT_temp_cdata_get(vertex, ss->limit_surface);
float *f = SCULPT_attr_vertex_data(vertex, scl);
SCULPT_neighbor_coords_average(ss, f, vertex, 0.0, true, weighted);
}

View File

@ -167,9 +167,9 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
// our temp layer. do this here before the brush check
// to ensure any geomtry dyntopo might subdivide has
// valid state.
int *stroke_id = (int *)SCULPT_temp_cdata_get(vd.vertex, stroke_id_scl);
float *color_buffer = (float *)SCULPT_temp_cdata_get(vd.vertex,
buffer_scl); // mv->origcolor;
int *stroke_id = (int *)SCULPT_attr_vertex_data(vd.vertex, stroke_id_scl);
float *color_buffer = (float *)SCULPT_attr_vertex_data(vd.vertex,
buffer_scl); // mv->origcolor;
if (*stroke_id != ss->stroke_id) {
*stroke_id = ss->stroke_id;
@ -421,20 +421,24 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
// reuse smear's buffer name
SCULPT_temp_customlayer_ensure(
SCULPT_attr_ensure_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
SCULPT_temp_customlayer_ensure(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, SCULPT_LAYER_STROKE_ID, &params_id);
SCULPT_attr_ensure_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&params_id);
SCULPT_temp_customlayer_get(
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &buffer_scl, &params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_LAYER_STROKE_ID,
&stroke_id_scl,
&params_id);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&stroke_id_scl,
&params_id);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
@ -494,7 +498,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
float current_disp[3];
float current_disp_norm[3];
float interp_color[4];
float *prev_color = (float *)SCULPT_temp_cdata_get(vd.vertex, data->scl);
float *prev_color = (float *)SCULPT_attr_vertex_data(vd.vertex, data->scl);
copy_v4_v4(interp_color, prev_color);
@ -517,7 +521,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
float vertex_disp[3];
float vertex_disp_norm[3];
sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.vertex), vd.co);
const float *neighbor_color = SCULPT_temp_cdata_get(ni.vertex, data->scl);
const float *neighbor_color = SCULPT_attr_vertex_data(ni.vertex, data->scl);
normalize_v3_v3(vertex_disp_norm, vertex_disp);
if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) {
@ -555,7 +559,7 @@ static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata,
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_vertex_color_get(ss, vd.vertex, (float *)SCULPT_temp_cdata_get(vd.vertex, data->scl));
SCULPT_vertex_color_get(ss, vd.vertex, (float *)SCULPT_attr_vertex_data(vd.vertex, data->scl));
}
BKE_pbvh_vertex_iter_end;
}
@ -574,9 +578,9 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptCustomLayer prev_scl;
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_temp_customlayer_ensure(
SCULPT_attr_ensure_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
SCULPT_temp_customlayer_get(
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &prev_scl, &params);
BKE_curvemapping_init(brush->curve);

View File

@ -481,7 +481,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
float *b1 = NULL, btot = 0.0f, b1_orig;
b1 = SCULPT_temp_cdata_get(vertex, bound_scl);
b1 = SCULPT_attr_vertex_data(vertex, bound_scl);
b1_orig = *b1;
*b1 = 0.0f;
@ -593,7 +593,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
float len = len_v3v3(co, tmp);
float w2 = 1.0f;
float *b2 = SCULPT_temp_cdata_get(ni.vertex, bound_scl);
float *b2 = SCULPT_attr_vertex_data(ni.vertex, bound_scl);
float b2_val = *b2 + len;
if (SCULPT_vertex_is_boundary(ss, ni.vertex, bflag)) {
@ -692,7 +692,7 @@ static void SCULPT_neighbor_coords_average_interior_boundary(SculptSession *ss,
}
if (args->vel_scl && totvel > 1) {
float *final_vel = SCULPT_temp_cdata_get(vertex, args->vel_scl);
float *final_vel = SCULPT_attr_vertex_data(vertex, args->vel_scl);
mul_v3_fl(vel, 1.0f / (float)totvel);
interp_v3_v3v3(final_vel, final_vel, vel, args->vel_smooth_fac);
@ -842,7 +842,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
if (args->vel_scl) {
/* propagate velocities */
float *vel2 = SCULPT_temp_cdata_get(ni.vertex, args->vel_scl);
float *vel2 = SCULPT_attr_vertex_data(ni.vertex, args->vel_scl);
madd_v3_v3fl(vel, vel2, w);
totvel += w;
}
@ -964,7 +964,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
}
if (args->vel_scl && totvel != 0.0f) {
float *final_vel = SCULPT_temp_cdata_get(vertex, args->vel_scl);
float *final_vel = SCULPT_attr_vertex_data(vertex, args->vel_scl);
mul_v3_fl(vel, 1.0f / totvel);
interp_v3_v3v3(final_vel, final_vel, vel, args->vel_smooth_fac);
@ -1521,7 +1521,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
thread_id);
float disp[3];
float *dir = SCULPT_temp_cdata_get(vd.vertex, data->scl);
float *dir = SCULPT_attr_vertex_data(vd.vertex, data->scl);
madd_v3_v3v3fl(disp, vd.co, dir, fade);
SCULPT_clip(sd, ss, vd.co, disp);
@ -1557,14 +1557,14 @@ static void do_enhance_details_brush_dir_task_cb_ex(void *__restrict userdata,
continue;
}
uint *strokeid = SCULPT_temp_cdata_get(vd.vertex, strokeid_scl);
uint *strokeid = SCULPT_attr_vertex_data(vd.vertex, strokeid_scl);
if ((*strokeid) >> 1UL != current_stroke_id) {
*strokeid = current_stroke_id << 1UL;
modified = true;
float avg[3];
float *dir = SCULPT_temp_cdata_get(vd.vertex, scl);
float *dir = SCULPT_attr_vertex_data(vd.vertex, scl);
float no[3];
SCULPT_vertex_normal_get(ss, vd.vertex, no);
@ -1626,7 +1626,7 @@ static void do_enhance_details_brush_dir2_task_cb_ex(void *__restrict userdata,
BKE_pbvh_get_vert_face_areas(ss->pbvh, vd.vertex, areas, valence);
}
// uint *strokeid = SCULPT_temp_cdata_get(vd.vertex, strokeid_scl);
// uint *strokeid = SCULPT_attr_vertex_data(vd.vertex, strokeid_scl);
/* this check here is overly restrictive,
we already get filtered by whether stage
@ -1641,7 +1641,7 @@ static void do_enhance_details_brush_dir2_task_cb_ex(void *__restrict userdata,
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float *dir2 = SCULPT_temp_cdata_get(ni.vertex, scl);
float *dir2 = SCULPT_attr_vertex_data(ni.vertex, scl);
float w = 1.0f;
@ -1660,7 +1660,7 @@ static void do_enhance_details_brush_dir2_task_cb_ex(void *__restrict userdata,
mul_v3_fl(avg, 1.0f / (float)tot);
float *dir = SCULPT_temp_cdata_get(vd.vertex, scl);
float *dir = SCULPT_attr_vertex_data(vd.vertex, scl);
interp_v3_v3v3(dir, dir, avg, 0.5f); // valence == 1 ? 0.5f : 0.75f);
}
}
@ -1704,15 +1704,24 @@ void SCULPT_enhance_details_brush(
SculptLayerParams params = {.permanent = false, .simple_array = false};
bool weighted = SCULPT_get_int(ss, use_weighted_smooth, sd, brush);
SCULPT_temp_customlayer_ensure(
SCULPT_attr_ensure_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &params);
SCULPT_temp_customlayer_ensure(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, SCULPT_LAYER_STROKE_ID, &params);
SCULPT_attr_ensure_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&params);
SCULPT_temp_customlayer_get(
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &scl, &params);
SCULPT_temp_customlayer_get(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, SCULPT_LAYER_STROKE_ID, &strokeid_scl, &params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&strokeid_scl,
&params);
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
SCULPT_vertex_random_access_ensure(ss);
@ -1723,7 +1732,7 @@ void SCULPT_enhance_details_brush(
for (int i = 0; i < totvert; i++) {
float avg[3];
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *dir = SCULPT_temp_cdata_get(vertex, &scl);
float *dir = SCULPT_attr_vertex_data(vertex, &scl);
float no[3];
SCULPT_vertex_normal_get(ss, vertex, no);
@ -1746,7 +1755,7 @@ void SCULPT_enhance_details_brush(
float avg[3] = {0.0f, 0.0f, 0.0f};
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *dir = SCULPT_temp_cdata_get(vertex, &scl);
float *dir = SCULPT_attr_vertex_data(vertex, &scl);
float tot = 0.0f;
float *areas = NULL;
int valence;
@ -1766,7 +1775,7 @@ void SCULPT_enhance_details_brush(
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
float *dir2 = SCULPT_temp_cdata_get(ni.vertex, &scl);
float *dir2 = SCULPT_attr_vertex_data(ni.vertex, &scl);
float w = 1.0f;
@ -1924,7 +1933,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
float startvel[3];
if (vel_scl) {
float *vel = SCULPT_temp_cdata_get(vd.vertex, vel_scl);
float *vel = SCULPT_attr_vertex_data(vd.vertex, vel_scl);
#if 1
if (isnan(dot_v3v3(vel, vel)) || !isfinite(dot_v3v3(vel, vel))) {
printf("NaN!");
@ -1956,7 +1965,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
/* Apply velocity smooth. The point of this is to
improve convergence for very high levels of smoothing*/
if (vel_scl) {
float *vel = SCULPT_temp_cdata_get(vd.vertex, vel_scl);
float *vel = SCULPT_attr_vertex_data(vd.vertex, vel_scl);
float veltmp[3];
copy_v3_v3(veltmp, vel);
@ -2012,13 +2021,13 @@ void SCULPT_bound_smooth_ensure(SculptSession *ss, Object *ob)
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] = MEM_callocN(sizeof(SculptCustomLayer),
"bound_scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_COLOR,
"t__smooth_bdist",
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_COLOR,
"t__smooth_bdist",
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS],
&params);
}
}
@ -2064,13 +2073,13 @@ void SCULPT_smooth(Sculpt *sd,
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL] = MEM_callocN(sizeof(SculptCustomLayer),
"vel_smooth_scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"__scl_smooth_vel",
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL],
&params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"__scl_smooth_vel",
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL],
&params);
}
}
@ -2220,7 +2229,7 @@ void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
mul_v3_v3fl(weigthed_o, origco, alpha);
mul_v3_v3fl(weigthed_q, co, 1.0f - alpha);
add_v3_v3v3(d, weigthed_o, weigthed_q);
sub_v3_v3v3((float *)SCULPT_temp_cdata_get(v_index, scl), laplacian_smooth_co, d);
sub_v3_v3v3((float *)SCULPT_attr_vertex_data(v_index, scl), laplacian_smooth_co, d);
sub_v3_v3v3(disp, laplacian_smooth_co, co);
}
@ -2239,14 +2248,14 @@ void SCULPT_surface_smooth_displace_step(SculptSession *ss,
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_index, ni) {
add_v3_v3(b_avg, (float *)SCULPT_temp_cdata_get(ni.vertex, scl));
add_v3_v3(b_avg, (float *)SCULPT_attr_vertex_data(ni.vertex, scl));
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (total > 0) {
mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / total);
madd_v3_v3fl(b_current_vertex, (float *)SCULPT_temp_cdata_get(v_index, scl), beta);
madd_v3_v3fl(b_current_vertex, (float *)SCULPT_attr_vertex_data(v_index, scl), beta);
mul_v3_fl(b_current_vertex, clamp_f(fade, 0.0f, 1.0f));
sub_v3_v3(co, b_current_vertex);
}
@ -2375,9 +2384,9 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_temp_customlayer_ensure(
SCULPT_attr_ensure_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &params);
SCULPT_temp_customlayer_get(
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &scl, &params);
if (SCULPT_stroke_is_first_brush_step(ss->cache) &&