@@ -10,7 +10,6 @@ pub(crate) struct RotationData {
10
10
current_camera_up : CartesianDirection ,
11
11
time_started_rotations : [ Duration ; 4 ] ,
12
12
reversed_axes : [ bool ; 4 ] ,
13
- camera_rotated_times : i32 ,
14
13
}
15
14
16
15
impl Default for RotationData {
@@ -20,7 +19,6 @@ impl Default for RotationData {
20
19
current_camera_up : CartesianDirection :: Y ,
21
20
time_started_rotations : Default :: default ( ) ,
22
21
reversed_axes : Default :: default ( ) ,
23
- camera_rotated_times : Default :: default ( ) ,
24
22
}
25
23
}
26
24
}
@@ -34,44 +32,38 @@ pub(crate) fn rotate(
34
32
let time = & * time;
35
33
let rotation_data = & mut * rotation_data;
36
34
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
+ }
63
56
} ;
64
- }
57
+ } ;
65
58
66
59
// 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 ) ;
71
64
if input. just_pressed ( KeyCode :: Space ) {
72
65
rotation_data. time_started_rotations [ 3 ] = time. elapsed ( ) ;
73
66
rotation_data. reversed_axes [ 3 ] = input. pressed ( KeyCode :: A ) ;
74
- rotation_data. camera_rotated_times += if input. pressed ( KeyCode :: A ) { -1 } else { 1 } ;
75
67
}
76
68
77
69
let mut rotation_needed = rotation_data. current_rotation ;
@@ -145,16 +137,20 @@ fn animate_camera_rotation(
145
137
return ; // No rotation happening on axis
146
138
}
147
139
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 ( ) ) ,
156
142
) ;
157
143
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
+
158
154
let quat_path = Quat :: from_rotation_arc ( current_camera_up. as_vec3 ( ) , target. as_vec3 ( ) ) ;
159
155
let rotation_amount = rotation_curve ( time_elapsed. as_secs_f32 ( ) / rotation_duration)
160
156
* quat_path. to_axis_angle ( ) . 1 ;
@@ -167,53 +163,73 @@ fn animate_camera_rotation(
167
163
}
168
164
}
169
165
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 ,
174
169
rot : Quat ,
175
- counterclockwise : bool ,
176
- ) -> CartesianDirection {
170
+ current_camera_up : CartesianDirection ,
171
+ clockwise_turns : u32 ,
172
+ ) -> Option < CartesianDirection > {
177
173
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 ( ) {
187
176
X => Y ,
188
177
Y => Z ,
189
178
Z => X ,
190
179
_ => unreachable ! ( ) ,
191
- } ;
180
+ }
192
181
}
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
+ }
195
200
}
196
- // Later, make a reset func to recover from errors, TODO
197
- new_axis_on_side_after_rotation ( only_camera, rot) . unwrap ( )
198
201
}
199
202
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 ,
205
207
current_camera_up : CartesianDirection ,
208
+ to_the_right : bool ,
206
209
) -> 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 ) ;
215
231
}
216
- new_axis_on_side_after_rotation ( axis_after_camera , rot )
232
+ Some ( side_indicies [ if to_the_right { 1 } else { 0 } ] . 0 )
217
233
}
218
234
219
235
fn rotation_curve ( time : f32 ) -> f32 {
@@ -252,6 +268,22 @@ fn new_axis_on_side_after_rotation(
252
268
unreachable ! ( )
253
269
}
254
270
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
+ }
255
287
/// # Arguments
256
288
/// axis: The first axis in the EulerRot should correspond to the axis animated
257
289
fn animate_axis (
@@ -281,6 +313,10 @@ fn animate_axis(
281
313
}
282
314
}
283
315
316
+ fn reset_everything ( ) {
317
+ todo ! ( )
318
+ }
319
+
284
320
mod tests {
285
321
#[ test]
286
322
fn new_axis_on_side_after_rotation_test ( ) {
@@ -298,25 +334,4 @@ mod tests {
298
334
}
299
335
}
300
336
}
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
- }
322
337
}
0 commit comments