module Ray
  ( Ray (..),
    rayAt,
    calculateRayNormal,
    buildRay,
    buildRayAA,
  )
where

import Camera
import Control.Monad.Random
import Linear.V3
import Linear.Vector
import Maths

data Ray = Ray {origin :: V3 Double, direction :: V3 Double}

-- P(t) = A + tB; A is origin, B is direction
rayAt :: Ray -> Double -> V3 Double
rayAt (Ray origin dir) t = origin + (t *^ dir)

-- get the normal of the point at t
calculateRayNormal :: Ray -> Double -> V3 Double
calculateRayNormal r t = unitVector (rayAt r t ^-^ V3 0.0 0.0 1.0)

buildRayAA :: (RandomGen g) => Double -> Double -> Camera -> Rand g Ray
buildRayAA u v camera = do
  ur <- rand
  vr <- rand
  return $ buildRay (u + ur) (v + vr) camera

buildRay :: Double -> Double -> Camera -> Ray
buildRay u v (Camera o ll h vv) = Ray o (ll ^+^ (v *^ h) ^+^ (u *^ vv) ^-^ o)