bevyengine / bevyengine/bevy

Curve extrapolation for curves which can be extrapolated

Open
#20,028 2 comments 0 reactions 0 assignees View on GitHub
A-Math C-Feature
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## What problem does this solve or what need does it fill?

Currently, there are few ways to make a Curve trait implementor continue beyond its domain. This is especially apparent for SampleCurve/UnevenSampleCurve. For example, when using a simple `lerp(a, b, t)` to interpolate, theres no reason i couldn't extrapolate by providing a `t > 1.0` or `t < 0.0`, and this can be very useful in some cases.

For example, this curve would translate something along a V shape:
```rs
UnevenSampleCurve::new(
vec![
(0.0, Vec2::new(1.0, 0.0)),
(0.5, Vec2::new(0.0, 1.0)),
(1.0, Vec2::new(1.0, 2.0))
],
|a, b, t| a.lerp(*b, t)
)
```
Its perfectly valid to extrapolate this in both directions infiniteley (making a larger/infinite V shape, in this case) but i can't find a builtin way to encode this in the Curve itself. The domain is `0.0..=1.0` and i can't find a way to change that which leads to the behaviour i'm looking for.

## What solution would you like?

I would like some way which allows me to get a infinite domain curve for all curves where extrapolation can make sense. Lerp is the most obvious extrapolate-able example, but bezier curves, for example, are also fine to extrapolate.

I think ideally this should be a wrapper struct, like the various ones returned by ChainExt methods. This would allow passing it to external code which calls `.sample(t)` more easily.

## What alternative(s) have you considered?

- `Curve::sample_unchecked` explicitly documents i can't use it for this (quote: "extrapolation beyond a curves domain should not be relied upon"). If that documentation is changed, external code may need to be updated to use sample_unchecked to allow for infinite domain curves. Also, would make it harder to prevent extrapolation for curves which can't/shouldn't be extrapolated.

## Additional context

A related feature to consider along with this is some way to cutoff and chain curves with infinite domains. Similar to `CurveExt::chain`, i would propose CurveExt::chain_at` with an extra `t` argument which defines the cutoff point. This could be implemented by having a wrapper struct, similar to the one i've proposed above, which overrides their domain to end at a specific value (which would make the implementation of `chain_at` something like this: `RightCutoff::new(my_curve, t).chain(LeftCutoff(t, my_other_curve))`).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.