38 dst[i] = src[i * scale + offset];
50 dst[i * 3 + 1] = src[i];
51 dst[i * 3 + 2] = src[i];
58 using T = decltype(dummy);
59 bezier_generic_to_nurbs(src.typed<T>(), dst.typed<T>());
69 dst_positions[i * 3] = src_handles_l[i];
70 dst_positions[i * 3 + 1] = src_positions[i];
71 dst_positions[i * 3 + 2] = src_handles_r[i];
83 constexpr float handle_scale = 1.0f / 6.0f;
85 if (src_positions.
size() == 1) {
91 const float3 first_offset = cyclic ? src_positions[1] - src_positions.
last() :
92 src_positions[1] - src_positions[0];
93 dst_handles_r.
first() = src_positions.
first() + first_offset * handle_scale;
94 dst_handles_l.
first() = src_positions.
first() - first_offset * handle_scale;
96 const float3 last_offset = cyclic ? src_positions.
first() - src_positions.
last(1) :
97 src_positions.
last() - src_positions.
last(1);
98 dst_handles_l.
last() = src_positions.
last() - last_offset * handle_scale;
99 dst_handles_r.
last() = src_positions.
last() + last_offset * handle_scale;
102 const float3 left_offset = src_positions[i - 1] - src_positions[i + 1];
103 dst_handles_l[i] = src_positions[i] + left_offset * handle_scale;
105 const float3 right_offset = src_positions[i + 1] - src_positions[i - 1];
106 dst_handles_r[i] = src_positions[i] + right_offset * handle_scale;
127 switch (knots_mode) {
130 dst[i] = src[(i + 1) % src.
size()];
150 using T = decltype(dummy);
151 nurbs_to_bezier_assign(src.typed<T>(), dst.typed<T>(), knots_mode);
158 const int nurbs_positions_num = nurbs_positions.
size();
164 handle_positions.
append(nurbs_positions[1] +
165 ((nurbs_positions[0] - nurbs_positions[1]) / 3));
168 handle_positions.
append(2 * nurbs_positions[0] - nurbs_positions[1]);
169 handle_positions.
append(nurbs_positions[1]);
174 const int segments_num = nurbs_positions_num - 1;
175 const bool ignore_interior_segment = segments_num == 3 && is_periodic ==
false;
176 if (ignore_interior_segment ==
false) {
177 const float mid_offset =
float(segments_num - 1) / 2.0f;
178 for (
const int i :
IndexRange(1, segments_num - 2)) {
180 const int divisor = is_periodic ?
182 std::min(3,
int(-std::abs(i - mid_offset) + mid_offset + 1.0f));
183 const float3 &p1 = nurbs_positions[i];
184 const float3 &p2 = nurbs_positions[i + 1];
185 const float3 displacement = (p2 - p1) / divisor;
186 const int num_handles_on_segment = divisor < 3 ? 1 : 2;
187 for (
int j :
IndexRange(1, num_handles_on_segment)) {
188 handle_positions.
append(p1 + (displacement * j));
193 const int last_index = nurbs_positions_num - 1;
196 nurbs_positions[last_index - 1] +
197 ((nurbs_positions[last_index] - nurbs_positions[last_index - 1]) / 3));
200 handle_positions.
append(nurbs_positions[last_index - 1]);
201 handle_positions.
append(2 * nurbs_positions[last_index] - nurbs_positions[last_index - 1]);
205 for (
const int i :
IndexRange(nurbs_positions_num)) {
209 handle_positions.
append(nurbs_positions[i]);
211 if (nurbs_positions_num % 3 == 1) {
214 else if (nurbs_positions_num % 3 == 2) {
215 const int last_index = nurbs_positions_num - 1;
216 handle_positions.
append(2 * nurbs_positions[last_index] - nurbs_positions[last_index - 1]);
220 return handle_positions;
229 for (
const int i : bezier_positions.
index_range()) {
231 handle_positions[i * 2], handle_positions[i * 2 + 1], 0.5f);
248 return cyclic ? src_size : std::max(1, src_size - 2);
250 return (src_size + 1) / 3;
286 selection.foreach_index(
GrainSize(1024), [&](
const int i) {
290 src_points_by_curve[i].
size());
303 "position",
"handle_type_left",
"handle_type_right",
"handle_right",
"handle_left"};
305 attributes_to_skip.
add_new(
"nurbs_weight");
319 src_points_by_curve, dst_points_by_curve, selection, src_positions, dst_positions);
321 selection.foreach_index(
GrainSize(512), [&](
const int i) {
322 const IndexRange src_points = src_points_by_curve[i];
323 const IndexRange dst_points = dst_points_by_curve[i];
326 dst_handles_l.
slice(dst_points),
327 dst_handles_r.
slice(dst_points));
332 src_points_by_curve, dst_points_by_curve, selection, attribute.src, attribute.dst.span);
338 src_points_by_curve, dst_points_by_curve, selection, src_positions, dst_positions);
346 src_points_by_curve, dst_points_by_curve, selection, attribute.src, attribute.dst.span);
357 src_points_by_curve, dst_points_by_curve, selection, src_positions, dst_positions);
359 src_points_by_curve, dst_points_by_curve, selection, src_handles_l, dst_handles_l);
361 src_points_by_curve, dst_points_by_curve, selection, src_handles_r, dst_handles_r);
363 src_points_by_curve, dst_points_by_curve, selection, src_types_l, dst_types_l);
365 src_points_by_curve, dst_points_by_curve, selection, src_types_r, dst_types_r);
371 src_points_by_curve, dst_points_by_curve, selection, attribute.src, attribute.dst.span);
381 selection.foreach_index(
GrainSize(64), [&](
const int i) {
382 const IndexRange src_points = src_points_by_curve[i];
383 const IndexRange dst_points = dst_points_by_curve[i];
385 if (dst_points.
size() == 1) {
386 const float3 &position = src_positions[src_points.first()];
387 dst_positions[dst_points.first()] = position;
388 dst_handles_l[dst_points.first()] = position;
389 dst_handles_r[dst_points.first()] = position;
399 nurbs_positions_vector.
extend(src_curve_positions);
400 nurbs_positions_vector.
append(src_curve_positions[0]);
401 nurbs_positions_vector.
append(src_curve_positions[1]);
402 nurbs_positions = nurbs_positions_vector;
413 nurbs_positions, handle_positions, knots_mode, dst_positions.
slice(dst_points));
417 selection.foreach_index(
GrainSize(512), [&](
const int i) {
418 const IndexRange src_points = src_points_by_curve[i];
419 const IndexRange dst_points = dst_points_by_curve[i];
422 attribute.dst.span.slice(dst_points));
430 catmull_rom_to_bezier,
436 attribute.dst.finish();
468 selection.foreach_index(
GrainSize(1024), [&](
const int i) {
490 if (src_attributes.
contains(
"nurbs_weight")) {
500 fill_weights_if_necessary(selection);
503 for (
const int i : segment) {
504 const IndexRange src_points = src_points_by_curve[i];
505 const IndexRange dst_points = dst_points_by_curve[i];
507 src_positions.
slice(src_points), src_cyclic[i], dst_positions.
slice(dst_points));
512 selection.foreach_index(
GrainSize(512), [&](
const int i) {
513 const IndexRange src_points = src_points_by_curve[i];
514 const IndexRange dst_points = dst_points_by_curve[i];
516 attribute.dst.span.slice(dst_points));
524 src_points_by_curve, dst_points_by_curve, selection, src_positions, dst_positions);
525 fill_weights_if_necessary(selection);
538 selection.foreach_index(
GrainSize(1024), [&](
const int i) {
545 src_points_by_curve, dst_points_by_curve, selection, attribute.src, attribute.dst.span);
556 fill_weights_if_necessary(selection);
558 selection.foreach_index(
GrainSize(512), [&](
const int i) {
559 const IndexRange src_points = src_points_by_curve[i];
560 const IndexRange dst_points = dst_points_by_curve[i];
562 src_handles_l.
slice(src_points),
563 src_handles_r.
slice(src_points),
564 dst_positions.
slice(dst_points));
568 selection.foreach_index(
GrainSize(512), [&](
const int i) {
569 const IndexRange src_points = src_points_by_curve[i];
570 const IndexRange dst_points = dst_points_by_curve[i];
572 attribute.dst.span.slice(dst_points));
579 src_points_by_curve, dst_points_by_curve, selection, src_positions, dst_positions);
591 src_points_by_curve, dst_points_by_curve, selection, attribute.src, attribute.dst.span);
598 catmull_rom_to_nurbs,
604 attribute.dst.finish();
637 options.convert_bezier_handles_to_catmull_rom_points :
638 options.convert_bezier_handles_to_poly_points;
656 selection.foreach_index(
GrainSize(1024), [&](
const int i) {
657 const IndexRange src_points = src_points_by_curve[i];
659 int &size = dst_offsets[i];
661 size = src_points.
size() * 3;
664 size = src_points.
size();
687 src_points_by_curve, dst_points_by_curve, selection, src_positions, dst_positions);
690 src_points_by_curve, dst_points_by_curve, selection, attribute.src, attribute.dst.span);
699 selection.foreach_index([&](
const int curve_i) {
700 const IndexRange src_points = src_points_by_curve[curve_i];
701 const IndexRange dst_points = dst_points_by_curve[curve_i];
703 const int src_point_i = src_points[i];
704 const int dst_points_start = dst_points.
start() + 3 * i;
705 dst_positions[dst_points_start + 0] = src_left_handles[src_point_i];
706 dst_positions[dst_points_start + 1] = src_positions[src_point_i];
707 dst_positions[dst_points_start + 2] = src_right_handles[src_point_i];
713 const CPPType &cpp_type = attribute.src.type();
714 selection.foreach_index([&](
const int curve_i) {
715 const IndexRange src_points = src_points_by_curve[curve_i];
716 const IndexRange dst_points = dst_points_by_curve[curve_i];
718 const int src_point_i = src_points[i];
719 const int dst_points_start = dst_points.
start() + 3 * i;
720 const void *src_value = attribute.src[src_point_i];
721 cpp_type.
fill_assign_n(src_value, attribute.dst.span[dst_points_start], 3);
730 convert_from_catmull_rom_or_poly_or_nurbs,
731 convert_from_catmull_rom_or_poly_or_nurbs,
733 convert_from_catmull_rom_or_poly_or_nurbs);
736 attribute.dst.finish();
763 selection,
GrainSize(4096), memory, [&](
const int curve_i) {
786 src_curves, selection, dst_type, attribute_filter,
options);
790 if (!
options.keep_bezier_shape_as_nurbs || !
options.keep_catmull_rom_shape_as_nurbs) {
793 src_curves, selection,
options);
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
@ NURBS_KNOT_MODE_ENDPOINT
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void fill_assign_n(const void *value, void *dst, int64_t n) const
const CPPType & type() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange index_range() const
constexpr IndexRange drop_front(int64_t n) 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
void add_new(const Key &key)
constexpr Span slice(int64_t start, int64_t size) 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
T get_internal_single() const
void append(const T &value)
void extend(Span< T > array)
Span< T > as_span() const
bool contains(const StringRef attribute_id) const
VArray< int8_t > handle_types_left() const
void remove_attributes_based_on_types()
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()
MutableSpan< int8_t > nurbs_knots_modes_for_write()
MutableSpan< int8_t > nurbs_orders_for_write()
Span< float > nurbs_weights() const
Span< float3 > handle_positions_left() const
VArray< int8_t > nurbs_knots_modes() const
Span< float3 > positions() const
bool has_curve_with_type(CurveType type) const
MutableSpan< float > nurbs_weights_for_write()
void resize(int points_num, int curves_num)
Span< float3 > handle_positions_right() const
void fill_curve_types(CurveType type)
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
void calculate_bezier_auto_handles()
MutableSpan< int8_t > handle_types_left_for_write()
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
CCL_NAMESPACE_BEGIN struct Options options
draw_view in_light_buf[] float
void copy_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
void fill_points(OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, GPointer value, GMutableSpan dst)
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={})
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
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 bke::CurvesGeometry convert_bezier_or_catmull_rom_to_poly_before_conversion_to_nurbs(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const ConvertCurvesOptions &options)
static bool is_nurbs_to_bezier_one_to_one(const KnotsMode knots_mode)
static void create_nurbs_to_bezier_positions(const Span< float3 > nurbs_positions, const Span< float3 > handle_positions, const KnotsMode knots_mode, MutableSpan< float3 > bezier_positions)
static void bezier_positions_to_nurbs(const Span< float3 > src_positions, const Span< float3 > src_handles_l, const Span< float3 > src_handles_r, MutableSpan< float3 > dst_positions)
static void nurbs_to_bezier_assign(const Span< T > src, const MutableSpan< T > dst, const KnotsMode knots_mode)
static int to_nurbs_size(const CurveType src_type, const int src_size)
static void catmull_rom_to_bezier_handles(const Span< float3 > src_positions, const bool cyclic, MutableSpan< float3 > dst_handles_l, MutableSpan< float3 > dst_handles_r)
static void bezier_generic_to_nurbs(const Span< T > src, MutableSpan< T > dst)
static bke::CurvesGeometry convert_curves_trivial(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const CurveType dst_type)
static void catmull_rom_to_nurbs_positions(const Span< float3 > src_positions, const bool cyclic, MutableSpan< float3 > dst_positions)
static Vector< float3 > create_nurbs_to_bezier_handles(const Span< float3 > nurbs_positions, const KnotsMode knots_mode)
static void scale_input_assign(const Span< T > src, const int scale, const int offset, MutableSpan< T > dst)
static bke::CurvesGeometry convert_curves_to_nurbs(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const bke::AttributeFilter &attribute_filter)
static bke::CurvesGeometry convert_curves_to_catmull_rom_or_poly(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const CurveType dst_type, const bke::AttributeFilter &attribute_filter, const ConvertCurvesOptions &options)
static bke::CurvesGeometry convert_curves_to_bezier(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const bke::AttributeFilter &attribute_filter)
static int to_bezier_size(const CurveType src_type, const bool cyclic, const KnotsMode knots_mode, const int src_size)
bke::CurvesGeometry convert_curves(const bke::CurvesGeometry &src_curves, const IndexMask &selection, CurveType dst_type, const bke::AttributeFilter &attribute_filter, const ConvertCurvesOptions &options={})
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
T interpolate(const T &a, const T &b, const FactorT &t)
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)
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[]