Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix questionable use of floats and re-work all ticking logic #21

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

SUPERCILEX
Copy link
Contributor

What's broken?

  • Float usage inconsistently used f64 or f32. I changed everything to be f32 since precision isn't really the priority in games.
  • Float rounding issues were present in several places. For example, the AnimClock never reset the elapsed time leading to a continual loss of precision as the animation progressed.
  • Sequences did not handle deltas that crossed animation boundaries. This meant that if a one-hour delta was received, only one animation would complete instead of all of them.
  • I tried to simplify all the other logic in the process while improving performance.

What's broken?
- Float usage inconsistently used f64 or f32. I changed everything to be f32 since precision isn't really the priority in graphics.
- Float rounding issues were present in several places. For example, the AnimClock never reset the elapsed time leading to a continual loss of precision as the animation progressed.
- Sequences did not handle deltas that crossed animation boundaries. This means that if a one-hour delta was received, only one animation would complete.
- I tried to simplify all the other logic in the process while improving performance.

Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Copy link
Owner

@djeedai djeedai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! There's a bunch of good things in there, but also unfortunately a few other ones that are either arguable or conflict with on-going works toward making Sequence (and possibly Tracks) loopable, and therefore would be reverted as soon as that work lands. I'm also not very clear on where are the bugs being fixed.

I'd suggest splitting the changes into smaller chunks, separating the targeted bug fix(es), the optimization(s), and the clean-ups around f32 / f64 mix. We can chat on Discord if you want.

Comment on lines +1 to 2
use std::cmp::min;
use std::time::Duration;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
use std::cmp::min;
use std::time::Duration;
use std::{cmp::min, time::Duration};

src/tweenable.rs Show resolved Hide resolved
src/tweenable.rs Show resolved Hide resolved
}

fn times_completed(&self) -> u32 {
self.times_completed
if self.index == self.tweens.len() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will get reverted by #16. Keeping self.times_completed seems like a better choice.

time: Duration,
times_completed: u32,
elapsed: Duration,
completed: bool,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will get reverted by #8. It seems better to keep times_completed.

fn set_progress(&mut self, progress: f32) -> u32 {
let progress = progress.max(0.);
let times_completed = progress as u32;
fn set_progress(&mut self, progress: f32) {
let progress = if self.is_looping {
progress.fract()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the deleted .max(0.), this may set progress to a negative value since (-3.6_f32).fract() == -0.6_f32, which will make Duration::mul_f32() panic.

In general the interface for set_progress() shouldn't allow negative values, that makes little sense unless the animation is infinitely looping. So it's better to just avoid it completely for the sake of simplicity and clarity of the API.

return;
}

self.elapsed = self.duration.mul_f32(progress.clamp(0., 1.));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface for set_progress() should accept values > 1., which allows jumping to iteration N of a repeating animation. Looping sequences are not yet implemented but there's work on-going for them (#16).

Comment on lines +641 to +642
let full_completions =
(tween.times_completed() - prev_completions - 1) * tween_duration;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this seems to attempt to handle a case that is currently not supported, namely having looping tweenables as part of a Sequence. Currently full_completions will always be zero. Also, if a tweenable is looping, it currently never return TweenState::Completed since looping tweenables are of infinite duration by definition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants