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_image_2d_curve_mask.cc')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc149
1 files changed, 149 insertions, 0 deletions
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);
+}
+