60 for (
const int i :
src.index_range()) {
62 dst[i * 3 + 1] =
src[i];
63 dst[i * 3 + 2] =
src[i];
70 using T = decltype(dummy);
71 bezier_generic_to_nurbs(src.typed<T>(), dst.typed<T>());
81 dst_positions[i * 3] = src_handles_l[i];
82 dst_positions[i * 3 + 1] = src_positions[i];
83 dst_positions[i * 3 + 2] = src_handles_r[i];
95 constexpr
float handle_scale = 1.0f / 6.0f;
97 if (src_positions.
size() == 1) {
103 const float3 first_offset = cyclic ? src_positions[1] - src_positions.
last() :
104 src_positions[1] - src_positions[0];
105 dst_handles_r.
first() = src_positions.
first() + first_offset * handle_scale;
106 dst_handles_l.
first() = src_positions.
first() - first_offset * handle_scale;
108 const float3 last_offset = cyclic ? src_positions.
first() - src_positions.
last(1) :
109 src_positions.
last() - src_positions.
last(1);
110 dst_handles_l.
last() = src_positions.
last() - last_offset * handle_scale;
111 dst_handles_r.
last() = src_positions.
last() + last_offset * handle_scale;
114 const float3 left_offset = src_positions[i - 1] - src_positions[i + 1];
115 dst_handles_l[i] = src_positions[i] + left_offset * handle_scale;
117 const float3 right_offset = src_positions[i + 1] - src_positions[i - 1];
118 dst_handles_r[i] = src_positions[i] + right_offset * handle_scale;
139 switch (knots_mode) {
142 dst[i] =
src[(i + 1) %
src.size()];
155 scale_input_assign<T>(
src, 3, 1, dst);
162 using T = decltype(dummy);
163 nurbs_to_bezier_assign(src.typed<T>(), dst.typed<T>(), knots_mode);
170 const int nurbs_positions_num = nurbs_positions.
size();
176 handle_positions.
append(nurbs_positions[1] +
177 ((nurbs_positions[0] - nurbs_positions[1]) / 3));
180 handle_positions.
append(2 * nurbs_positions[0] - nurbs_positions[1]);
181 handle_positions.
append(nurbs_positions[1]);
187 const bool ignore_interior_segment =
segments_num == 3 && is_periodic ==
false;
188 if (ignore_interior_segment ==
false) {
192 const int divisor = is_periodic ?
195 const float3 &p1 = nurbs_positions[i];
196 const float3 &p2 = nurbs_positions[i + 1];
197 const float3 displacement = (p2 - p1) / divisor;
198 const int num_handles_on_segment = divisor < 3 ? 1 : 2;
199 for (
int j :
IndexRange(1, num_handles_on_segment)) {
200 handle_positions.
append(p1 + (displacement * j));
205 const int last_index = nurbs_positions_num - 1;
208 nurbs_positions[last_index - 1] +
209 ((nurbs_positions[last_index] - nurbs_positions[last_index - 1]) / 3));
212 handle_positions.
append(nurbs_positions[last_index - 1]);
213 handle_positions.
append(2 * nurbs_positions[last_index] - nurbs_positions[last_index - 1]);
217 for (
const int i :
IndexRange(nurbs_positions_num)) {
221 handle_positions.
append(nurbs_positions[i]);
223 if (nurbs_positions_num % 3 == 1) {
226 else if (nurbs_positions_num % 3 == 2) {
227 const int last_index = nurbs_positions_num - 1;
228 handle_positions.
append(2 * nurbs_positions[last_index] - nurbs_positions[last_index - 1]);
232 return handle_positions;
241 for (
const int i : bezier_positions.
index_range()) {
243 handle_positions[i * 2], handle_positions[i * 2 + 1], 0.5f);
260 return cyclic ? src_size : src_size - 2;
262 return (src_size + 1) / 3;
283 for (const int i : range) {
284 sizes[i] = curves.points_for_curve(i).size();
307 if (!(id.is_named() && ELEM(id,
"tilt",
"radius"))) {
318 attributes.
dst.append(dst_attribute.
span);
319 attributes.
attributes.append(std::move(dst_attribute));
339 for (const int i : selection.slice(range)) {
340 dst_offsets[i] = to_bezier_size(
341 CurveType(src_types[i]), src_cyclic[i], KnotsMode(src_knot_modes[i]), dst_offsets[i]);
345 dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
350 GenericAttributes attributes;
360 auto catmull_rom_to_bezier = [&](
IndexMask selection) {
366 for (const int i : selection.slice(range)) {
367 const IndexRange src_points = src_curves.points_for_curve(i);
368 const IndexRange dst_points = dst_curves.points_for_curve(i);
369 catmull_rom_to_bezier_handles(src_positions.slice(src_points),
371 dst_handles_l.slice(dst_points),
372 dst_handles_r.slice(dst_points));
376 for (
const int i : attributes.src.index_range()) {
378 src_curves, dst_curves, selection, attributes.src[i], attributes.dst[i]);
382 auto poly_to_bezier = [&](IndexMask selection) {
386 dst_curves.calculate_bezier_auto_handles();
387 for (
const int i : attributes.src.index_range()) {
389 src_curves, dst_curves, selection, attributes.src[i], attributes.dst[i]);
393 auto bezier_to_bezier = [&](IndexMask selection) {
394 const VArraySpan<int8_t> src_types_l = src_curves.handle_types_left();
395 const VArraySpan<int8_t> src_types_r = src_curves.handle_types_right();
396 const Span<float3> src_handles_l = src_curves.handle_positions_left();
397 const Span<float3> src_handles_r = src_curves.handle_positions_right();
405 dst_curves.calculate_bezier_auto_handles();
407 for (
const int i : attributes.src.index_range()) {
409 src_curves, dst_curves, selection, attributes.src[i], attributes.dst[i]);
413 auto nurbs_to_bezier = [&](IndexMask selection) {
416 bke::curves::fill_points<float>(dst_curves, selection, 0.0f, dst_weights);
419 for (const int i : selection.slice(range)) {
420 const IndexRange src_points = src_curves.points_for_curve(i);
421 const IndexRange dst_points = dst_curves.points_for_curve(i);
422 const Span<float3> src_curve_positions = src_positions.slice(src_points);
424 KnotsMode knots_mode = KnotsMode(src_knot_modes[i]);
425 Span<float3> nurbs_positions = src_curve_positions;
426 Vector<float3> nurbs_positions_vector;
427 if (src_cyclic[i] && is_nurbs_to_bezier_one_to_one(knots_mode)) {
430 nurbs_positions_vector.extend(src_curve_positions);
431 nurbs_positions_vector.append(src_curve_positions[0]);
432 nurbs_positions_vector.append(src_curve_positions[1]);
433 nurbs_positions = nurbs_positions_vector;
434 knots_mode = NURBS_KNOT_MODE_NORMAL;
437 const Vector<float3> handle_positions = create_nurbs_to_bezier_handles(nurbs_positions,
440 scale_input_assign(handle_positions.as_span(), 2, 0, dst_handles_l.slice(dst_points));
441 scale_input_assign(handle_positions.as_span(), 2, 1, dst_handles_r.slice(dst_points));
443 create_nurbs_to_bezier_positions(
444 nurbs_positions, handle_positions, knots_mode, dst_positions.slice(dst_points));
448 for (
const int i_attribute : attributes.src.index_range()) {
450 for (const int i : selection.slice(range)) {
451 const IndexRange src_points = src_curves.points_for_curve(i);
452 const IndexRange dst_points = dst_curves.points_for_curve(i);
453 nurbs_to_bezier_assign(attributes.src[i_attribute].slice(src_points),
454 KnotsMode(src_knot_modes[i]),
455 attributes.dst[i_attribute].slice(dst_points));
462 src_curves.curve_type_counts(),
464 catmull_rom_to_bezier,
469 const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert(
470 src_curves.curves_range());
472 for (
const int i : attributes.src.index_range()) {
474 src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]);
477 for (bke::GSpanAttributeWriter &
attribute : attributes.attributes) {
497 for (const int i : selection.slice(range)) {
498 dst_offsets[i] = to_nurbs_size(CurveType(src_types[i]), dst_offsets[i]);
502 dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
507 GenericAttributes attributes;
512 auto fill_weights_if_necessary = [&](
const IndexMask selection) {
513 if (!src_curves.nurbs_weights().is_empty()) {
518 auto catmull_rom_to_nurbs = [&](IndexMask selection) {
519 dst_curves.nurbs_orders_for_write().fill_indices(selection, 4);
521 fill_weights_if_necessary(selection);
524 for (const int i : selection.slice(range)) {
525 const IndexRange src_points = src_curves.points_for_curve(i);
526 const IndexRange dst_points = dst_curves.points_for_curve(i);
527 catmull_rom_to_nurbs_positions(
528 src_positions.slice(src_points), src_cyclic[i], dst_positions.slice(dst_points));
532 for (
const int i_attribute : attributes.src.index_range()) {
534 for (const int i : selection.slice(range)) {
535 const IndexRange src_points = src_curves.points_for_curve(i);
536 const IndexRange dst_points = dst_curves.points_for_curve(i);
537 bezier_generic_to_nurbs(attributes.src[i_attribute].slice(src_points),
538 attributes.dst[i_attribute].slice(dst_points));
544 auto poly_to_nurbs = [&](IndexMask selection) {
545 dst_curves.nurbs_orders_for_write().fill_indices(selection, 4);
547 fill_weights_if_necessary(selection);
551 if (src_cyclic.is_single()) {
552 dst_curves.nurbs_knots_modes_for_write().fill_indices(
557 VArraySpan<bool> cyclic{src_cyclic};
558 MutableSpan<int8_t> knots_modes = dst_curves.nurbs_knots_modes_for_write();
560 for (const int i : selection.slice(range)) {
561 knots_modes[i] = cyclic[i] ? NURBS_KNOT_MODE_NORMAL : NURBS_KNOT_MODE_ENDPOINT;
566 for (
const int i_attribute : attributes.src.index_range()) {
570 attributes.src[i_attribute],
571 attributes.dst[i_attribute]);
575 auto bezier_to_nurbs = [&](IndexMask selection) {
576 const Span<float3> src_handles_l = src_curves.handle_positions_left();
577 const Span<float3> src_handles_r = src_curves.handle_positions_right();
579 dst_curves.nurbs_orders_for_write().fill_indices(selection, 4);
581 fill_weights_if_necessary(selection);
584 for (const int i : selection.slice(range)) {
585 const IndexRange src_points = src_curves.points_for_curve(i);
586 const IndexRange dst_points = dst_curves.points_for_curve(i);
587 bezier_positions_to_nurbs(src_positions.slice(src_points),
588 src_handles_l.slice(src_points),
589 src_handles_r.slice(src_points),
590 dst_positions.slice(dst_points));
594 for (
const int i_attribute : attributes.src.index_range()) {
596 for (const int i : selection.slice(range)) {
597 const IndexRange src_points = src_curves.points_for_curve(i);
598 const IndexRange dst_points = dst_curves.points_for_curve(i);
599 bezier_generic_to_nurbs(attributes.src[i_attribute].slice(src_points),
600 attributes.dst[i_attribute].slice(dst_points));
606 auto nurbs_to_nurbs = [&](IndexMask selection) {
609 if (!src_curves.nurbs_weights().is_empty()) {
613 src_curves.nurbs_weights(),
614 dst_curves.nurbs_weights_for_write());
617 for (
const int i_attribute : attributes.src.index_range()) {
621 attributes.src[i_attribute],
622 attributes.dst[i_attribute]);
627 src_curves.curve_type_counts(),
629 catmull_rom_to_nurbs,
634 const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert(
635 src_curves.curves_range());
637 for (
const int i : attributes.src.index_range()) {
639 src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]);
642 for (bke::GSpanAttributeWriter &
attribute : attributes.attributes) {
684 curves.fill_curve_types(selection, dst_type);
685 curves.remove_attributes_based_on_types();
typedef float(TangentPoint)[2]
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
@ NURBS_KNOT_MODE_ENDPOINT
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
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 Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise 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
GSpan get_internal_span() const
IndexRange index_range() const
constexpr IndexRange drop_back(int64_t n) const
constexpr IndexRange drop_front(int64_t n) const
constexpr T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr T & first() const
constexpr const T & first() const
constexpr const T & last(const int64_t n=0) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
bool is_builtin(const AttributeIDRef &attribute_id) const
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
bool for_all(const AttributeForeachCallback fn) const
void remove_attributes_based_on_types()
VArray< int8_t > nurbs_knots_modes() const
Span< float3 > positions() const
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
GSpanAttributeWriter lookup_or_add_for_write_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefault())
SyclQueue void void * src
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
void accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
int segments_num(const int points_num, const bool cyclic)
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
void fill_points(const CurvesGeometry &curves, IndexMask curve_selection, GPointer value, GMutableSpan dst)
void copy_point_data(const CurvesGeometry &src_curves, const CurvesGeometry &dst_curves, Span< IndexRange > curve_ranges, GSpan src, GMutableSpan dst)
void foreach_curve_by_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, IndexMask selection, FunctionRef< void(IndexMask)> catmull_rom_fn, FunctionRef< void(IndexMask)> poly_fn, FunctionRef< void(IndexMask)> bezier_fn, FunctionRef< void(IndexMask)> nurbs_fn)
static Vector< float3 > create_nurbs_to_bezier_handles(const Span< float3 > nurbs_positions, const KnotsMode knots_mode)
static bke::CurvesGeometry convert_curves_to_nurbs(const bke::CurvesGeometry &src_curves, const IndexMask selection)
static void retrieve_generic_point_attributes(const bke::AttributeAccessor &src_attributes, bke::MutableAttributeAccessor &dst_attributes, GenericAttributes &attributes)
static bool is_nurbs_to_bezier_one_to_one(const KnotsMode knots_mode)
static bke::CurvesGeometry convert_curves_trivial(const bke::CurvesGeometry &src_curves, const IndexMask selection, const CurveType dst_type)
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 bool conversion_can_change_point_num(const CurveType dst_type)
bke::CurvesGeometry convert_curves(const bke::CurvesGeometry &src_curves, IndexMask selection, CurveType dst_type)
static void bezier_generic_to_nurbs(const Span< T > src, MutableSpan< T > dst)
static void catmull_rom_to_nurbs_positions(const Span< float3 > src_positions, const bool cyclic, MutableSpan< float3 > dst_positions)
bool try_curves_conversion_in_place(IndexMask selection, CurveType dst_type, FunctionRef< bke::CurvesGeometry &()> get_writable_curves_fn)
static void retrieve_curve_sizes(const bke::CurvesGeometry &curves, MutableSpan< int > sizes)
static void scale_input_assign(const Span< T > src, const int scale, const int offset, MutableSpan< T > dst)
static bke::CurvesGeometry convert_curves_to_bezier(const bke::CurvesGeometry &src_curves, const IndexMask selection)
static int to_bezier_size(const CurveType src_type, const bool cyclic, const KnotsMode knots_mode, const int src_size)
T interpolate(const T &a, const T &b, const FactorT &t)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Vector< bke::GSpanAttributeWriter > attributes
Vector< GMutableSpan > dst