Sculpt-dev: Cleanup sculpt temp attribute API

* The sculpt code now handles lifetime ownership
  of SculptCustomLayer structs.  This removes the
  need to create temp attributes and get their
  SculptCustomLayer reference structs in seperate
  steps, as the code can internally update e.g. bmesh
  block offsets for all SculptCustomLayer instances.
* Removed ss->custom_layers.  The SCULPT_SCL_XXX enums
  are no longer used to reference standard attributes
  (though they are used, at the moment, to provide names
   for them).  Instead a new accessor struct, ss->scl,
   has pointers to standard attributes (e.g. ss->scl.automasking_factor,
   ss->scl.fairing_mask, etc).

This is the final version of the API that will be ported to master
(possibly minus the SCULPT_xxx alias functions that simply call
BKE_sculptsession_XXX equivalents).
This commit is contained in:
Joseph Eagar 2022-07-15 20:18:44 -07:00
parent 93b96bab9a
commit ed8ffec61f
20 changed files with 2610 additions and 2644 deletions

View File

@ -1037,7 +1037,7 @@ static void MemorY_ErroR(const char *block, const char *error)
print_error("Memoryblock %s: %s\n", block, error);
#ifdef WITH_ASSERT_ABORT
abort();
abort();
#endif
}

View File

@ -641,10 +641,16 @@ typedef struct SculptFakeNeighbors {
/* Custom Temporary Attributes */
typedef struct SculptLayerParams {
int simple_array : 1; // cannot be combined with permanent
int permanent : 1; // cannot be combined with simple_array
/* Allocate a flat array outside the CustomData system. Cannot be combined with permanent. */
int simple_array : 1;
/* Do not mark CustomData layer as temporary. Cannot be combined with simple_array. Doesn't
* work with PBVH_GRIDS.
*/
int permanent : 1; // cannot be combined with simple_array
int nocopy : 1;
int nointerp : 1;
int stroke_only : 1; /* release layer at end of struct, except for PBVH_BMESH */
} SculptLayerParams;
typedef struct SculptCustomLayer {
@ -665,10 +671,7 @@ typedef struct SculptCustomLayer {
bool ready;
} SculptCustomLayer;
/* These custom attributes have references
(SculptCustomLayer pointers) inside of ss->custom_layers
that are kept up to date with SCULPT_update_customdata_refs.
*/
/* Standard names for sculpt attributes. */
typedef enum {
SCULPT_SCL_FAIRING_MASK,
SCULPT_SCL_FAIRING_FADE,
@ -688,6 +691,8 @@ typedef enum {
#define SCULPT_SCL_GET_NAME(stdattr) ("__" #stdattr)
#define SCULPT_MAX_TEMP_LAYERS 64
typedef struct SculptSession {
/* Mesh data (not copied) can come either directly from a Mesh, or from a MultiresDM */
struct { /* Special handling for multires meshes */
@ -897,17 +902,41 @@ typedef struct SculptSession {
struct MSculptVert *mdyntopo_verts; // for non-bmesh
int mdyntopo_verts_size;
/*list of up to date custom layer references,
note that entries can be NULL if layer doesn't
exist. See SCULPT_SCL_XXX enum above.*/
struct SculptCustomLayer *custom_layers[SCULPT_SCL_LAYER_MAX];
/* This is a fixed-size array so we can pass pointers to its elements
* to client code. This is important to keep bmesh offsets up to date.
*/
struct SculptCustomLayer temp_layers[SCULPT_MAX_TEMP_LAYERS];
/*
PBVH_GRIDS cannot store customdata layers in real CustomDataLayers,
so we queue the memory allocated for them to free later
*/
struct SculptCustomLayer **layers_to_free;
int tot_layers_to_free;
/* Convienence SculptCusotmLayer pointers. */
struct {
/* Persistent base. */
SculptCustomLayer *persistent_co;
SculptCustomLayer *persistent_no;
SculptCustomLayer *persistent_disp;
/* Fairing. */
SculptCustomLayer *fairing_fade;
SculptCustomLayer *fairing_mask;
SculptCustomLayer *prefairing_co;
/* Automasking. */
SculptCustomLayer *automasking_factor;
/* Layer brush. */
SculptCustomLayer *layer_disp;
SculptCustomLayer *layer_id;
/* Limit Surface */
SculptCustomLayer *limit_surface;
/* Smooth */
SculptCustomLayer *smooth_bdist;
SculptCustomLayer *smooth_vel;
/* Face Sets */
SculptCustomLayer *orig_fsets;
} scl;
bool save_temp_layers;
@ -943,12 +972,12 @@ 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_attr_get_layer(struct Object *ob,
eAttrDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params);
SculptCustomLayer *BKE_sculptsession_attr_layer_get(struct Object *ob,
eAttrDomain domain,
int proptype,
const char *name,
SculptLayerParams *params,
bool *r_is_new);
bool BKE_sculptsession_attr_release_layer(struct Object *ob, SculptCustomLayer *scl);
void BKE_sculptsession_update_attr_refs(struct Object *ob);

View File

@ -1104,7 +1104,7 @@ void reset_clay_mappings(BrushChannelSet *chset, bool strips)
}
// adds any missing channels to brushes
ATTR_NO_OPT void BKE_brush_builtin_patch(Brush *brush, int tool)
void BKE_brush_builtin_patch(Brush *brush, int tool)
{
check_builtin_init();

View File

@ -4245,6 +4245,10 @@ void BKE_object_sculpt_data_create(Object *ob)
BLI_assert((ob->sculpt == nullptr) && (ob->mode & OB_MODE_ALL_SCULPT));
ob->sculpt = MEM_cnew<SculptSession>(__func__);
ob->sculpt->mode_type = (eObjectMode)ob->mode;
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
ob->sculpt->temp_layers[i].released = true;
}
}
bool BKE_object_obdata_texspace_get(Object *ob, char **r_texflag, float **r_loc, float **r_size)

View File

@ -1543,28 +1543,18 @@ void BKE_sculptsession_free(Object *ob)
sculptsession_free_pbvh(ob);
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
MEM_SAFE_FREE(ss->custom_layers[i]);
}
MEM_SAFE_FREE(ss->epmap);
MEM_SAFE_FREE(ss->epmap_mem);
MEM_SAFE_FREE(ss->vemap);
MEM_SAFE_FREE(ss->vemap_mem);
bool SCULPT_attr_release_layer(
SculptSession * ss, Object * ob, struct SculptCustomLayer * scl);
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
SculptCustomLayer *scl = ss->temp_layers + i;
if (ss->layers_to_free) {
for (int i = 0; i < ss->tot_layers_to_free; i++) {
if (ss->layers_to_free[i]) {
SCULPT_attr_release_layer(ss, ob, ss->layers_to_free[i]);
// SCULPT_attr_release_layer frees layers_to_free[i] itself
}
if (!scl->released && !scl->is_cdlayer) {
BKE_sculptsession_attr_release_layer(ob, scl);
}
MEM_freeN(ss->layers_to_free);
}
if (ss->tex_pool) {
@ -2192,6 +2182,8 @@ void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
if (object->sculpt && object->sculpt->pbvh) {
BKE_pbvh_update_active_vcol(object->sculpt->pbvh, orig_me);
}
BKE_sculptsession_update_attr_refs(object);
}
void BKE_sculpt_update_object_for_edit(
@ -3264,31 +3256,6 @@ static bool sculpt_attr_get_layer(SculptSession *ss,
out->elemsize = elemsize;
out->ready = true;
/*grids cannot store normal customdata layers, and thus
we cannot rely on the customdata api to keep track of
and free their memory for us.
so instead we queue them in a dynamic array inside of
SculptSession.
*/
if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
ss->tot_layers_to_free++;
if (!ss->layers_to_free) {
ss->layers_to_free = MEM_calloc_arrayN(
ss->tot_layers_to_free, sizeof(void *), "ss->layers_to_free");
}
else {
ss->layers_to_free = MEM_recallocN(ss->layers_to_free,
sizeof(void *) * ss->tot_layers_to_free);
}
SculptCustomLayer *cpy = MEM_callocN(sizeof(SculptCustomLayer), "SculptCustomLayer cpy");
*cpy = *out;
ss->layers_to_free[ss->tot_layers_to_free - 1] = cpy;
}
return true;
}
@ -3446,23 +3413,51 @@ static bool sculpt_attr_get_layer(SculptSession *ss,
}
out->ready = true;
out->released = false;
return true;
}
bool BKE_sculptsession_attr_get_layer(Object *ob,
eAttrDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params)
SculptCustomLayer *BKE_sculptsession_attr_layer_get(Object *ob,
eAttrDomain domain,
int proptype,
const char *name,
SculptLayerParams *params,
bool *r_is_new)
{
SculptSession *ss = ob->sculpt;
bool ret = sculpt_attr_get_layer(ss, ob, domain, proptype, name, scl, true, params);
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
SculptCustomLayer *scl = ss->temp_layers + i;
if (!scl->released && STREQ(scl->name, name) && scl->proptype == proptype &&
scl->domain == domain) {
if (r_is_new) {
*r_is_new = true;
}
return scl;
}
}
SculptCustomLayer *scl = NULL;
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
if (ss->temp_layers[i].released) {
scl = ss->temp_layers + i;
break;
}
}
BLI_assert(scl != NULL);
bool is_newlayer = sculpt_attr_get_layer(ss, ob, domain, proptype, name, scl, true, params);
if (r_is_new) {
*r_is_new = is_newlayer;
}
BKE_sculptsession_update_attr_refs(ob);
return ret;
return scl;
}
void BKE_sculptsession_bmesh_attr_update_internal(Object *ob)
@ -3488,14 +3483,10 @@ void BKE_sculptsession_update_attr_refs(Object *ob)
SculptSession *ss = ob->sculpt;
/* run twice, in case SCULPT_attr_get_layer had to recreate a layer and
messed up the ordering. */
messed up the bmesh offsets. */
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->ready) {
continue;
}
for (int j = 0; j < SCULPT_MAX_TEMP_LAYERS; j++) {
SculptCustomLayer *scl = ss->temp_layers + j;
if (!scl->released && !scl->params.simple_array) {
sculpt_attr_get_layer(
@ -3555,37 +3546,56 @@ bool BKE_sculptsession_attr_release_layer(Object *ob, SculptCustomLayer *scl)
eAttrDomain domain = scl->domain;
if (scl->released) {
return false;
return false; /* layer already released? */
}
// remove from layers_to_free list if necassary
for (int i = 0; scl->data && i < ss->tot_layers_to_free; i++) {
if (ss->layers_to_free[i] && ss->layers_to_free[i]->data == scl->data) {
MEM_freeN(ss->layers_to_free[i]);
ss->layers_to_free[i] = NULL;
/* Remove from internal temp_layers array. */
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
SculptCustomLayer *scl2 = ss->temp_layers + i;
if (STREQ(scl2->name, scl->name) && scl2->domain == scl->domain &&
scl2->proptype == scl->proptype) {
scl2->released = true;
}
}
scl->released = true;
if (!scl->from_bmesh) {
// for now, don't clean up bmesh temp layers
if (scl->is_cdlayer && BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
/* TODO: support PBVH_BMESH */
if (scl->is_cdlayer) {
CustomData *cdata = NULL;
int totelem = 0;
switch (domain) {
case ATTR_DOMAIN_POINT:
cdata = ss->vdata;
totelem = ss->totvert;
break;
case ATTR_DOMAIN_FACE:
cdata = ss->pdata;
totelem = ss->totfaces;
break;
default:
printf("error, unknown domain in %s\n", __func__);
return false;
if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
switch (domain) {
case ATTR_DOMAIN_POINT:
cdata = ss->vdata;
totelem = ss->totvert;
break;
case ATTR_DOMAIN_FACE:
cdata = ss->pdata;
totelem = ss->totfaces;
break;
default:
printf("error, unknown domain in %s\n", __func__);
return false;
}
}
else {
switch (domain) {
case ATTR_DOMAIN_POINT:
cdata = &ss->temp_vdata;
totelem = ss->temp_vdata_elems;
break;
case ATTR_DOMAIN_FACE:
cdata = &ss->temp_pdata;
totelem = ss->temp_pdata_elems;
break;
default:
printf("error, unknown domain in %s\n", __func__);
return false;
}
}
CustomData_free_layer(cdata, scl->layer->type, totelem, scl->layer - cdata->layers);
@ -3597,5 +3607,11 @@ bool BKE_sculptsession_attr_release_layer(Object *ob, SculptCustomLayer *scl)
scl->data = NULL;
}
else {
/* TODO: implement me! */
}
scl->released = true;
return true;
}

View File

@ -4827,6 +4827,7 @@ bool BKE_pbvh_cache_is_valid(const struct Object *ob,
{
if (pbvh->invalid) {
printf("pbvh invalid!\n");
return false;
}
if (pbvh->type != pbvh_type) {
@ -4837,6 +4838,19 @@ bool BKE_pbvh_cache_is_valid(const struct Object *ob,
int totvert = 0, totedge = 0, totloop = 0, totpoly = 0;
const CustomData *vdata, *edata, *ldata, *pdata;
MultiresModifierData *mmd = NULL;
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type == eModifierType_Multires) {
mmd = (MultiresModifierData *)md;
break;
}
}
if (mmd && (mmd->flags & eModifierMode_Realtime)) {
// return false;
}
switch (pbvh_type) {
case PBVH_BMESH:
if (!pbvh->bm || pbvh->bm != pbvh->cached_data.bm) {
@ -4865,15 +4879,6 @@ bool BKE_pbvh_cache_is_valid(const struct Object *ob,
pdata = &me->pdata;
break;
case PBVH_GRIDS: {
MultiresModifierData *mmd = NULL;
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type == eModifierType_Multires) {
mmd = (MultiresModifierData *)md;
break;
}
}
if (!mmd) {
return false;
}

View File

@ -1174,7 +1174,7 @@ static void vertex_paint_init_session(Depsgraph *depsgraph,
BKE_sculpt_toolsettings_data_ensure(scene);
BLI_assert(ob->sculpt == nullptr);
ob->sculpt = (SculptSession *)MEM_callocN(sizeof(SculptSession), "sculpt session");
BKE_object_sculpt_data_create(ob);
ob->sculpt->mode_type = object_mode;
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true);
}

View File

@ -458,8 +458,7 @@ void SCULPT_vertex_normal_get(SculptSession *ss, SculptVertRef vertex, float no[
bool SCULPT_has_persistent_base(SculptSession *ss)
{
if (!ss->pbvh) {
// just see if ss->custom_layer entries exist
return ss->custom_layers[SCULPT_SCL_PERS_CO] != NULL;
return ss->scl.persistent_co;
}
int idx = -1;
@ -472,7 +471,7 @@ bool SCULPT_has_persistent_base(SculptSession *ss)
idx = CustomData_get_named_layer_index(ss->vdata, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_CO);
break;
case PBVH_GRIDS:
return ss->custom_layers[SCULPT_SCL_PERS_CO];
return ss->scl.persistent_co;
}
return idx >= 0;
@ -480,8 +479,8 @@ 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_attr_vertex_data(index, ss->custom_layers[SCULPT_SCL_PERS_CO]);
if (ss->scl.persistent_co) {
return (float *)SCULPT_attr_vertex_data(index, ss->scl.persistent_co);
}
return SCULPT_vertex_co_get(ss, index);
@ -507,8 +506,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->custom_layers[SCULPT_SCL_LIMIT_SURFACE]) {
float *f = SCULPT_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE]);
if (ss->scl.limit_surface) {
float *f = SCULPT_attr_vertex_data(vertex, ss->scl.limit_surface);
copy_v3_v3(r_co, f);
}
else {
@ -530,8 +529,8 @@ 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_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_PERS_NO]);
if (ss->scl.persistent_no) {
float *no2 = SCULPT_attr_vertex_data(vertex, ss->scl.persistent_no);
copy_v3_v3(no, no2);
}
else {
@ -574,17 +573,10 @@ bool SCULPT_attr_ensure_layer(SculptSession *ss,
const char *name,
SculptLayerParams *params)
{
SculptCustomLayer scl;
bool is_newlayer;
BKE_sculptsession_attr_layer_get(ob, domain, proptype, name, params, &is_newlayer);
// call SCULPT_update_customdata_refs before and after,
// thoeretically it can allocate new layers
SCULPT_update_customdata_refs(ss, ob);
bool ret = SCULPT_attr_get_layer(ss, ob, domain, proptype, name, &scl, params);
SCULPT_update_customdata_refs(ss, ob);
return ret;
return is_newlayer;
}
/* TODO: thoroughly test this function */
@ -629,15 +621,14 @@ bool SCULPT_attr_release_layer(SculptSession *ss, Object *ob, SculptCustomLayer
return BKE_sculptsession_attr_release_layer(ob, scl);
}
bool SCULPT_attr_get_layer(SculptSession *ss,
Object *ob,
eAttrDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params)
SculptCustomLayer *SCULPT_attr_get_layer(SculptSession *ss,
Object *ob,
eAttrDomain domain,
int proptype,
const char *name,
SculptLayerParams *params)
{
return BKE_sculptsession_attr_get_layer(ob, domain, proptype, name, scl, params);
return BKE_sculptsession_attr_layer_get(ob, domain, proptype, name, params, NULL);
}
SculptVertRef SCULPT_active_vertex_get(SculptSession *ss)
@ -5332,13 +5323,13 @@ typedef struct BrushRunCommandData {
float radius_max;
} BrushRunCommandData;
ATTR_NO_OPT static void get_nodes_undo(Sculpt *sd,
Object *ob,
Brush *brush,
UnifiedPaintSettings *ups,
PaintModeSettings *paint_mode_settings,
BrushRunCommandData *data,
int tool)
static void get_nodes_undo(Sculpt *sd,
Object *ob,
Brush *brush,
UnifiedPaintSettings *ups,
PaintModeSettings *paint_mode_settings,
BrushRunCommandData *data,
int tool)
{
PBVHNode **nodes = NULL;
int totnode = 0;
@ -5528,12 +5519,12 @@ bool SCULPT_needs_area_normal(SculptSession *ss, Sculpt *sd, Brush *brush)
SCULPT_get_float(ss, tip_scale_x, sd, brush) != 1.0f;
}
ATTR_NO_OPT static void SCULPT_run_command(Sculpt *sd,
Object *ob,
Brush *brush,
UnifiedPaintSettings *ups,
PaintModeSettings *paint_mode_settings,
void *userdata)
static void SCULPT_run_command(Sculpt *sd,
Object *ob,
Brush *brush,
UnifiedPaintSettings *ups,
PaintModeSettings *paint_mode_settings,
void *userdata)
{
SculptSession *ss = ob->sculpt;
BrushRunCommandData *data = userdata;
@ -6605,16 +6596,30 @@ void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
}
#endif
if (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;
}
/* Free a few temporary attributes if it's cheap to do so, otherwise wait for sculpt mode exit.
*/
if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
SculptCustomLayer **ptrs = (SculptCustomLayer **)&ss->scl;
int ptrs_num = sizeof(ss->scl) / sizeof(void *);
if (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;
/* Go over pointers inside of ss->scl first. */
for (int i = 0; i < ptrs_num; i++) {
SculptCustomLayer *scl = ptrs[i];
if (scl && !scl->released && scl->params.stroke_only) {
SCULPT_attr_release_layer(ss, ob, scl);
ptrs[i] = NULL;
}
}
/* Now go over the main attribute array and release any remaining attributes. */
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
SculptCustomLayer *scl = ss->temp_layers + i;
if (scl && !scl->released && scl->params.stroke_only) {
SCULPT_attr_release_layer(ss, ob, scl);
}
}
}
MEM_SAFE_FREE(cache->prev_colors);
@ -6624,26 +6629,6 @@ void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
BKE_brush_commandlist_free(ss->cache->commandlist);
}
if (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_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_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;
}
if (ss->cache->channels_final) {
BKE_brush_channelset_free(ss->cache->channels_final);
}
@ -6687,26 +6672,22 @@ void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
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]) {
if (non_customdata_only && !ss->custom_layers[i]->params.simple_array) {
continue;
}
for (int i = 0; i < SCULPT_MAX_TEMP_LAYERS; i++) {
SculptCustomLayer *scl = ss->temp_layers + i;
SCULPT_attr_release_layer(ss, ob, ss->custom_layers[i]);
MEM_freeN(ss->custom_layers[i]);
ss->custom_layers[i] = NULL;
if (scl->released || (non_customdata_only && !scl->params.simple_array)) {
continue;
}
SCULPT_attr_release_layer(ss, ob, scl);
}
memset(&ss->scl, 0, sizeof(ss->scl));
}
void SCULPT_clear_scl_pointers(SculptSession *ss)
{
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
MEM_SAFE_FREE(ss->custom_layers[i]);
ss->custom_layers[i] = NULL;
}
memset(&ss->scl, 0, sizeof(ss->scl));
}
/* Initialize mirror modifier clipping. */

View File

@ -86,28 +86,10 @@ static void sculpt_array_datalayers_init(Object *ob, SculptArray *array, SculptS
{
SculptLayerParams params = {.permanent = true, .simple_array = false};
if (!array->scl_inst) {
array->scl_inst = MEM_callocN(sizeof(SculptCustomLayer), __func__);
}
if (!array->scl_sym) {
array->scl_sym = MEM_callocN(sizeof(SculptCustomLayer), __func__);
}
SCULPT_attr_ensure_layer(
array->scl_inst = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, &params);
SCULPT_attr_ensure_layer(
array->scl_sym = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, &params);
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
}
static void sculpt_array_datalayers_add(SculptArray *array, SculptSession *ss, Mesh *mesh)
@ -161,24 +143,10 @@ void SCULPT_array_datalayers_free(SculptArray *array, Object *ob)
SculptLayerParams params = {.permanent = true, .simple_array = false};
if (array->scl_inst) {
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_instance_cd_name,
array->scl_inst,
&params);
SCULPT_attr_release_layer(ss, ob, array->scl_inst);
}
if (array->scl_sym) {
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
SCULPT_attr_release_layer(ss, ob, array->scl_sym);
}
@ -353,15 +321,10 @@ static void sculpt_array_ensure_geometry_indices(Object *ob, SculptArray *array)
SculptLayerParams params = {.permanent = true, .simple_array = false};
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
array->scl_inst = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, &params);
array->scl_sym = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, &params);
array->copy_index = MEM_malloc_arrayN(totvert, sizeof(int), "array copy index");
array->symmetry_pass = MEM_malloc_arrayN(totvert, sizeof(int), "array symmetry pass index");

View File

@ -260,11 +260,10 @@ void SCULPT_automasking_cache_free(SculptSession *ss, Object *ob, AutomaskingCac
return;
}
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;
/* Not worth reallocating bmesh customdata blocks here. */
if (ss->scl.automasking_factor && (!ss->pbvh || BKE_pbvh_type(ss->pbvh) != PBVH_BMESH)) {
SCULPT_attr_release_layer(ss, ob, ss->scl.automasking_factor);
ss->scl.automasking_factor = nullptr;
}
MEM_SAFE_FREE(automasking);
@ -558,33 +557,21 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
SCULPT_vertex_random_access_ensure(ss);
SCULPT_face_random_access_ensure(ss);
if (!ss->custom_layers[SCULPT_SCL_AUTOMASKING]) {
ss->custom_layers[SCULPT_SCL_AUTOMASKING] = (SculptCustomLayer *)MEM_callocN(
sizeof(SculptCustomLayer), "automasking->factorlayer");
if (!ss->scl.automasking_factor) {
SculptLayerParams params;
params.permanent = false;
params.simple_array = false;
if (!SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_SCL_GET_NAME(SCULPT_SCL_AUTOMASKING),
ss->custom_layers[SCULPT_SCL_AUTOMASKING],
&params)) {
// failed
MEM_freeN(ss->custom_layers[SCULPT_SCL_AUTOMASKING]);
ss->custom_layers[SCULPT_SCL_AUTOMASKING] = NULL;
return automasking;
}
ss->scl.automasking_factor = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_SCL_GET_NAME(SCULPT_SCL_AUTOMASKING),
&params);
}
automasking->factorlayer = ss->custom_layers[SCULPT_SCL_AUTOMASKING];
automasking->factorlayer = ss->scl.automasking_factor;
// automasking->factorlayer = SCULPT_attr_ensure_layer()
// automasking->factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
for (int i : IndexRange(totvert)) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float *f = (float *)SCULPT_attr_vertex_data(vertex, automasking->factorlayer);

View File

@ -307,9 +307,9 @@ static void sculpt_project_v3_normal_align(SculptSession *ss,
/** \name Sculpt Draw Brush
* \{ */
ATTR_NO_OPT static void do_draw_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
static void do_draw_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
@ -1794,7 +1794,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
const bool is_bmesh = BKE_pbvh_type(ss->pbvh) == PBVH_BMESH;
if (is_bmesh) {
use_persistent_base = use_persistent_base && ss->custom_layers[SCULPT_SCL_PERS_CO];
use_persistent_base = use_persistent_base && ss->scl.persistent_co;
#if 0
// check if we need to zero displacement factor
@ -1820,7 +1820,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
#endif
}
else {
use_persistent_base = use_persistent_base && ss->custom_layers[SCULPT_SCL_PERS_CO];
use_persistent_base = use_persistent_base && ss->scl.persistent_co;
}
SculptCustomLayer *scl_disp = data->scl;
@ -1865,8 +1865,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
float *disp_factor;
if (use_persistent_base) {
disp_factor = (float *)SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_PERS_DISP]);
disp_factor = (float *)SCULPT_attr_vertex_data(vd.vertex, ss->scl.persistent_disp);
}
else {
disp_factor = (float *)SCULPT_attr_vertex_data(vd.vertex, scl_disp);
@ -1996,37 +1995,14 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
void SCULPT_ensure_persistent_layers(SculptSession *ss, Object *ob)
{
if (!ss->custom_layers[SCULPT_SCL_PERS_CO]) {
SculptLayerParams params = {.permanent = true, .simple_array = false};
SculptLayerParams params = {.permanent = true, .simple_array = false};
ss->custom_layers[SCULPT_SCL_PERS_CO] = MEM_callocN(sizeof(SculptCustomLayer), "scl_pers_co");
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_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_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_PERS_DISP,
ss->custom_layers[SCULPT_SCL_PERS_DISP],
&params);
}
ss->scl.persistent_co = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_CO, &params);
ss->scl.persistent_no = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_NO, &params);
ss->scl.persistent_disp = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_LAYER_PERS_DISP, &params);
}
void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
@ -2046,41 +2022,32 @@ void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SCULPT_ensure_persistent_layers(ss, ob);
}
if (!ss->custom_layers[SCULPT_SCL_LAYER_DISP]) {
ss->custom_layers[SCULPT_SCL_LAYER_DISP] = MEM_callocN(sizeof(SculptCustomLayer),
"layer disp scl");
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_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}));
}
SculptCustomLayer *disp_scl = ss->scl.layer_disp = SCULPT_attr_get_layer(
ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_DISP),
&((SculptLayerParams){.permanent = false, .simple_array = false, .stroke_only = true}));
SculptCustomLayer *id_scl = ss->scl.layer_id = SCULPT_attr_get_layer(
ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&((SculptLayerParams){.permanent = false, .simple_array = false, .stroke_only = true}));
if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
ss->cache->layer_displacement_factor = ss->custom_layers[SCULPT_SCL_LAYER_DISP]->data;
ss->cache->layer_stroke_id = ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]->data;
ss->cache->layer_displacement_factor = disp_scl->data;
ss->cache->layer_stroke_id = id_scl->data;
}
SculptThreadedTaskData data = {.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
.scl = ss->custom_layers[SCULPT_SCL_LAYER_DISP],
.scl2 = ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID],
.scl = disp_scl,
.scl2 = id_scl,
#ifdef LAYER_FACE_SET_MODE
.face_set = fset,
.face_set2 = fset + 1
@ -3443,8 +3410,7 @@ static void do_fairing_brush_tag_store_task_cb_ex(void *__restrict userdata,
continue;
}
float *prefair = SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
float *prefair = SCULPT_attr_vertex_data(vd.vertex, ss->scl.prefairing_co);
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
@ -3460,10 +3426,8 @@ static void do_fairing_brush_tag_store_task_cb_ex(void *__restrict userdata,
continue;
}
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]);
float *fairing_fade = SCULPT_attr_vertex_data(vd.vertex, ss->scl.fairing_fade);
uchar *fairing_mask = SCULPT_attr_vertex_data(vd.vertex, ss->scl.fairing_mask);
*fairing_fade = max_ff(fade, *fairing_fade);
*fairing_mask = true;
@ -3486,57 +3450,37 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SCULPT_vertex_random_access_ensure(ss);
SCULPT_face_random_access_ensure(ss);
if (!ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) {
// 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");
SculptLayerParams params = {.permanent = false, .simple_array = true, .stroke_only = true};
ss->custom_layers[SCULPT_SCL_FAIRING_MASK] = MEM_callocN(sizeof(SculptCustomLayer),
"ss->Cache->fairing_mask");
ss->custom_layers[SCULPT_SCL_FAIRING_FADE] = MEM_callocN(sizeof(SculptCustomLayer),
"ss->Cache->fairing_fade");
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO] = MEM_callocN(sizeof(SculptCustomLayer),
"ss->Cache->prefairing_co");
ss->scl.fairing_mask = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_BOOL,
SCULPT_SCL_GET_NAME(SCULPT_SCL_FAIRING_MASK),
&params);
SculptLayerParams params = {.permanent = false, .simple_array = true};
ss->scl.fairing_fade = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_SCL_GET_NAME(SCULPT_SCL_FAIRING_FADE),
&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_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_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);
}
ss->scl.prefairing_co = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_SCL_GET_NAME(SCULPT_SCL_PREFAIRING_CO),
&params);
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
for (int i = 0; i < totvert; i++) {
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
*(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_attr_vertex_data(vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]),
SCULPT_vertex_co_get(ss, vertex));
*(uchar *)SCULPT_attr_vertex_data(vertex, ss->scl.fairing_mask) = false;
*(float *)SCULPT_attr_vertex_data(vertex, ss->scl.fairing_fade) = 0.0f;
copy_v3_v3((float *)SCULPT_attr_vertex_data(vertex, ss->scl.prefairing_co),
SCULPT_vertex_co_get(ss, vertex));
}
}
@ -3563,19 +3507,13 @@ 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 (!*(uchar *)SCULPT_attr_vertex_data(vd.vertex,
ss->custom_layers[SCULPT_SCL_FAIRING_MASK])) {
if (!*(uchar *)SCULPT_attr_vertex_data(vd.vertex, ss->scl.fairing_mask)) {
continue;
}
float disp[3];
sub_v3_v3v3(disp,
vd.co,
SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]));
mul_v3_fl(
disp,
*(float *)SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]));
copy_v3_v3(vd.co,
SCULPT_attr_vertex_data(vd.vertex, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]));
sub_v3_v3v3(disp, vd.co, SCULPT_attr_vertex_data(vd.vertex, ss->scl.prefairing_co));
mul_v3_fl(disp, *(float *)SCULPT_attr_vertex_data(vd.vertex, ss->scl.fairing_fade));
copy_v3_v3(vd.co, SCULPT_attr_vertex_data(vd.vertex, ss->scl.prefairing_co));
add_v3_v3(vd.co, disp);
if (vd.mvert) {
BKE_pbvh_vert_mark_update(ss->pbvh, vd.vertex);
@ -3592,22 +3530,20 @@ void SCULPT_fairing_brush_exec_fairing_for_cache(Sculpt *sd, Object *ob)
Brush *brush = BKE_paint_brush(&sd->paint);
Mesh *mesh = ob->data;
if (!ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) {
if (!ss->scl.fairing_mask) {
return;
}
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
BKE_mesh_prefair_and_fair_vertices(mesh,
mvert,
ss->custom_layers[SCULPT_SCL_FAIRING_MASK]->data,
MESH_FAIRING_DEPTH_TANGENCY);
BKE_mesh_prefair_and_fair_vertices(
mesh, mvert, ss->scl.fairing_mask->data, MESH_FAIRING_DEPTH_TANGENCY);
} break;
case PBVH_BMESH: {
// note that we allocated fairing_mask.data in simple array mode
BKE_bmesh_prefair_and_fair_vertices(
ss->bm, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]->data, MESH_FAIRING_DEPTH_TANGENCY);
ss->bm, ss->scl.fairing_mask->data, MESH_FAIRING_DEPTH_TANGENCY);
} break;
case PBVH_GRIDS:
BLI_assert(false);

