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();
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]);
102 using T = decltype(dummy);
103 subdivide_attribute_linear(src_points_by_curve,
121 const IndexRange src_points = src_points_by_curve[curve_i];
124 const IndexRange dst_points = dst_points_by_curve[curve_i];
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);
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(),
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);
364 const IndexRange src_points = src_points_by_curve[curve_i];
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));
386 attribute_filter_with_skip_ref(attribute_filter,
405 auto subdivide_nurbs = subdivide_poly;
410 subdivide_catmull_rom,
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
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
constexpr const T & last(const int64_t n=0) const
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 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()
local_group_size(16, 16) .push_constant(Type b
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 interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst)
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
IndexRange per_curve_point_offsets_range(const IndexRange points, const int curve_index)
void foreach_curve_by_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const IndexMask &selection, FunctionRef< void(IndexMask)> catmull_rom_fn, FunctionRef< void(IndexMask)> poly_fn, FunctionRef< void(IndexMask)> bezier_fn, FunctionRef< void(IndexMask)> nurbs_fn)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
void copy_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
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 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))
VecBase< float, 3 > float3
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[]