rewrote slider processing & fixed catmull

This commit is contained in:
MaxOhn
2021-11-08 17:03:49 +01:00
parent 98bc687422
commit 6041da3d50
4 changed files with 53 additions and 46 deletions
+7 -3
View File
@@ -243,6 +243,10 @@ impl Curve {
}
fn approximate_catmull(path: &mut Vec<Pos2>, points: &[Pos2]) {
if points.len() == 1 {
return;
}
path.reserve_exact((points.len() - 1) * CATMULL_DETAIL * 2);
// Handle first iteration distinctly because of v1
@@ -254,7 +258,7 @@ impl Curve {
Self::catmull_subpath(path, v1, v2, v3, v4);
// Remaining iterations
for (i, (&v1, &v2)) in (2..).zip(points.iter().zip(points.iter().skip(1))) {
for (i, (&v1, &v2)) in (2..points.len()).zip(points.iter().zip(points.iter().skip(1))) {
let v3 = points.get(i).copied().unwrap_or_else(|| v2 * 2.0 - v1);
let v4 = points.get(i + 1).copied().unwrap_or_else(|| v3 * 2.0 - v2);
@@ -421,12 +425,12 @@ impl Curve {
}
fn catmull_subpath(path: &mut Vec<Pos2>, v1: Pos2, v2: Pos2, v3: Pos2, v4: Pos2) {
let x1 = 2.0 * v1.x;
let x1 = 2.0 * v2.x;
let x2 = -v1.x + v3.x;
let x3 = 2.0 * v1.x - 5.0 * v2.x + 4.0 * v3.x - v4.x;
let x4 = -v1.x + 3.0 * (v2.x - v3.x) + v4.x;
let y1 = 2.0 * v1.y;
let y1 = 2.0 * v2.y;
let y2 = -v1.y + v3.y;
let y3 = 2.0 * v1.y - 5.0 * v2.y + 4.0 * v3.y - v4.y;
let y4 = -v1.y + 3.0 * (v2.y - v3.y) + v4.y;
+2 -2
View File
@@ -54,7 +54,7 @@ fn custom_osu() {
use crate::{Beatmap, OsuPP};
let path = "E:Games/osu!/beatmaps/156352_.osu";
let path = "E:Games/osu!/beatmaps/70090.osu";
let file = File::open(path).unwrap();
let start = Instant::now();
@@ -76,7 +76,7 @@ fn custom_osu() {
println!("Parsing average: {:?}", accum / iters);
let start = Instant::now();
let result = OsuPP::new(&map).mods(1024).calculate();
let result = OsuPP::new(&map).mods(8 + 16 + 64).calculate();
let iters = 100;
let accum = start.elapsed();
+2 -2
View File
@@ -84,7 +84,7 @@ pub fn stars(
map,
radius,
scaling_factor,
attributes: &mut diff_attributes,
max_combo: &mut diff_attributes.max_combo,
slider_state: SliderState::new(map),
ticks: Vec::new(),
curve_bufs: CurveBuffers::default(),
@@ -292,7 +292,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
map,
radius,
scaling_factor,
attributes: &mut diff_attributes,
max_combo: &mut diff_attributes.max_combo,
slider_state: SliderState::new(map),
ticks: Vec::new(),
curve_bufs: CurveBuffers::default(),
+42 -39
View File
@@ -1,4 +1,3 @@
use super::super::super::DifficultyAttributes;
use super::slider_state::SliderState;
use crate::{
@@ -34,7 +33,7 @@ pub(crate) struct ObjectParameters<'a> {
pub(crate) map: &'a Beatmap,
pub(crate) radius: f32,
pub(crate) scaling_factor: f32,
pub(crate) attributes: &'a mut DifficultyAttributes,
pub(crate) max_combo: &'a mut usize,
pub(crate) ticks: Vec<f32>,
pub(crate) slider_state: SliderState<'a>,
pub(crate) curve_bufs: CurveBuffers,
@@ -47,13 +46,13 @@ impl OsuObject {
map,
radius,
scaling_factor,
attributes,
max_combo,
ticks,
slider_state,
curve_bufs,
} = params;
attributes.max_combo += 1; // hitcircle, slider head, or spinner
**max_combo += 1; // hitcircle, slider head, or spinner
let mut pos = h.pos;
if hr {
@@ -103,10 +102,8 @@ impl OsuObject {
// Called on each slider object except for the head.
// Increases combo and adjusts `end_pos` and `travel_dist`
// w.r.t. the object position at the given time on the slider curve.
let mut compute_vertex = |time: f32| {
attributes.max_combo += 1;
let mut progress = (time - h.start_time) / span_duration;
let mut compute_vertex = |mut progress: f32| {
**max_combo += 1;
if progress % 2.0 >= 1.0 {
progress = 1.0 - progress % 1.0;
@@ -114,7 +111,6 @@ impl OsuObject {
progress %= 1.0;
}
// TODO: Correct addition?
let mut curr_pos = h.pos + curve.position_at(progress);
if hr {
@@ -132,53 +128,60 @@ impl OsuObject {
}
};
let mut current_distance = tick_dist;
let time_add = duration * (tick_dist / (pixel_len * span_count));
// * A very lenient maximum length of a slider for ticks to be generated.
// * This exists for edge cases such as /b/1573664 where the beatmap has
// * been edited by the user, and should never be reached in normal usage.
let max_len = 100_000.0;
let target = pixel_len - tick_dist / 8.0;
ticks.reserve((target / tick_dist) as usize);
let len = curve.dist().min(max_len);
tick_dist = tick_dist.clamp(0.0, len);
let min_dist_from_end = velocity * 10.0;
let mut curr_dist = tick_dist;
ticks.clear();
ticks.reserve((len / tick_dist) as usize);
// Tick of the first span
if current_distance < target {
for tick_idx in 1.. {
let time = h.start_time + time_add * tick_idx as f32;
compute_vertex(time);
ticks.push(time);
current_distance += tick_dist;
while curr_dist < len - min_dist_from_end {
let progress = curr_dist / len;
if current_distance >= target {
break;
}
}
compute_vertex(progress);
ticks.push(progress);
curr_dist += tick_dist;
}
// Other spans
if *repeats > 1 {
for repeat_id in 1..*repeats {
let time_offset = (duration / *repeats as f32) * repeat_id as f32;
for span_idx in 1..=*repeats {
let progress = (span_idx % 2 == 1) as u8 as f32;
// Reverse tick
compute_vertex(h.start_time + time_offset);
// Reverse tick
compute_vertex(progress);
// Actual ticks
if repeat_id & 1 == 1 {
ticks.iter().rev().for_each(|&time| compute_vertex(time));
} else {
ticks.iter().for_each(|&time| compute_vertex(time));
}
// Actual ticks
if span_idx & 1 == 1 {
ticks
.iter()
.rev()
.for_each(|&tick_progress| compute_vertex(tick_progress + progress));
} else {
ticks
.iter()
.for_each(|&tick_progress| compute_vertex(tick_progress + progress));
}
}
// Slider tail
let final_span_idx = repeats.saturating_sub(1);
let final_span_start_time = h.start_time + final_span_idx as f32 * span_duration;
let final_span_start_time = h.start_time + *repeats as f32 * span_duration;
let final_span_end_time = (h.start_time + duration / 2.0)
.max(final_span_start_time + span_duration - LEGACY_LAST_TICK_OFFSET);
compute_vertex(final_span_end_time);
let progress = (*repeats % 2 == 1) as u8 as f32;
let final_progress =
(final_span_end_time - final_span_start_time) / span_duration + progress;
ticks.clear();
compute_vertex(final_progress);
let progress = (*repeats % 2 == 0) as u8 as f32;
let mut end_pos = h.pos + curve.position_at(progress);
travel_dist *= *scaling_factor;