View File

@ -2187,9 +2187,9 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
if (SCULPT_has_persistent_base(ss)) {
SCULPT_ensure_persistent_layers(ss, ob);
cloth_sim->cd_pers_co = ss->custom_layers[SCULPT_SCL_PERS_CO]->cd_offset;
cloth_sim->cd_pers_no = ss->custom_layers[SCULPT_SCL_PERS_NO]->cd_offset;
cloth_sim->cd_pers_disp = ss->custom_layers[SCULPT_SCL_PERS_DISP]->cd_offset;
cloth_sim->cd_pers_co = ss->scl.persistent_co->cd_offset;
cloth_sim->cd_pers_no = ss->scl.persistent_no->cd_offset;
cloth_sim->cd_pers_disp = ss->scl.persistent_disp->cd_offset;
}
else {
cloth_sim->cd_pers_co = cloth_sim->cd_pers_no = cloth_sim->cd_pers_disp = -1;

View File

@ -117,11 +117,11 @@ const char orig_faceset_attr_name[] = "_sculpt_original_fsets";
void SCULPT_face_check_origdata(SculptSession *ss, SculptFaceRef face)
{
if (!ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
if (!ss->scl.orig_fsets) {
return;
}
short *s = (short *)SCULPT_attr_face_data(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
short *s = (short *)SCULPT_attr_face_data(face, ss->scl.orig_fsets);
// pack ss->stroke_id in higher 16 bits
if (s[1] != ss->stroke_id) {
@ -132,11 +132,11 @@ void SCULPT_face_check_origdata(SculptSession *ss, SculptFaceRef face)
int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face)
{
if (!ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
if (!ss->scl.orig_fsets) {
return SCULPT_face_set_get(ss, face);
}
short *s = (short *)SCULPT_attr_face_data(face, ss->custom_layers[SCULPT_SCL_ORIG_FSETS]);
short *s = (short *)SCULPT_attr_face_data(face, ss->scl.orig_fsets);
if (s[1] != ss->stroke_id) {
s[0] = SCULPT_face_set_get(ss, face);
@ -148,21 +148,13 @@ int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face)
void SCULPT_face_ensure_original(SculptSession *ss, Object *ob)
{
if (ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
return;
}
SculptCustomLayer *scl = MEM_callocN(sizeof(*scl), "orig fset scl");
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_FACE,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_ORIG_FSETS),
scl,
&((SculptLayerParams){.permanent = false, .simple_array = false}));
ss->custom_layers[SCULPT_SCL_ORIG_FSETS] = scl;
ss->scl.orig_fsets = SCULPT_attr_get_layer(
ss,
ob,
ATTR_DOMAIN_FACE,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_ORIG_FSETS),
&((SculptLayerParams){.permanent = false, .simple_array = false}));
}
int SCULPT_face_set_flag_get(SculptSession *ss, SculptFaceRef face, char flag)

View File

@ -385,15 +385,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,
.bevel_smooth_factor = bevel_smooth_fac,
.bound_scl = bsmooth > 0.0f ? ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] : 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,
.bevel_smooth_factor = bevel_smooth_fac,
.bound_scl = bsmooth > 0.0f ? ss->scl.smooth_bdist : NULL}));
sub_v3_v3v3(val, avg, orig_co);
madd_v3_v3v3fl(val, orig_co, val, fade);
@ -903,7 +902,6 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->bevel_smooth_fac = RNA_float_get(op->ptr, "bevel_smooth_fac");
if (filter_type == MESH_FILTER_SMOOTH && ss->filter_cache->bound_smooth_radius != 0.0f) {
/*ensure ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] exists*/
SCULPT_bound_smooth_ensure(ss, ob);
}

