Blender  V3.3
paint_image_2d_curve_mask.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "BLI_math.h"
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_brush_types.h"
13 
14 #include "BKE_brush.h"
15 
16 #include "paint_intern.h"
17 
18 namespace blender::ed::sculpt_paint {
19 
25 constexpr int CurveSamplesBaseLen = 1024;
33 
34 static int aa_samples_per_texel_axis(const Brush *brush, const float radius)
35 {
36  int aa_samples = 1.0f / (radius * 0.20f);
38  aa_samples = clamp_i(
40  }
41  else {
42  aa_samples = 1;
43  }
44  return aa_samples;
45 }
46 
47 /* create a mask with the falloff strength */
48 static void update_curve_mask(CurveMaskCache *curve_mask_cache,
49  const Brush *brush,
50  const int diameter,
51  const float radius,
52  const float cursor_position[2])
53 {
54  BLI_assert(curve_mask_cache->curve_mask != nullptr);
55  int offset = (int)floorf(diameter / 2.0f);
56  int clamped_radius = max_ff(radius, 1.0);
57 
58  unsigned short *m = curve_mask_cache->curve_mask;
59 
60  const int aa_samples = aa_samples_per_texel_axis(brush, radius);
61  const float aa_offset = 1.0f / (2.0f * (float)aa_samples);
62  const float aa_step = 1.0f / (float)aa_samples;
63 
64  float bpos[2];
65  bpos[0] = cursor_position[0] - floorf(cursor_position[0]) + offset;
66  bpos[1] = cursor_position[1] - floorf(cursor_position[1]) + offset;
67 
68  float weight_factor = 65535.0f / (float)(aa_samples * aa_samples);
69 
70  for (int y = 0; y < diameter; y++) {
71  for (int x = 0; x < diameter; x++, m++) {
72  float pixel_xy[2];
73  pixel_xy[0] = static_cast<float>(x) + aa_offset;
74  float total_weight = 0;
75 
76  for (int i = 0; i < aa_samples; i++) {
77  pixel_xy[1] = static_cast<float>(y) + aa_offset;
78  for (int j = 0; j < aa_samples; j++) {
79  const float len = len_v2v2(pixel_xy, bpos);
80  const int sample_index = min_ii((len / clamped_radius) * CurveSamplesBaseLen,
81  CurveSamplesLen - 1);
82  const float sample_weight = curve_mask_cache->sampled_curve[sample_index];
83 
84  total_weight += sample_weight;
85 
86  pixel_xy[1] += aa_step;
87  }
88  pixel_xy[0] += aa_step;
89  }
90  *m = (unsigned short)(total_weight * weight_factor);
91  }
92  }
93 }
94 
95 static bool is_sampled_curve_valid(const CurveMaskCache *curve_mask_cache, const Brush *brush)
96 {
97  if (curve_mask_cache->sampled_curve == nullptr) {
98  return false;
99  }
100  return curve_mask_cache->last_curve_timestamp == brush->curve->changed_timestamp;
101 }
102 
103 static void sampled_curve_free(CurveMaskCache *curve_mask_cache)
104 {
105  MEM_SAFE_FREE(curve_mask_cache->sampled_curve);
106  curve_mask_cache->last_curve_timestamp = 0;
107 }
108 
109 static void update_sampled_curve(CurveMaskCache *curve_mask_cache, const Brush *brush)
110 {
111  if (curve_mask_cache->sampled_curve == nullptr) {
112  curve_mask_cache->sampled_curve = static_cast<float *>(
113  MEM_mallocN(CurveSamplesLen * sizeof(float), __func__));
114  }
115 
116  for (int i = 0; i < CurveSamplesLen; i++) {
117  const float len = i / float(CurveSamplesBaseLen);
118  const float sample_weight = BKE_brush_curve_strength_clamped(brush, len, 1.0f);
119  curve_mask_cache->sampled_curve[i] = sample_weight;
120  }
121  curve_mask_cache->last_curve_timestamp = brush->curve->changed_timestamp;
122 }
123 
124 static size_t diameter_to_curve_mask_size(const int diameter)
125 {
126  return diameter * diameter * sizeof(ushort);
127 }
128 
129 static bool is_curve_mask_size_valid(const CurveMaskCache *curve_mask_cache, const int diameter)
130 {
131  return curve_mask_cache->curve_mask_size == diameter_to_curve_mask_size(diameter);
132 }
133 
134 static void curve_mask_free(CurveMaskCache *curve_mask_cache)
135 {
136  curve_mask_cache->curve_mask_size = 0;
137  MEM_SAFE_FREE(curve_mask_cache->curve_mask);
138 }
139 
140 static void curve_mask_allocate(CurveMaskCache *curve_mask_cache, const int diameter)
141 {
142  const size_t curve_mask_size = diameter_to_curve_mask_size(diameter);
143  curve_mask_cache->curve_mask = static_cast<unsigned short *>(
144  MEM_mallocN(curve_mask_size, __func__));
145  curve_mask_cache->curve_mask_size = curve_mask_size;
146 }
147 
148 } // namespace blender::ed::sculpt_paint
149 
150 using namespace blender::ed::sculpt_paint;
151 
153 {
154  sampled_curve_free(curve_mask_cache);
155  curve_mask_free(curve_mask_cache);
156 }
157 
159  const Brush *brush,
160  const int diameter,
161  const float radius,
162  const float cursor_position[2])
163 {
164  if (!is_sampled_curve_valid(curve_mask_cache, brush)) {
165  update_sampled_curve(curve_mask_cache, brush);
166  }
167 
168  if (!is_curve_mask_size_valid(curve_mask_cache, diameter)) {
169  curve_mask_free(curve_mask_cache);
170  curve_mask_allocate(curve_mask_cache, diameter);
171  }
172  update_curve_mask(curve_mask_cache, brush, diameter, radius, cursor_position);
173 }
typedef float(TangentPoint)[2]
float BKE_brush_curve_strength_clamped(const struct Brush *br, float p, float len)
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
#define M_SQRT2
Definition: BLI_math_base.h:29
MINLINE int clamp_i(int value, int min, int max)
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
unsigned short ushort
Definition: BLI_sys_types.h:68
@ BRUSH_PAINT_ANTIALIASING
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
int len
Definition: draw_manager.c:108
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define floorf(x)
Definition: metal/compat.h:224
constexpr int CurveSamplesBaseLen
Number of samples to use between 0..1.
static void sampled_curve_free(CurveMaskCache *curve_mask_cache)
static int aa_samples_per_texel_axis(const Brush *brush, const float radius)
static void update_curve_mask(CurveMaskCache *curve_mask_cache, const Brush *brush, const int diameter, const float radius, const float cursor_position[2])
static size_t diameter_to_curve_mask_size(const int diameter)
static void curve_mask_free(CurveMaskCache *curve_mask_cache)
static bool is_sampled_curve_valid(const CurveMaskCache *curve_mask_cache, const Brush *brush)
static void curve_mask_allocate(CurveMaskCache *curve_mask_cache, const int diameter)
static bool is_curve_mask_size_valid(const CurveMaskCache *curve_mask_cache, const int diameter)
static void update_sampled_curve(CurveMaskCache *curve_mask_cache, const Brush *brush)
constexpr int CurveSamplesLen
Number of samples to store in the cache.
void paint_curve_mask_cache_free_data(CurveMaskCache *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])
struct CurveMapping * curve
int sampling_flag
Caching structure for curve mask.
Definition: paint_intern.h:287
ushort * curve_mask
Curve mask that can be passed as curve_mask parameter when.
Definition: paint_intern.h:310
float * sampled_curve
sampled version of the brush curve-mapping.
Definition: paint_intern.h:298
int last_curve_timestamp
Last CurveMapping.changed_timestamp being read.
Definition: paint_intern.h:293
size_t curve_mask_size
Size in bytes of the curve_mask field.
Definition: paint_intern.h:305