26 selection.foreach_index(
GrainSize(1024), [&](
const int curve_i) {
27 const IndexRange src_points = src_points_by_curve[curve_i];
34 if (src_points.
size() == 1) {
35 point_counts.
first() = 1;
39 for (
int &
count : point_counts) {
43 if (!cyclic[curve_i]) {
45 point_counts.
last() = 1;
50 dst_curve_offsets[curve_i] = point_offsets.
last();
59 const float step = 1.0f / dst.
size();
73 selection.foreach_index(
GrainSize(512), [&](
const int curve_i) {
74 const IndexRange src_points = src_points_by_curve[curve_i];
78 const IndexRange dst_points = dst_points_by_curve[curve_i];
83 for (const int i : range) {
84 const IndexRange segment_points = curve_offsets[i];
85 linear_interpolation(curve_src[i], curve_src[i + 1], curve_dst.slice(segment_points));
89 const IndexRange dst_last_segment = dst_points.
slice(curve_offsets[src_points.size() - 1]);
101 bke::attribute_math::convert_to_static_type(dst.
type(), [&](
auto dummy) {
102 using T = decltype(dummy);
103 subdivide_attribute_linear(src_points_by_curve,
120 selection.foreach_index(
GrainSize(512), [&](
const int curve_i) {
121 const IndexRange src_points = src_points_by_curve[curve_i];
122 const IndexRange src_segments = bke::curves::per_curve_point_offsets_range(src_points,
124 const IndexRange dst_points = dst_points_by_curve[curve_i];
125 bke::curves::catmull_rom::interpolate_to_evaluated(src.
slice(src_points),
127 all_point_offsets.
slice(src_segments),
128 dst.
slice(dst_points));
133 const float3 &handle_prev,
134 const float3 &handle_next,
135 const float3 &position_next,
144 const bool is_last_cyclic_segment)
146 auto fill_segment_handle_types = [&](
const HandleType type) {
150 dst_types_r.
slice(segment_points).
fill(type);
153 if (bke::curves::bezier::segment_is_vector(type_prev, type_next)) {
159 dst_positions[segment_points.
first()] = position_prev;
169 float3 segment_start = position_prev;
170 float3 segment_handle_prev = handle_prev;
171 float3 segment_handle_next = handle_next;
172 const float3 segment_end = position_next;
175 const float parameter = 1.0f / (segment_points.
size() - i);
176 const int point_i = segment_points[i];
178 segment_start, segment_handle_prev, segment_handle_next, segment_end, parameter);
181 dst_handles_r[point_i] =
insert.handle_prev;
182 dst_handles_l[point_i + 1] =
insert.left_handle;
183 dst_positions[point_i + 1] =
insert.position;
186 segment_start =
insert.position;
187 segment_handle_prev =
insert.right_handle;
188 segment_handle_next =
insert.handle_next;
192 const int i_segment_last = is_last_cyclic_segment ? 0 : segment_points.
one_after_last();
193 dst_handles_r[segment_points.
last()] = segment_handle_prev;
194 dst_handles_l[i_segment_last] = segment_handle_next;
212 for (const int segment_i : range) {
213 const IndexRange segment = evaluated_offsets[segment_i];
214 subdivide_bezier_segment(src_positions[segment_i],
215 src_handles_r[segment_i],
216 src_handles_l[segment_i + 1],
217 src_positions[segment_i + 1],
218 HandleType(src_types_r[segment_i]),
219 HandleType(src_types_l[segment_i + 1]),
231 const int last_index = src_positions.index_range().last();
232 const IndexRange segment = evaluated_offsets[last_index];
235 subdivide_bezier_segment(src_positions.last(),
236 src_handles_r.last(),
237 src_handles_l.first(),
238 src_positions.first(),
249 if (bke::curves::bezier::segment_is_vector(type_prev, type_next)) {
259 dst_positions.last() = src_positions.last();
260 dst_types_l.first() = src_types_l.first();
261 dst_types_r.last() = src_types_r.last();
262 dst_handles_l.first() = src_handles_l.first();
263 dst_handles_r.last() = src_handles_r.last();
267 bke::curves::bezier::calculate_auto_handles(
268 cyclic, dst_types_l, dst_types_r, dst_positions, dst_handles_l, dst_handles_r);
302 all_point_offset_data.
fill(-1);
310 all_point_offset_data);
313 const Span<int> all_point_offsets(all_point_offset_data);
321 for (
auto &attribute : bke::retrieve_attributes_for_transfer(
331 attribute.dst.finish();
336 for (
auto &attribute : bke::retrieve_attributes_for_transfer(
345 attribute.dst.finish();
363 selection.foreach_index(
GrainSize(512), [&](
const int curve_i) {
364 const IndexRange src_points = src_points_by_curve[curve_i];
365 const IndexRange src_segments = bke::curves::per_curve_point_offsets_range(src_points,
367 const IndexRange dst_points = dst_points_by_curve[curve_i];
369 src_types_l.
slice(src_points),
370 src_types_r.
slice(src_points),
371 src_handles_l.
slice(src_points),
372 src_handles_r.
slice(src_points),
373 all_point_offsets.
slice(src_segments),
375 dst_positions.
slice(dst_points),
376 dst_types_l.
slice(dst_points),
377 dst_types_r.
slice(dst_points),
378 dst_handles_l.
slice(dst_points),
379 dst_handles_r.
slice(dst_points));
382 for (
auto &attribute :
383 bke::retrieve_attributes_for_transfer(src_attributes,
386 attribute_filter_with_skip_ref(attribute_filter,
399 attribute.dst.finish();
405 auto subdivide_nurbs = subdivide_poly;
407 bke::curves::foreach_curve_by_type(src_curves.
curve_types(),
410 subdivide_catmull_rom,
415 bke::copy_attributes_group_to_group(src_attributes,
416 bke::AttrDomain::Point,
417 bke::AttrDomain::Point,
Low-level operations for curves.
Low-level operations for curves.
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
void fill(const T &value) const
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
GSpan slice(const int64_t start, int64_t size) const
constexpr int64_t first() const
constexpr int64_t one_after_last() const
constexpr IndexRange shift(int64_t n) 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 IndexRange slice(int64_t start, int64_t size) 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 MutableSpan drop_back(const int64_t n) const
constexpr void fill(const T &value) const
constexpr MutableSpan slice_safe(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 Span slice(int64_t start, int64_t size) const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
void materialize_compressed(const IndexMask &mask, MutableSpan< T > r_span) const
VArray< int8_t > handle_types_left() const
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
MutableSpan< int8_t > handle_types_right_for_write()
VArray< int8_t > handle_types_right() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
Span< float3 > handle_positions_left() const
Span< int > offsets() const
Span< float3 > positions() const
void resize(int points_num, int curves_num)
Span< float3 > handle_positions_right() const
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
MutableSpan< int8_t > handle_types_left_for_write()
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
local_group_size(16, 16) .push_constant(Type b
T mix2(float factor, const T &a, const T &b)
IndexRange per_curve_point_offsets_range(const IndexRange points, const int curve_index)
static void calculate_result_offsets(const OffsetIndices< int > src_points_by_curve, const IndexMask &selection, const IndexMask &unselected, const VArray< float > &radii, const VArray< int > &counts, const Span< bool > cyclic, MutableSpan< int > dst_curve_offsets, MutableSpan< int > dst_point_offsets)
static void subdivide_bezier_positions(const Span< float3 > src_positions, const Span< int8_t > src_types_l, const Span< int8_t > src_types_r, const Span< float3 > src_handles_l, const Span< float3 > src_handles_r, const OffsetIndices< int > evaluated_offsets, const bool cyclic, MutableSpan< float3 > dst_positions, MutableSpan< int8_t > dst_types_l, MutableSpan< int8_t > dst_types_r, MutableSpan< float3 > dst_handles_l, MutableSpan< float3 > dst_handles_r)
static void linear_interpolation(const T &a, const T &b, MutableSpan< T > dst)
static void calculate_result_offsets(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const IndexMask &unselected, const VArray< int > &cuts, const Span< bool > cyclic, MutableSpan< int > dst_curve_offsets, MutableSpan< int > dst_point_offsets)
static void subdivide_bezier_segment(const float3 &position_prev, const float3 &handle_prev, const float3 &handle_next, const float3 &position_next, const HandleType type_prev, const HandleType type_next, const IndexRange segment_points, MutableSpan< float3 > dst_positions, MutableSpan< float3 > dst_handles_l, MutableSpan< float3 > dst_handles_r, MutableSpan< int8_t > dst_types_l, MutableSpan< int8_t > dst_types_r, const bool is_last_cyclic_segment)
bke::CurvesGeometry subdivide_curves(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const VArray< int > &cuts, const bke::AttributeFilter &attribute_filter={})
static void subdivide_attribute_catmull_rom(const OffsetIndices< int > src_points_by_curve, const OffsetIndices< int > dst_points_by_curve, const IndexMask &selection, const Span< int > all_point_offsets, const Span< bool > cyclic, const GSpan src, GMutableSpan dst)
static void subdivide_attribute_linear(const OffsetIndices< int > src_points_by_curve, const OffsetIndices< int > dst_points_by_curve, const IndexMask &selection, const Span< int > all_point_offsets, const Span< T > src, MutableSpan< T > dst)
void copy_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]