File diff suppressed because it is too large Load Diff

View File

@ -127,9 +127,9 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
SCULPT_ensure_persistent_layers(ss, ob);
scl_co = ss->custom_layers[SCULPT_SCL_PERS_CO];
scl_no = ss->custom_layers[SCULPT_SCL_PERS_NO];
scl_disp = ss->custom_layers[SCULPT_SCL_PERS_DISP];
scl_co = ss->scl.persistent_co;
scl_no = ss->scl.persistent_no;
scl_disp = ss->scl.persistent_disp;
const int totvert = SCULPT_vertex_count_get(ss);
@ -376,7 +376,8 @@ static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene,
BKE_sculptsession_free(ob);
}
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
BKE_object_sculpt_data_create(ob);
ob->sculpt->mode_type = OB_MODE_SCULPT;
ob->sculpt->active_face_index.i = SCULPT_REF_NONE;
ob->sculpt->active_vertex_index.i = SCULPT_REF_NONE;
@ -1352,22 +1353,16 @@ static int sculpt_set_limit_surface_exec(bContext *C, wmOperator *UNUSED(op))
SCULPT_vertex_random_access_ensure(ss);
if (!ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE]) {
ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE] = MEM_callocN(sizeof(SculptCustomLayer),
"SculptCustomLayer");
}
SculptLayerParams params = {.permanent = false, .simple_array = false};
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);
ss->scl.limit_surface = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LIMIT_SURFACE),
&params);
const SculptCustomLayer *scl = ss->custom_layers[SCULPT_SCL_LIMIT_SURFACE];
const SculptCustomLayer *scl = ss->scl.limit_surface;
const int totvert = SCULPT_vertex_count_get(ss);
const bool weighted = false;

