Blender  V3.3
BKE_attribute_math.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
5 #include "BLI_array.hh"
6 #include "BLI_color.hh"
7 #include "BLI_cpp_type.hh"
8 #include "BLI_math_color.hh"
9 #include "BLI_math_vector.h"
10 #include "BLI_math_vector.hh"
11 
12 #include "BKE_customdata.h"
13 
15 
19 template<typename Func>
20 inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
21 {
22  cpp_type.to_static_type_tag<float,
23  float2,
24  float3,
25  int,
26  bool,
27  int8_t,
29  ColorGeometry4b>([&](auto type_tag) {
30  using T = typename decltype(type_tag)::type;
31  if constexpr (std::is_same_v<T, void>) {
32  /* It's expected that the given cpp type is one of the supported ones. */
34  }
35  else {
36  func(T());
37  }
38  });
39 }
40 
41 template<typename Func>
42 inline void convert_to_static_type(const eCustomDataType data_type, const Func &func)
43 {
44  const CPPType &cpp_type = *bke::custom_data_type_to_cpp_type(data_type);
45  convert_to_static_type(cpp_type, func);
46 }
47 
48 /* -------------------------------------------------------------------- */
54 template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
55 
56 template<>
57 inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
58 {
59  return static_cast<int8_t>(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2));
60 }
61 
62 template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
63 {
64  return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
65 }
66 
67 template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2)
68 {
69  return static_cast<int>(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2));
70 }
71 
72 template<>
73 inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2)
74 {
75  return weights.x * v0 + weights.y * v1 + weights.z * v2;
76 }
77 
78 template<>
79 inline float2 mix3(const float3 &weights, const float2 &v0, const float2 &v1, const float2 &v2)
80 {
81  return weights.x * v0 + weights.y * v1 + weights.z * v2;
82 }
83 
84 template<>
85 inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, const float3 &v2)
86 {
87  return weights.x * v0 + weights.y * v1 + weights.z * v2;
88 }
89 
90 template<>
91 inline ColorGeometry4f mix3(const float3 &weights,
92  const ColorGeometry4f &v0,
93  const ColorGeometry4f &v1,
94  const ColorGeometry4f &v2)
95 {
97  interp_v4_v4v4v4(result, v0, v1, v2, weights);
98  return result;
99 }
100 
101 template<>
102 inline ColorGeometry4b mix3(const float3 &weights,
103  const ColorGeometry4b &v0,
104  const ColorGeometry4b &v1,
105  const ColorGeometry4b &v2)
106 {
107  const float4 v0_f{&v0.r};
108  const float4 v1_f{&v1.r};
109  const float4 v2_f{&v2.r};
110  const float4 mixed = v0_f * weights[0] + v1_f * weights[1] + v2_f * weights[2];
111  return ColorGeometry4b{static_cast<uint8_t>(mixed[0]),
112  static_cast<uint8_t>(mixed[1]),
113  static_cast<uint8_t>(mixed[2]),
114  static_cast<uint8_t>(mixed[3])};
115 }
116 
119 /* -------------------------------------------------------------------- */
125 template<typename T> T mix2(float factor, const T &a, const T &b);
126 
127 template<> inline bool mix2(const float factor, const bool &a, const bool &b)
128 {
129  return ((1.0f - factor) * a + factor * b) >= 0.5f;
130 }
131 
132 template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
133 {
134  return static_cast<int8_t>(std::round((1.0f - factor) * a + factor * b));
135 }
136 
137 template<> inline int mix2(const float factor, const int &a, const int &b)
138 {
139  return static_cast<int>(std::round((1.0f - factor) * a + factor * b));
140 }
141 
142 template<> inline float mix2(const float factor, const float &a, const float &b)
143 {
144  return (1.0f - factor) * a + factor * b;
145 }
146 
147 template<> inline float2 mix2(const float factor, const float2 &a, const float2 &b)
148 {
149  return math::interpolate(a, b, factor);
150 }
151 
152 template<> inline float3 mix2(const float factor, const float3 &a, const float3 &b)
153 {
154  return math::interpolate(a, b, factor);
155 }
156 
157 template<>
158 inline ColorGeometry4f mix2(const float factor, const ColorGeometry4f &a, const ColorGeometry4f &b)
159 {
160  return math::interpolate(a, b, factor);
161 }
162 
163 template<>
164 inline ColorGeometry4b mix2(const float factor, const ColorGeometry4b &a, const ColorGeometry4b &b)
165 {
166  return math::interpolate(a, b, factor);
167 }
168 
171 /* -------------------------------------------------------------------- */
179 template<typename T> class SimpleMixer {
180  private:
181  MutableSpan<T> buffer_;
182  T default_value_;
183  Array<float> total_weights_;
184 
185  public:
190  SimpleMixer(MutableSpan<T> buffer, T default_value = {})
191  : buffer_(buffer), default_value_(default_value), total_weights_(buffer.size(), 0.0f)
192  {
193  BLI_STATIC_ASSERT(std::is_trivial_v<T>, "");
194  memset(buffer_.data(), 0, sizeof(T) * buffer_.size());
195  }
196 
200  void mix_in(const int64_t index, const T &value, const float weight = 1.0f)
201  {
202  BLI_assert(weight >= 0.0f);
203  buffer_[index] += value * weight;
204  total_weights_[index] += weight;
205  }
206 
210  void finalize()
211  {
212  for (const int64_t i : buffer_.index_range()) {
213  const float weight = total_weights_[i];
214  if (weight > 0.0f) {
215  buffer_[i] *= 1.0f / weight;
216  }
217  else {
218  buffer_[i] = default_value_;
219  }
220  }
221  }
222 };
223 
233  private:
234  MutableSpan<bool> buffer_;
235 
236  public:
241  {
242  buffer_.fill(false);
243  }
244 
248  void mix_in(const int64_t index, const bool value, [[maybe_unused]] const float weight = 1.0f)
249  {
250  buffer_[index] |= value;
251  }
252 
256  void finalize()
257  {
258  }
259 };
260 
265 template<typename T, typename AccumulationT, T (*ConvertToT)(const AccumulationT &value)>
267  private:
268  struct Item {
269  /* Store both values together, because they are accessed together. */
270  AccumulationT value = {0};
271  float weight = 0.0f;
272  };
273 
274  MutableSpan<T> buffer_;
275  T default_value_;
276  Array<Item> accumulation_buffer_;
277 
278  public:
280  : buffer_(buffer), default_value_(default_value), accumulation_buffer_(buffer.size())
281  {
282  }
283 
284  void mix_in(const int64_t index, const T &value, const float weight = 1.0f)
285  {
286  const AccumulationT converted_value = static_cast<AccumulationT>(value);
287  Item &item = accumulation_buffer_[index];
288  item.value += converted_value * weight;
289  item.weight += weight;
290  }
291 
292  void finalize()
293  {
294  for (const int64_t i : buffer_.index_range()) {
295  const Item &item = accumulation_buffer_[i];
296  if (item.weight > 0.0f) {
297  const float weight_inv = 1.0f / item.weight;
298  const T converted_value = ConvertToT(item.value * weight_inv);
299  buffer_[i] = converted_value;
300  }
301  else {
302  buffer_[i] = default_value_;
303  }
304  }
305  }
306 };
307 
309  private:
311  ColorGeometry4f default_color_;
312  Array<float> total_weights_;
313 
314  public:
316  ColorGeometry4f default_color = ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
317  void mix_in(int64_t index, const ColorGeometry4f &color, float weight = 1.0f);
318  void finalize();
319 };
320 
322  private:
324  ColorGeometry4b default_color_;
325  Array<float> total_weights_;
326  Array<float4> accumulation_buffer_;
327 
328  public:
330  ColorGeometry4b default_color = ColorGeometry4b(0, 0, 0, 255));
331  void mix_in(int64_t index, const ColorGeometry4b &color, float weight = 1.0f);
332  void finalize();
333 };
334 
335 template<typename T> struct DefaultMixerStruct {
336  /* Use void by default. This can be checked for in `if constexpr` statements. */
337  using type = void;
338 };
339 template<> struct DefaultMixerStruct<float> {
341 };
342 template<> struct DefaultMixerStruct<float2> {
344 };
345 template<> struct DefaultMixerStruct<float3> {
347 };
349  /* Use a special mixer for colors. ColorGeometry4f can't be added/multiplied, because this is not
350  * something one should usually do with colors. */
352 };
355 };
356 template<> struct DefaultMixerStruct<int> {
357  static int double_to_int(const double &value)
358  {
359  return static_cast<int>(std::round(value));
360  }
361  /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
362  * uses double instead of float so that it is accurate for all 32 bit integers. */
364 };
365 template<> struct DefaultMixerStruct<bool> {
366  static bool float_to_bool(const float &value)
367  {
368  return value >= 0.5f;
369  }
370  /* Store interpolated booleans in a float temporary.
371  * Otherwise information provided by weights is easily rounded away. */
373 };
374 
375 template<> struct DefaultMixerStruct<int8_t> {
376  static int8_t float_to_int8_t(const float &value)
377  {
378  return static_cast<int8_t>(std::round(value));
379  }
380  /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
382 };
383 
384 template<typename T> struct DefaultPropatationMixerStruct {
385  /* Use void by default. This can be checked for in `if constexpr` statements. */
387 };
388 
391 };
392 
398 template<typename T>
400 
401 /* Utility to get a good default mixer for a given type. This is `void` when there is no default
402  * mixer for the given type. */
403 template<typename T> using DefaultMixer = typename DefaultMixerStruct<T>::type;
404 
407 } // namespace blender::attribute_math
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_STATIC_ASSERT(a, msg)
Definition: BLI_assert.h:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
void interp_v4_v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float w[3])
Definition: math_vector.c:180
eCustomDataType
_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 type
_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 GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
ATTR_WARN_UNUSED_RESULT const BMVert * v2
void to_static_type_tag(const Fn &fn) const
ChannelStorageType r
Definition: BLI_color.hh:85
constexpr int64_t size() const
Definition: BLI_span.hh:511
constexpr void fill(const T &value)
Definition: BLI_span.hh:527
constexpr IndexRange index_range() const
Definition: BLI_span.hh:661
constexpr T * data() const
Definition: BLI_span.hh:548
void mix_in(const int64_t index, const bool value, [[maybe_unused]] const float weight=1.0f)
ColorGeometry4bMixer(MutableSpan< ColorGeometry4b > buffer, ColorGeometry4b default_color=ColorGeometry4b(0, 0, 0, 255))
void mix_in(int64_t index, const ColorGeometry4b &color, float weight=1.0f)
ColorGeometry4fMixer(MutableSpan< ColorGeometry4f > buffer, ColorGeometry4f default_color=ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f))
void mix_in(int64_t index, const ColorGeometry4f &color, float weight=1.0f)
void mix_in(const int64_t index, const T &value, const float weight=1.0f)
SimpleMixerWithAccumulationType(MutableSpan< T > buffer, T default_value={})
void mix_in(const int64_t index, const T &value, const float weight=1.0f)
SimpleMixer(MutableSpan< T > buffer, T default_value={})
SyclQueue void void size_t num_bytes void
ccl_global float * buffer
#define T
static unsigned a[3]
Definition: RandGen.cpp:78
typename DefaultMixerStruct< T >::type DefaultMixer
T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2)
typename DefaultPropatationMixerStruct< T >::type DefaultPropatationMixer
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
T mix2(float factor, const T &a, const T &b)
const blender::CPPType * custom_data_type_to_cpp_type(const eCustomDataType type)
Definition: customdata.cc:5312
T interpolate(const T &a, const T &b, const FactorT &t)
vec_base< float, 3 > float3
vec_base< float, 2 > float2
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
Definition: BLI_color.hh:347
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition: BLI_color.hh:346
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
__int64 int64_t
Definition: stdint.h:89
unsigned char uint8_t
Definition: stdint.h:78
signed char int8_t
Definition: stdint.h:75