Sculpt-dev: fix pbvh_bmesh_normals_update

This commit is contained in:
Joseph Eagar 2021-12-14 10:19:21 -08:00
parent 268e18e9a3
commit 4a9495ef7d
6 changed files with 203 additions and 94 deletions

View File

@ -62,8 +62,7 @@ struct UnifiedPaintSettings;
#define MAKE_BUILTIN_CH_NAME(idname) BRUSH_BUILTIN_##idname
/* these macros check channel names at compile time */
/* these macros validate channel names at compile time */
#define BRUSHSET_LOOKUP_FINAL(childset, parentset, idname) \
BKE_brush_channelset_lookup_final(childset, parentset, MAKE_BUILTIN_CH_NAME(idname))
#define BRUSHSET_LOOKUP(chset, channel) \
@ -76,8 +75,7 @@ struct UnifiedPaintSettings;
BKE_brush_channelset_get_final_float(childset, parentset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_INT(chset, channel, mapdata) \
BKE_brush_channelset_get_int(chset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_BOOL(chset, channel, mapdata) \
(!!BRUSHSET_GET_INT(chset, channel, mapdata))
#define BRUSHSET_GET_BOOL(chset, channel, mapdata) (!!BRUSHSET_GET_INT(chset, channel, mapdata))
#define BRUSHSET_GET_FINAL_INT(child, parent, channel, mapdata) \
BKE_brush_channelset_get_final_int(child, parent, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_FINAL_BOOL(child, parent, channel, mapdata) \
@ -107,7 +105,7 @@ typedef void (*BrushChannelIDCallback)(void *userdata,
struct ID *id,
BrushChannelSet *chset,
BrushChannel *ch);
/* TODO: clean up this struct */
typedef struct BrushMappingDef {
int curve;
bool enabled;
@ -125,12 +123,15 @@ typedef struct BrushMappingPreset {
struct BrushMappingDef pressure, xtilt, ytilt, angle, speed, random, stroke_t;
} BrushMappingPreset;
/* input mapping data */
typedef struct BrushMappingData {
float pressure, xtilt, ytilt, angle, speed, random, stroke_t;
} BrushMappingData;
#define MAX_BRUSH_ENUM_DEF 32
/* copy of PropertyEnumItem only with static char arrays instead of pointers
for strings */
typedef struct BrushEnumDef {
int value;
const char identifier[64];
@ -139,6 +140,10 @@ typedef struct BrushEnumDef {
const char description[512];
} BrushEnumDef;
/*
Defines a brush channel. Includes limits, UI data,
default values, etc.
*/
typedef struct BrushChannelType {
char name[128], idname[64], tooltip[512], category[128];
float min, max, soft_min, soft_max;
@ -146,18 +151,19 @@ typedef struct BrushChannelType {
int type, flag;
int subtype;
int ivalue;
int ivalue; /* for int, bool, enum and bitmask types */
int icon;
float fvalue;
float vector[4];
float vector[4]; /* for vector3 & vector4 types */
int curve_preset;
bool curve_preset_slope_neg;
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; /* for enum/bitmask types */
EnumPropertyItem *rna_enumdef;
bool user_defined;
struct StructRNA *rna_ext;
bool user_defined; /* this is a user-defined channel; currently unused */
struct StructRNA *rna_ext; /* private rna pointer */
} BrushChannelType;
/* since MTex is going away lets'
@ -166,7 +172,10 @@ typedef struct BrushChannelType {
point of view it's just a bunch of
BrushChannels.
This will eventually end up in DNA.*/
This will eventually end up in DNA.
Note, this hasn't been fully implemented yet.
*/
typedef struct BrushTex {
struct BrushTex *next, *prev;
@ -186,14 +195,17 @@ void BKE_brush_tex_start(BrushTex *btex, BrushChannelSet *chset, BrushMappingDat
#define MAKE_BRUSHTEX_SLOTS 5
typedef struct BrushCommand {
int tool;
float last_spacing_t[512]; // this is an array for different symmetry passes
struct BrushChannelSet *params;
struct BrushChannelSet *params_final; // with inheritence applied
struct BrushChannelSet *params_mapped; // with pressure etc applied
/*
BrushTex *texture_slots[MAKE_BRUSHTEX_SLOTS];
*/
typedef struct BrushCommand {
int tool; /* SCULPT_TOOL_XXX value */
float last_spacing_t[512]; /* has values for all possible symmetry passes */
struct BrushChannelSet *params;
struct BrushChannelSet *params_final; /* with inheritence applied */
struct BrushChannelSet *params_mapped; /* with pressure etc applied */
BrushTex *texture_slots[MAKE_BRUSHTEX_SLOTS]; /* currently unused */
} BrushCommand;
typedef struct BrushCommandList {
@ -203,14 +215,39 @@ typedef struct BrushCommandList {
void BKE_brush_channel_free_data(BrushChannel *ch);
void BKE_brush_channel_free(BrushChannel *ch);
/* creates all the channels needed for a given sculpt tool */
void BKE_brush_builtin_create(struct Brush *brush, int tool);
/*
Copies channel data from src to dst. Dst's data
will be freed first.
*/
void BKE_brush_channel_copy_data(BrushChannel *dst,
BrushChannel *src,
bool keep_mappings,
bool keep_idname_and_def);
/* Initialize a channel from a channel definition */
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
/* Lookup a built-in channel definition by name */
BrushChannelType *BKE_brush_builtin_channel_def_find(const char *name);
/* Create new channel set; info is a guardedalloc tag and should point
to a static/permanent string */
BrushChannelSet *BKE_brush_channelset_create(const char *info);
/* adds missing channels to exising .channels in brush.
* if channels do not exist use BKE_brush_builtin_create.
*/
void BKE_brush_builtin_patch(struct Brush *brush, int tool);
/* loads old brush settings to/from channels */
void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
struct Brush *brush,
bool to_channels);
#ifdef DEBUG_CURVE_MAPPING_ALLOC
BrushChannelSet *_BKE_brush_channelset_copy(BrushChannelSet *src);
# define BKE_brush_channelset_copy(src) \
@ -231,35 +268,28 @@ void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *c
/* does not free ch or its data */
void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch);
// does not free ch or its data
/* does not free ch or its data */
bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname);
// checks is a channel with existing->idname exists; if not a copy of existing is made and inserted
/* checks if a channel with existing->idname exists; if not a copy of existing
is made and inserted
*/
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing);
/* Lookup a channel in chset; returns NULL if it does not exist */
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
/* Looks up a channel in child; if it is set to inherit or does not exist, then
the channel will be looked up in parent; otherwise the one in child is returned.
Note that this does not apply brush mapping inheritance.
*/
BrushChannel *BKE_brush_channelset_lookup_final(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname);
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
void BKE_brush_mapping_reset(BrushChannel *ch, int tool, int mapping);
void BKE_brush_mapping_inherit_all(BrushChannel *ch);
void BKE_brush_channelset_inherit_mappings(BrushChannelSet *chset);
void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent);
void BKE_brush_channel_apply_mapping_flags(BrushChannel *dst,
BrushChannel *child,
BrushChannel *parent);
bool BKE_brush_mapping_is_enabled(BrushChannel *child, BrushChannel *parent, int mapping);
/*takes child and parent channels and builds inherited channel
/*
takes child and parent channels and builds inherited channel
in dst, with channel and brush mapping inheritance flags
properly resolved.
@ -271,27 +301,53 @@ void BKE_brush_channel_copy_final_data(BrushChannel *dst,
bool keep_mapping,
bool keep_idname_and_def);
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
void BKE_brush_mapping_reset(BrushChannel *ch, int tool, int mapping);
void BKE_brush_mapping_inherit_all(BrushChannel *ch);
void BKE_brush_channelset_inherit_mappings(BrushChannelSet *chset);
void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent);
void BKE_brush_channel_apply_mapping_flags(BrushChannel *dst,
BrushChannel *child,
BrushChannel *parent);
bool BKE_brush_mapping_is_enabled(BrushChannel *child, BrushChannel *parent, int mapping);
/* iterators over each channel in brush->channels, and any set to inherit will be
overwritten by equivalent channel in sd->channels */
void BKE_brush_resolve_channels(struct Brush *brush, struct Sculpt *sd);
void BKE_brush_channelset_set_final_int(BrushChannelSet *brushset,
BrushChannelSet *toolset,
/* sets channel value in either child or parent depending on inheritance flag */
void BKE_brush_channelset_set_final_int(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
int value);
int BKE_brush_channelset_get_final_int(BrushChannelSet *brushset,
BrushChannelSet *toolset,
/* gets channel value in either child or parent depending on inheritance flag */
int BKE_brush_channelset_get_final_int(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
BrushMappingData *mapdata);
/* note that mapdata can be NULL */
int BKE_brush_channelset_get_int(BrushChannelSet *chset,
const char *idname,
BrushMappingData *mapdata);
bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val);
void BKE_brush_channel_set_int(BrushChannel *ch, int val);
float BKE_brush_channel_get_int(BrushChannel *ch, BrushMappingData *mapdata);
// mapdata is optional, can be NULL
/* mapdata may be NULL */
float BKE_brush_channel_get_int(BrushChannel *ch, BrushMappingData *mapdata);
/* mapdata may be NULL */
float BKE_brush_channel_get_float(BrushChannel *ch, BrushMappingData *mapdata);
@ -303,6 +359,7 @@ float BKE_brush_channelset_get_float(BrushChannelSet *chset,
BrushMappingData *mapdata);
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, const char *idname, float val);
/* mapdata may be NULL */
float BKE_brush_channelset_get_final_float(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
@ -317,12 +374,20 @@ void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4]);
int BKE_brush_channel_get_vector_size(BrushChannel *ch);
float BKE_brush_channel_curve_evaluate(BrushChannel *ch, float val, const float maxval);
/* feeds f through a brush channel's mapping stack and returns the result */
double BKE_brush_channel_eval_mappings(BrushChannel *ch,
BrushMappingData *mapdata,
double f,
int idx);
/* note the brush system caches curvemappings to avoid excessive copying
(profiling showed this to be a major problem), so make sure to
call BKE_brush_channel_curve_ensure_write(curve) before calling this
function if you want to edit the curve */
CurveMapping *BKE_brush_channel_curvemapping_get(BrushCurve *curve, bool force_create);
/* ensure we can write to this brush curve */
bool BKE_brush_channel_curve_ensure_write(BrushCurve *curve);
void BKE_brush_channel_curve_assign(BrushChannel *ch, BrushCurve *curve);
@ -339,34 +404,45 @@ void BKE_brush_channelset_set_final_vector(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
float vec[4]);
/* returns size of vector */
int BKE_brush_channelset_get_vector(BrushChannelSet *chset,
const char *idname,
float r_vec[4],
BrushMappingData *mapdata);
bool BKE_brush_channelset_set_vector(BrushChannelSet *chset, const char *idname, float vec[4]);
extern void BKE_brush_channelset_to_unified_settings(BrushChannelSet *chset,
struct UnifiedPaintSettings *ups);
void BKE_brush_channelset_flag_clear(BrushChannelSet *chset, const char *channel, int flag);
void BKE_brush_channelset_flag_set(BrushChannelSet *chset, const char *channel, int flag);
void BKE_brush_channelset_to_unified_settings(BrushChannelSet *chset,
struct UnifiedPaintSettings *ups);
void BKE_brush_init_toolsettings(struct Sculpt *sd);
void BKE_brush_builtin_create(struct Brush *brush, int tool);
void BKE_brush_channelset_clear_inherit(BrushChannelSet *chset);
void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData *mapdata);
/*** brush command list stuff ****/
BrushCommandList *BKE_brush_commandlist_create(void);
BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool);
BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl,
BrushChannelSet *chset_template,
bool auto_inherit);
void BKE_builtin_commandlist_create(struct Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *map_data); // map_data may be NULL
void BKE_brush_commandlist_start(BrushCommandList *list,
struct Brush *brush,
BrushChannelSet *chset_final);
void BKE_brush_commandlist_free(BrushCommandList *cl);
BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl,
BrushChannelSet *chset_template,
bool auto_inherit);
BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool);
/***** filing reading/linking stuff *******/
void BKE_builtin_commandlist_create(struct Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *map_data); // map_data may be NULL
void BKE_brush_channelset_read(struct BlendDataReader *reader, BrushChannelSet *cset);
void BKE_brush_channelset_write(struct BlendWriter *writer, BrushChannelSet *cset);
void BKE_brush_channelset_read_lib(struct BlendLibReader *reader,
@ -379,21 +455,12 @@ void BKE_brush_channelset_foreach_id(void *userdata,
BrushChannelSet *chset,
BrushChannelIDCallback callback);
/******** brush mapping stuff *******/
void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src);
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping);
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping);
void BKE_brush_channelset_flag_clear(BrushChannelSet *chset, const char *channel, int flag);
void BKE_brush_channelset_flag_set(BrushChannelSet *chset, const char *channel, int flag);
/* adds missing channels to exising .channels in brush.
* if channels do not exist use BKE_brush_builtin_create.
*/
void BKE_brush_builtin_patch(struct Brush *brush, int tool);
void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
struct Brush *brush,
bool to_channels);
/********* misc utility functions *********/
// merge in channels the ui requested
void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override);
@ -401,17 +468,20 @@ void BKE_brush_channeltype_rna_check(BrushChannelType *def,
int (*getIconFromName)(const char *name));
bool BKE_brush_mapping_ensure_write(BrushMapping *mp);
void BKE_brush_channelset_clear_inherit(BrushChannelSet *chset);
void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData *mapdata);
void BKE_brush_check_toolsettings(struct Sculpt *sd);
void BKE_brush_channelset_ui_init(struct Brush *brush, int tool);
void BKE_brush_channelset_check_radius(BrushChannelSet *chset);
/* applies "hard edge mode", currently just sets fset_slide to 0.0f */
void BKE_builtin_apply_hard_edge_mode(BrushChannelSet *chset, bool do_apply);
const char *BKE_brush_channel_category_get(BrushChannel *ch);
void BKE_brush_channel_category_set(BrushChannel *ch, const char *str);
/* set up brush curvemapping cache */
void BKE_brush_channel_system_init(void);
/* frees brush curvemapping cache */
void BKE_brush_channel_system_exit(void);
/*

View File

@ -1433,7 +1433,7 @@ int BKE_brush_channelset_get_vector(BrushChannelSet *chset,
if (!ch) {
printf("%s, unknown channel %s", __func__, idname);
return 0.0f;
return 0;
}
return BKE_brush_channel_get_vector(ch, r_vec, mapdata);

View File

@ -71,13 +71,14 @@ void namestack_pop();
/*
Instructions to add a built-in channel:
1. Add to brush_builtin_channels
1. Add to brush_channel_define.h
2. Add to BKE_brush_builtin_patch to insert it in old brushes (without converting data)
To enable converting to/from old data:
3. If not a boolean mapping to a bitflag: Add to brush_settings_map
4. If a boolean mapping to a bitflag: Add to brush_flags_map_len.
*/
#define ICON_NONE "NONE"
/* clang-format off */

