module Maths ( dotP, lengthSquared, unitVector, randV3, rand, reflect, refract, reflectance, clamp, ) where import Control.Monad.Random import Control.Monad.State (State, evalState, get, put) import Debug.Trace import Linear.V3 import Linear.Vector import System.Random rand :: (RandomGen g) => Rand g Double rand = getRandomR (-1.0, 1.0 :: Double) randV3 :: (RandomGen g) => Rand g (V3 Double) randV3 = do x <- rand y <- rand z <- rand if vectorLength (V3 x y z) >= 1.0 then randV3 else return $ unitVector (V3 x y z) -- _ -> randV3 --inf = read "Infinity" degToRadians :: (Floating a) => a -> a degToRadians d = (d * pi) / 180.0 dotP :: (Num a) => V3 a -> V3 a -> a dotP (V3 a b c) (V3 d e f) = a * d + b * e + c * f lengthSquared :: (Num a) => V3 a -> a lengthSquared (V3 x y z) = x ^ 2 + y ^ 2 + z ^ 2 vectorLength :: (Floating f) => V3 f -> f vectorLength v = sqrt (lengthSquared v) unitVector :: (Floating f) => V3 f -> V3 f unitVector v = v ^/ vectorLength v reflect :: (Floating f) => V3 f -> V3 f -> V3 f reflect v n = v - (2 * (v `dotP` n)) *^ n refract :: (RealFloat f) => V3 f -> V3 f -> f -> V3 f refract uv n etai_over_etat = perp ^+^ parallel where ct = min (uv `dotP` n) 1.0 perp = etai_over_etat *^ ((-1.0 *^ uv) ^+^ (ct *^ n)) parallel = -1.0 * sqrt (abs (1.0 - lengthSquared perp)) *^ n reflectance :: Double -> Double -> Double reflectance c r = r00 + (1 - r00) * (1 - c) ^ 5 where r0 = (1 - r) / (1 + r) r00 = r0 * r0 clamp :: Double -> Double -> Double -> Double clamp x mi ma | x < mi = mi | x > ma = ma | otherwise = x