141 lines
No EOL
5.4 KiB
Rust
141 lines
No EOL
5.4 KiB
Rust
use std::f32::consts::FRAC_PI_2;
|
|
use crate::states::linear::*;
|
|
use crate::{FACTOR};
|
|
use bevy::prelude::*;
|
|
use bevy::reflect::List;
|
|
|
|
pub const CENTER_X: f32 = 0.0;
|
|
pub const CENTER_Y: f32 = 0.0;
|
|
|
|
// pub const FACTOR_RADIUS: f32 = FACTOR as f32 / 2.0;
|
|
|
|
pub const STEP: f32 = FACTOR as f32 / SCALE;
|
|
pub const SCALE: f32 = 2.0;
|
|
|
|
|
|
pub fn setup_linear_track() -> Track {
|
|
println!("Построение трека начато");
|
|
Track {
|
|
start_point: Vec2 {
|
|
x: CENTER_X - FACTOR as f32 * 7.0,
|
|
y: CENTER_Y - FACTOR as f32 * 4.0,
|
|
},
|
|
start_direction: Vec2::X,
|
|
segments: vec![
|
|
PathSegment::Line { length: STEP * 6.0 },
|
|
PathSegment::Turn { radius: STEP, left: true },
|
|
PathSegment::Line { length: STEP },
|
|
PathSegment::Turn { radius: STEP, left: false },
|
|
PathSegment::Line { length: STEP * 18.0 },
|
|
PathSegment::Turn { radius: STEP, left: true },
|
|
PathSegment::Line { length: STEP * 4.0 },
|
|
PathSegment::Turn { radius: STEP, left: true },
|
|
PathSegment::Turn { radius: STEP, left: false },
|
|
PathSegment::Line { length: STEP * 4.0 },
|
|
PathSegment::Turn { radius: STEP, left: true },
|
|
PathSegment::Line { length: STEP * 20.0 },
|
|
PathSegment::Turn { radius: STEP, left: true },
|
|
PathSegment::Line { length: STEP * 5.0 },
|
|
PathSegment::Turn { radius: STEP, left: true },
|
|
PathSegment::Line { length: STEP * 10.0 },
|
|
PathSegment::Turn { radius: STEP, left: false },
|
|
PathSegment::Line { length: STEP * 2.0 },
|
|
],
|
|
}
|
|
}
|
|
|
|
pub fn precalculate_track(track: &Track) -> PrecalculatedTrack {
|
|
let mut pt = PrecalculatedTrack { segments: vec![] };
|
|
let mut cumulative_length: Vec<f32> = vec![0.0];
|
|
|
|
let mut current_pos = track.start_point;
|
|
let mut current_dir = track.start_direction;
|
|
|
|
// на первом проходе заполняем все, кроме t_start и t_end,
|
|
// потому что мы не можем посчитать их без общей длины
|
|
for seg in track.segments.iter(){
|
|
match seg {
|
|
PathSegment::Line { length } => {
|
|
let calc_seg = PTSegment {
|
|
t_start: 0.0,
|
|
t_end: 0.0,
|
|
segment_type: SegementType::Line,
|
|
start_pos: current_pos,
|
|
direction: current_dir,
|
|
center: Vec2::ZERO,
|
|
radius: 0.0,
|
|
start_angle: 0.0,
|
|
sweep_sign: 0.0,
|
|
};
|
|
|
|
pt.segments.push(calc_seg);
|
|
// сдвигаем позицию для следующего сегмента
|
|
current_pos = current_pos + length * current_dir;
|
|
// направление не меняем, пропуск
|
|
// накапливаем длину
|
|
cumulative_length.push(cumulative_length[cumulative_length.len() -1] + *length);
|
|
}
|
|
|
|
PathSegment::Turn {radius, left } => {
|
|
let arc = helper_arc_calculator(current_pos, current_dir, *left, *radius);
|
|
|
|
let calc_seg = PTSegment {
|
|
t_start: 0.0,
|
|
t_end: 0.0,
|
|
segment_type: SegementType::Turn,
|
|
start_pos: current_pos,
|
|
direction: current_dir,
|
|
center: arc.center,
|
|
radius: *radius,
|
|
start_angle: arc.start_angle,
|
|
sweep_sign: arc.sweep_sign,
|
|
};
|
|
pt.segments.push(calc_seg);
|
|
// сдвигаем позицию для следующего сегмента
|
|
current_pos = arc.end_pos;
|
|
current_dir = arc.normal;
|
|
// накапливаем длину
|
|
cumulative_length.push(cumulative_length[cumulative_length.len() -1] + (FRAC_PI_2 * radius));
|
|
}
|
|
}
|
|
}
|
|
|
|
let last_index = cumulative_length.len() - 1;
|
|
let total_length = cumulative_length[last_index];
|
|
|
|
// итерируемся уже по прекалькулированному вектору
|
|
// заполняем точки на треке в пересчете на общую длину
|
|
println!("Precalculated track:");
|
|
for (i, seg) in pt.segments.iter_mut().enumerate() {
|
|
seg.t_start = cumulative_length[i] / total_length;
|
|
if i < last_index {
|
|
seg.t_end = cumulative_length[i+1] / total_length;
|
|
} else {
|
|
seg.t_end = 1.0;
|
|
}
|
|
println!("{:?}", seg);
|
|
}
|
|
|
|
pt
|
|
}
|
|
|
|
pub fn helper_arc_calculator(pos: Vec2, dir: Vec2, turn_to: bool, radius: f32) -> ArcCalculation{
|
|
let (normal, sign): (Vec2, f32) = if turn_to {
|
|
(Vec2::new(-dir.y, dir.x), -1.0)
|
|
} else {
|
|
(Vec2::new(dir.y, -dir.x), 1.0)
|
|
};
|
|
|
|
let center = pos + normal * radius;
|
|
let start_vec = pos - center;
|
|
let initial_vec = if turn_to { -start_vec.perp() } else { -start_vec };
|
|
let angle = initial_vec.to_angle();
|
|
|
|
ArcCalculation{
|
|
normal,
|
|
center,
|
|
start_angle: angle,
|
|
sweep_sign: sign,
|
|
end_pos: center + normal.perp() * radius * sign,
|
|
}
|
|
} |