View File

@ -1689,6 +1689,8 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->depsgraph = depsgraph;
ss->bm_smooth_shading = scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING;
ss->deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob);
ss->show_mask = (sd->flags & SCULPT_HIDE_MASK) == 0;
ss->show_face_sets = (sd->flags & SCULPT_HIDE_FACE_SETS) == 0;

View File

@ -1204,6 +1204,7 @@ typedef struct UpdateNormalsTaskData {
int tot_border_verts;
int cd_sculpt_vert;
int cd_vert_node_offset;
int cd_face_node_offset;
int node_nr;
} UpdateNormalsTaskData;
@ -1215,26 +1216,59 @@ static void pbvh_update_normals_task_cb(void *__restrict userdata,
BMFace *f;
UpdateNormalsTaskData *data = ((UpdateNormalsTaskData *)userdata) + n;
PBVHNode *node = data->node;
int node_nr = data->node_nr;
const int node_nr = data->node_nr;
BMVert **bordervs = NULL;
BLI_array_declare(bordervs);
const int cd_face_node_offset = data->cd_face_node_offset;
const int cd_vert_node_offset = data->cd_vert_node_offset;
node->flag |= PBVH_UpdateCurvatureDir;
TGSET_ITER (v, node->bm_unique_verts) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, v);
int ni2 = BM_ELEM_CD_GET_INT(v, data->cd_vert_node_offset);
bool bad = ni2 != node_nr || (mv->flag & SCULPTVERT_PBVH_BOUNDARY);
#ifdef NORMAL_VERT_BAD
# undef NORMAL_VERT_BAD
#endif
#define NORMAL_VERT_BAD(v) \
(!v->e || BM_ELEM_CD_GET_INT((v), cd_vert_node_offset) != node_nr || \
(BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, (v))->flag & SCULPTVERT_PBVH_BOUNDARY))
const char tag = BM_ELEM_TAG_ALT;
TGSET_ITER (v, node->bm_unique_verts) {
PBVH_CHECK_NAN(v->no);
if (bad) {
if (NORMAL_VERT_BAD(v)) {
v->head.hflag |= tag;
BLI_array_append(bordervs, v);
continue;
}
else {
zero_v3(v->no);
v->head.hflag &= ~tag;
BMEdge *e = v->e;
do {
BMLoop *l = e->l;
if (!l) {
continue;
}
do {
if (BM_ELEM_CD_GET_INT(l->f, cd_face_node_offset) != node_nr) {
v->head.hflag |= tag;
goto loop_exit;
}
} while ((l = l->radial_next) != e->l);
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
loop_exit:
if (v->head.hflag & tag) {
BLI_array_append(bordervs, v);
continue;
}
zero_v3(v->no);
}
TGSET_ITER_END
@ -1245,13 +1279,9 @@ static void pbvh_update_normals_task_cb(void *__restrict userdata,
BMLoop *l = f->l_first;
do {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, l->v);
int ni2 = BM_ELEM_CD_GET_INT(l->v, data->cd_vert_node_offset);
bool bad = ni2 != node_nr || (mv->flag & SCULPTVERT_PBVH_BOUNDARY);
PBVH_CHECK_NAN(l->v->no);
if (!bad) {
if (BM_ELEM_CD_GET_INT(l->v, cd_vert_node_offset) == node_nr && !(l->v->head.hflag & tag)) {
add_v3_v3(l->v->no, f->no);
}
} while ((l = l->next) != f->l_first);
@ -1259,13 +1289,14 @@ static void pbvh_update_normals_task_cb(void *__restrict userdata,
TGSET_ITER_END
TGSET_ITER (v, node->bm_unique_verts) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(data->cd_sculpt_vert, v);
int ni2 = BM_ELEM_CD_GET_INT(v, data->cd_vert_node_offset);
bool bad = ni2 != node_nr || (mv->flag & SCULPTVERT_PBVH_BOUNDARY);
PBVH_CHECK_NAN(v->no);
if (!bad) {
if (dot_v3v3(v->no, v->no) == 0.0f) {
BLI_array_append(bordervs, v);
continue;
}
if (!(v->head.hflag & tag)) {
normalize_v3(v->no);
}
}
@ -1281,12 +1312,12 @@ void pbvh_bmesh_normals_update(PBVH *pbvh, PBVHNode **nodes, int totnode)
{
TaskParallelSettings settings;
UpdateNormalsTaskData *datas = MEM_calloc_arrayN(totnode, sizeof(*datas), "bmesh normal update");
BMesh *bm = pbvh->bm;
for (int i = 0; i < totnode; i++) {
datas[i].node = nodes[i];
datas[i].cd_sculpt_vert = pbvh->cd_sculpt_vert;
datas[i].cd_vert_node_offset = pbvh->cd_vert_node_offset;
datas[i].cd_face_node_offset = pbvh->cd_face_node_offset;
datas[i].node_nr = nodes[i] - pbvh->nodes;
BKE_pbvh_bmesh_check_tris(pbvh, nodes[i]);
@ -1295,8 +1326,11 @@ void pbvh_bmesh_normals_update(PBVH *pbvh, PBVHNode **nodes, int totnode)
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, datas, pbvh_update_normals_task_cb, &settings);
/* not sure it's worth calling BM_mesh_elem_index_ensure here */
#if 0
BLI_bitmap *visit = BLI_BITMAP_NEW(bm->totvert, "visit");
BM_mesh_elem_index_ensure(bm, BM_VERT);
#endif
for (int i = 0; i < totnode; i++) {
UpdateNormalsTaskData *data = datas + i;
@ -1316,6 +1350,7 @@ void pbvh_bmesh_normals_update(PBVH *pbvh, PBVHNode **nodes, int totnode)
continue;
}
#if 0
if (v->head.index < 0 || v->head.index >= bm->totvert) {
printf("%s: error, v->head.index was out of bounds!\n", __func__);
continue;
@ -1326,6 +1361,7 @@ void pbvh_bmesh_normals_update(PBVH *pbvh, PBVHNode **nodes, int totnode)
}
BLI_BITMAP_ENABLE(visit, v->head.index);
#endif
// manual iteration
BMEdge *e = v->e;
@ -1350,7 +1386,10 @@ void pbvh_bmesh_normals_update(PBVH *pbvh, PBVHNode **nodes, int totnode)
MEM_SAFE_FREE(data->border_verts);
}
#if 0
MEM_SAFE_FREE(visit);
#endif
MEM_SAFE_FREE(datas);
}

View File

@ -639,9 +639,6 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
ss->mdyntopo_verts = NULL;
}
ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) !=
0;
/* Dynamic topology doesn't ensure selection state is valid, so remove T36280. */
BKE_mesh_mselect_clear(me);