Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc')
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc393
1 files changed, 216 insertions, 177 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
index 6a47aceb2b0..bd015784ad7 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
@@ -12,11 +12,15 @@
#include "DNA_scene_types.h"
#include "BLI_array.hh"
+#include "BLI_index_mask_ops.hh"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
+#include "BLI_vector.hh"
+#include "BKE_attribute_math.hh"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_geometry_set.hh"
#include "BKE_mesh.h"
#include "DEG_depsgraph.h"
@@ -32,6 +36,10 @@
#include "paint_intern.h" /* own include */
using blender::Array;
+using blender::ColorGeometry4f;
+using blender::GMutableSpan;
+using blender::IndexMask;
+using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name Internal Utility Functions
@@ -62,34 +70,57 @@ static void tag_object_after_update(Object *object)
static bool vertex_paint_from_weight(Object *ob)
{
- Mesh *me;
- const MPoly *mp;
- int vgroup_active;
+ using namespace blender;
+ Mesh *me;
if (((me = BKE_mesh_from_object(ob)) == nullptr ||
(ED_mesh_color_ensure(me, nullptr)) == false)) {
return false;
}
- /* TODO: respect selection. */
- /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway. */
- mp = me->mpoly;
- vgroup_active = me->vertex_group_active_index - 1;
- for (int i = 0; i < me->totpoly; i++, mp++) {
- MLoopCol *lcol = &me->mloopcol[mp->loopstart];
- uint j = 0;
- do {
- uint vidx = me->mloop[mp->loopstart + j].v;
- const float weight = BKE_defvert_find_weight(&me->dvert[vidx], vgroup_active);
- const uchar grayscale = weight * 255;
- lcol->r = grayscale;
- lcol->b = grayscale;
- lcol->g = grayscale;
- lcol++;
- j++;
- } while (j < mp->totloop);
+ const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id);
+ if (active_color_layer == nullptr) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ const int active_vertex_group_index = me->vertex_group_active_index - 1;
+ const bDeformGroup *deform_group = static_cast<const bDeformGroup *>(
+ BLI_findlink(&me->vertex_group_names, active_vertex_group_index));
+ if (deform_group == nullptr) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ MeshComponent component;
+ component.replace(me, GeometryOwnershipType::Editable);
+
+ bke::WriteAttributeLookup color_attribute = component.attribute_try_get_for_write(
+ active_color_layer->name);
+ if (!color_attribute) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ /* Retrieve the vertex group with the domain and type of the existing color
+ * attribute, in order to let the attribute API handle both conversions. */
+ const GVArray vertex_group = component.attribute_get_for_read(
+ deform_group->name,
+ ATTR_DOMAIN_POINT,
+ bke::cpp_type_to_custom_data_type(color_attribute.varray.type()));
+ if (!vertex_group) {
+ BLI_assert_unreachable();
+ return false;
}
+ GVArray_GSpan interpolated{component.attribute_try_adapt_domain(
+ vertex_group, ATTR_DOMAIN_POINT, color_attribute.domain)};
+
+ color_attribute.varray.set_all(interpolated.data());
+
+ if (color_attribute.tag_modified_fn) {
+ color_attribute.tag_modified_fn();
+ }
tag_object_after_update(ob);
return true;
@@ -128,99 +159,81 @@ void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
/** \name Smooth Vertex Colors Operator
* \{ */
-static void vertex_color_smooth_looptag(Mesh *me, const bool *mlooptag)
+static IndexMask get_selected_indices(const Mesh &mesh,
+ const eAttrDomain domain,
+ Vector<int64_t> &indices)
{
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const MPoly *mp;
- bool has_shared = false;
+ using namespace blender;
+ Span<MVert> verts(mesh.mvert, mesh.totvert);
+ Span<MPoly> faces(mesh.mpoly, mesh.totpoly);
+
+ MeshComponent component;
+ component.replace(&const_cast<Mesh &>(mesh), GeometryOwnershipType::ReadOnly);
+
+ if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) {
+ const VArray<bool> selection = component.attribute_try_adapt_domain(
+ VArray<bool>::ForFunc(faces.size(),
+ [&](const int i) { return faces[i].flag & ME_FACE_SEL; }),
+ ATTR_DOMAIN_FACE,
+ domain);
+
+ return index_mask_ops::find_indices_based_on_predicate(
+ IndexMask(component.attribute_domain_num(domain)), 4096, indices, [&](const int i) {
+ return selection[i];
+ });
+ }
+ if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) {
+ const VArray<bool> selection = component.attribute_try_adapt_domain(
+ VArray<bool>::ForFunc(verts.size(), [&](const int i) { return verts[i].flag & SELECT; }),
+ ATTR_DOMAIN_POINT,
+ domain);
+
+ return index_mask_ops::find_indices_based_on_predicate(
+ IndexMask(component.attribute_domain_num(domain)), 4096, indices, [&](const int i) {
+ return selection[i];
+ });
+ }
+ return IndexMask(component.attribute_domain_num(domain));
+}
- if (me->mloopcol == nullptr || me->totvert == 0 || me->totpoly == 0) {
+static void face_corner_color_equalize_vertices(Mesh &mesh, const IndexMask selection)
+{
+ using namespace blender;
+
+ const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id);
+ if (active_color_layer == nullptr) {
+ BLI_assert_unreachable();
return;
}
- int(*scol)[4] = static_cast<int(*)[4]>(MEM_callocN(sizeof(int) * me->totvert * 5, "scol"));
-
- int i;
- for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
- if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
- const MLoop *ml = me->mloop + mp->loopstart;
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
- for (int j = 0; j < mp->totloop; j++, ml++, lcol++) {
- scol[ml->v][0] += lcol->r;
- scol[ml->v][1] += lcol->g;
- scol[ml->v][2] += lcol->b;
- scol[ml->v][3] += 1;
- has_shared = 1;
- }
- }
+ MeshComponent component;
+ component.replace(&mesh, GeometryOwnershipType::Editable);
+
+ if (component.attribute_get_meta_data(active_color_layer->name)->domain == ATTR_DOMAIN_POINT) {
+ return;
}
- if (has_shared) {
- for (i = 0; i < me->totvert; i++) {
- if (scol[i][3] != 0) {
- scol[i][0] = divide_round_i(scol[i][0], scol[i][3]);
- scol[i][1] = divide_round_i(scol[i][1], scol[i][3]);
- scol[i][2] = divide_round_i(scol[i][2], scol[i][3]);
- }
- }
+ GVArray color_attribute_point = component.attribute_try_get_for_read(active_color_layer->name,
+ ATTR_DOMAIN_POINT);
- for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
- if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
- const MLoop *ml = me->mloop + mp->loopstart;
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
- for (int j = 0; j < mp->totloop; j++, ml++, lcol++) {
- if (mlooptag[mp->loopstart + j]) {
- lcol->r = scol[ml->v][0];
- lcol->g = scol[ml->v][1];
- lcol->b = scol[ml->v][2];
- }
- }
- }
- }
- }
+ GVArray color_attribute_corner = component.attribute_try_adapt_domain(
+ color_attribute_point, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER);
- MEM_freeN(scol);
+ color_attribute_corner.materialize(selection, active_color_layer->data);
}
static bool vertex_color_smooth(Object *ob)
{
Mesh *me;
- const MPoly *mp;
- int i, j;
-
if (((me = BKE_mesh_from_object(ob)) == nullptr) ||
(ED_mesh_color_ensure(me, nullptr) == false)) {
return false;
}
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-
- Array<bool> loop_tag(me->totloop, false);
-
- /* simply tag loops of selected faces */
- mp = me->mpoly;
- for (i = 0; i < me->totpoly; i++, mp++) {
- const MLoop *ml = me->mloop + mp->loopstart;
-
- if (use_face_sel && !(mp->flag & ME_FACE_SEL)) {
- continue;
- }
-
- j = 0;
- do {
- if (!(use_vert_sel && !(me->mvert[ml->v].flag & SELECT))) {
- loop_tag[mp->loopstart + j] = true;
- }
- ml++;
- j++;
- } while (j < mp->totloop);
- }
-
- /* remove stale me->mcol, will be added later */
- BKE_mesh_tessface_clear(me);
+ Vector<int64_t> indices;
+ const IndexMask selection = get_selected_indices(*me, ATTR_DOMAIN_CORNER, indices);
- vertex_color_smooth_looptag(me, loop_tag.data());
+ face_corner_color_equalize_vertices(*me, selection);
tag_object_after_update(ob);
@@ -258,22 +271,52 @@ void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
/** \name Vertex Color Transformation Operators
* \{ */
-struct VPaintTx_BrightContrastData {
- /* pre-calculated */
- float gain;
- float offset;
-};
-
-static void vpaint_tx_brightness_contrast(const float col[3],
- const void *user_data,
- float r_col[3])
+template<typename TransformFn>
+static bool transform_active_color(Mesh &mesh, const TransformFn &transform_fn)
{
- const VPaintTx_BrightContrastData *data = static_cast<const VPaintTx_BrightContrastData *>(
- user_data);
+ using namespace blender;
- for (int i = 0; i < 3; i++) {
- r_col[i] = data->gain * col[i] + data->offset;
+ const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id);
+ if (active_color_layer == nullptr) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ MeshComponent component;
+ component.replace(&mesh, GeometryOwnershipType::Editable);
+
+ bke::WriteAttributeLookup color_attribute = component.attribute_try_get_for_write(
+ active_color_layer->name);
+ if (!color_attribute) {
+ BLI_assert_unreachable();
+ return false;
}
+
+ Vector<int64_t> indices;
+ const IndexMask selection = get_selected_indices(mesh, color_attribute.domain, indices);
+
+ attribute_math::convert_to_static_type(color_attribute.varray.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ threading::parallel_for(selection.index_range(), 1024, [&](IndexRange range) {
+ for (const int i : selection.slice(range)) {
+ if constexpr (std::is_same_v<T, ColorGeometry4f>) {
+ ColorGeometry4f color = color_attribute.varray.get<ColorGeometry4f>(i);
+ transform_fn(color);
+ color_attribute.varray.set_by_copy(i, &color);
+ }
+ else if constexpr (std::is_same_v<T, ColorGeometry4b>) {
+ ColorGeometry4f color = color_attribute.varray.get<ColorGeometry4b>(i).decode();
+ transform_fn(color);
+ ColorGeometry4b color_encoded = color.encode();
+ color_attribute.varray.set_by_copy(i, &color_encoded);
+ }
+ }
+ });
+ });
+
+ DEG_id_tag_update(&mesh.id, 0);
+
+ return true;
}
static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
@@ -303,15 +346,20 @@ static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
}
}
- VPaintTx_BrightContrastData user_data{};
- user_data.gain = gain;
- user_data.offset = offset;
-
- if (ED_vpaint_color_transform(obact, vpaint_tx_brightness_contrast, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ for (int i = 0; i < 3; i++) {
+ color[i] = gain * color[i] + offset;
+ }
+ });
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
@@ -337,45 +385,39 @@ void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
RNA_def_property_ui_range(prop, min, max, 1, 1);
}
-struct VPaintTx_HueSatData {
- float hue;
- float sat;
- float val;
-};
-
-static void vpaint_tx_hsv(const float col[3], const void *user_data, float r_col[3])
+static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
{
- const VPaintTx_HueSatData *data = static_cast<const VPaintTx_HueSatData *>(user_data);
- float hsv[3];
- rgb_to_hsv_v(col, hsv);
+ Object *obact = CTX_data_active_object(C);
- hsv[0] += (data->hue - 0.5f);
- if (hsv[0] > 1.0f) {
- hsv[0] -= 1.0f;
- }
- else if (hsv[0] < 0.0f) {
- hsv[0] += 1.0f;
+ const float hue = RNA_float_get(op->ptr, "h");
+ const float sat = RNA_float_get(op->ptr, "s");
+ const float val = RNA_float_get(op->ptr, "v");
+
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- hsv[1] *= data->sat;
- hsv[2] *= data->val;
- hsv_to_rgb_v(hsv, r_col);
-}
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ float hsv[3];
+ rgb_to_hsv_v(color, hsv);
-static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
-{
- Object *obact = CTX_data_active_object(C);
+ hsv[0] += (hue - 0.5f);
+ if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+ else if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ hsv[1] *= sat;
+ hsv[2] *= val;
- VPaintTx_HueSatData user_data{};
- user_data.hue = RNA_float_get(op->ptr, "h");
- user_data.sat = RNA_float_get(op->ptr, "s");
- user_data.val = RNA_float_get(op->ptr, "v");
+ hsv_to_rgb_v(hsv, color);
+ });
- if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
@@ -398,22 +440,24 @@ void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
}
-static void vpaint_tx_invert(const float col[3], const void *UNUSED(user_data), float r_col[3])
-{
- for (int i = 0; i < 3; i++) {
- r_col[i] = 1.0f - col[i];
- }
-}
-
static int vertex_color_invert_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obact = CTX_data_active_object(C);
- if (ED_vpaint_color_transform(obact, vpaint_tx_invert, nullptr)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ for (int i = 0; i < 3; i++) {
+ color[i] = 1.0f - color[i];
+ }
+ });
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
@@ -431,32 +475,27 @@ void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct VPaintTx_LevelsData {
- float gain;
- float offset;
-};
-
-static void vpaint_tx_levels(const float col[3], const void *user_data, float r_col[3])
-{
- const VPaintTx_LevelsData *data = static_cast<const VPaintTx_LevelsData *>(user_data);
- for (int i = 0; i < 3; i++) {
- r_col[i] = data->gain * (col[i] + data->offset);
- }
-}
-
static int vertex_color_levels_exec(bContext *C, wmOperator *op)
{
Object *obact = CTX_data_active_object(C);
- VPaintTx_LevelsData user_data{};
- user_data.gain = RNA_float_get(op->ptr, "gain");
- user_data.offset = RNA_float_get(op->ptr, "offset");
+ const float gain = RNA_float_get(op->ptr, "gain");
+ const float offset = RNA_float_get(op->ptr, "offset");
- if (ED_vpaint_color_transform(obact, vpaint_tx_levels, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ for (int i = 0; i < 3; i++) {
+ color[i] = gain * (color[i] + offset);
+ }
+ });
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_levels(wmOperatorType *ot)