module Maths ( dotP, lengthSquared, unitVector, randV3, rand, reflect, refract, reflectance, clamp, ) where import Control.Monad.Random 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 :: Double -> Double degToRadians d = (d * pi) / 180.0 dotP :: V3 Double -> V3 Double -> Double dotP (V3 a b c) (V3 d e f) = a * d + b * e + c * f lengthSquared :: V3 Double -> Double lengthSquared (V3 x y z) = x ^ 2 + y ^ 2 + z ^ 2 vectorLength :: V3 Double -> Double vectorLength v = sqrt (lengthSquared v) unitVector :: V3 Double -> V3 Double unitVector v = v ^/ vectorLength v reflect :: V3 Double -> V3 Double -> V3 Double reflect v n = v - (2 * (v `dotP` n)) *^ n refract :: V3 Double -> V3 Double -> Double -> V3 Double 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