WIP: Sculpt: cleanup sculpt attribute API #106920
|
@ -499,6 +499,7 @@ typedef struct SculptAttributeParams {
|
|||
*/
|
||||
int permanent : 1; /* Cannot be combined with simple_array. */
|
||||
int stroke_only : 1; /* Release layer at end of struct */
|
||||
bool read_only : 1;
|
||||
} SculptAttributeParams;
|
||||
|
||||
typedef struct SculptAttribute {
|
||||
|
@ -780,11 +781,18 @@ SculptAttribute *BKE_sculpt_attribute_ensure(struct Object *ob,
|
|||
const char *name,
|
||||
const SculptAttributeParams *params);
|
||||
|
||||
/* Returns nullptr if attribute does not exist. */
|
||||
/* Returns nullptr if attribute does not exist. params may be nullptr. */
|
||||
SculptAttribute *BKE_sculpt_attribute_get(struct Object *ob,
|
||||
eAttrDomain domain,
|
||||
eCustomDataType proptype,
|
||||
const char *name);
|
||||
const char *name,
|
||||
const SculptAttributeParams *params);
|
||||
|
||||
/* Release this attribute handle (does not destroying the attribute itself).
|
||||
* Any pointers inside SculptSession.attrs that point to attr will be
|
||||
* null'd.
|
||||
*/
|
||||
void BKE_sculpt_attribute_release(struct Object *ob, SculptAttribute *attr);
|
||||
|
||||
bool BKE_sculpt_attribute_exists(struct Object *ob,
|
||||
eAttrDomain domain,
|
||||
|
@ -799,48 +807,6 @@ void BKE_sculpt_attribute_destroy_temporary_all(struct Object *ob);
|
|||
/* Destroy attributes that were marked as stroke only in SculptAttributeParams. */
|
||||
void BKE_sculpt_attributes_destroy_temporary_stroke(struct Object *ob);
|
||||
|
||||
BLI_INLINE void *BKE_sculpt_vertex_attr_get(const PBVHVertRef vertex, const SculptAttribute *attr)
|
||||
{
|
||||
if (attr->data) {
|
||||
char *p = (char *)attr->data;
|
||||
int idx = (int)vertex.i;
|
||||
|
||||
if (attr->data_for_bmesh) {
|
||||
BMElem *v = (BMElem *)vertex.i;
|
||||
idx = v->head.index;
|
||||
}
|
||||
|
||||
return p + attr->elem_size * (int)idx;
|
||||
}
|
||||
else {
|
||||
BMElem *v = (BMElem *)vertex.i;
|
||||
return BM_ELEM_CD_GET_VOID_P(v, attr->bmesh_cd_offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE void *BKE_sculpt_face_attr_get(const PBVHFaceRef vertex, const SculptAttribute *attr)
|
||||
{
|
||||
if (attr->data) {
|
||||
char *p = (char *)attr->data;
|
||||
int idx = (int)vertex.i;
|
||||
|
||||
if (attr->data_for_bmesh) {
|
||||
BMElem *v = (BMElem *)vertex.i;
|
||||
idx = v->head.index;
|
||||
}
|
||||
|
||||
return p + attr->elem_size * (int)idx;
|
||||
}
|
||||
else {
|
||||
BMElem *v = (BMElem *)vertex.i;
|
||||
return BM_ELEM_CD_GET_VOID_P(v, attr->bmesh_cd_offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -943,4 +909,83 @@ struct CurveMapping *BKE_sculpt_default_cavity_curve(void);
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
}
|
||||
|
||||
namespace blender::bke::paint {
|
||||
Hans Goudey
commented
Could avoid the temporary variable here and return the pointer inside the if statement. Could avoid the temporary variable here and return the pointer inside the if statement.
|
||||
|
||||
/* Base implementation for vertex_attr_*** and face_attr_*** methods.
|
||||
* Returns a pointer to the attribute data (as defined by attr) for elem.
|
||||
*/
|
||||
template<typename T, typename ElemRef = PBVHVertRef>
|
||||
static T *elem_attr_ptr(const ElemRef elem, const SculptAttribute *attr)
|
||||
{
|
||||
void *ptr = nullptr;
|
||||
|
||||
if (attr->data) {
|
||||
char *p = (char *)attr->data;
|
||||
int idx = (int)elem.i;
|
||||
|
||||
if (attr->data_for_bmesh) {
|
||||
BMElem *e = (BMElem *)elem.i;
|
||||
idx = e->head.index;
|
||||
}
|
||||
|
||||
ptr = p + attr->elem_size * (int)idx;
|
||||
}
|
||||
else {
|
||||
BMElem *v = (BMElem *)elem.i;
|
||||
ptr = BM_ELEM_CD_GET_VOID_P(v, attr->bmesh_cd_offset);
|
||||
}
|
||||
|
||||
return static_cast<T *>(ptr);
|
||||
}
|
||||
Hans Goudey
commented
I think exposing the pointer where a value is stored might not work well with different attribute storage methods in the future, and exposes the internal of the system a bit more than necessary. (For example, virtual arrays don't provide that ability, not that we would use them here exactly). The alternative is using a I think exposing the pointer where a value is stored might not work well with different attribute storage methods in the future, and exposes the internal of the system a bit more than necessary. (For example, virtual arrays don't provide that ability, not that we would use them here exactly). The alternative is using a `get`/`set` combo when that's actually necessary.
|
||||
|
||||
/*
|
||||
* Get a pointer to attribute data at vertex.
|
||||
*
|
||||
* Example: float *persistent_co = vertex_attr_ptr<float>(vertex, ss->attrs.persistent_co);
|
||||
*/
|
||||
template<typename T>
|
||||
static T *vertex_attr_ptr(const PBVHVertRef vertex, const SculptAttribute *attr)
|
||||
{
|
||||
return elem_attr_ptr<T, PBVHVertRef>(vertex, attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get attribute data at vertex.
|
||||
*
|
||||
* Example: float weight = vertex_attr_get<float>(vertex, ss->attrs.automasking_factor);
|
||||
*/
|
||||
template<typename T>
|
||||
static T vertex_attr_get(const PBVHVertRef vertex, const SculptAttribute *attr)
|
||||
{
|
||||
return *vertex_attr_ptr<T>(vertex, attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set attribute data at vertex.
|
||||
*
|
||||
* vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, 1.0f);
|
||||
*/
|
||||
template<typename T>
|
||||
static void vertex_attr_set(const PBVHVertRef vertex, const SculptAttribute *attr, T data)
|
||||
{
|
||||
*vertex_attr_ptr<T>(vertex, attr) = data;
|
||||
}
|
||||
|
||||
template<typename T> static T *face_attr_ptr(const PBVHFaceRef face, const SculptAttribute *attr)
|
||||
{
|
||||
return elem_attr_ptr<T, PBVHFaceRef>(face, attr);
|
||||
}
|
||||
|
||||
template<typename T> static T face_attr_get(const PBVHFaceRef face, const SculptAttribute *attr)
|
||||
{
|
||||
return *face_attr_ptr<T>(face, attr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void face_attr_set(const PBVHFaceRef face, const SculptAttribute *attr, T data)
|
||||
{
|
||||
*face_attr_ptr<T>(face, attr) = data;
|
||||
}
|
||||
} // namespace blender::bke::paint
|
||||
#endif
|
||||
|
|
|
@ -1652,11 +1652,11 @@ static void sculpt_update_persistent_base(Object *ob)
|
|||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
ss->attrs.persistent_co = BKE_sculpt_attribute_get(
|
||||
ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_co));
|
||||
ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_co), nullptr);
|
||||
ss->attrs.persistent_no = BKE_sculpt_attribute_get(
|
||||
ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_no));
|
||||
ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_no), nullptr);
|
||||
ss->attrs.persistent_disp = BKE_sculpt_attribute_get(
|
||||
ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(persistent_disp));
|
||||
ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(persistent_disp), nullptr);
|
||||
}
|
||||
|
||||
static void sculpt_update_object(
|
||||
|
@ -2574,7 +2574,9 @@ static bool sculpt_attr_update(Object *ob, SculptAttribute *attr)
|
|||
attr->bmesh_cd_offset = cdata->layers[layer_index].offset;
|
||||
}
|
||||
else {
|
||||
attr->data = cdata->layers[layer_index].data;
|
||||
attr->data = attr->params.read_only ?
|
||||
cdata->layers[layer_index].data :
|
||||
CustomData_get_layer_for_write(cdata, attr->proptype, elem_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2650,21 +2652,14 @@ static SculptAttribute *sculpt_alloc_attr(SculptSession *ss)
|
|||
SculptAttribute *BKE_sculpt_attribute_get(struct Object *ob,
|
||||
eAttrDomain domain,
|
||||
eCustomDataType proptype,
|
||||
const char *name)
|
||||
const char *name,
|
||||
const SculptAttributeParams *params)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
/* See if attribute is cached in ss->temp_attributes. */
|
||||
SculptAttribute *attr = sculpt_get_cached_layer(ss, domain, proptype, name);
|
||||
|
||||
if (attr) {
|
||||
if (sculpt_attr_update(ob, attr)) {
|
||||
sculpt_attribute_update_refs(ob);
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
/* Does attribute exist in CustomData layout? */
|
||||
CustomData *cdata = sculpt_get_cdata(ob, domain);
|
||||
if (cdata) {
|
||||
|
@ -2687,7 +2682,14 @@ SculptAttribute *BKE_sculpt_attribute_get(struct Object *ob,
|
|||
|
||||
attr = sculpt_alloc_attr(ss);
|
||||
|
||||
attr->used = true;
|
||||
if (params) {
|
||||
attr->params = *params;
|
||||
}
|
||||
else {
|
||||
attr->params = {};
|
||||
}
|
||||
|
||||
attr->params.permanent = !(cdata->layers[index].flag & CD_FLAG_TEMPORARY);
|
||||
attr->domain = domain;
|
||||
attr->proptype = proptype;
|
||||
attr->data = cdata->layers[index].data;
|
||||
|
@ -2697,10 +2699,17 @@ SculptAttribute *BKE_sculpt_attribute_get(struct Object *ob,
|
|||
attr->elem_size = CustomData_get_elem_size(attr->layer);
|
||||
|
||||
STRNCPY_UTF8(attr->name, name);
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
if (sculpt_attr_update(ob, attr)) {
|
||||
sculpt_attribute_update_refs(ob);
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -2713,7 +2722,7 @@ static SculptAttribute *sculpt_attribute_ensure_ex(Object *ob,
|
|||
bool flat_array_for_bmesh)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
SculptAttribute *attr = BKE_sculpt_attribute_get(ob, domain, proptype, name);
|
||||
SculptAttribute *attr = BKE_sculpt_attribute_get(ob, domain, proptype, name, params);
|
||||
|
||||
if (attr) {
|
||||
sculpt_attr_update(ob, attr);
|
||||
|
@ -2837,12 +2846,9 @@ void BKE_sculpt_attribute_destroy_temporary_all(Object *ob)
|
|||
}
|
||||
}
|
||||
|
||||
bool BKE_sculpt_attribute_destroy(Object *ob, SculptAttribute *attr)
|
||||
void BKE_sculpt_attribute_release(struct Object *ob, SculptAttribute *attr)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
eAttrDomain domain = attr->domain;
|
||||
|
||||
BLI_assert(attr->used);
|
||||
|
||||
/* Remove from convenience pointer struct. */
|
||||
SculptAttribute **ptrs = (SculptAttribute **)&ss->attrs;
|
||||
|
@ -2854,7 +2860,18 @@ bool BKE_sculpt_attribute_destroy(Object *ob, SculptAttribute *attr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Remove from internal temp_attributes array. */
|
||||
attr->used = false;
|
||||
attr->data = nullptr;
|
||||
}
|
||||
|
||||
bool BKE_sculpt_attribute_destroy(Object *ob, SculptAttribute *attr)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
eAttrDomain domain = attr->domain;
|
||||
|
||||
BLI_assert(attr->used);
|
||||
|
||||
/* Remove any duplicates from internal temp_attributes array. */
|
||||
for (int i = 0; i < SCULPT_MAX_ATTRIBUTES; i++) {
|
||||
SculptAttribute *attr2 = ss->temp_attributes + i;
|
||||
|
||||
|
@ -2901,12 +2918,12 @@ bool BKE_sculpt_attribute_destroy(Object *ob, SculptAttribute *attr)
|
|||
if (layer_i != 0) {
|
||||
CustomData_free_layer(cdata, attr->proptype, totelem, layer_i);
|
||||
}
|
||||
|
||||
sculpt_attribute_update_refs(ob);
|
||||
}
|
||||
|
||||
attr->data = nullptr;
|
||||
attr->used = false;
|
||||
BKE_sculpt_attribute_release(ob, attr);
|
||||
|
||||
/* Make sure the remaining SculptAttributes are valid. */
|
||||
sculpt_attribute_update_refs(ob);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ void SCULPT_vertex_normal_get(SculptSession *ss, PBVHVertRef vertex, float no[3]
|
|||
const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, PBVHVertRef vertex)
|
||||
{
|
||||
if (ss->attrs.persistent_co) {
|
||||
return (const float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_co);
|
||||
return blender::bke::paint::vertex_attr_ptr<const float>(vertex, ss->attrs.persistent_co);
|
||||
}
|
||||
|
||||
return SCULPT_vertex_co_get(ss, vertex);
|
||||
|
@ -258,7 +258,7 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, PBVHVertRef vertex, floa
|
|||
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, PBVHVertRef vertex, float no[3])
|
||||
{
|
||||
if (ss->attrs.persistent_no) {
|
||||
copy_v3_v3(no, (float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_no));
|
||||
copy_v3_v3(no, blender::bke::paint::vertex_attr_ptr<float>(vertex, ss->attrs.persistent_no));
|
||||
return;
|
||||
}
|
||||
SCULPT_vertex_normal_get(ss, vertex, no);
|
||||
|
@ -6354,7 +6354,7 @@ void SCULPT_face_set_set(SculptSession *ss, PBVHFaceRef face, int fset)
|
|||
int SCULPT_vertex_island_get(SculptSession *ss, PBVHVertRef vertex)
|
||||
{
|
||||
if (ss->attrs.topology_island_key) {
|
||||
return *static_cast<uint8_t *>(SCULPT_vertex_attr_get(vertex, ss->attrs.topology_island_key));
|
||||
return blender::bke::paint::vertex_attr_get<uint8_t>(vertex, ss->attrs.topology_island_key);
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -6401,8 +6401,8 @@ void SCULPT_topology_islands_ensure(Object *ob)
|
|||
PBVHVertRef vertex2 = stack.pop_last();
|
||||
SculptVertexNeighborIter ni;
|
||||
|
||||
*static_cast<uint8_t *>(
|
||||
SCULPT_vertex_attr_get(vertex2, ss->attrs.topology_island_key)) = island_nr;
|
||||
blender::bke::paint::vertex_attr_set<uint8_t>(
|
||||
vertex2, ss->attrs.topology_island_key, island_nr);
|
||||
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex2, ni) {
|
||||
if (visit.add(ni.vertex) && SCULPT_vertex_any_face_visible_get(ss, ni.vertex)) {
|
||||
|
|
|
@ -266,10 +266,10 @@ static float automasking_view_occlusion_factor(AutomaskingCache *automasking,
|
|||
uchar stroke_id,
|
||||
AutomaskingNodeData * /*automask_data*/)
|
||||
{
|
||||
char f = *(char *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_occlusion);
|
||||
char f = blender::bke::paint::vertex_attr_get<char>(vertex, ss->attrs.automasking_occlusion);
|
||||
|
||||
if (stroke_id != automasking->current_stroke_id) {
|
||||
Hans Goudey
commented
Can this use Same with a few places below. Can this use `vertex_attr_get` instead of `*vertex_attr_ptr`?
Same with a few places below.
|
||||
f = *(char *)SCULPT_vertex_attr_get(
|
||||
f = *blender::bke::paint::vertex_attr_ptr<char>(
|
||||
vertex,
|
||||
ss->attrs.automasking_occlusion) = SCULPT_vertex_is_occluded(ss, vertex, true) ? 2 : 1;
|
||||
}
|
||||
|
@ -284,8 +284,8 @@ static float automasking_factor_end(SculptSession *ss,
|
|||
float value)
|
||||
{
|
||||
if (ss->attrs.automasking_stroke_id) {
|
||||
*(uchar *)SCULPT_vertex_attr_get(
|
||||
vertex, ss->attrs.automasking_stroke_id) = automasking->current_stroke_id;
|
||||
blender::bke::paint::vertex_attr_set<uchar>(
|
||||
vertex, ss->attrs.automasking_stroke_id, automasking->current_stroke_id);
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -445,7 +445,7 @@ static void sculpt_calc_blurred_cavity(SculptSession *ss,
|
|||
|
||||
factor_sum = sculpt_cavity_calc_factor(automasking, factor_sum);
|
||||
|
||||
*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_cavity) = factor_sum;
|
||||
blender::bke::paint::vertex_attr_set<float>(vertex, ss->attrs.automasking_cavity, factor_sum);
|
||||
}
|
||||
|
||||
int SCULPT_automasking_settings_hash(Object *ob, AutomaskingCache *automasking)
|
||||
|
@ -499,13 +499,14 @@ static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
|
|||
SculptSession *ss,
|
||||
PBVHVertRef vertex)
|
||||
{
|
||||
uchar stroke_id = *(uchar *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_stroke_id);
|
||||
uchar stroke_id = blender::bke::paint::vertex_attr_get<uchar>(vertex,
|
||||
ss->attrs.automasking_stroke_id);
|
||||
|
||||
if (stroke_id != automasking->current_stroke_id) {
|
||||
sculpt_calc_blurred_cavity(ss, automasking, automasking->settings.cavity_blur_steps, vertex);
|
||||
}
|
||||
|
||||
float factor = *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_cavity);
|
||||
float factor = blender::bke::paint::vertex_attr_get<float>(vertex, ss->attrs.automasking_cavity);
|
||||
bool inverted = automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_INVERTED;
|
||||
|
||||
if ((automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) &&
|
||||
|
@ -542,7 +543,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 (ss->attrs.automasking_factor) {
|
||||
float factor = *(float *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_factor);
|
||||
float factor = blender::bke::paint::vertex_attr_get<float>(vert, ss->attrs.automasking_factor);
|
||||
|
||||
if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
|
||||
factor *= sculpt_automasking_cavity_factor(automasking, ss, vert);
|
||||
|
@ -551,9 +552,9 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
|||
return automasking_factor_end(ss, automasking, vert, factor * mask);
|
||||
}
|
||||
|
||||
uchar stroke_id = ss->attrs.automasking_stroke_id ?
|
||||
*(uchar *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_stroke_id) :
|
||||
-1;
|
||||
uchar stroke_id = ss->attrs.automasking_stroke_id ? blender::bke::paint::vertex_attr_get<uchar>(
|
||||
vert, ss->attrs.automasking_stroke_id) :
|
||||
-1;
|
||||
|
||||
bool do_occlusion = (automasking->settings.flags &
|
||||
(BRUSH_AUTOMASKING_VIEW_OCCLUSION | BRUSH_AUTOMASKING_VIEW_NORMAL)) ==
|
||||
|
@ -627,8 +628,8 @@ static bool automask_floodfill_cb(
|
|||
{
|
||||
AutomaskFloodFillData *data = (AutomaskFloodFillData *)userdata;
|
||||
|
||||
*(float *)SCULPT_vertex_attr_get(to_v, ss->attrs.automasking_factor) = 1.0f;
|
||||
*(float *)SCULPT_vertex_attr_get(from_v, ss->attrs.automasking_factor) = 1.0f;
|
||||
blender::bke::paint::vertex_attr_set<float>(to_v, ss->attrs.automasking_factor, 1.0f);
|
||||
blender::bke::paint::vertex_attr_set<float>(from_v, ss->attrs.automasking_factor, 1.0f);
|
||||
return (!data->use_radius ||
|
||||
SCULPT_is_vertex_inside_brush_radius_symm(
|
||||
SCULPT_vertex_co_get(ss, to_v), data->location, data->radius, data->symm));
|
||||
|
@ -648,7 +649,7 @@ static void SCULPT_topology_automasking_init(Sculpt *sd, Object *ob)
|
|||
for (int i : IndexRange(totvert)) {
|
||||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
(*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor)) = 0.0f;
|
||||
blender::bke::paint::vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, 0.0f);
|
||||
}
|
||||
|
||||
/* Flood fill automask to connected vertices. Limited to vertices inside
|
||||
|
@ -689,7 +690,7 @@ static void sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob)
|
|||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
if (!SCULPT_vertex_has_face_set(ss, vertex, active_face_set)) {
|
||||
*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = 0.0f;
|
||||
blender::bke::paint::vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -754,7 +755,7 @@ static 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_vertex_attr_get(
|
||||
*blender::bke::paint::vertex_attr_ptr<float>(
|
||||
vertex, ss->attrs.automasking_factor) *= (1.0f - edge_boundary_automask);
|
||||
}
|
||||
|
||||
|
@ -800,7 +801,7 @@ static void sculpt_normal_occlusion_automasking_fill(AutomaskingCache *automaski
|
|||
for (int i = 0; i < totvert; i++) {
|
||||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
float f = *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor);
|
||||
float f = blender::bke::paint::vertex_attr_get<float>(vertex, ss->attrs.automasking_factor);
|
||||
|
||||
if (int(mode) & BRUSH_AUTOMASKING_VIEW_NORMAL) {
|
||||
if (int(mode) & BRUSH_AUTOMASKING_VIEW_OCCLUSION) {
|
||||
|
@ -811,10 +812,11 @@ static void sculpt_normal_occlusion_automasking_fill(AutomaskingCache *automaski
|
|||
}
|
||||
|
||||
if (ss->attrs.automasking_stroke_id) {
|
||||
*(uchar *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_stroke_id) = ss->stroke_id;
|
||||
blender::bke::paint::vertex_attr_set<uchar>(
|
||||
vertex, ss->attrs.automasking_stroke_id, ss->stroke_id);
|
||||
}
|
||||
|
||||
*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = f;
|
||||
blender::bke::paint::vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,7 +938,8 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
|
|||
for (int i : IndexRange(totvert)) {
|
||||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
(*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor)) = initial_value;
|
||||
blender::bke::paint::vertex_attr_set<float>(
|
||||
vertex, ss->attrs.automasking_factor, initial_value);
|
||||
}
|
||||
|
||||
const int boundary_propagation_steps = brush ?
|
||||
|
|
|
@ -1550,7 +1550,8 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
|
|||
const int vi = vd.index;
|
||||
float *disp_factor;
|
||||
if (use_persistent_base) {
|
||||
disp_factor = (float *)SCULPT_vertex_attr_get(vd.vertex, ss->attrs.persistent_disp);
|
||||
disp_factor = blender::bke::paint::vertex_attr_ptr<float>(vd.vertex,
|
||||
ss->attrs.persistent_disp);
|
||||
}
|
||||
else {
|
||||
disp_factor = &ss->cache->layer_displacement_factor[vi];
|
||||
|
|
|
@ -1913,8 +1913,3 @@ void SCULPT_topology_islands_invalidate(SculptSession *ss);
|
|||
int SCULPT_vertex_island_get(SculptSession *ss, PBVHVertRef vertex);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* Make SCULPT_ alias to a few blenkernel sculpt methods. */
|
||||
|
||||
#define SCULPT_vertex_attr_get BKE_sculpt_vertex_attr_get
|
||||
#define SCULPT_face_attr_get BKE_sculpt_face_attr_get
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "BLI_ghash.h"
|
||||
#include "BLI_gsqueue.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -71,6 +72,8 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using blender::float3;
|
||||
|
||||
/* Reset the copy of the mesh that is being sculpted on (currently just for the layer brush). */
|
||||
|
||||
static int sculpt_set_persistent_base_exec(bContext *C, wmOperator * /*op*/)
|
||||
|
@ -101,11 +104,11 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator * /*op*/)
|
|||
for (int i = 0; i < totvert; i++) {
|
||||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
copy_v3_v3((float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_co),
|
||||
SCULPT_vertex_co_get(ss, vertex));
|
||||
blender::bke::paint::vertex_attr_set<float3>(
|
||||
vertex, ss->attrs.persistent_co, SCULPT_vertex_co_get(ss, vertex));
|
||||
SCULPT_vertex_normal_get(
|
||||
ss, vertex, (float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_no));
|
||||
(*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_disp)) = 0.0f;
|
||||
ss, vertex, blender::bke::paint::vertex_attr_ptr<float>(vertex, ss->attrs.persistent_no));
|
||||
blender::bke::paint::vertex_attr_set<float>(vertex, ss->attrs.persistent_disp, 0.0f);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
Loading…
Reference in New Issue
I think it might be clearer to avoid
Tptr
and just useT *
in the code below.