17 void BezierSpline::copy_settings(
Spline &dst)
const
20 bezier.resolution_ = resolution_;
23 void BezierSpline::copy_data(
Spline &dst)
const
26 bezier.positions_ = positions_;
27 bezier.handle_types_left_ = handle_types_left_;
28 bezier.handle_positions_left_ = handle_positions_left_;
29 bezier.handle_types_right_ = handle_types_right_;
30 bezier.handle_positions_right_ = handle_positions_right_;
31 bezier.radii_ = radii_;
32 bezier.tilts_ = tilts_;
37 const int size = positions_.size();
62 handle_positions_left_.resize(
size);
63 positions_.resize(
size);
65 handle_positions_right_.resize(
size);
98 return handle_types_left_;
102 return handle_types_left_;
107 return handle_positions_left_;
114 return handle_positions_left_;
119 return handle_types_right_;
123 return handle_types_right_;
128 return handle_positions_right_;
135 return handle_positions_right_;
142 std::swap(this->handle_positions_left_, this->handle_positions_right_);
146 std::swap(this->handle_types_left_, this->handle_types_right_);
173 if (!auto_handles_dirty_) {
177 std::lock_guard
lock{auto_handle_mutex_};
178 if (!auto_handles_dirty_) {
182 if (this->
size() == 1) {
183 auto_handles_dirty_ =
false;
195 if (prev_len == 0.0f) {
198 if (next_len == 0.0f) {
201 const float3 dir = next_diff / next_len + prev_diff / prev_len;
207 const float prev_len_clamped =
std::min(prev_len, next_len * 5.0f);
208 handle_positions_left_[i] = positions_[i] + dir * -(prev_len_clamped /
len);
211 const float next_len_clamped =
std::min(next_len, prev_len * 5.0f);
212 handle_positions_right_[i] = positions_[i] + dir * (next_len_clamped /
len);
228 auto_handles_dirty_ =
false;
234 position += translation;
237 handle_position += translation;
240 handle_position += translation;
248 position = matrix * position;
251 handle_position = matrix * handle_position;
254 handle_position = matrix * handle_position;
279 handle_other = position - dir *
length;
286 static_cast<HandleType>(handle_types_right_[index]),
287 static_cast<HandleType>(handle_types_left_[index]),
289 handle_positions_right_[index],
290 handle_positions_left_[index]);
296 static_cast<HandleType>(handle_types_right_[index]),
297 static_cast<HandleType>(handle_types_left_[index]),
299 handle_positions_left_[index],
300 handle_positions_right_[index]);
314 if (index == this->
size() - 1) {
329 offset_cache_dirty_ =
true;
330 position_cache_dirty_ =
true;
331 mapping_cache_dirty_ =
true;
335 auto_handles_dirty_ =
true;
344 void BezierSpline::correct_end_tangents()
const
353 if (handle_positions_right_.first() != positions_.first()) {
354 tangents.first() =
normalize(handle_positions_right_.first() - positions_.first());
356 if (handle_positions_left_.last() != positions_.last()) {
362 const int next_index,
363 const float parameter)
367 BLI_assert(parameter <= 1.0f && parameter >= 0.0f);
369 const float3 &point_prev = positions_[index];
370 const float3 &handle_prev = handle_positions_right_[index];
371 const float3 &handle_next = handle_positions_left_[next_index];
372 const float3 &point_next = positions_[next_index];
391 const float inv_len = 1.0f /
static_cast<float>(
result.size());
392 const float inv_len_squared = inv_len * inv_len;
393 const float inv_len_cubed = inv_len_squared * inv_len;
395 const float3 rt1 = 3.0f * (point_1 - point_0) * inv_len;
396 const float3 rt2 = 3.0f * (point_0 - 2.0f * point_1 + point_2) * inv_len_squared;
397 const float3 rt3 = (point_3 - point_0 + 3.0f * (point_1 - point_2)) * inv_len_cubed;
401 float3 q2 = 2.0f * rt2 + 6.0f * rt3;
403 for (
const int i :
result.index_range()) {
412 const int next_index,
421 handle_positions_right_[index],
422 handle_positions_left_[next_index],
423 positions_[next_index],
430 if (!offset_cache_dirty_) {
431 return offset_cache_;
434 std::lock_guard
lock{offset_cache_mutex_};
435 if (!offset_cache_dirty_) {
436 return offset_cache_;
456 offset_cache_dirty_ =
false;
466 const float first_segment_len_inv = 1.0f / offsets[1];
467 for (
const int i :
IndexRange(0, offsets[1])) {
468 r_mappings[i] = i * first_segment_len_inv;
473 for (
const int i_control_point : range) {
474 const int segment_len = offsets[i_control_point + 1] - offsets[i_control_point];
475 const float segment_len_inv = 1.0f / segment_len;
477 r_mappings[offsets[i_control_point] + i] = i_control_point + i * segment_len_inv;
483 const int last_segment_len = offsets[
size] - offsets[
size - 1];
484 const float last_segment_len_inv = 1.0f / last_segment_len;
485 for (
const int i :
IndexRange(last_segment_len)) {
486 r_mappings[offsets[
size - 1] + i] =
size - 1 + i * last_segment_len_inv;
496 if (!mapping_cache_dirty_) {
497 return evaluated_mapping_cache_;
500 std::lock_guard
lock{mapping_cache_mutex_};
501 if (!mapping_cache_dirty_) {
502 return evaluated_mapping_cache_;
505 const int num = this->
size();
507 evaluated_mapping_cache_.
resize(eval_num);
511 mappings.
first() = 0.0f;
512 mapping_cache_dirty_ =
false;
523 mapping_cache_dirty_ =
false;
529 if (!position_cache_dirty_) {
530 return evaluated_position_cache_;
533 std::lock_guard
lock{position_cache_mutex_};
534 if (!position_cache_dirty_) {
535 return evaluated_position_cache_;
538 const int num = this->
size();
540 evaluated_position_cache_.resize(eval_num);
548 position_cache_dirty_ =
false;
556 const int grain_size =
std::max(512 / resolution_, 1);
560 for (
const int i : range) {
567 num - 1, 0,
positions.slice(offsets[num - 1], offsets[num] - offsets[num - 1]));
575 position_cache_dirty_ =
false;
580 const float index_factor)
const
582 const int num = this->
size();
585 if (index_factor < num) {
587 const int next_index = (index < num - 1) ? index + 1 : 0;
593 if (index_factor < num - 1) {
595 const int next_index = index + 1;
615 const T &value =
src[
interp.control_point_index];
616 const T &next_value =
src[
interp.next_control_point_index];
626 if (
src.is_single()) {
637 using T = decltype(dummy);
638 if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
639 Array<T> values(eval_num);
640 interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values);
641 new_varray = VArray<T>::ForContainer(std::move(values));
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
blender::MutableSpan< float > tilts() final
blender::Span< blender::float3 > handle_positions_right() const
bool segment_is_vector(int start_index) const
blender::Span< float > evaluated_mappings() const
void resize(int size) final
blender::Span< blender::float3 > handle_positions_left() const
void set_handle_position_left(int index, const blender::float3 &value)
void transform(const blender::float4x4 &matrix) override
void evaluate_segment(int index, int next_index, blender::MutableSpan< blender::float3 > positions) const
InsertResult calculate_segment_insertion(int index, int next_index, float parameter)
int evaluated_points_num() const final
blender::Span< int8_t > handle_types_left() const
void ensure_auto_handles() const
InterpolationData interpolation_data_from_index_factor(float index_factor) const
blender::Span< int > control_point_offsets() const
void translate(const blender::float3 &translation) override
virtual blender::GVArray interpolate_to_evaluated(const blender::GVArray &src) const override
bool point_is_sharp(int index) const
void mark_cache_invalid() final
void set_resolution(int value)
blender::Span< int8_t > handle_types_right() const
blender::Span< blender::float3 > evaluated_positions() const final
void set_handle_position_right(int index, const blender::float3 &value)
void reverse_impl() override
blender::MutableSpan< blender::float3 > positions() final
blender::MutableSpan< float > radii() final
bool tangent_cache_dirty_
blender::Vector< blender::float3 > evaluated_tangents_cache_
blender::bke::CustomDataAttributes attributes
constexpr int64_t size() const
constexpr T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr T & first() const
constexpr const T & last(const int64_t n=0) const
const T & last(const int64_t n=0) const
void resize(const int64_t new_size)
void reallocate(int size)
SyclQueue void void * src
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
T mix2(float factor, const T &a, const T &b)
void interpolate(const Span< T > src, const Span< int > indices, const Span< float > factors, MutableSpan< T > dst)
T length(const vec_base< T, Size > &a)
T distance(const T &a, const T &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
SymEdge< T > * prev(const SymEdge< T > *se)
void isolate_task(const Function &function)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
vec_base< float, 3 > float3
MutableSpan< float3 > positions
MutableSpan< float3 > tangents
static void calculate_mappings_linear_resolution(Span< int > offsets, const int size, const int resolution, const bool is_cyclic, MutableSpan< float > r_mappings)
static void bezier_forward_difference_3d(const float3 &point_0, const float3 &point_1, const float3 &point_2, const float3 &point_3, MutableSpan< float3 > result)
static float3 next_position(Span< float3 > positions, const bool cyclic, const int i)
static void set_handle_position(const float3 &position, const HandleType type, const HandleType type_other, const float3 &new_value, float3 &handle, float3 &handle_other)
static float3 previous_position(Span< float3 > positions, const bool cyclic, const int i)
static void interpolate_to_evaluated_impl(const BezierSpline &spline, const blender::VArray< T > &src, MutableSpan< T > dst)