View File

@ -410,32 +410,24 @@ void SCULPT_do_paint_brush(
}
}
SculptCustomLayer buffer_scl;
SculptCustomLayer stroke_id_scl;
SculptLayerParams params = {.permanent = false, .simple_array = false};
SculptLayerParams params_id = {
.permanent = false, .simple_array = false, .nocopy = false, .nointerp = true};
SculptCustomLayer *buffer_scl;
SculptCustomLayer *stroke_id_scl;
// reuse smear's buffer name
SculptLayerParams params = {.permanent = false, .simple_array = false, .stroke_only = true};
SculptLayerParams params_id = {.permanent = false,
.simple_array = false,
.nocopy = false,
.nointerp = true,
.stroke_only = true};
SCULPT_attr_ensure_layer(
buffer_scl = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
SCULPT_attr_ensure_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&params_id);
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &buffer_scl, &params);
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);
stroke_id_scl = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&params_id);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
@ -446,8 +438,8 @@ void SCULPT_do_paint_brush(
.wet_mix_sampled_color = wet_color,
.mat = mat,
.hue_offset = SCULPT_get_float(ss, hue_offset, sd, brush),
.scl = &buffer_scl,
.scl2 = &stroke_id_scl,
.scl = buffer_scl,
.scl2 = stroke_id_scl,
.brush_color = brush_color,
};
@ -639,20 +631,16 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SCULPT_vertex_random_access_ensure(ss);
SculptCustomLayer prev_scl;
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_attr_ensure_layer(
SculptCustomLayer *prev_scl = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &prev_scl, &params);
BKE_curvemapping_init(brush->curve);
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.scl = &prev_scl,
.scl = prev_scl,
.brush = brush,
.nodes = nodes,
};

