Curve method changes & fixed all_included

This commit is contained in:
MaxOhn
2021-04-28 22:44:50 +02:00
parent 643a67888d
commit 964b972eac
6 changed files with 46 additions and 77 deletions
+18 -10
View File
@@ -3,7 +3,10 @@
all(feature = "osu", not(feature = "no_sliders_no_leniency"))
))]
use crate::{math_util, parse::Pos2};
use crate::{
math_util,
parse::{PathType, Pos2},
};
const BEZIER_TOLERANCE: f32 = 0.25;
const CATMULL_DETAIL: f32 = 50.0;
@@ -26,11 +29,16 @@ pub(crate) enum Curve<'p> {
impl<'p> Curve<'p> {
#[inline]
pub(crate) fn linear(points: &'p [Pos2]) -> Self {
Self::Linear(points)
pub(crate) fn new(points: &'p [Pos2], kind: PathType) -> Self {
match kind {
PathType::Bezier => Self::bezier(points),
PathType::Catmull => Self::catmull(points),
PathType::Linear => Self::Linear(points),
PathType::PerfectCurve => Self::perfect(points),
}
}
pub(crate) fn bezier(points: &[Pos2]) -> Self {
fn bezier(points: &[Pos2]) -> Self {
if points.len() == 1 {
return Self::Bezier(Points::Single(points[0]));
}
@@ -70,7 +78,7 @@ impl<'p> Curve<'p> {
}
}
pub(crate) fn catmull(points: &[Pos2]) -> Self {
fn catmull(points: &[Pos2]) -> Self {
if points.len() == 1 {
return Self::Catmull(Points::Single(points[0]));
}
@@ -123,7 +131,7 @@ impl<'p> Curve<'p> {
}
}
pub(crate) fn perfect(points: &[Pos2]) -> Self {
fn perfect(points: &[Pos2]) -> Self {
let (a, b, c) = (points[0], points[1], points[2]);
let (center, mut radius) = math_util::get_circum_circle(a, b, c);
radius *= ((!math_util::is_left(a, b, c)) as i8 * 2 - 1) as f32;
@@ -135,21 +143,21 @@ impl<'p> Curve<'p> {
}
}
pub(crate) fn point_at_distance(&self, len: f32) -> Pos2 {
pub(crate) fn point_at_distance(&self, dist: f32) -> Pos2 {
let points = match self {
Self::Bezier(points) => points,
Self::Catmull(points) => points,
Self::Linear(points) => return math_util::point_on_lines(points, len),
Self::Linear(points) => return math_util::point_on_lines(points, dist),
Self::Perfect {
origin,
center,
radius,
} => return math_util::rotate(*center, *origin, len / *radius),
} => return math_util::rotate(*center, *origin, dist / *radius),
};
match points {
Points::Single(point) => *point,
Points::Multi(points) => math_util::point_at_distance(points, len),
Points::Multi(points) => math_util::point_at_distance(points, dist),
}
}
}
+3 -22
View File
@@ -14,7 +14,7 @@ use slider_state::SliderState;
use crate::{
curve::Curve,
parse::{HitObjectKind, PathType, Pos2},
parse::{HitObjectKind, Pos2},
Beatmap, Mods, StarResult, Strains,
};
@@ -90,12 +90,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
/ 100.0;
// Build the curve w.r.t. the curve points
let curve = match path_type {
PathType::Linear => Curve::linear(curve_points),
PathType::Bezier => Curve::bezier(curve_points),
PathType::Catmull => Curve::catmull(curve_points),
PathType::PerfectCurve => Curve::perfect(curve_points),
};
let curve = Curve::new(curve_points, *path_type);
let mut current_distance = tick_distance;
let time_add = duration * (tick_distance / (*pixel_len * *repeats as f32));
@@ -327,22 +322,8 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
/ (map.sv * slider_state.speed_mult)
/ 100.0;
// Ensure path type validity
let path_type = if *path_type == PathType::PerfectCurve && curve_points.len() > 3 {
PathType::Bezier
} else if curve_points.len() == 2 {
PathType::Linear
} else {
*path_type
};
// Build the curve w.r.t. the curve points
let curve = match path_type {
PathType::Linear => Curve::linear(curve_points),
PathType::Bezier => Curve::bezier(curve_points),
PathType::Catmull => Curve::catmull(curve_points),
PathType::PerfectCurve => Curve::perfect(curve_points),
};
let curve = Curve::new(curve_points, *path_type);
let mut current_distance = tick_distance;
let time_add = duration * (tick_distance / (*pixel_len * *repeats as f32));
+15 -25
View File
@@ -12,10 +12,11 @@ pub(crate) fn cpn(mut p: i32, n: i32) -> f32 {
}
p = p.min(n - p);
let diff = n - p;
let mut out = 1.0;
for i in 1..=p {
out *= (n - p + i) as f32 / i as f32;
out *= (diff + i) as f32 / i as f32;
}
out
@@ -55,43 +56,32 @@ pub(crate) fn point_on_lines(points: &[Pos2], len: f32) -> Pos2 {
point_on_line(points[points.len() - 2], points[points.len() - 1], len)
}
#[inline]
pub(crate) fn distance_from_points(arr: &[Pos2]) -> f32 {
arr.iter()
.skip(1)
.zip(arr.iter())
.map(|(curr, prev)| curr.distance(*prev))
.sum()
}
pub(crate) fn point_at_distance(array: &[Pos2], distance: f32) -> Pos2 {
if array.len() < 2 {
pub(crate) fn point_at_distance(points: &[Pos2], dist: f32) -> Pos2 {
if points.len() < 2 {
return Pos2 { x: 0.0, y: 0.0 };
} else if distance.abs() <= f32::EPSILON {
return array[0];
} else if distance_from_points(array) <= distance {
return array[array.len() - 1];
} else if dist.abs() <= f32::EPSILON {
return points[0];
}
let mut current_distance = 0.0;
let mut new_distance;
let mut curr_dist = 0.0;
let mut new_dist;
for (&curr, &next) in array.iter().zip(array.iter().skip(1)) {
new_distance = (curr - next).length();
current_distance += new_distance;
for (&curr, &next) in points.iter().zip(points.iter().skip(1)) {
new_dist = (curr - next).length();
curr_dist += new_dist;
if distance <= current_distance {
let remaining_dist = distance - (current_distance - new_distance);
if dist <= curr_dist {
let remaining_dist = dist - (curr_dist - new_dist);
return if remaining_dist.abs() <= f32::EPSILON {
curr
} else {
curr + (next - curr) * (remaining_dist / new_distance)
curr + (next - curr) * (remaining_dist / new_dist)
};
}
}
array[array.len() - 1]
points[points.len() - 1]
}
pub(crate) fn get_circum_circle(p0: Pos2, p1: Pos2, p2: Pos2) -> (Pos2, f32) {
+6 -6
View File
@@ -369,18 +369,18 @@ fn stacking(hit_objects: &mut [OsuObject], stack_threshold: f32) {
}
if hit_objects[n].is_slider()
&& hit_objects[n].end_pos().distance(&hit_objects[i].pos) < STACK_DISTANCE
&& hit_objects[n].end_pos().distance(hit_objects[i].pos) < STACK_DISTANCE
{
let offset = hit_objects[i].stack_height - hit_objects[n].stack_height + 1.0;
for j in n + 1..=i {
if hit_objects[n].pos.distance(&hit_objects[j].pos) < STACK_DISTANCE {
if hit_objects[n].pos.distance(hit_objects[j].pos) < STACK_DISTANCE {
hit_objects[j].stack_height -= offset;
}
}
break;
} else if hit_objects[n].pos.distance(&hit_objects[i].pos) < STACK_DISTANCE {
} else if hit_objects[n].pos.distance(hit_objects[i].pos) < STACK_DISTANCE {
hit_objects[n].stack_height = hit_objects[i].stack_height + 1.0;
i = n;
}
@@ -396,7 +396,7 @@ fn stacking(hit_objects: &mut [OsuObject], stack_threshold: f32) {
continue;
} else if hit_objects[i].time - hit_objects[n].time > stack_threshold {
break;
} else if hit_objects[n].end_pos().distance(&hit_objects[i].pos) < STACK_DISTANCE {
} else if hit_objects[n].end_pos().distance(hit_objects[i].pos) < STACK_DISTANCE {
hit_objects[n].stack_height = hit_objects[i].stack_height + 1.0;
i = n;
}
@@ -421,10 +421,10 @@ fn old_stacking(hit_objects: &mut [OsuObject], stack_threshold: f32) {
break;
}
if hit_objects[j].pos.distance(&hit_objects[i].pos) < STACK_DISTANCE {
if hit_objects[j].pos.distance(hit_objects[i].pos) < STACK_DISTANCE {
hit_objects[i].stack_height += 1.0;
start_time = hit_objects[j].end_time();
} else if hit_objects[j].pos.distance(&end_pos) < STACK_DISTANCE {
} else if hit_objects[j].pos.distance(end_pos) < STACK_DISTANCE {
slider_stack += 1.0;
hit_objects[j].stack_height -= slider_stack;
start_time = hit_objects[j].end_time();
+2 -7
View File
@@ -3,7 +3,7 @@ use super::slider_state::SliderState;
use crate::{
curve::Curve,
parse::{HitObject, HitObjectKind, PathType, Pos2},
parse::{HitObject, HitObjectKind, Pos2},
Beatmap,
};
@@ -76,12 +76,7 @@ impl OsuObject {
let span_duration = duration / *repeats as f32;
// Build the curve w.r.t. the curve points
let curve = match path_type {
PathType::Linear => Curve::linear(curve_points[0], curve_points[1]),
PathType::Bezier => Curve::bezier(&curve_points),
PathType::Catmull => Curve::catmull(&curve_points),
PathType::PerfectCurve => Curve::perfect(&curve_points),
};
let curve = Curve::new(curve_points, *path_type);
// Called on each slider object except for the head.
// Increases combo and adjusts `end_pos` and `travel_dist`
+2 -7
View File
@@ -3,7 +3,7 @@ use super::slider_state::SliderState;
use crate::{
curve::Curve,
parse::{HitObject, HitObjectKind, PathType, Pos2},
parse::{HitObject, HitObjectKind, Pos2},
Beatmap,
};
@@ -63,12 +63,7 @@ impl OsuObject {
let span_duration = duration / *repeats as f32;
// Build the curve w.r.t. the curve points
let curve = match path_type {
PathType::Linear => Curve::linear(curve_points),
PathType::Bezier => Curve::bezier(curve_points),
PathType::Catmull => Curve::catmull(curve_points),
PathType::PerfectCurve => Curve::perfect(curve_points),
};
let curve = Curve::new(curve_points, *path_type);
// Called on each slider object except for the head.
// Increases combo and adjusts `end_pos` and `travel_dist`