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;
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);
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));
338 src_points_by_curve, dst_points_by_curve,
selection, src_positions, dst_positions);
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);
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));
418 const IndexRange src_points = src_points_by_curve[i];
419 const IndexRange dst_points = dst_points_by_curve[i];
430 catmull_rom_to_bezier,
490 if (src_attributes.
contains(
"nurbs_weight")) {
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));
513 const IndexRange src_points = src_points_by_curve[i];
514 const IndexRange dst_points = dst_points_by_curve[i];
524 src_points_by_curve, dst_points_by_curve,
selection, src_positions, dst_positions);
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));
569 const IndexRange src_points = src_points_by_curve[i];
570 const IndexRange dst_points = dst_points_by_curve[i];
579 src_points_by_curve, dst_points_by_curve,
selection, src_positions, dst_positions);
598 catmull_rom_to_nurbs,
637 options.convert_bezier_handles_to_catmull_rom_points :
638 options.convert_bezier_handles_to_poly_points;
657 const IndexRange src_points = src_points_by_curve[i];
659 int &
size = dst_offsets[i];
687 src_points_by_curve, dst_points_by_curve,
selection, src_positions, dst_positions);
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];
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];
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);
790 if (!
options.keep_bezier_shape_as_nurbs || !
options.keep_catmull_rom_shape_as_nurbs) {
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
@ NURBS_KNOT_MODE_ENDPOINT
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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr bool is_empty() const
void fill_assign_n(const void *value, void *dst, int64_t n) const
const CPPType & type() const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
constexpr int64_t first() 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
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()
CCL_NAMESPACE_BEGIN struct Options options
draw_view in_light_buf[] float
ccl_device_inline float4 mask(const int4 mask, const float4 a)
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)
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[]