View File

@ -1654,7 +1654,7 @@ void SCULPT_enhance_details_brush(
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
SculptCustomLayer strokeid_scl;
SculptCustomLayer *strokeid_scl;
bool use_area_weights = (ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT);
@ -1680,28 +1680,18 @@ void SCULPT_enhance_details_brush(
SCULPT_boundary_info_ensure(ob);
SculptCustomLayer scl;
SculptCustomLayer *scl;
SculptLayerParams params = {.permanent = false, .simple_array = false};
bool weighted = SCULPT_get_int(ss, use_weighted_smooth, sd, brush);
SCULPT_attr_ensure_layer(
scl = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &params);
SCULPT_attr_ensure_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&params);
SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &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);
strokeid_scl = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_SCL_GET_NAME(SCULPT_SCL_LAYER_STROKE_ID),
&params);
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
SCULPT_vertex_random_access_ensure(ss);
@ -1787,8 +1777,8 @@ void SCULPT_enhance_details_brush(
.cd_temp = 0,
.cd_temp2 = 0,
.nodes = nodes,
.scl = &scl,
.scl2 = &strokeid_scl};
.scl = scl,
.scl2 = strokeid_scl};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@ -1997,17 +1987,13 @@ void SCULPT_bound_smooth_ensure(SculptSession *ss, Object *ob)
{
SculptLayerParams params = {.permanent = false, .simple_array = false};
if (!ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS]) {
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] = MEM_callocN(sizeof(SculptCustomLayer),
"bound_scl");
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_COLOR,
"t__smooth_bdist",
ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS],
&params);
if (!ss->scl.smooth_bdist) {
ss->scl.smooth_bdist = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_COLOR,
SCULPT_SCL_GET_NAME(SCULPT_SCL_SMOOTH_BDIS),
&params);
}
}
@ -2048,19 +2034,13 @@ void SCULPT_smooth(Sculpt *sd,
SculptLayerParams params = {.permanent = false, .simple_array = false};
if (do_vel_smooth) {
if (!ss->custom_layers[SCULPT_SCL_SMOOTH_VEL]) {
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL] = MEM_callocN(sizeof(SculptCustomLayer),
"vel_smooth_scl");
SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"__scl_smooth_vel",
ss->custom_layers[SCULPT_SCL_SMOOTH_VEL],
&params);
}
if (do_vel_smooth && !ss->scl.smooth_vel) {
ss->scl.smooth_vel = SCULPT_attr_get_layer(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_SCL_GET_NAME(SCULPT_SCL_SMOOTH_VEL),
&params);
}
float bstrength2 = bstrength;
@ -2103,7 +2083,6 @@ void SCULPT_smooth(Sculpt *sd,
if (bound_smooth > 0.0f) {
bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
/* ensure ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] exists */
SCULPT_bound_smooth_ensure(ss, ob);
}
@ -2137,8 +2116,8 @@ void SCULPT_smooth(Sculpt *sd,
.smooth_projection = projection,
.fset_slide = fset_slide,
.bound_smooth = bound_smooth,
.scl = do_vel ? ss->custom_layers[SCULPT_SCL_SMOOTH_VEL] : NULL,
.scl2 = bound_smooth > 0.0f ? ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] : NULL,
.scl = do_vel ? ss->scl.smooth_vel : NULL,
.scl2 = bound_smooth > 0.0f ? ss->scl.smooth_bdist : NULL,
.vel_smooth_fac = vel_fac,
.do_origco = do_origco,
.iterations = count + 1,
@ -2360,14 +2339,9 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
SculptCustomLayer scl;
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_attr_ensure_layer(
SculptCustomLayer *scl = SCULPT_attr_get_layer(
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &params);
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) &&
(ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT)) {
@ -2380,7 +2354,7 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
.brush = brush,
.nodes = nodes,
.smooth_projection = brush->autosmooth_projection,
.scl = &scl};
.scl = scl};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);

