Skip to content

Commit ac52005

Browse files
committed
Try to fix rotation, might me close maybe
1 parent be9c8e4 commit ac52005

File tree

1 file changed

+112
-97
lines changed

1 file changed

+112
-97
lines changed

src/cube_rotation.rs

Lines changed: 112 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ pub(crate) struct RotationData {
1010
current_camera_up: CartesianDirection,
1111
time_started_rotations: [Duration; 4],
1212
reversed_axes: [bool; 4],
13-
camera_rotated_times: i32,
1413
}
1514

1615
impl Default for RotationData {
@@ -20,7 +19,6 @@ impl Default for RotationData {
2019
current_camera_up: CartesianDirection::Y,
2120
time_started_rotations: Default::default(),
2221
reversed_axes: Default::default(),
23-
camera_rotated_times: Default::default(),
2422
}
2523
}
2624
}
@@ -34,44 +32,38 @@ pub(crate) fn rotate(
3432
let time = &*time;
3533
let rotation_data = &mut *rotation_data;
3634
let rotation_duration = 1.;
37-
macro_rules! input_handling {
38-
($keycode:tt, $axis:tt, $camera_rotation: expr) => {
39-
if input.just_pressed(KeyCode::$keycode) {
40-
let axis = direction_after_spatial_and_camera_rotation(
41-
CartesianDirection::$axis,
42-
rotation_data.current_rotation,
43-
rotation_data.camera_rotated_times,
44-
rotation_data.current_camera_up,
45-
)
46-
.expect("Current rotation does not have anything other than quarter turns")
47-
.as_vec3()
48-
* PI
49-
/ 2.;
50-
let axis_num = utils::first_nonzero_component(axis).unwrap() as usize;
51-
if rotation_data.time_started_rotations[axis_num].is_zero()
52-
&& (rotation_data.time_started_rotations[3].is_zero() || $camera_rotation == 0)
53-
{
54-
rotation_data.reversed_axes[axis_num] = axis[axis_num] < 0.;
55-
rotation_data.time_started_rotations[axis_num] = time.elapsed();
56-
// if $camera_rotation != 0 {
57-
// rotation_data.time_started_rotations[3] = time.elapsed();
58-
// rotation_data.reversed_axes[3] = $camera_rotation == -1;
59-
// rotation_data.camera_rotated_times += $camera_rotation;
60-
// }
61-
}
62-
};
35+
let mut input_handling = |keycode: KeyCode, axis: CartesianDirection, camera_rotation: i32| {
36+
if input.just_pressed(keycode) {
37+
let axis = direction_after_camera_turn(
38+
axis.abs(),
39+
rotation_data.current_rotation,
40+
rotation_data.current_camera_up,
41+
0,
42+
)
43+
.expect("Current rotation does not have anything other than quarter turns");
44+
let axis_num = axis.axis_num() as usize;
45+
if rotation_data.time_started_rotations[axis_num].is_zero()
46+
&& (rotation_data.time_started_rotations[3].is_zero() || camera_rotation == 0)
47+
{
48+
rotation_data.reversed_axes[axis_num] = axis.is_negative();
49+
rotation_data.time_started_rotations[axis_num] = time.elapsed();
50+
// if $camera_rotation != 0 {
51+
// rotation_data.time_started_rotations[3] = time.elapsed();
52+
// rotation_data.reversed_axes[3] = $camera_rotation == -1;
53+
// rotation_data.camera_rotated_times += $camera_rotation;
54+
// }
55+
}
6356
};
64-
}
57+
};
6558

6659
// Input
67-
input_handling!(Left, Y, 0);
68-
input_handling!(Right, NegY, 0);
69-
input_handling!(Down, NegZ, 1);
70-
input_handling!(Up, Z, -1);
60+
input_handling(KeyCode::Left, CartesianDirection::Y, 0);
61+
input_handling(KeyCode::Right, CartesianDirection::NegY, 0);
62+
input_handling(KeyCode::Down, CartesianDirection::NegZ, 1);
63+
input_handling(KeyCode::Up, CartesianDirection::Z, -1);
7164
if input.just_pressed(KeyCode::Space) {
7265
rotation_data.time_started_rotations[3] = time.elapsed();
7366
rotation_data.reversed_axes[3] = input.pressed(KeyCode::A);
74-
rotation_data.camera_rotated_times += if input.pressed(KeyCode::A) { -1 } else { 1 };
7567
}
7668

7769
let mut rotation_needed = rotation_data.current_rotation;
@@ -145,16 +137,20 @@ fn animate_camera_rotation(
145137
return; // No rotation happening on axis
146138
}
147139
let time_elapsed = time.elapsed() - time_started_rotation.to_owned();
148-
// Cancel out rotation because direction_after_spatial_and_camera_turn rotates it again, TODO
149-
let target = direction_after_spatial_and_camera_turn(
150-
CartesianDirection::from_vec3_round(
151-
rotation.inverse().mul_vec3(current_camera_up.as_vec3()),
152-
)
153-
.unwrap(),
154-
rotation,
155-
reversed,
140+
let cancelled_out_camera_up = CartesianDirection::from_vec3_round(
141+
rotation.inverse().mul_vec3(current_camera_up.as_vec3()),
156142
);
157143

144+
// Two clockwise => counterclockwise
145+
let target = direction_after_camera_turn(
146+
cancelled_out_camera_up.unwrap(),
147+
rotation,
148+
*current_camera_up,
149+
if reversed { 2 } else { 1 },
150+
)
151+
.unwrap();
152+
let target = direction_after_rotation(target, rotation).unwrap();
153+
158154
let quat_path = Quat::from_rotation_arc(current_camera_up.as_vec3(), target.as_vec3());
159155
let rotation_amount = rotation_curve(time_elapsed.as_secs_f32() / rotation_duration)
160156
* quat_path.to_axis_angle().1;
@@ -167,53 +163,73 @@ fn animate_camera_rotation(
167163
}
168164
}
169165

170-
/// Takes the normal and gives back a new normal where the cube is both rotated and the camera
171-
/// turned a third of a turn either clockwise or counterclockwise
172-
fn direction_after_spatial_and_camera_turn(
173-
normal: CartesianDirection,
166+
/// Note: The normal inputted has to be UNROTATED
167+
fn direction_after_camera_turn(
168+
mut normal: CartesianDirection,
174169
rot: Quat,
175-
counterclockwise: bool,
176-
) -> CartesianDirection {
170+
current_camera_up: CartesianDirection,
171+
clockwise_turns: u32,
172+
) -> Option<CartesianDirection> {
177173
use CartesianDirection::*;
178-
let mut only_camera = match normal.abs() {
179-
X => Y,
180-
Y => Z,
181-
Z => X,
182-
_ => unreachable!(),
183-
};
184-
if counterclockwise {
185-
// Two clockwise => one counterclockwise
186-
only_camera = match only_camera {
174+
for _ in 0..clockwise_turns {
175+
normal = match normal.abs() {
187176
X => Y,
188177
Y => Z,
189178
Z => X,
190179
_ => unreachable!(),
191-
};
180+
}
192181
}
193-
if only_camera.is_negative() {
194-
only_camera = only_camera.opposite();
182+
match normal {
183+
CartesianDirection::Y => Some(current_camera_up),
184+
CartesianDirection::Z => to_the_side_from_camera_perspective(
185+
rot.mul_vec3(Vec3::splat(1.)),
186+
current_camera_up,
187+
false,
188+
),
189+
CartesianDirection::X => to_the_side_from_camera_perspective(
190+
rot.mul_vec3(Vec3::splat(1.)),
191+
current_camera_up,
192+
true,
193+
),
194+
_ => {
195+
// TODO: Reset everything instead
196+
error!("The normal is not visible from current position");
197+
dbg!(current_camera_up, normal);
198+
None
199+
}
195200
}
196-
// Later, make a reset func to recover from errors, TODO
197-
new_axis_on_side_after_rotation(only_camera, rot).unwrap()
198201
}
199202

200-
/// TODO: Come up with better names dude
201-
fn direction_after_spatial_and_camera_rotation(
202-
normal: CartesianDirection,
203-
rot: Quat,
204-
camera_rotated_times: i32,
203+
/// From the camera perspective, gets the leftmost or rightmost side normal.
204+
/// current_camera_up has to be visible from the camera loc
205+
fn to_the_side_from_camera_perspective(
206+
camera_loc: Vec3,
205207
current_camera_up: CartesianDirection,
208+
to_the_right: bool,
206209
) -> Option<CartesianDirection> {
207-
let mut axis_after_camera = match camera_rotated_times % 3 {
208-
0 => normal,
209-
1 | -2 => direction_after_spatial_and_camera_turn(normal, rot, false),
210-
2 | -1 => direction_after_spatial_and_camera_turn(normal, rot, true),
211-
_ => unreachable!(),
212-
};
213-
if normal == CartesianDirection::Y {
214-
axis_after_camera = current_camera_up;
210+
let sides = order_of_sides(current_camera_up);
211+
let mut side_indicies = Vec::with_capacity(2);
212+
for i in 0..3 {
213+
let c = camera_loc[i];
214+
let mut side = Vec3::ZERO;
215+
side[i] = c;
216+
let axis = CartesianDirection::from_vec3_round(side).unwrap();
217+
if current_camera_up.axis_num() == i as u32 {
218+
if current_camera_up != axis {
219+
// The side camera up is not visible
220+
return None;
221+
}
222+
continue;
223+
}
224+
side_indicies.push((axis, sides.iter().position(|&side| side == axis).unwrap()));
225+
}
226+
assert_eq!(side_indicies.len(), 2);
227+
side_indicies.sort_by_key(|side_index| side_index.1);
228+
229+
if side_indicies[0].1 == 0 && side_indicies[1].1 == 3 {
230+
return Some(side_indicies[if to_the_right { 0 } else { 1 }].0);
215231
}
216-
new_axis_on_side_after_rotation(axis_after_camera, rot)
232+
Some(side_indicies[if to_the_right { 1 } else { 0 }].0)
217233
}
218234

219235
fn rotation_curve(time: f32) -> f32 {
@@ -252,6 +268,22 @@ fn new_axis_on_side_after_rotation(
252268
unreachable!()
253269
}
254270

271+
/// Outputs the order that the sides on the side come in when the inputted side is on the top. In
272+
/// clockwise order when looking at it from the bottom up.
273+
fn order_of_sides(up: CartesianDirection) -> [CartesianDirection; 4] {
274+
use CartesianDirection::*;
275+
let mut output = match up.abs() {
276+
X => [Y, Z, NegY, NegZ],
277+
Y => [Z, X, NegZ, NegX],
278+
Z => [X, Y, NegX, NegY],
279+
_ => unreachable!(),
280+
};
281+
282+
if up.is_negative() {
283+
output.reverse();
284+
}
285+
output
286+
}
255287
/// # Arguments
256288
/// axis: The first axis in the EulerRot should correspond to the axis animated
257289
fn animate_axis(
@@ -281,6 +313,10 @@ fn animate_axis(
281313
}
282314
}
283315

316+
fn reset_everything() {
317+
todo!()
318+
}
319+
284320
mod tests {
285321
#[test]
286322
fn new_axis_on_side_after_rotation_test() {
@@ -298,25 +334,4 @@ mod tests {
298334
}
299335
}
300336
}
301-
302-
#[test]
303-
fn direction_after_spatial_and_camera_turn_test() {
304-
for to in crate::utils::CartesianDirection::directions() {
305-
for from in crate::utils::CartesianDirection::directions() {
306-
let rot = bevy::prelude::Quat::from_rotation_arc(from.as_vec3(), to.as_vec3());
307-
308-
let o = crate::cube_rotation::direction_after_spatial_and_camera_turn(
309-
crate::utils::CartesianDirection::Y,
310-
rot,
311-
true,
312-
);
313-
314-
let camera_loc = rot.inverse().mul_vec3(bevy::prelude::Vec3::splat(1.));
315-
316-
if (camera_loc[o.axis_num() as usize] < 0.) != o.is_negative() {
317-
panic!("The side given back by function is not currently visible");
318-
}
319-
}
320-
}
321-
}
322337
}

0 commit comments

Comments
 (0)