Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/curves_geometry.cc')
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc253
1 files changed, 232 insertions, 21 deletions
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 3eea579230a..dd91e788e5a 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -84,6 +84,42 @@ CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other)
return *this;
}
+/* The source should be empty, but in a valid state so that using it further will work. */
+static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
+{
+ dst.point_size = src.point_size;
+ std::swap(dst.point_data, src.point_data);
+ CustomData_free(&src.point_data, src.point_size);
+ src.point_size = 0;
+
+ dst.curve_size = src.curve_size;
+ std::swap(dst.curve_data, dst.curve_data);
+ CustomData_free(&src.curve_data, src.curve_size);
+ src.curve_size = 0;
+
+ std::swap(dst.curve_offsets, src.curve_offsets);
+ MEM_SAFE_FREE(src.curve_offsets);
+
+ std::swap(dst.runtime, src.runtime);
+
+ src.update_customdata_pointers();
+ dst.update_customdata_pointers();
+}
+
+CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
+ : CurvesGeometry(other.point_size, other.curve_size)
+{
+ move_curves_geometry(*this, other);
+}
+
+CurvesGeometry &CurvesGeometry::operator=(CurvesGeometry &&other)
+{
+ if (this != &other) {
+ move_curves_geometry(*this, other);
+ }
+ return *this;
+}
+
CurvesGeometry::~CurvesGeometry()
{
CustomData_free(&this->point_data, this->point_size);
@@ -124,29 +160,83 @@ int CurvesGeometry::evaluated_points_size() const
IndexRange CurvesGeometry::range_for_curve(const int index) const
{
+ BLI_assert(this->curve_size > 0);
+ BLI_assert(this->curve_offsets != nullptr);
const int offset = this->curve_offsets[index];
const int offset_next = this->curve_offsets[index + 1];
return {offset, offset_next - offset};
}
-VArray<int8_t> CurvesGeometry::curve_types() const
+IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
+{
+ BLI_assert(this->curve_size > 0);
+ BLI_assert(this->curve_offsets != nullptr);
+ const int offset = this->curve_offsets[curves.start()];
+ const int offset_next = this->curve_offsets[curves.one_after_last()];
+ return {offset, offset_next - offset};
+}
+
+static int domain_size(const CurvesGeometry &curves, const AttributeDomain domain)
{
- if (const int8_t *data = (const int8_t *)CustomData_get_layer_named(
- &this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str())) {
- return VArray<int8_t>::ForSpan({data, this->curve_size});
+ return domain == ATTR_DOMAIN_POINT ? curves.points_size() : curves.curves_size();
+}
+
+static CustomData &domain_custom_data(CurvesGeometry &curves, const AttributeDomain domain)
+{
+ return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data;
+}
+
+static const CustomData &domain_custom_data(const CurvesGeometry &curves,
+ const AttributeDomain domain)
+{
+ return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data;
+}
+
+template<typename T>
+static VArray<T> get_varray_attribute(const CurvesGeometry &curves,
+ const AttributeDomain domain,
+ const StringRefNull name,
+ const T default_value)
+{
+ const int size = domain_size(curves, domain);
+ const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>());
+ const CustomData &custom_data = domain_custom_data(curves, domain);
+
+ const T *data = (const T *)CustomData_get_layer_named(&custom_data, type, name.c_str());
+ if (data != nullptr) {
+ return VArray<T>::ForSpan(Span<T>(data, size));
+ }
+ return VArray<T>::ForSingle(default_value, size);
+}
+
+template<typename T>
+static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
+ const AttributeDomain domain,
+ const StringRefNull name)
+{
+ const int size = domain_size(curves, domain);
+ const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>());
+ CustomData &custom_data = domain_custom_data(curves, domain);
+
+ T *data = (T *)CustomData_duplicate_referenced_layer_named(
+ &custom_data, type, name.c_str(), size);
+ if (data != nullptr) {
+ return {data, size};
}
- return VArray<int8_t>::ForSingle(CURVE_TYPE_CATMULL_ROM, this->curve_size);
+ data = (T *)CustomData_add_layer_named(
+ &custom_data, type, CD_CALLOC, nullptr, size, name.c_str());
+ return {data, size};
+}
+
+VArray<int8_t> CurvesGeometry::curve_types() const
+{
+ return get_varray_attribute<int8_t>(
+ *this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE, CURVE_TYPE_CATMULL_ROM);
}
MutableSpan<int8_t> CurvesGeometry::curve_types()
{
- int8_t *data = (int8_t *)CustomData_add_layer_named(&this->curve_data,
- CD_PROP_INT8,
- CD_CALLOC,
- nullptr,
- this->curve_size,
- ATTR_CURVE_TYPE.c_str());
- return {data, this->curve_size};
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE);
}
MutableSpan<float3> CurvesGeometry::positions()
@@ -171,19 +261,12 @@ Span<int> CurvesGeometry::offsets() const
VArray<bool> CurvesGeometry::cyclic() const
{
- const bool *data = (const bool *)CustomData_get_layer_named(
- &this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
- if (data != nullptr) {
- return VArray<bool>::ForSpan(Span(data, this->curve_size));
- }
- return VArray<bool>::ForSingle(false, this->curve_size);
+ return get_varray_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC, false);
}
MutableSpan<bool> CurvesGeometry::cyclic()
{
- bool *data = (bool *)CustomData_add_layer_named(
- &this->curve_data, CD_PROP_BOOL, CD_CALLOC, nullptr, this->curve_size, ATTR_CYCLIC.c_str());
- return {data, this->curve_size};
+ return get_mutable_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC);
}
void CurvesGeometry::resize(const int point_size, const int curve_size)
@@ -269,6 +352,134 @@ void CurvesGeometry::update_customdata_pointers()
&this->point_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
}
+static void *ensure_customdata_layer(CustomData &custom_data,
+ const StringRefNull name,
+ const CustomDataType data_type,
+ const int tot_elements)
+{
+ for (const int other_layer_i : IndexRange(custom_data.totlayer)) {
+ CustomDataLayer &new_layer = custom_data.layers[other_layer_i];
+ if (name == StringRef(new_layer.name)) {
+ return new_layer.data;
+ }
+ }
+ return CustomData_add_layer_named(
+ &custom_data, data_type, CD_DEFAULT, nullptr, tot_elements, name.c_str());
+}
+
+static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
+ const IndexMask curves_to_delete)
+{
+ const Span<int> old_offsets = curves.offsets();
+ const Vector<IndexRange> old_curve_ranges = curves_to_delete.extract_ranges_invert(
+ curves.curves_range(), nullptr);
+ Vector<IndexRange> new_curve_ranges;
+ Vector<IndexRange> old_point_ranges;
+ Vector<IndexRange> new_point_ranges;
+ int new_tot_points = 0;
+ int new_tot_curves = 0;
+ for (const IndexRange &curve_range : old_curve_ranges) {
+ new_curve_ranges.append(IndexRange(new_tot_curves, curve_range.size()));
+ new_tot_curves += curve_range.size();
+
+ const IndexRange old_point_range = curves.range_for_curves(curve_range);
+ old_point_ranges.append(old_point_range);
+ new_point_ranges.append(IndexRange(new_tot_points, old_point_range.size()));
+ new_tot_points += old_point_range.size();
+ }
+
+ CurvesGeometry new_curves{new_tot_points, new_tot_curves};
+
+ threading::parallel_invoke(
+ /* Initialize curve offsets. */
+ [&]() {
+ MutableSpan<int> new_offsets = new_curves.offsets();
+ new_offsets.last() = new_tot_points;
+ threading::parallel_for(
+ old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+ for (const int range_i : ranges_range) {
+ const IndexRange old_curve_range = old_curve_ranges[range_i];
+ const IndexRange new_curve_range = new_curve_ranges[range_i];
+ const IndexRange old_point_range = old_point_ranges[range_i];
+ const IndexRange new_point_range = new_point_ranges[range_i];
+ const int offset_shift = new_point_range.start() - old_point_range.start();
+ const int curves_in_range = old_curve_range.size();
+ threading::parallel_for(
+ IndexRange(curves_in_range), 512, [&](const IndexRange range) {
+ for (const int i : range) {
+ const int old_curve_i = old_curve_range[i];
+ const int new_curve_i = new_curve_range[i];
+ const int old_offset = old_offsets[old_curve_i];
+ const int new_offset = old_offset + offset_shift;
+ new_offsets[new_curve_i] = new_offset;
+ }
+ });
+ }
+ });
+ },
+ /* Copy over point attributes. */
+ [&]() {
+ const CustomData &old_point_data = curves.point_data;
+ CustomData &new_point_data = new_curves.point_data;
+ for (const int layer_i : IndexRange(old_point_data.totlayer)) {
+ const CustomDataLayer &old_layer = old_point_data.layers[layer_i];
+ const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
+ const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
+
+ const void *src_buffer = old_layer.data;
+ void *dst_buffer = ensure_customdata_layer(
+ new_point_data, old_layer.name, data_type, new_tot_points);
+
+ threading::parallel_for(
+ old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+ for (const int range_i : ranges_range) {
+ const IndexRange old_point_range = old_point_ranges[range_i];
+ const IndexRange new_point_range = new_point_ranges[range_i];
+
+ type.copy_construct_n(
+ POINTER_OFFSET(src_buffer, type.size() * old_point_range.start()),
+ POINTER_OFFSET(dst_buffer, type.size() * new_point_range.start()),
+ old_point_range.size());
+ }
+ });
+ }
+ },
+ /* Copy over curve attributes. */
+ [&]() {
+ const CustomData &old_curve_data = curves.curve_data;
+ CustomData &new_curve_data = new_curves.curve_data;
+ for (const int layer_i : IndexRange(old_curve_data.totlayer)) {
+ const CustomDataLayer &old_layer = old_curve_data.layers[layer_i];
+ const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
+ const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
+
+ const void *src_buffer = old_layer.data;
+ void *dst_buffer = ensure_customdata_layer(
+ new_curve_data, old_layer.name, data_type, new_tot_points);
+
+ threading::parallel_for(
+ old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+ for (const int range_i : ranges_range) {
+ const IndexRange old_curve_range = old_curve_ranges[range_i];
+ const IndexRange new_curve_range = new_curve_ranges[range_i];
+
+ type.copy_construct_n(
+ POINTER_OFFSET(src_buffer, type.size() * old_curve_range.start()),
+ POINTER_OFFSET(dst_buffer, type.size() * new_curve_range.start()),
+ old_curve_range.size());
+ }
+ });
+ }
+ });
+
+ return new_curves;
+}
+
+void CurvesGeometry::remove_curves(const IndexMask curves_to_delete)
+{
+ *this = copy_with_removed_curves(*this, curves_to_delete);
+}
+
/** \} */
/* -------------------------------------------------------------------- */