mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Add CubicCurve::segment_count
+ iter_samples
adjustment (#8711)
## Objective - Provide a way to use `CubicCurve` non-iter methods - Accept a `FnMut` over a `fn` pointer on `iter_samples` - Improve `build_*_cubic_100_points` benchmark by -45% (this means they are twice as fast) ### Solution Previously, the only way to iterate over an evenly spaced set of points on a `CubicCurve` was to use one of the `iter_*` methods. The return value of those methods were bound by `&self` lifetime, making them unusable in certain contexts. Furthermore, other `CubicCurve` methods (`position`, `velocity`, `acceleration`) required normalizing `t` over the `CubicCurve`'s internal segment count. There were no way to access this segment count, making those methods pretty much unusable. The newly added `segment_count` allows accessing the segment count. `iter_samples` used to accept a `fn`, a function pointer. This is surprising and contrary to the rust stdlib APIs, which accept `Fn` traits for `Iterator` combinators. `iter_samples` now accepts a `FnMut`. I don't trust a bit the bevy benchmark suit, but according to it, this doubles (-45%) the performance on the `build_pos_cubic_100_points` and `build_accel_cubic_100_points` benchmarks. --- ## Changelog - Added the `CubicCurve::segments` method to access the underlying segments of a cubic curve - Allow closures as `CubicCurve::iter_samples` `sample_function` argument.
This commit is contained in:
parent
ca81d3e435
commit
c8167c1276
1 changed files with 30 additions and 13 deletions
|
@ -472,22 +472,39 @@ impl<P: Point> CubicCurve<P> {
|
|||
/// A flexible iterator used to sample curves with arbitrary functions.
|
||||
///
|
||||
/// This splits the curve into `subdivisions` of evenly spaced `t` values across the
|
||||
/// length of the curve from start (t = 0) to end (t = 1), returning an iterator that evaluates
|
||||
/// the curve with the supplied `sample_function` at each `t`.
|
||||
/// length of the curve from start (t = 0) to end (t = n), where `n = self.segment_count()`,
|
||||
/// returning an iterator evaluating the curve with the supplied `sample_function` at each `t`.
|
||||
///
|
||||
/// Given `subdivisions = 2`, this will split the curve into two lines, or three points, and
|
||||
/// return an iterator over those three points, one at the start, middle, and end.
|
||||
/// For `subdivisions = 2`, this will split the curve into two lines, or three points, and
|
||||
/// return an iterator with 3 items, the three points, one at the start, middle, and end.
|
||||
#[inline]
|
||||
pub fn iter_samples(
|
||||
&self,
|
||||
pub fn iter_samples<'a, 'b: 'a>(
|
||||
&'b self,
|
||||
subdivisions: usize,
|
||||
sample_function: fn(&Self, f32) -> P,
|
||||
) -> impl Iterator<Item = P> + '_ {
|
||||
(0..=subdivisions).map(move |i| {
|
||||
mut sample_function: impl FnMut(&Self, f32) -> P + 'a,
|
||||
) -> impl Iterator<Item = P> + 'a {
|
||||
self.iter_uniformly(subdivisions)
|
||||
.map(move |t| sample_function(self, t))
|
||||
}
|
||||
|
||||
/// An iterator that returns values of `t` uniformly spaced over `0..=subdivisions`.
|
||||
#[inline]
|
||||
fn iter_uniformly(&self, subdivisions: usize) -> impl Iterator<Item = f32> {
|
||||
let segments = self.segments.len() as f32;
|
||||
let t = i as f32 / subdivisions as f32 * segments;
|
||||
sample_function(self, t)
|
||||
})
|
||||
let step = segments / subdivisions as f32;
|
||||
(0..=subdivisions).map(move |i| i as f32 * step)
|
||||
}
|
||||
|
||||
/// The list of segments contained in this `CubicCurve`.
|
||||
///
|
||||
/// This spline's global `t` value is equal to how many segments it has.
|
||||
///
|
||||
/// All method accepting `t` on `CubicCurve` depends on the global `t`.
|
||||
/// When sampling over the entire curve, you should either use one of the
|
||||
/// `iter_*` methods or account for the segment count using `curve.segments().len()`.
|
||||
#[inline]
|
||||
pub fn segments(&self) -> &[CubicSegment<P>] {
|
||||
&self.segments
|
||||
}
|
||||
|
||||
/// Iterate over the curve split into `subdivisions`, sampling the position at each step.
|
||||
|
|
Loading…
Reference in a new issue