BLI: Simplify and extend OffsetIndices class

Add `index_range()` and `is_empty()` functions, rename `ranges_num()`
to `size()` (clarifying the final extra integer as an implementation
detail). Also remove the `size(index)` function which gave almost the
same assembly as `[index].size()` (https://godbolt.org/z/PYzqYs3Kr).
This commit is contained in:
Hans Goudey
2023-03-20 13:34:04 -04:00
parent 23c5e06932
commit 309553fc07
15 changed files with 60 additions and 59 deletions

View File

@@ -254,7 +254,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
int poly_offset = 0;
for (const int i_main : info.main.curves_range()) {
const bool main_cyclic = info.main_cyclic[i_main];
const int main_point_num = main_offsets.size(i_main);
const int main_point_num = main_offsets[i_main].size();
const int main_segment_num = curves::segments_num(main_point_num, main_cyclic);
for (const int i_profile : info.profile.curves_range()) {
result.vert[mesh_index] = vert_offset;
@@ -266,7 +266,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
result.profile_indices[mesh_index] = i_profile;
const bool profile_cyclic = info.profile_cyclic[i_profile];
const int profile_point_num = profile_offsets.size(i_profile);
const int profile_point_num = profile_offsets[i_profile].size();
const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic);
const bool has_caps = fill_caps && !main_cyclic && profile_cyclic && profile_point_num > 2;

View File

@@ -864,7 +864,7 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
const OffsetIndices points_by_curve = this->points_by_curve();
const IndexRange points = points_by_curve[curve_index];
BLI_assert(src.size() == points.size());
BLI_assert(dst.size() == this->evaluated_points_by_curve().size(curve_index));
BLI_assert(dst.size() == this->evaluated_points_by_curve()[curve_index].size());
evaluate_generic_data_for_curve(curve_index,
points,
this->curve_types(),

View File

@@ -16,7 +16,7 @@ void copy_curve_sizes(const OffsetIndices<int> points_by_curve,
{
threading::parallel_for(mask.index_range(), 4096, [&](IndexRange ranges_range) {
for (const int64_t i : mask.slice(ranges_range)) {
sizes[i] = points_by_curve.size(i);
sizes[i] = points_by_curve[i].size();
}
});
}
@@ -29,7 +29,7 @@ void copy_curve_sizes(const OffsetIndices<int> points_by_curve,
for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) {
threading::parallel_for(curves_range, 4096, [&](IndexRange range) {
for (const int i : range) {
sizes[i] = points_by_curve.size(i);
sizes[i] = points_by_curve[i].size();
}
});
}

View File

@@ -29,28 +29,31 @@ template<typename T> class OffsetIndices {
BLI_assert(std::is_sorted(offsets_.begin(), offsets_.end()));
}
T size(const int64_t index) const
{
BLI_assert(index >= 0);
BLI_assert(index < offsets_.size() - 1);
const int64_t begin = offsets_[index];
const int64_t end = offsets_[index + 1];
const int64_t size = end - begin;
return size;
}
/** Return the total number of elements in the the referenced arrays. */
T total_size() const
{
return offsets_.last();
}
/** Return the number of ranges encoded by the offsets. */
T ranges_num() const
/**
* Return the number of ranges encoded by the offsets, not including the last value used
* internally.
*/
int64_t size() const
{
return offsets_.size() - 1;
}
bool is_empty() const
{
return this->size() == 0;
}
IndexRange index_range() const
{
return IndexRange(this->size());
}
IndexRange operator[](const int64_t index) const
{
BLI_assert(index >= 0);

View File

@@ -111,7 +111,7 @@ static void curve_eval_render_wire_verts_edges_len_get(const blender::bke::Curve
*r_vert_len = points_by_curve.total_size();
*r_edge_len = 0;
for (const int i : curves.curves_range()) {
*r_edge_len += blender::bke::curves::segments_num(points_by_curve.size(i), cyclic[i]);
*r_edge_len += blender::bke::curves::segments_num(points_by_curve[i].size(), cyclic[i]);
}
}

View File

@@ -525,8 +525,9 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
[&](const IndexRange curves_range, const FindClosestData &init) {
FindClosestData best_match = init;
for (const int curve_i : curves_range) {
if (points_by_curve.size(curve_i) == 1) {
const float3 pos = deformation.positions[points_by_curve[curve_i].first()];
const IndexRange points = points_by_curve[curve_i];
if (points.size() == 1) {
const float3 pos = deformation.positions[points.first()];
/* Find the position of the point in screen space. */
float2 pos_proj;
@@ -548,7 +549,7 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
@@ -658,19 +659,18 @@ bool select_box(const ViewContext &vc,
else if (selection_domain == ATTR_DOMAIN_CURVE) {
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) {
if (points_by_curve.size(curve_i) == 1) {
const IndexRange points = points_by_curve[curve_i];
if (points.size() == 1) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(vc.region,
deformation.positions[points_by_curve[curve_i].first()],
pos_proj,
projection.ptr());
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[points.first()], pos_proj, projection.ptr());
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
}
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
@@ -736,12 +736,11 @@ bool select_lasso(const ViewContext &vc,
else if (selection_domain == ATTR_DOMAIN_CURVE) {
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) {
if (points_by_curve.size(curve_i) == 1) {
const IndexRange points = points_by_curve[curve_i];
if (points.size() == 1) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(vc.region,
deformation.positions[points_by_curve[curve_i].first()],
pos_proj,
projection.ptr());
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[points.first()], pos_proj, projection.ptr());
/* Check the lasso bounding box first as an optimization. */
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
BLI_lasso_is_point_inside(
@@ -751,7 +750,7 @@ bool select_lasso(const ViewContext &vc,
}
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
@@ -820,19 +819,18 @@ bool select_circle(const ViewContext &vc,
else if (selection_domain == ATTR_DOMAIN_CURVE) {
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) {
if (points_by_curve.size(curve_i) == 1) {
const IndexRange points = points_by_curve[curve_i];
if (points.size() == 1) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(vc.region,
deformation.positions[points_by_curve[curve_i].first()],
pos_proj,
projection.ptr());
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[points.first()], pos_proj, projection.ptr());
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
}
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];

View File

@@ -296,7 +296,7 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves,
interpolate_from_neighbors<int>(
neighbors_per_curve,
inputs.fallback_point_count,
[&](const int curve_i) { return old_points_by_curve.size(curve_i); },
[&](const int curve_i) { return old_points_by_curve[curve_i].size(); },
new_point_counts_per_curve);
}
else {

View File

@@ -1341,8 +1341,8 @@ static void weld_poly_find_doubles(const Span<int> corner_verts,
if (doubles_num) {
int loop_kill_num = 0;
OffsetIndices<int> doubles_offset_indices = OffsetIndices<int>(doubles_offsets);
for (const int i : IndexRange(doubles_offset_indices.ranges_num())) {
OffsetIndices<int> doubles_offset_indices(doubles_offsets);
for (const int i : doubles_offset_indices.index_range()) {
const int poly_dst = wpoly[doubles_buffer[doubles_offsets[i]]].poly_orig;
for (const int offset : doubles_offset_indices[i].drop_front(1)) {

View File

@@ -334,7 +334,7 @@ static CurvesGeometry resample_to_uniform(const CurvesGeometry &src_curves,
dst.slice(dst_points));
}
else {
evaluated_buffer.reinitialize(sizeof(T) * evaluated_points_by_curve.size(i_curve));
evaluated_buffer.reinitialize(sizeof(T) * evaluated_points_by_curve[i_curve].size());
MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>();
src_curves.interpolate_to_evaluated(i_curve, src.slice(src_points), evaluated);

View File

@@ -301,7 +301,7 @@ static bke::CurvesGeometry convert_curves_to_bezier(
dst_offsets[i] = to_bezier_size(CurveType(src_types[i]),
src_cyclic[i],
KnotsMode(src_knot_modes[i]),
src_points_by_curve.size(i));
src_points_by_curve[i].size());
}
});
offset_indices::accumulate_counts_to_offsets(dst_offsets);
@@ -489,7 +489,7 @@ static bke::CurvesGeometry convert_curves_to_nurbs(
bke::curves::copy_curve_sizes(src_points_by_curve, unselected_ranges, dst_offsets);
threading::parallel_for(selection.index_range(), 1024, [&](IndexRange range) {
for (const int i : selection.slice(range)) {
dst_offsets[i] = to_nurbs_size(CurveType(src_types[i]), src_points_by_curve.size(i));
dst_offsets[i] = to_nurbs_size(CurveType(src_types[i]), src_points_by_curve[i].size());
}
});
offset_indices::accumulate_counts_to_offsets(dst_offsets);

View File

@@ -129,7 +129,7 @@ static bke::curves::CurvePoint lookup_point_bezier(
const int num_curve_points)
{
if (bke::curves::bezier::has_vector_handles(
num_curve_points, evaluated_points_by_curve.size(curve_index), cyclic, resolution)) {
num_curve_points, evaluated_points_by_curve[curve_index].size(), cyclic, resolution)) {
const Span<int> bezier_offsets = src_curves.bezier_evaluated_offsets_for_curve(curve_index);
return lookup_point_bezier(
bezier_offsets, accumulated_lengths, sample_length, cyclic, num_curve_points);
@@ -176,7 +176,7 @@ static bke::curves::CurvePoint lookup_curve_point(
/* Handle evaluated curve. */
BLI_assert(resolution > 0);
return lookup_point_polygonal(
accumulated_lengths, sample_length, cyclic, evaluated_points_by_curve.size(curve_index));
accumulated_lengths, sample_length, cyclic, evaluated_points_by_curve[curve_index].size());
}
}
@@ -793,7 +793,7 @@ static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
const IndexRange src_points = src_points_by_curve[curve_i];
/* Interpolate onto the evaluated point domain and sample the evaluated domain. */
evaluated_buffer.reinitialize(sizeof(T) * src_evaluated_points_by_curve.size(curve_i));
evaluated_buffer.reinitialize(sizeof(T) * src_evaluated_points_by_curve[curve_i].size());
MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>();
src_curves.interpolate_to_evaluated(curve_i, attribute.src.slice(src_points), evaluated);
sample_interval_linear<T>(evaluated,
@@ -849,10 +849,10 @@ static void compute_curve_trim_parameters(const bke::CurvesGeometry &curves,
int point_count;
if (curve_type == CURVE_TYPE_NURBS) {
/* The result curve is a poly curve. */
point_count = evaluated_points_by_curve.size(curve_i);
point_count = evaluated_points_by_curve[curve_i].size();
}
else {
point_count = points_by_curve.size(curve_i);
point_count = points_by_curve[curve_i].size();
}
if (point_count == 1) {
/* Single point. */

View File

@@ -151,7 +151,7 @@ class CurvePointCountInput final : public bke::CurvesFieldInput {
}
const OffsetIndices points_by_curve = curves.points_by_curve();
return VArray<int>::ForFunc(curves.curves_num(), [points_by_curve](const int64_t curve_i) {
return points_by_curve.size(curve_i);
return points_by_curve[curve_i].size();
});
}

View File

@@ -115,7 +115,7 @@ static void threaded_id_offset_copy(const OffsetIndices<int> offsets,
MutableSpan<int> all_dst)
{
BLI_assert(offsets.total_size() == all_dst.size());
threading::parallel_for(IndexRange(offsets.ranges_num()), 512, [&](IndexRange range) {
threading::parallel_for(offsets.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
MutableSpan<int> dst = all_dst.slice(offsets[i]);
if (dst.is_empty()) {
@@ -280,7 +280,7 @@ static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves,
const int i_src_curve = selection[i_selection];
const Span<int> curve_src = src.slice(src_points_by_curve[i_src_curve]);
const IndexRange duplicates_range = offsets[i_selection];
for (const int i_duplicate : IndexRange(offsets.size(i_selection)).drop_front(1)) {
for (const int i_duplicate : IndexRange(offsets[i_selection].size()).drop_front(1)) {
const int i_dst_curve = duplicates_range[i_duplicate];
copy_hashed_ids(curve_src, i_duplicate, dst.slice(dst_points_by_curve[i_dst_curve]));
}
@@ -326,7 +326,7 @@ static void duplicate_curves(GeometrySet &geometry_set,
curve_offset_data[i_curve] = dst_curves_num;
point_offset_data[i_curve] = dst_points_num;
dst_curves_num += count;
dst_points_num += count * points_by_curve.size(selection[i_curve]);
dst_points_num += count * points_by_curve[selection[i_curve]].size();
}
curve_offset_data.last() = dst_curves_num;
point_offset_data.last() = dst_points_num;

View File

@@ -20,7 +20,7 @@ static VArray<int> construct_curve_point_count_gvarray(const bke::CurvesGeometry
const eAttrDomain domain)
{
const OffsetIndices points_by_curve = curves.points_by_curve();
auto count_fn = [points_by_curve](int64_t i) { return points_by_curve.size(i); };
auto count_fn = [points_by_curve](int64_t i) { return points_by_curve[i].size(); };
if (domain == ATTR_DOMAIN_CURVE) {
return VArray<int>::ForFunc(curves.curves_num(), count_fn);

View File

@@ -74,9 +74,9 @@ static Map<int, int> compute_points_per_curve_by_group(
const OffsetIndices points_by_curve = guide_curves.points_by_curve();
Map<int, int> points_per_curve_by_group;
for (const auto &[group, guide_curve_indices] : guides_by_group.items()) {
int group_control_points = points_by_curve.size(guide_curve_indices[0]);
int group_control_points = points_by_curve[guide_curve_indices[0]].size();
for (const int guide_curve_i : guide_curve_indices.as_span().drop_front(1)) {
const int control_points = points_by_curve.size(guide_curve_i);
const int control_points = points_by_curve[guide_curve_i].size();
if (group_control_points != control_points) {
group_control_points = -1;
break;
@@ -260,7 +260,7 @@ static void compute_point_counts_per_child(const bke::CurvesGeometry &guide_curv
for (const int neighbor_i : IndexRange(neighbor_count)) {
const int neighbor_index = neighbor_indices[neighbor_i];
const float neighbor_weight = neighbor_weights[neighbor_i];
const int neighbor_points = guide_points_by_curve.size(neighbor_index);
const int neighbor_points = guide_points_by_curve[neighbor_index].size();
neighbor_points_weighted_sum += neighbor_weight * float(neighbor_points);
}
const int points_in_child = std::max<int>(1, roundf(neighbor_points_weighted_sum));
@@ -282,7 +282,7 @@ static void parameterize_guide_curves(const bke::CurvesGeometry &guide_curves,
threading::parallel_for(guide_curves.curves_range(), 1024, [&](const IndexRange range) {
for (const int guide_curve_i : range) {
r_parameterized_guide_offsets[guide_curve_i] = length_parameterize::segments_num(
guide_points_by_curve.size(guide_curve_i), false);
guide_points_by_curve[guide_curve_i].size(), false);
}
});
offset_indices::accumulate_counts_to_offsets(r_parameterized_guide_offsets);