Blender  V2.93
BKE_attribute_math.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "BLI_array.hh"
18 #include "BLI_color.hh"
19 #include "BLI_float2.hh"
20 #include "BLI_float3.hh"
21 
22 #include "DNA_customdata_types.h"
23 
25 
29 template<typename Func>
30 void convert_to_static_type(const CustomDataType data_type, const Func &func)
31 {
32  switch (data_type) {
33  case CD_PROP_FLOAT:
34  func(float());
35  break;
36  case CD_PROP_FLOAT2:
37  func(float2());
38  break;
39  case CD_PROP_FLOAT3:
40  func(float3());
41  break;
42  case CD_PROP_INT32:
43  func(int());
44  break;
45  case CD_PROP_BOOL:
46  func(bool());
47  break;
48  case CD_PROP_COLOR:
49  func(Color4f());
50  break;
51  default:
53  break;
54  }
55 }
56 
57 /* -------------------------------------------------------------------- */
63 template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
64 
65 template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
66 {
67  return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
68 }
69 
70 template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2)
71 {
72  return static_cast<int>(weights.x * v0 + weights.y * v1 + weights.z * v2);
73 }
74 
75 template<>
76 inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2)
77 {
78  return weights.x * v0 + weights.y * v1 + weights.z * v2;
79 }
80 
81 template<>
82 inline float2 mix3(const float3 &weights, const float2 &v0, const float2 &v1, const float2 &v2)
83 {
84  return weights.x * v0 + weights.y * v1 + weights.z * v2;
85 }
86 
87 template<>
88 inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, const float3 &v2)
89 {
90  return weights.x * v0 + weights.y * v1 + weights.z * v2;
91 }
92 
93 template<>
94 inline Color4f mix3(const float3 &weights, const Color4f &v0, const Color4f &v1, const Color4f &v2)
95 {
97  interp_v4_v4v4v4(result, v0, v1, v2, weights);
98  return result;
99 }
100 
103 /* -------------------------------------------------------------------- */
111 template<typename T> class SimpleMixer {
112  private:
113  MutableSpan<T> buffer_;
114  T default_value_;
115  Array<float> total_weights_;
116 
117  public:
122  SimpleMixer(MutableSpan<T> buffer, T default_value = {})
123  : buffer_(buffer), default_value_(default_value), total_weights_(buffer.size(), 0.0f)
124  {
125  BLI_STATIC_ASSERT(std::is_trivial_v<T>, "");
126  memset(buffer_.data(), 0, sizeof(T) * buffer_.size());
127  }
128 
132  void mix_in(const int64_t index, const T &value, const float weight = 1.0f)
133  {
134  BLI_assert(weight >= 0.0f);
135  buffer_[index] += value * weight;
136  total_weights_[index] += weight;
137  }
138 
142  void finalize()
143  {
144  for (const int64_t i : buffer_.index_range()) {
145  const float weight = total_weights_[i];
146  if (weight > 0.0f) {
147  buffer_[i] *= 1.0f / weight;
148  }
149  else {
150  buffer_[i] = default_value_;
151  }
152  }
153  }
154 };
155 
158 template<typename T, typename AccumulationT, T (*ConvertToT)(const AccumulationT &value)>
160  private:
161  struct Item {
162  /* Store both values together, because they are accessed together. */
163  AccumulationT value = {0};
164  float weight = 0.0f;
165  };
166 
167  MutableSpan<T> buffer_;
168  T default_value_;
169  Array<Item> accumulation_buffer_;
170 
171  public:
173  : buffer_(buffer), default_value_(default_value), accumulation_buffer_(buffer.size())
174  {
175  }
176 
177  void mix_in(const int64_t index, const T &value, const float weight = 1.0f)
178  {
179  const AccumulationT converted_value = static_cast<AccumulationT>(value);
180  Item &item = accumulation_buffer_[index];
181  item.value += converted_value * weight;
182  item.weight += weight;
183  }
184 
185  void finalize()
186  {
187  for (const int64_t i : buffer_.index_range()) {
188  const Item &item = accumulation_buffer_[i];
189  if (item.weight > 0.0f) {
190  const float weight_inv = 1.0f / item.weight;
191  const T converted_value = ConvertToT(item.value * weight_inv);
192  buffer_[i] = converted_value;
193  }
194  else {
195  buffer_[i] = default_value_;
196  }
197  }
198  }
199 };
200 
202  private:
203  MutableSpan<Color4f> buffer_;
204  Color4f default_color_;
205  Array<float> total_weights_;
206 
207  public:
208  Color4fMixer(MutableSpan<Color4f> buffer, Color4f default_color = {0, 0, 0, 1});
209  void mix_in(const int64_t index, const Color4f &color, const float weight = 1.0f);
210  void finalize();
211 };
212 
213 template<typename T> struct DefaultMixerStruct {
214  /* Use void by default. This can be check for in `if constexpr` statements. */
215  using type = void;
216 };
217 template<> struct DefaultMixerStruct<float> {
219 };
220 template<> struct DefaultMixerStruct<float2> {
222 };
223 template<> struct DefaultMixerStruct<float3> {
225 };
226 template<> struct DefaultMixerStruct<Color4f> {
227  /* Use a special mixer for colors. Color4f can't be added/multiplied, because this is not
228  * something one should usually do with colors. */
230 };
231 template<> struct DefaultMixerStruct<int> {
232  static int double_to_int(const double &value)
233  {
234  return static_cast<int>(value);
235  }
236  /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
237  * uses double instead of float so that it is accurate for all 32 bit integers. */
239 };
240 template<> struct DefaultMixerStruct<bool> {
241  static bool float_to_bool(const float &value)
242  {
243  return value >= 0.5f;
244  }
245  /* Store interpolated booleans in a float temporary.
246  * Otherwise information provided by weights is easily rounded away. */
248 };
249 
250 /* Utility to get a good default mixer for a given type. This is `void` when there is no default
251  * mixer for the given type. */
252 template<typename T> using DefaultMixer = typename DefaultMixerStruct<T>::type;
253 
256 } // namespace blender::attribute_math
typedef float(TangentPoint)[2]
#define BLI_assert_unreachable()
Definition: BLI_assert.h:96
#define BLI_STATIC_ASSERT(a, msg)
Definition: BLI_assert.h:86
#define BLI_assert(a)
Definition: BLI_assert.h:58
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:213
CustomDataType
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_COLOR
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_PROP_BOOL
_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
ATTR_WARN_UNUSED_RESULT const BMVert * v2
constexpr int64_t size() const
Definition: BLI_span.hh:524
constexpr IndexRange index_range() const
Definition: BLI_span.hh:659
constexpr T * data() const
Definition: BLI_span.hh:561
void mix_in(const int64_t index, const Color4f &color, const float weight=1.0f)
Color4fMixer(MutableSpan< Color4f > buffer, Color4f default_color={0, 0, 0, 1})
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={})
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
#define T
typename DefaultMixerStruct< T >::type DefaultMixer
T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2)
void convert_to_static_type(const CustomDataType data_type, const Func &func)
__int64 int64_t
Definition: stdint.h:92