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:
-rw-r--r--source/blender/blenkernel/BKE_curves.hh37
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc2
-rw-r--r--source/blender/blenkernel/intern/curve_to_mesh_convert.cc23
-rw-r--r--source/blender/blenkernel/intern/curves.cc2
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc48
-rw-r--r--source/blender/blenkernel/intern/curves_geometry_test.cc15
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curves.cc11
-rw-r--r--source/blender/geometry/intern/mesh_to_curve_convert.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc7
9 files changed, 92 insertions, 55 deletions
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 6e4d4d560f7..dea9c17d159 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -60,6 +60,12 @@ struct BasisCache {
class CurvesGeometryRuntime {
public:
/**
+ * The cached number of curves with each type. Unlike other caches here, this is not computed
+ * lazily, since it is needed so often and types are not adjusted much anyway.
+ */
+ std::array<int, CURVE_TYPES_NUM> type_counts;
+
+ /**
* Cache of offsets into the evaluated array for each curve, accounting for all previous
* evaluated points, Bezier curve vector segments, different resolutions per curve, etc.
*/
@@ -156,15 +162,23 @@ class CurvesGeometry : public ::CurvesGeometry {
/** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
VArray<int8_t> curve_types() const;
- /** Mutable access to curve types. Call #tag_topology_changed after changing any type. */
+ /**
+ * Mutable access to curve types. Call #tag_topology_changed and #update_curve_types after
+ * changing any type. Consider using the other methods to change types below.
+ * */
MutableSpan<int8_t> curve_types_for_write();
+ /** Set all curve types to the value and call #update_curve_types. */
+ void fill_curve_types(CurveType type);
+ /** Set the types for the curves in the selection and call #update_curve_types. */
+ void fill_curve_types(IndexMask selection, CurveType type);
+ /** Update the cached count of curves of each type, necessary after #curve_types_for_write. */
+ void update_curve_types();
bool has_curve_with_type(const CurveType type) const;
- /** Return the number of curves with each type. */
- std::array<int, CURVE_TYPES_NUM> count_curve_types() const;
-
/** Return true if all of the curves have the provided type. */
bool is_single_type(CurveType type) const;
+ /** Return the number of curves with each type. */
+ const std::array<int, CURVE_TYPES_NUM> &curve_type_counts() const;
Span<float3> positions() const;
MutableSpan<float3> positions_for_write();
@@ -624,6 +638,8 @@ Curves *curves_new_nomain(int points_num, int curves_num);
*/
Curves *curves_new_nomain_single(int points_num, CurveType type);
+std::array<int, CURVE_TYPES_NUM> calculate_type_counts(const VArray<int8_t> &types);
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -649,7 +665,18 @@ inline IndexRange CurvesGeometry::curves_range() const
inline bool CurvesGeometry::is_single_type(const CurveType type) const
{
- return this->count_curve_types()[type] == this->curves_num();
+ return this->curve_type_counts()[type] == this->curves_num();
+}
+
+inline bool CurvesGeometry::has_curve_with_type(const CurveType type) const
+{
+ return this->curve_type_counts()[type] > 0;
+}
+
+inline const std::array<int, CURVE_TYPES_NUM> &CurvesGeometry::curve_type_counts() const
+{
+ BLI_assert(this->runtime->type_counts == calculate_type_counts(this->curve_types()));
+ return this->runtime->type_counts;
}
inline IndexRange CurvesGeometry::points_for_curve(const int index) const
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index d1ec9499298..3d9dd3ecf31 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -523,6 +523,8 @@ Curves *curve_eval_to_curves(const CurveEval &curve_eval)
}
}
+ geometry.update_curve_types();
+
normal_mode.save();
nurbs_weight.save();
nurbs_order.save();
diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
index d7fd8f7a2b6..0dc46f87537 100644
--- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
+++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc
@@ -229,19 +229,10 @@ struct CurvesInfo {
/* Make sure these are spans because they are potentially accessed many times. */
VArray_Span<bool> main_cyclic;
VArray_Span<bool> profile_cyclic;
-
- /* TODO: Remove once these are cached on #CurvesGeometry. */
- std::array<int, CURVE_TYPES_NUM> main_type_counts;
- std::array<int, CURVE_TYPES_NUM> profile_type_counts;
};
static CurvesInfo get_curves_info(const CurvesGeometry &main, const CurvesGeometry &profile)
{
- return {main,
- profile,
- main.cyclic(),
- profile.cyclic(),
- main.count_curve_types(),
- profile.count_curve_types()};
+ return {main, profile, main.cyclic(), profile.cyclic()};
}
struct ResultOffsets {
@@ -360,7 +351,7 @@ static bool should_add_attribute_to_mesh(const CurveComponent &curve_component,
static GSpan evaluated_attribute_if_necessary(const GVArray &src,
const CurvesGeometry &curves,
- const Span<int> type_counts,
+ const std::array<int, CURVE_TYPES_NUM> &type_counts,
Vector<std::byte> &buffer)
{
if (type_counts[CURVE_TYPE_POLY] == curves.curves_num() && src.is_span()) {
@@ -691,7 +682,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
radii = evaluated_attribute_if_necessary(
main_component.attribute_get_for_read<float>("radius", ATTR_DOMAIN_POINT, 1.0f),
main,
- curves_info.main_type_counts,
+ main.curve_type_counts(),
eval_buffer)
.typed<float>();
}
@@ -707,7 +698,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
verts.slice(info.vert_range));
});
- if (curves_info.profile_type_counts[CURVE_TYPE_BEZIER] > 0) {
+ if (profile.curve_type_counts()[CURVE_TYPE_BEZIER] > 0) {
const VArray<int8_t> curve_types = profile.curve_types();
const VArray_Span<int8_t> handle_types_left{profile.handle_types_left()};
const VArray_Span<int8_t> handle_types_right{profile.handle_types_right()};
@@ -752,7 +743,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
curves_info,
offsets,
dst_domain,
- evaluated_attribute_if_necessary(src, main, curves_info.main_type_counts, eval_buffer),
+ evaluated_attribute_if_necessary(src, main, main.curve_type_counts(), eval_buffer),
dst.as_span());
}
else if (src_domain == ATTR_DOMAIN_CURVE) {
@@ -787,8 +778,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
curves_info,
offsets,
dst_domain,
- evaluated_attribute_if_necessary(
- src, profile, curves_info.profile_type_counts, eval_buffer),
+ evaluated_attribute_if_necessary(src, profile, profile.curve_type_counts(), eval_buffer),
dst.as_span());
}
else if (src_domain == ATTR_DOMAIN_CURVE) {
@@ -808,6 +798,7 @@ static CurvesGeometry get_curve_single_vert()
CurvesGeometry curves(1, 1);
curves.offsets_for_write().last() = 1;
curves.positions_for_write().fill(float3(0));
+ curves.fill_curve_types(CURVE_TYPE_POLY);
return curves;
}
diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc
index 5b51fb8af31..a3b40b27583 100644
--- a/source/blender/blenkernel/intern/curves.cc
+++ b/source/blender/blenkernel/intern/curves.cc
@@ -370,7 +370,7 @@ Curves *curves_new_nomain_single(const int points_num, const CurveType type)
Curves *curves = curves_new_nomain(points_num, 1);
CurvesGeometry &geometry = CurvesGeometry::wrap(curves->geometry);
geometry.offsets_for_write().last() = points_num;
- geometry.curve_types_for_write().first() = type;
+ geometry.fill_curve_types(type);
return curves;
}
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 8e97884516c..7a09b87490b 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -85,6 +85,9 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
dst.tag_topology_changed();
+ /* Though type counts are a cache, they must be copied because they are calculated eagerly. */
+ dst.runtime->type_counts = src.runtime->type_counts;
+
dst.update_customdata_pointers();
}
@@ -237,38 +240,38 @@ MutableSpan<int8_t> CurvesGeometry::curve_types_for_write()
return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE);
}
-bool CurvesGeometry::has_curve_with_type(const CurveType type) const
+void CurvesGeometry::fill_curve_types(const CurveType type)
{
- const VArray<int8_t> curve_types = this->curve_types();
- if (curve_types.is_single()) {
- return curve_types.get_internal_single() == type;
- }
- if (curve_types.is_span()) {
- return curve_types.get_internal_span().contains(type);
- }
- /* The curves types array should be a single value or a span. */
- BLI_assert_unreachable();
- return false;
+ this->curve_types_for_write().fill(type);
+ this->runtime->type_counts.fill(0);
+ this->runtime->type_counts[type] = this->curves_num();
+ this->tag_topology_changed();
}
-std::array<int, CURVE_TYPES_NUM> CurvesGeometry::count_curve_types() const
+void CurvesGeometry::fill_curve_types(const IndexMask selection, const CurveType type)
{
- using CountsType = std::array<int, CURVE_TYPES_NUM>;
+ /* A potential performance optimization is only counting the changed indices. */
+ this->curve_types_for_write().fill_indices(selection, type);
+ this->update_curve_types();
+ this->tag_topology_changed();
+}
- CountsType identity;
- identity.fill(0);
+std::array<int, CURVE_TYPES_NUM> calculate_type_counts(const VArray<int8_t> &types)
+{
+ using CountsType = std::array<int, CURVE_TYPES_NUM>;
+ CountsType counts;
+ counts.fill(0);
- const VArray<int8_t> types = this->curve_types();
if (types.is_single()) {
- identity[types.get_internal_single()] = this->curves_num();
- return identity;
+ counts[types.get_internal_single()] = types.size();
+ return counts;
}
Span<int8_t> types_span = types.get_internal_span();
return threading::parallel_reduce(
- this->curves_range(),
+ types.index_range(),
2048,
- identity,
+ counts,
[&](const IndexRange curves_range, const CountsType &init) {
CountsType result = init;
for (const int curve_index : curves_range) {
@@ -285,6 +288,11 @@ std::array<int, CURVE_TYPES_NUM> CurvesGeometry::count_curve_types() const
});
}
+void CurvesGeometry::update_curve_types()
+{
+ this->runtime->type_counts = calculate_type_counts(this->curve_types());
+}
+
Span<float3> CurvesGeometry::positions() const
{
return {(const float3 *)this->position, this->point_size};
diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc
index 56e488b9034..48493743cfc 100644
--- a/source/blender/blenkernel/intern/curves_geometry_test.cc
+++ b/source/blender/blenkernel/intern/curves_geometry_test.cc
@@ -78,7 +78,8 @@ TEST(curves_geometry, TypeCount)
CURVE_TYPE_POLY,
CURVE_TYPE_POLY,
});
- std::array<int, CURVE_TYPES_NUM> counts = curves.count_curve_types();
+ curves.update_curve_types();
+ const std::array<int, CURVE_TYPES_NUM> &counts = curves.curve_type_counts();
EXPECT_EQ(counts[CURVE_TYPE_CATMULL_ROM], 3);
EXPECT_EQ(counts[CURVE_TYPE_POLY], 3);
EXPECT_EQ(counts[CURVE_TYPE_BEZIER], 1);
@@ -88,7 +89,7 @@ TEST(curves_geometry, TypeCount)
TEST(curves_geometry, CatmullRomEvaluation)
{
CurvesGeometry curves(4, 1);
- curves.curve_types_for_write().fill(CURVE_TYPE_CATMULL_ROM);
+ curves.fill_curve_types(CURVE_TYPE_CATMULL_ROM);
curves.resolution_for_write().fill(12);
curves.offsets_for_write().last() = 4;
curves.cyclic_for_write().fill(false);
@@ -221,7 +222,7 @@ TEST(curves_geometry, CatmullRomEvaluation)
TEST(curves_geometry, CatmullRomTwoPointCyclic)
{
CurvesGeometry curves(2, 1);
- curves.curve_types_for_write().fill(CURVE_TYPE_CATMULL_ROM);
+ curves.fill_curve_types(CURVE_TYPE_CATMULL_ROM);
curves.resolution_for_write().fill(12);
curves.offsets_for_write().last() = 2;
curves.cyclic_for_write().fill(true);
@@ -233,7 +234,7 @@ TEST(curves_geometry, CatmullRomTwoPointCyclic)
TEST(curves_geometry, BezierPositionEvaluation)
{
CurvesGeometry curves(2, 1);
- curves.curve_types_for_write().fill(CURVE_TYPE_BEZIER);
+ curves.fill_curve_types(CURVE_TYPE_BEZIER);
curves.resolution_for_write().fill(12);
curves.offsets_for_write().last() = 2;
@@ -270,7 +271,7 @@ TEST(curves_geometry, BezierPositionEvaluation)
}
curves.resize(4, 2);
- curves.curve_types_for_write().fill(CURVE_TYPE_BEZIER);
+ curves.fill_curve_types(CURVE_TYPE_BEZIER);
curves.resolution_for_write().fill(9);
curves.offsets_for_write().last() = 4;
handles_left = curves.handle_positions_left_for_write();
@@ -317,7 +318,7 @@ TEST(curves_geometry, BezierPositionEvaluation)
TEST(curves_geometry, NURBSEvaluation)
{
CurvesGeometry curves(4, 1);
- curves.curve_types_for_write().fill(CURVE_TYPE_NURBS);
+ curves.fill_curve_types(CURVE_TYPE_NURBS);
curves.resolution_for_write().fill(10);
curves.offsets_for_write().last() = 4;
@@ -407,7 +408,7 @@ TEST(curves_geometry, NURBSEvaluation)
TEST(curves_geometry, BezierGenericEvaluation)
{
CurvesGeometry curves(3, 1);
- curves.curve_types_for_write().fill(CURVE_TYPE_BEZIER);
+ curves.fill_curve_types(CURVE_TYPE_BEZIER);
curves.resolution_for_write().fill(8);
curves.offsets_for_write().last() = 3;
diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc
index 4796135b32f..bc9bba3ee2f 100644
--- a/source/blender/blenkernel/intern/geometry_component_curves.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curves.cc
@@ -291,6 +291,15 @@ static void tag_component_topology_changed(GeometryComponent &component)
}
}
+static void tag_component_curve_types_changed(GeometryComponent &component)
+{
+ Curves *curves = get_curves_from_component_for_write(component);
+ if (curves) {
+ blender::bke::CurvesGeometry::wrap(curves->geometry).update_curve_types();
+ blender::bke::CurvesGeometry::wrap(curves->geometry).tag_topology_changed();
+ }
+}
+
static void tag_component_positions_changed(GeometryComponent &component)
{
Curves *curves = get_curves_from_component_for_write(component);
@@ -506,7 +515,7 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
curve_access,
make_array_read_attribute<int8_t>,
make_array_write_attribute<int8_t>,
- tag_component_topology_changed);
+ tag_component_curve_types_changed);
static BuiltinCustomDataLayerProvider resolution("resolution",
ATTR_DOMAIN_CURVE,
diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc
index a8eaa828caf..a1e5f0216b6 100644
--- a/source/blender/geometry/intern/mesh_to_curve_convert.cc
+++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc
@@ -38,7 +38,7 @@ static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_componen
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
curves.offsets_for_write().drop_back(1).copy_from(curve_offsets);
curves.offsets_for_write().last() = vert_indices.size();
- curves.curve_types_for_write().fill(CURVE_TYPE_POLY);
+ curves.fill_curve_types(CURVE_TYPE_POLY);
curves.cyclic_for_write().fill(false);
curves.cyclic_for_write().slice(cyclic_curves).fill(true);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index fababfd027b..121ee015d2d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -173,7 +173,6 @@ static void gather_point_attributes_to_interpolate(const CurveComponent &src_com
{
const Curves &dst_curves_id = *dst_component.get_for_read();
const bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id.geometry);
- const std::array<int, CURVE_TYPES_NUM> type_counts = dst_curves.count_curve_types();
VectorSet<AttributeIDRef> ids;
VectorSet<AttributeIDRef> ids_no_interpolation;
@@ -182,7 +181,7 @@ static void gather_point_attributes_to_interpolate(const CurveComponent &src_com
if (meta_data.domain != ATTR_DOMAIN_POINT) {
return true;
}
- if (!interpolate_attribute_to_curves(id, type_counts)) {
+ if (!interpolate_attribute_to_curves(id, dst_curves.curve_type_counts())) {
return true;
}
if (interpolate_attribute_to_poly_curve(id)) {
@@ -318,7 +317,7 @@ static Curves *resample_to_uniform_count(const CurveComponent &src_component,
dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
/* All resampled curves are poly curves. */
- dst_curves.curve_types_for_write().fill_indices(selection, CURVE_TYPE_POLY);
+ dst_curves.fill_curve_types(selection, CURVE_TYPE_POLY);
VArray<bool> curves_cyclic = src_curves.cyclic();
VArray<int8_t> curve_types = src_curves.curve_types();
@@ -464,7 +463,7 @@ static Curves *resample_to_evaluated(const CurveComponent &src_component,
CD_DUPLICATE,
src_curves.curves_num());
/* All resampled curves are poly curves. */
- dst_curves.curve_types_for_write().fill_indices(selection, CURVE_TYPE_POLY);
+ dst_curves.fill_curve_types(selection, CURVE_TYPE_POLY);
MutableSpan<int> dst_offsets = dst_curves.offsets_for_write();
src_curves.ensure_evaluated_offsets();