20 const int segment_index)
24 handle_types_left[segment_index + 1]);
39 const int size = handle_types_left.
size();
42 evaluated_offsets.
first() = 0;
44 evaluated_offsets.
last() = 1;
48 const int points_per_segment = std::max(1, resolution);
52 evaluated_offsets[
i] = offset;
53 offset +=
segment_is_vector(handle_types_left, handle_types_right,
i) ? 1 : points_per_segment;
56 evaluated_offsets.
last(1) = offset;
66 evaluated_offsets.
last() = offset;
76 BLI_assert(parameter <= 1.0f && parameter >= 0.0f);
90 const float3 &other_handle,
91 const float3 &aligned_handle)
97 return position - dir *
length;
103 const float3 prev_position,
104 const float3 next_position,
109 const float3 prev_diff = position - prev_position;
110 const float3 next_diff = next_position - position;
113 if (prev_len == 0.0f) {
116 if (next_len == 0.0f) {
119 const float3 dir = next_diff / next_len + prev_diff / prev_len;
139 const float prev_len_clamped = std::min(prev_len, next_len * 5.0f);
140 left = position + dir * -(prev_len_clamped /
len);
143 const float next_len_clamped = std::min(next_len, prev_len * 5.0f);
144 right = position + dir * (next_len_clamped /
len);
194 positions[point], align_with[point], align_handles[point]);
205 const int points_num = positions.
size();
206 if (points_num == 1) {
213 cyclic ? positions.
last() : 2.0f * positions.
first() - positions[1],
215 positions_left.
first(),
216 positions_right.
first());
219 for (
const int i : range) {
234 cyclic ? positions.
first() : 2.0f * positions.
last() - positions.
last(1),
235 positions_left.
last(),
236 positions_right.
last());
245 const float inv_len_squared = inv_len * inv_len;
246 const float inv_len_cubed = inv_len_squared * inv_len;
248 const T rt1 = 3.0f * (point_1 - point_0) * inv_len;
249 const T rt2 = 3.0f * (point_0 - 2.0f * point_1 + point_2) * inv_len_squared;
250 const T rt3 = (point_3 - point_0 + 3.0f * (point_1 - point_2)) * inv_len_cubed;
253 T q1 = rt1 + rt2 + rt3;
254 T q2 = 2.0f * rt2 + 6.0f * rt3;
256 for (
const int i :
result.index_range()) {
290 evaluated_positions.
first() = positions.
first();
296 handles_right.
first(),
299 evaluated_positions.
slice(evaluated_offsets[0]));
302 const int grain_size = std::max<int>(evaluated_positions.
size() / positions.
size() * 32, 1);
305 for (
const int i : range) {
306 const IndexRange evaluated_range = evaluated_offsets[
i];
307 if (evaluated_range.
size() == 1) {
308 evaluated_positions[evaluated_range.
first()] = positions[
i];
315 evaluated_positions.
slice(evaluated_range));
322 if (last_segment_points.size() == 1) {
323 evaluated_positions.
last() = positions.
last();
327 handles_right.
last(),
328 handles_left.
first(),
330 evaluated_positions.
slice(last_segment_points));
338 const float step = 1.0f / dst.
size();
351 if (src.
size() == 1) {
361 for (const int i : range) {
362 const IndexRange segment = evaluated_offsets[i];
363 linear_interpolation(src[i], src[i + 1], dst.slice(segment));
367 const IndexRange last_segment = evaluated_offsets[src.index_range().last()];
376 using T = decltype(dummy);
377 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
378 interpolate_to_evaluated(src.typed<T>(), evaluated_offsets, dst.typed<T>());
Low-level operations for curves.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
const CPPType & type() const
constexpr int64_t first() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool contains(int64_t value) const
constexpr IndexRange drop_front(int64_t n) const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T & first() const
constexpr IndexRange index_range() const
constexpr T & last(const int64_t n=0) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
void foreach_index_optimized(Fn &&fn) const
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
float length(VecOp< float, D >) RET
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
T mix2(float factor, const T &a, const T &b)
Insertion insert(const float3 &point_prev, const float3 &handle_prev, const float3 &handle_next, const float3 &point_next, float parameter)
bool segment_is_vector(const HandleType left, const HandleType right)
void calculate_auto_handles(bool cyclic, Span< int8_t > types_left, Span< int8_t > types_right, Span< float3 > positions, MutableSpan< float3 > positions_left, MutableSpan< float3 > positions_right)
void calculate_evaluated_offsets(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right, bool cyclic, int resolution, MutableSpan< int > evaluated_offsets)
float3 calculate_vector_handle(const float3 &point, const float3 &next_point)
static void calculate_point_handles(const HandleType type_left, const HandleType type_right, const float3 position, const float3 prev_position, const float3 next_position, float3 &left, float3 &right)
void calculate_aligned_handles(const IndexMask &selection, Span< float3 > positions, Span< float3 > align_by, MutableSpan< float3 > align)
bool last_cyclic_segment_is_vector(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right)
static float3 calculate_aligned_handle(const float3 &position, const float3 &other_handle, const float3 &aligned_handle)
void evaluate_segment(const T &point_0, const T &point_1, const T &point_2, const T &point_3, MutableSpan< T > result)
void calculate_evaluated_positions(Span< float3 > positions, Span< float3 > handles_left, Span< float3 > handles_right, OffsetIndices< int > evaluated_offsets, MutableSpan< float3 > evaluated_positions)
void interpolate_to_evaluated(GSpan src, OffsetIndices< int > evaluated_offsets, GMutableSpan dst)
void evaluate_segment_ex(const T &point_0, const T &point_1, const T &point_2, const T &point_3, MutableSpan< T > result)
void set_handle_position(const float3 &position, HandleType type, HandleType type_other, const float3 &new_handle, float3 &handle, float3 &handle_other)
static void linear_interpolation(const T &a, const T &b, MutableSpan< T > dst)
T distance(const T &a, const T &b)
T length(const VecBase< T, Size > &a)
T interpolate(const T &a, const T &b, const FactorT &t)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 2 > float2
VecBase< float, 3 > float3