Sculpt: cleanup sculpt attribute API
* `BKE_sculpt_vertex_attr_get` (and it's alias `SCULPT_vertex_attr_get`) is now `blender::bke::paint::vertex_attr_ptr`. Same for the face versions of those functions. The SCULPT_XXX aliases are removed. * Removed code duplication; `[vertex/face]_attr_ptr` now just calls a generic template (`elem_attr_ptr`). * Added `[vertex/face]_attr_get` and `[vertex/face]_attr_set` functions to get/set attribute data without pointer wrangling. * Given the unwieldly length of `blender::bke::paint::` it's recommended to do a `using blender::bke::paint;` at the top of sculpt files. Example: `float w = vertex_attr_get<float>(vertex, ss->attrs.automasking_factor);`
This commit is contained in:
@@ -799,48 +799,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 +901,84 @@ struct CurveMapping *BKE_sculpt_default_cavity_curve(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace blender::bke::paint {
|
||||
|
||||
/* Base implementation for vertex_attr_*** and face_attr_*** methods.
|
||||
* Returns a pointer to the attribute data (as defined by attr) for elem.
|
||||
*/
|
||||
template<typename Tptr, typename ElemRef = PBVHVertRef>
|
||||
static Tptr 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<Tptr>(ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a pointer to attribute data at vertex.
|
||||
*
|
||||
* Example: float *persistent_co = vertex_attr_ptr<float*>(vertex, ss->attrs.persistent_co);
|
||||
*/
|
||||
template<typename Tptr>
|
||||
static Tptr vertex_attr_ptr(const PBVHVertRef vertex, const SculptAttribute *attr)
|
||||
{
|
||||
return elem_attr_ptr<Tptr, 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 Tptr>
|
||||
static Tptr face_attr_ptr(const PBVHVertRef face, const SculptAttribute *attr)
|
||||
{
|
||||
return elem_attr_ptr<Tptr, 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
|
||||
|
@@ -81,6 +81,8 @@ using blender::MutableSpan;
|
||||
using blender::Set;
|
||||
using blender::Vector;
|
||||
|
||||
using namespace blender::bke::paint;
|
||||
|
||||
static float sculpt_calc_radius(ViewContext *vc,
|
||||
const Brush *brush,
|
||||
const Scene *scene,
|
||||
@@ -209,7 +211,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 vertex_attr_ptr<const float *>(vertex, ss->attrs.persistent_co);
|
||||
}
|
||||
|
||||
return SCULPT_vertex_co_get(ss, vertex);
|
||||
@@ -257,7 +259,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, vertex_attr_ptr<float *>(vertex, ss->attrs.persistent_no));
|
||||
return;
|
||||
}
|
||||
SCULPT_vertex_normal_get(ss, vertex, no);
|
||||
@@ -6385,7 +6387,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 vertex_attr_get<uint8_t>(vertex, ss->attrs.topology_island_key);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -6432,8 +6434,7 @@ 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;
|
||||
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)) {
|
||||
|
@@ -56,6 +56,7 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::Set;
|
||||
using blender::Vector;
|
||||
using namespace blender::bke::paint;
|
||||
|
||||
AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
|
||||
{
|
||||
@@ -264,10 +265,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 = vertex_attr_get<char>(vertex, ss->attrs.automasking_occlusion);
|
||||
|
||||
if (stroke_id != automasking->current_stroke_id) {
|
||||
f = *(char *)SCULPT_vertex_attr_get(
|
||||
f = *vertex_attr_ptr<char *>(
|
||||
vertex,
|
||||
ss->attrs.automasking_occlusion) = SCULPT_vertex_is_occluded(ss, vertex, true) ? 2 : 1;
|
||||
}
|
||||
@@ -282,8 +283,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;
|
||||
vertex_attr_set<uchar>(
|
||||
vertex, ss->attrs.automasking_stroke_id, automasking->current_stroke_id);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -443,7 +444,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;
|
||||
vertex_attr_set<float>(vertex, ss->attrs.automasking_cavity, factor_sum);
|
||||
}
|
||||
|
||||
int SCULPT_automasking_settings_hash(Object *ob, AutomaskingCache *automasking)
|
||||
@@ -497,13 +498,13 @@ 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 = 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 = 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) &&
|
||||
@@ -538,7 +539,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 = 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);
|
||||
@@ -548,7 +549,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
||||
}
|
||||
|
||||
uchar stroke_id = ss->attrs.automasking_stroke_id ?
|
||||
*(uchar *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_stroke_id) :
|
||||
vertex_attr_get<uchar>(vert, ss->attrs.automasking_stroke_id) :
|
||||
-1;
|
||||
|
||||
bool do_occlusion = (automasking->settings.flags &
|
||||
@@ -620,8 +621,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;
|
||||
vertex_attr_set<float>(to_v, ss->attrs.automasking_factor, 1.0f);
|
||||
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));
|
||||
@@ -641,7 +642,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;
|
||||
vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, 0.0f);
|
||||
}
|
||||
|
||||
/* Flood fill automask to connected vertices. Limited to vertices inside
|
||||
@@ -682,7 +683,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;
|
||||
vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -747,8 +748,8 @@ 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(
|
||||
vertex, ss->attrs.automasking_factor) *= (1.0f - edge_boundary_automask);
|
||||
*vertex_attr_ptr<float *>(vertex,
|
||||
ss->attrs.automasking_factor) *= (1.0f - edge_boundary_automask);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(edge_distance);
|
||||
@@ -793,7 +794,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 = vertex_attr_get<float>(vertex, ss->attrs.automasking_factor);
|
||||
|
||||
if (int(mode) & BRUSH_AUTOMASKING_VIEW_NORMAL) {
|
||||
if (int(mode) & BRUSH_AUTOMASKING_VIEW_OCCLUSION) {
|
||||
@@ -804,10 +805,10 @@ 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;
|
||||
vertex_attr_set<uchar>(vertex, ss->attrs.automasking_stroke_id, ss->stroke_id);
|
||||
}
|
||||
|
||||
*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = f;
|
||||
vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -926,7 +927,7 @@ 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;
|
||||
vertex_attr_set<float>(vertex, ss->attrs.automasking_factor, initial_value);
|
||||
}
|
||||
|
||||
const int boundary_propagation_steps = brush ?
|
||||
|
@@ -39,6 +39,8 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using namespace blender::bke::paint;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name SculptProjectVector
|
||||
*
|
||||
@@ -1543,7 +1545,7 @@ 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 = vertex_attr_ptr<float *>(vd.vertex, ss->attrs.persistent_disp);
|
||||
}
|
||||
else {
|
||||
disp_factor = &ss->cache->layer_displacement_factor[vi];
|
||||
|
@@ -1910,8 +1910,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
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
@@ -71,6 +72,9 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using namespace blender::bke::paint;
|
||||
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 +105,10 @@ 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));
|
||||
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, vertex_attr_ptr<float *>(vertex, ss->attrs.persistent_no));
|
||||
vertex_attr_set<float>(vertex, ss->attrs.persistent_disp, 0.0f);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
Reference in New Issue
Block a user