{-# LANGUAGE Arrows, OverloadedStrings, TypeFamilies #-} module Sky (getSkyInfo, sky, Models.Sky.default_sky, Models.Sky.default_sun, skyAbsorbtionFilter, SkyInfo, Models.Sky.LightingConfiguration(..), Sky.lightingConfiguration) where import Models.Sky import Animation import Tables import Scene import Models.LibraryData import RSAGL.Math import RSAGL.FRP import Data.Maybe import Control.Arrow import RSAGL.Modeling import RSAGL.Animation import System.Random () import Control.Monad.Random import Globals import qualified Data.ByteString.Char8 as B -- | Get the current SkyInfo data for the current planet. getSkyInfo :: (FRPModel m,StateOf m ~ AnimationState) => FRP e m () SkyInfo getSkyInfo = proc () -> do random_id <- sticky isJust Nothing <<< driverGetAnswerA -< "plane-random-id" m_biome <- sticky isJust Nothing <<< driverGetAnswerA -< "biome" clingy Discrete (==) (uncurry generateSkyInfo) -< (random_id,m_biome) generateSkyInfo :: Maybe B.ByteString -> Maybe B.ByteString -> SkyInfo generateSkyInfo random_id m_biome = fst $ flip runRand (mkStdGen $ fromInteger $ fromMaybe 0 $ random_id >>= readInteger) $ do temperature <- getRandomR (10000,2000) degrees_after_midnight <- getRandomR (0,360) degrees_latitude <- getRandomR(-90,90) degrees_axial_tilt <- getRandomR (0,90) degrees_orbital <- getRandomR (0,360) return $ default_sky { sky_info_biome = fromMaybe "" m_biome, sky_info_solar_kelvins = temperature, sky_info_degrees_after_midnight = degrees_after_midnight, sky_info_degrees_latitude = degrees_latitude, sky_info_degrees_axial_tilt = degrees_axial_tilt, sky_info_degrees_orbital = degrees_orbital } sky :: (FRPModel m,StateOf m ~ AnimationState) => FRP e m SkyInfo () sky = proc sky_info -> do sky_on <- readGlobal global_sky_on -< () libraryA -< (scene_layer_sky_sphere,if sky_on then SkySphere sky_info else NullModel) let sun_vector = sunVector sky_info whenJust (transformA sun) -< if angleBetween sun_vector (Vector3D 0 1 0) < fromDegrees 135 && sky_on then Just (affineOf $ rotateToFrom (sunVector sky_info) (Vector3D 0 (-1) 0),sky_info) else Nothing returnA -< () lighting_configuration <- Sky.lightingConfiguration -< sky_info let nightlight_intensity = lighting_nightlight lighting_configuration let skylight_intensity = lighting_skylight lighting_configuration skylight_color <- clingy HashedDiscrete (==) ambientSkyRadiation -< sky_info accumulateSceneA -< (scene_layer_local,lightSource $ case () of () | nightlight_intensity > 0.05 && sky_on -> mapLightSource (mapBoth $ scaleRGB nightlight_intensity) $ DirectionalLight { lightsource_direction = Vector3D 0 1 0, lightsource_color = rgb 0.1 0.1 0.2, lightsource_ambient = rgb 0.0 0.0 0.3 } () | otherwise -> NoLight) accumulateSceneA -< (scene_layer_local,lightSource $ case () of () | skylight_intensity > 0.05 && sky_on -> mapLightSource (mapBoth $ scaleRGB skylight_intensity) $ skylight (Vector3D 0 1 0) skylight_color () | lighting_artificial lighting_configuration <= 0.05 && not sky_on -> skylight (Vector3D 0 1 0) white () | otherwise -> NoLight) sun :: (FRPModel m,StateOf m ~ AnimationState) => FRP e m SkyInfo () sun = proc sky_info -> do libraryA -< (scene_layer_distant,SunDisc $ sunInfoOf sky_info) lighting_configuration <- Sky.lightingConfiguration -< sky_info sky_on <- readGlobal global_sky_on -< () let sunlight_intensity = lighting_sunlight lighting_configuration accumulateSceneA -< (scene_layer_distant,lightSource $ case () of () | sunlight_intensity > 0.05 && sky_on -> PointLight { lightsource_position = Point3D 0 (-10) 0, lightsource_radius = measure origin_point_3d (Point3D 0 (-10) 0), lightsource_color = sunColor $ sunInfoOf sky_info, lightsource_ambient = blackbody} () | otherwise -> NoLight) lightingConfiguration :: (FRPModel m) => FRP e m SkyInfo LightingConfiguration lightingConfiguration = proc sky_info -> do nightlight <- approachA 1.0 (perSecond 1.0) -< lighting_nightlight $ Models.Sky.lightingConfiguration sky_info artificial <- approachA 1.0 (perSecond 1.0) -< lighting_artificial $ Models.Sky.lightingConfiguration sky_info returnA -< (Models.Sky.lightingConfiguration sky_info) { lighting_nightlight = nightlight, lighting_artificial = artificial }