packages feed

crocodile-0.1: app/src/Distribution.hs

-- Module for generating sample patterns for distributed ray tracing
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}

module Distribution (generatePointsOnSphere, generatePointsOnQuad, generatePointsOnHemisphere) where

import Vector
import System.Random.Mersenne.Pure64
import Control.Monad.State

type GeneratorState = State PureMT

-- Generate a pair of random normalised floats
randomUV :: GeneratorState (Double, Double)
randomUV = do generator <- get
              let !(u, generator') = randomDouble generator
              let !(v, generator'') = randomDouble generator'
              put generator''
              return (u, v)

-- Generate a list of N random UVs
generateRandomUVs :: Int -> GeneratorState [(Double, Double)]
generateRandomUVs n = replicateM n randomUV

-- Generate a list of random points on a sphere
generatePointsOnSphere :: Int -> Double -> Int -> [Position]
generatePointsOnSphere numPoints r seed = map uvToPosition randomUVs
    where
      randomUVs = evalState (generateRandomUVs numPoints) (pureMT (fromIntegral seed))
      uvToPosition (!u, !v) = Vector (r * x) (r * y) (r * z) 1
          where
            !z = 2 * u - 1
            !t = 2 * pi * v
            !w = sqrt (1 - z * z)
            !x = w * cos t
            !y = w * sin t

-- Generate a list of random points on a hemisphere (z > 0)
generatePointsOnHemisphere :: Int -> Double -> Int -> [Position]
generatePointsOnHemisphere numPoints r seed = map uvToPosition randomUVs
    where
      randomUVs = evalState (generateRandomUVs numPoints) (pureMT (fromIntegral seed))
      uvToPosition (!u, !v) = Vector (r * x) (r * y) (r * z) 1
          where
            !y = 2 * u - 1
            !t = pi * v
            !w = sqrt (1 - y * y)
            !x = w * cos t
            !z = w * sin t

generatePointsOnQuad :: Position -> Direction -> Direction -> Int -> Int -> [Position]
generatePointsOnQuad pos deltaU deltaV numPoints seed = map uvToPosition randomUVs
    where
      randomUVs = evalState (generateRandomUVs numPoints) (pureMT (fromIntegral seed))
      uvToPosition (u, v) = pos + (deltaU <*> u) + (deltaV <*> v)