This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/blenkernel/intern/curves_utils.cc
Hans Goudey 9e393fc2f1 Curves: Port set type node to new data-block
This commit ports the "Set Spline Type" node to the new curves type.
Performance should be improved in similar ways to the other refactors
from the conversion task (T95443). Converting to and from Catmull Rom
curves is now supported. There are a few cases where a lot of work can
be skipped: when the number of points doesn't change, and when the
types already match the goal type.

The refactor has a few other explicit goals as well:
 - Don't count on initialization of attribute arrays when they are
   first allocated.
 - Avoid copying the entire data-block when possible.
 - Make decisions about which attributes to copy when changing curves
   more obvious.
 - Use higher-level methods to copy data between curve points.
 - Optimize for the common cases of single types and full selections.
 - Process selected curves of the same types in the same loop.

The Bezier to NURBS conversion is written by Piotr Makal (@pmakal).

Differential Revision: https://developer.blender.org/D14769
2022-06-08 15:37:46 +02:00

123 lines
4.6 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include "BLI_index_mask_ops.hh"
#include "BKE_curves_utils.hh"
namespace blender::bke::curves {
void fill_curve_counts(const bke::CurvesGeometry &curves,
const Span<IndexRange> curve_ranges,
MutableSpan<int> counts)
{
threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) {
for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) {
threading::parallel_for(curves_range, 4096, [&](IndexRange range) {
for (const int i : range) {
counts[i] = curves.points_for_curve(i).size();
}
});
}
});
}
void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, const int start_offset)
{
int offset = start_offset;
for (const int i : counts_to_offsets.index_range().drop_back(1)) {
const int count = counts_to_offsets[i];
BLI_assert(count > 0);
counts_to_offsets[i] = offset;
offset += count;
}
counts_to_offsets.last() = offset;
}
void copy_point_data(const CurvesGeometry &src_curves,
const CurvesGeometry &dst_curves,
const Span<IndexRange> curve_ranges,
const GSpan src,
GMutableSpan dst)
{
threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange range) {
for (const IndexRange range : curve_ranges.slice(range)) {
const IndexRange src_points = src_curves.points_for_curves(range);
const IndexRange dst_points = dst_curves.points_for_curves(range);
/* The arrays might be large, so a threaded copy might make sense here too. */
dst.slice(dst_points).copy_from(src.slice(src_points));
}
});
}
void copy_point_data(const CurvesGeometry &src_curves,
const CurvesGeometry &dst_curves,
const IndexMask src_curve_selection,
const GSpan src,
GMutableSpan dst)
{
threading::parallel_for(src_curve_selection.index_range(), 512, [&](IndexRange range) {
for (const int i : src_curve_selection.slice(range)) {
const IndexRange src_points = src_curves.points_for_curve(i);
const IndexRange dst_points = dst_curves.points_for_curve(i);
/* The arrays might be large, so a threaded copy might make sense here too. */
dst.slice(dst_points).copy_from(src.slice(src_points));
}
});
}
void fill_points(const CurvesGeometry &curves,
const IndexMask curve_selection,
const GPointer value,
GMutableSpan dst)
{
BLI_assert(*value.type() == dst.type());
const CPPType &type = dst.type();
threading::parallel_for(curve_selection.index_range(), 512, [&](IndexRange range) {
for (const int i : curve_selection.slice(range)) {
const IndexRange points = curves.points_for_curve(i);
type.fill_assign_n(value.get(), dst.slice(curves.points_for_curve(i)).data(), points.size());
}
});
}
IndexMask indices_for_type(const VArray<int8_t> &types,
const std::array<int, CURVE_TYPES_NUM> &type_counts,
const CurveType type,
const IndexMask selection,
Vector<int64_t> &r_indices)
{
if (type_counts[type] == types.size()) {
return selection;
}
if (types.is_single()) {
return types.get_internal_single() == type ? IndexMask(types.size()) : IndexMask(0);
}
Span<int8_t> types_span = types.get_internal_span();
return index_mask_ops::find_indices_based_on_predicate(
selection, 4096, r_indices, [&](const int index) { return types_span[index] == type; });
}
void foreach_curve_by_type(const VArray<int8_t> &types,
const std::array<int, CURVE_TYPES_NUM> &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<int64_t> catmull_rom;
Vector<int64_t> poly;
Vector<int64_t> bezier;
Vector<int64_t> nurbs;
catmull_rom_fn(indices_for_type(types, counts, CURVE_TYPE_CATMULL_ROM, selection, catmull_rom));
poly_fn(indices_for_type(types, counts, CURVE_TYPE_POLY, selection, poly));
bezier_fn(indices_for_type(types, counts, CURVE_TYPE_BEZIER, selection, bezier));
nurbs_fn(indices_for_type(types, counts, CURVE_TYPE_NURBS, selection, nurbs));
}
} // namespace blender::bke::curves