View File

@ -26,11 +26,11 @@
#include "BKE_attribute.h"
#include "BKE_ccg.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_global.h"
#include "GPU_batch.h"
#include "GPU_buffers.h"
@ -1743,7 +1743,7 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(PBVHGPUFormat *vbo_id,
}
if (have_uv) {
for (int j = 0; j < cd_uv_count; j++) {
for (int j = 0; j < vbo_id->totuv; j++) {
MLoopUV *mu = BM_ELEM_CD_GET_VOID_P(l, cd_uvs[j].cd_offset);
GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->uv[j], i, mu->uv);
}
@ -1994,7 +1994,7 @@ void GPU_pbvh_bmesh_buffers_update(PBVHGPUFormat *vbo_id, PBVHGPUBuildArgs *args
cd_vcol_count);
if (have_uv) {
for (int k = 0; k < cd_uv_count; k++) {
for (int k = 0; k < vbo_id->totuv; k++) {
MLoopUV *mu = BM_ELEM_CD_GET_VOID_P(l[j], cd_uvs[k].cd_offset);
GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->uv[k], v_index, mu->uv);
}
@ -2057,7 +2057,7 @@ bool GPU_pbvh_attribute_names_update(PBVHType pbvh_type,
&vbo_id->format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
vbo_id->totcol = 0;
if (pbvh_type == PBVH_FACES) {
if (ELEM(pbvh_type, PBVH_FACES, PBVH_BMESH)) {
int ci = 0;
Mesh me_query;
@ -2117,7 +2117,8 @@ bool GPU_pbvh_attribute_names_update(PBVHType pbvh_type,
&vbo_id->format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
vbo_id->totuv = 0;
if (pbvh_type == PBVH_FACES && ldata && CustomData_has_layer(ldata, CD_MLOOPUV)) {
if (ELEM(pbvh_type, PBVH_FACES, PBVH_BMESH) && ldata &&
CustomData_has_layer(ldata, CD_MLOOPUV)) {
GPUAttrRef uv_layers[MAX_GPU_ATTR];
CustomDataLayer *active = NULL, *render = NULL;

View File

@ -4108,7 +4108,7 @@ void *BPy_bm_new_customdata_layout_pre(BMesh *bm, CustomData *cdata, char htype)
return ptrs;
}
ATTR_NO_OPT void BPy_bm_new_customdata_layout(BMesh *bm, CustomData *cdata, void *state, char htype)
void BPy_bm_new_customdata_layout(BMesh *bm, CustomData *cdata, void *state, char htype)
{
/*
* Un-invalidate python pointers, which got invalidated when the customdata layout