This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/BLI_offset_indices.hh
Jacques Lucke 2c2178549b Curves: add OffsetIndices abstraction
This changes how we access the points that correspond to each curve in a `CurvesGeometry`.
Previously, `CurvesGeometry::points_for_curve(int curve_index) -> IndexRange`
was called for every curve in many loops. Now one has to call
`CurvesGeometry::points_by_curve() -> OffsetIndices` before the
loop and use the returned value inside the loop.

While this is a little bit more verbose in general, it has some benefits:
* Better standardization of how "offset indices" are used. The new data
  structure can be used independent of curves.
* Allows for better data oriented design. Generally, we want to retrieve
  all the arrays we need for a loop first and then do the processing.
  Accessing the old `CurvesGeometry::points_for_curve(...)` did not follow
  that design because it hid the underlying offset array.
* Makes it easier to pass the offsets to a function without having to
  pass the entire `CurvesGeometry`.
* Can improve performance in theory due to one less memory access
  because `this` does not have to be dereferenced every time.
  This likely doesn't have a noticable impact in practice.

Differential Revision: https://developer.blender.org/D17025
2023-01-18 11:52:37 +01:00

71 lines
2.1 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_index_range.hh"
#include "BLI_span.hh"
namespace blender::offset_indices {
/**
* References an array of ascending indices. A pair of consecutive indices encode an index range.
* Another common way to store the same kind of data is to store the start and size of every range
* separately. Using offsets instead halves the memory consumption. The downside is that the
* array has to be one element longer than the total number of ranges. The extra element is
* necessary to be able to get the last index range without requiring an extra branch for the case.
*
* This class is a thin wrapper around such an array that makes it easy to retrieve the index range
* at a specific index.
*/
template<typename T> class OffsetIndices {
private:
static_assert(std::is_integral_v<T>);
Span<T> offsets_;
public:
OffsetIndices(const Span<T> offsets) : offsets_(offsets)
{
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;
}
IndexRange operator[](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 IndexRange(begin, size);
}
IndexRange operator[](const IndexRange indices) const
{
const int64_t begin = offsets_[indices.start()];
const int64_t end = offsets_[indices.one_after_last()];
const int64_t size = end - begin;
return IndexRange(begin, size);
}
};
/**
* Turn an array of sizes into the offset at each index including all previous sizes.
*/
void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, int start_offset = 0);
} // namespace blender::offset_indices
namespace blender {
using offset_indices::OffsetIndices;
}