@@ -75,3 +75,45 @@ impl<T: PartialOrd> ClampRef for T {
7575 clamp_ref ( self , min, max) ;
7676 }
7777}
78+
79+ #[ cfg( feature = "game" ) ]
80+ pub mod game {
81+ use std:: f32:: consts:: PI ;
82+
83+ pub fn sun_direction ( time_of_day : f32 , latitude : f32 , time_of_year : f32 ) -> ( f32 , f32 , f32 ) {
84+ // Convert time of day from [0, 1] to [-π, π]
85+ let solar_time_rads = 2.0 * PI * ( time_of_day - 0.5 ) ;
86+
87+ // Convert time of year from [0, 1] to [-0.41, 0.41]
88+ // offset by 0.25 so declination is 0 at equinoxes
89+ let declination_rads = ( 2.0 * PI * ( time_of_year - 0.25 ) ) . sin ( ) * 23.45f32 . to_radians ( ) ;
90+
91+ // Convert latitude from [0, 1] to [-π/2, π/2]
92+ let latitude_rads = PI * ( latitude - 0.5 ) ;
93+
94+ // equations adapted from https://stackoverflow.com/questions/8708048/position-of-the-sun-given-time-of-day-latitude-and-longitude
95+ let zenith_rads = ( latitude_rads. sin ( ) * declination_rads. sin ( )
96+ + latitude_rads. cos ( ) * declination_rads. cos ( ) * solar_time_rads. cos ( ) )
97+ . acos ( ) ;
98+
99+ let mut azimuth_rads = ( ( latitude_rads. sin ( ) * zenith_rads. cos ( ) - declination_rads. sin ( ) )
100+ / ( latitude_rads. cos ( ) * zenith_rads. sin ( ) ) )
101+ . acos ( ) ;
102+
103+ let elevation_rads = ( declination_rads. sin ( ) * latitude_rads. sin ( )
104+ + declination_rads. cos ( ) * latitude_rads. cos ( ) * solar_time_rads. cos ( ) )
105+ . asin ( ) ;
106+
107+ if solar_time_rads > 0.0f32 {
108+ azimuth_rads += PI ;
109+ } else {
110+ azimuth_rads = 3.0 * PI - azimuth_rads;
111+ }
112+
113+ let x = azimuth_rads. sin ( ) * elevation_rads. cos ( ) ;
114+ let y = elevation_rads. sin ( ) ;
115+ let z = azimuth_rads. cos ( ) * elevation_rads. cos ( ) ;
116+
117+ ( x, y, z)
118+ }
119+ }
0 commit comments