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:
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c103
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc149
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h41
4 files changed, 195 insertions, 99 deletions
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 3b668a1bd4c..b826ff8701d 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
paint_hide.c
paint_image.c
paint_image_2d.c
+ paint_image_2d_curve_mask.cc
paint_image_proj.c
paint_mask.c
paint_ops.c
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 318180e5eb4..7191431cf4c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -78,12 +78,13 @@ typedef struct BrushPainterCache {
ImBuf *ibuf;
ImBuf *texibuf;
- ushort *curve_mask;
ushort *tex_mask;
ushort *tex_mask_old;
uint tex_mask_old_w;
uint tex_mask_old_h;
+ CurveMaskCache curve_mask_cache;
+
int image_size[2];
} BrushPainterCache;
@@ -169,9 +170,6 @@ static void brush_painter_2d_require_imbuf(
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
}
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- }
if (cache->tex_mask) {
MEM_freeN(cache->tex_mask);
}
@@ -179,7 +177,6 @@ static void brush_painter_2d_require_imbuf(
MEM_freeN(cache->tex_mask_old);
}
cache->ibuf = NULL;
- cache->curve_mask = NULL;
cache->tex_mask = NULL;
cache->lastdiameter = -1; /* force ibuf create in refresh */
cache->invert = invert;
@@ -200,9 +197,7 @@ static void brush_painter_cache_2d_free(BrushPainterCache *cache)
if (cache->texibuf) {
IMB_freeImBuf(cache->texibuf);
}
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- }
+ paint_curve_mask_cache_free_data(&cache->curve_mask_cache);
if (cache->tex_mask) {
MEM_freeN(cache->tex_mask);
}
@@ -380,92 +375,6 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
cache->tex_mask_old_h = diameter;
}
-/* create a mask with the falloff strength */
-static ushort *brush_painter_curve_mask_init(
- ushort *mask, BrushPainter *painter, int diameter, float radius, const float pos[2])
-{
- BLI_assert_msg(MEM_allocN_len(mask) == diameter * diameter * sizeof(ushort),
- "Allocated size of mask doesn't match.");
-
- Brush *brush = painter->brush;
-
- int offset = (int)floorf(diameter / 2.0f);
-
- ushort *m;
- m = mask;
-
- int aa_samples = 1.0f / (radius * 0.20f);
- if (brush->sampling_flag & BRUSH_PAINT_ANTIALIASING) {
- aa_samples = clamp_i(aa_samples, 3, 16);
- }
- else {
- aa_samples = 1;
- }
-
- /* Temporal until we have the brush properties */
- const float hardness = 1.0f;
- const float rotation = 0.0f;
-
- float aa_offset = 1.0f / (2.0f * (float)aa_samples);
- float aa_step = 1.0f / (float)aa_samples;
-
- float bpos[2];
- bpos[0] = pos[0] - floorf(pos[0]) + offset - aa_offset;
- bpos[1] = pos[1] - floorf(pos[1]) + offset - aa_offset;
-
- const float co = cosf(DEG2RADF(rotation));
- const float si = sinf(DEG2RADF(rotation));
-
- float norm_factor = 65535.0f / (float)(aa_samples * aa_samples);
-
- for (int y = 0; y < diameter; y++) {
- for (int x = 0; x < diameter; x++, m++) {
- float total_samples = 0;
- for (int i = 0; i < aa_samples; i++) {
- for (int j = 0; j < aa_samples; j++) {
- float pixel_xy[2] = {x + (aa_step * i), y + (aa_step * j)};
- float xy_rot[2];
- sub_v2_v2(pixel_xy, bpos);
-
- xy_rot[0] = co * pixel_xy[0] - si * pixel_xy[1];
- xy_rot[1] = si * pixel_xy[0] + co * pixel_xy[1];
-
- float len = len_v2(xy_rot);
- float p = len / radius;
- if (hardness < 1.0f) {
- p = (p - hardness) / (1.0f - hardness);
- p = 1.0f - p;
- CLAMP(p, 0.0f, 1.0f);
- }
- else {
- p = 1.0;
- }
- float hardness_factor = 3.0f * p * p - 2.0f * p * p * p;
- float curve = BKE_brush_curve_strength_clamped(brush, len, radius);
- total_samples += curve * hardness_factor;
- }
- }
- *m = (ushort)(total_samples * norm_factor);
- }
- }
-
- return mask;
-}
-
-static void brush_painter_curve_mask_refresh(
- BrushPainter *painter, ImagePaintTile *tile, int diameter, float radius, const float pos[2])
-{
- BrushPainterCache *cache = &tile->cache;
-
- if (diameter != cache->lastdiameter) {
- if (cache->curve_mask != NULL) {
- MEM_freeN(cache->curve_mask);
- }
- cache->curve_mask = MEM_mallocN(sizeof(ushort) * diameter * diameter, "brush_painter_mask");
- }
- brush_painter_curve_mask_init(cache->curve_mask, painter, diameter, radius, pos);
-}
-
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(
BrushPainter *painter, ImagePaintTile *tile, const int size, float pressure, float distance)
@@ -872,7 +781,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
}
/* Re-initialize the curve mask. Mask is always recreated due to the change of position. */
- brush_painter_curve_mask_refresh(painter, tile, diameter, size, pos);
+ paint_curve_mask_cache_update(&cache->curve_mask_cache, brush, diameter, size, pos);
/* detect if we need to recreate image brush buffer */
if (diameter != cache->lastdiameter || (tex_rotation != cache->last_tex_rotation) || do_random ||
@@ -1336,7 +1245,7 @@ static void paint_2d_do_making_brush(ImagePaintState *s,
&tmpbuf,
frombuf,
mask,
- tile->cache.curve_mask,
+ tile->cache.curve_mask_cache.curve_mask,
tile->cache.tex_mask,
mask_max,
region->destx,
@@ -1485,7 +1394,7 @@ static int paint_2d_op(void *state,
canvas,
frombuf,
NULL,
- tile->cache.curve_mask,
+ tile->cache.curve_mask_cache.curve_mask,
tile->cache.tex_mask,
mask_max,
region[a].destx,
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
new file mode 100644
index 00000000000..639dfcdae72
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
@@ -0,0 +1,149 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup ed
+ */
+
+#include "BLI_math.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+
+#include "BKE_brush.h"
+
+#include "paint_intern.h"
+
+namespace blender::ed::sculpt_paint {
+
+/* create a mask with the falloff strength */
+static void update_curve_mask(CurveMaskCache *curve_mask_cache,
+ const Brush *brush,
+ const int diameter,
+ const float radius,
+ const float cursor_position[2])
+{
+ BLI_assert(curve_mask_cache->curve_mask != nullptr);
+ int offset = (int)floorf(diameter / 2.0f);
+
+ unsigned short *m = curve_mask_cache->curve_mask;
+
+ int aa_samples = 1.0f / (radius * 0.20f);
+ if (brush->sampling_flag & BRUSH_PAINT_ANTIALIASING) {
+ aa_samples = clamp_i(aa_samples, 3, 16);
+ }
+ else {
+ aa_samples = 1;
+ }
+
+ /* Temporal until we have the brush properties */
+ const float hardness = 1.0f;
+ const float rotation = 0.0f;
+
+ float aa_offset = 1.0f / (2.0f * (float)aa_samples);
+ float aa_step = 1.0f / (float)aa_samples;
+
+ float bpos[2];
+ bpos[0] = cursor_position[0] - floorf(cursor_position[0]) + offset - aa_offset;
+ bpos[1] = cursor_position[1] - floorf(cursor_position[1]) + offset - aa_offset;
+
+ const float co = cosf(DEG2RADF(rotation));
+ const float si = sinf(DEG2RADF(rotation));
+
+ float norm_factor = 65535.0f / (float)(aa_samples * aa_samples);
+
+ for (int y = 0; y < diameter; y++) {
+ for (int x = 0; x < diameter; x++, m++) {
+ float total_samples = 0;
+ for (int i = 0; i < aa_samples; i++) {
+ for (int j = 0; j < aa_samples; j++) {
+ float pixel_xy[2] = {x + (aa_step * i), y + (aa_step * j)};
+ float xy_rot[2];
+ sub_v2_v2(pixel_xy, bpos);
+
+ xy_rot[0] = co * pixel_xy[0] - si * pixel_xy[1];
+ xy_rot[1] = si * pixel_xy[0] + co * pixel_xy[1];
+
+ float len = len_v2(xy_rot);
+ float p = len / radius;
+ if (hardness < 1.0f) {
+ p = (p - hardness) / (1.0f - hardness);
+ p = 1.0f - p;
+ CLAMP(p, 0.0f, 1.0f);
+ }
+ else {
+ p = 1.0;
+ }
+ float hardness_factor = 3.0f * p * p - 2.0f * p * p * p;
+ float curve = BKE_brush_curve_strength_clamped(brush, len, radius);
+ total_samples += curve * hardness_factor;
+ }
+ }
+ *m = (unsigned short)(total_samples * norm_factor);
+ }
+ }
+}
+
+static size_t diameter_to_curve_mask_size(const int diameter)
+{
+ return diameter * diameter * sizeof(ushort);
+}
+
+static bool is_curve_mask_size_valid(const CurveMaskCache *curve_mask_cache, const int diameter)
+{
+ return curve_mask_cache->curve_mask_size == diameter_to_curve_mask_size(diameter);
+}
+
+static void curve_mask_free(CurveMaskCache *curve_mask_cache)
+{
+ curve_mask_cache->curve_mask_size = 0;
+ MEM_SAFE_FREE(curve_mask_cache->curve_mask);
+}
+
+static void curve_mask_allocate(CurveMaskCache *curve_mask_cache, const int diameter)
+{
+ const size_t curve_mask_size = diameter_to_curve_mask_size(diameter);
+ curve_mask_cache->curve_mask = static_cast<unsigned short *>(
+ MEM_mallocN(curve_mask_size, __func__));
+ curve_mask_cache->curve_mask_size = curve_mask_size;
+}
+
+} // namespace blender::ed::sculpt_paint
+
+using namespace blender::ed::sculpt_paint;
+
+void paint_curve_mask_cache_free_data(CurveMaskCache *curve_mask_cache)
+{
+ curve_mask_free(curve_mask_cache);
+}
+
+void paint_curve_mask_cache_update(CurveMaskCache *curve_mask_cache,
+ const Brush *brush,
+ const int diameter,
+ const float radius,
+ const float cursor_position[2])
+{
+ if (!is_curve_mask_size_valid(curve_mask_cache, diameter)) {
+ curve_mask_free(curve_mask_cache);
+ curve_mask_allocate(curve_mask_cache, diameter);
+ }
+ update_curve_mask(curve_mask_cache, brush, diameter, radius, cursor_position);
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 7341d984c91..13ae2b34860 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -23,6 +23,13 @@
#pragma once
+#include "BKE_paint.h"
+#include "DNA_scene_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct Brush;
struct ColorManagedDisplay;
@@ -43,8 +50,6 @@ struct wmEvent;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
-enum ePaintMode;
-enum ePaintSymmetryFlags;
typedef struct CoNo {
float co[3];
@@ -245,6 +250,33 @@ void PAINT_OT_add_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
void PAINT_OT_add_simple_uvs(struct wmOperatorType *ot);
+/* paint_image_2d_curve_mask.cc */
+/**
+ * \brief Caching structure for curve mask.
+ *
+ * When 2d painting images the curve mask is used as an input.
+ */
+typedef struct CurveMaskCache {
+ /**
+ * \brief Size in bytes of the curve_mask field.
+ *
+ * Used to determine if the curve_mask needs to be re-allocated.
+ */
+ size_t curve_mask_size;
+
+ /**
+ * \brief Curve mask that can be passed as curve_mask parameter when.
+ */
+ ushort *curve_mask;
+} CurveMaskCache;
+
+void paint_curve_mask_cache_free_data(CurveMaskCache *curve_mask_cache);
+void paint_curve_mask_cache_update(CurveMaskCache *curve_mask_cache,
+ const struct Brush *brush,
+ const int diameter,
+ const float radius,
+ const float cursor_position[2]);
+
/* sculpt_uv.c */
void SCULPT_OT_uv_sculpt_stroke(struct wmOperatorType *ot);
@@ -366,3 +398,8 @@ void paint_delete_blur_kernel(BlurKernel *);
/* paint curve defines */
#define PAINT_CURVE_NUM_SEGMENTS 40
+
+#ifdef __cplusplus
+}
+#endif
+