module Geometry.Algorithms.PerlinNoise (
      PerlinParameters(..)
    , perlin1
    , perlin2
    , perlin3
) where



import           Data.Default.Class
import           Data.Maybe
import           Geometry.Core
import qualified Math.Noise         as Perlin



-- | Named arguments for the @perlin*@ functions.
data PerlinParameters = PerlinParameters
    { PerlinParameters -> Double
_perlinFrequency :: Double
        -- ^ Frequency of the first octave, e.g. \(\frac1{2\text{width}}\) to span the whole width of the picture.
        --   'def'ault: 1.

    , PerlinParameters -> Double
_perlinLacunarity :: Double
        -- ^ Amplitude factor between octaves.
        --   'def'ault: 2.

    , PerlinParameters -> Int
_perlinOctaves :: Int
        -- ^ Number of octaves to generate.
        --   'def'ault: 6.

    , PerlinParameters -> Double
_perlinPersistence :: Double
        -- ^ Amplitude multiplier between octaves.
        --   'def'ault: 0.5.

    , PerlinParameters -> Int
_perlinSeed :: Int
        -- ^ RNG seed.
    } deriving (PerlinParameters -> PerlinParameters -> Bool
(PerlinParameters -> PerlinParameters -> Bool)
-> (PerlinParameters -> PerlinParameters -> Bool)
-> Eq PerlinParameters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PerlinParameters -> PerlinParameters -> Bool
== :: PerlinParameters -> PerlinParameters -> Bool
$c/= :: PerlinParameters -> PerlinParameters -> Bool
/= :: PerlinParameters -> PerlinParameters -> Bool
Eq, Eq PerlinParameters
Eq PerlinParameters
-> (PerlinParameters -> PerlinParameters -> Ordering)
-> (PerlinParameters -> PerlinParameters -> Bool)
-> (PerlinParameters -> PerlinParameters -> Bool)
-> (PerlinParameters -> PerlinParameters -> Bool)
-> (PerlinParameters -> PerlinParameters -> Bool)
-> (PerlinParameters -> PerlinParameters -> PerlinParameters)
-> (PerlinParameters -> PerlinParameters -> PerlinParameters)
-> Ord PerlinParameters
PerlinParameters -> PerlinParameters -> Bool
PerlinParameters -> PerlinParameters -> Ordering
PerlinParameters -> PerlinParameters -> PerlinParameters
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PerlinParameters -> PerlinParameters -> Ordering
compare :: PerlinParameters -> PerlinParameters -> Ordering
$c< :: PerlinParameters -> PerlinParameters -> Bool
< :: PerlinParameters -> PerlinParameters -> Bool
$c<= :: PerlinParameters -> PerlinParameters -> Bool
<= :: PerlinParameters -> PerlinParameters -> Bool
$c> :: PerlinParameters -> PerlinParameters -> Bool
> :: PerlinParameters -> PerlinParameters -> Bool
$c>= :: PerlinParameters -> PerlinParameters -> Bool
>= :: PerlinParameters -> PerlinParameters -> Bool
$cmax :: PerlinParameters -> PerlinParameters -> PerlinParameters
max :: PerlinParameters -> PerlinParameters -> PerlinParameters
$cmin :: PerlinParameters -> PerlinParameters -> PerlinParameters
min :: PerlinParameters -> PerlinParameters -> PerlinParameters
Ord, Int -> PerlinParameters -> ShowS
[PerlinParameters] -> ShowS
PerlinParameters -> String
(Int -> PerlinParameters -> ShowS)
-> (PerlinParameters -> String)
-> ([PerlinParameters] -> ShowS)
-> Show PerlinParameters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PerlinParameters -> ShowS
showsPrec :: Int -> PerlinParameters -> ShowS
$cshow :: PerlinParameters -> String
show :: PerlinParameters -> String
$cshowList :: [PerlinParameters] -> ShowS
showList :: [PerlinParameters] -> ShowS
Show)

instance Default PerlinParameters where
    def :: PerlinParameters
def = PerlinParameters
        { _perlinFrequency :: Double
_perlinFrequency   = Double
1
        , _perlinLacunarity :: Double
_perlinLacunarity  = Double
2
        , _perlinOctaves :: Int
_perlinOctaves     = Int
6
        , _perlinPersistence :: Double
_perlinPersistence = Double
0.5
        , _perlinSeed :: Int
_perlinSeed        = Int
0
        }

marshalPP :: PerlinParameters -> Perlin.Perlin
marshalPP :: PerlinParameters -> Perlin
marshalPP PerlinParameters{Double
Int
_perlinFrequency :: PerlinParameters -> Double
_perlinLacunarity :: PerlinParameters -> Double
_perlinOctaves :: PerlinParameters -> Int
_perlinPersistence :: PerlinParameters -> Double
_perlinSeed :: PerlinParameters -> Int
_perlinFrequency :: Double
_perlinLacunarity :: Double
_perlinOctaves :: Int
_perlinPersistence :: Double
_perlinSeed :: Int
..} = Perlin.Perlin
    { perlinFrequency :: Double
perlinFrequency   = Double
_perlinFrequency
    , perlinLacunarity :: Double
perlinLacunarity  = Double
_perlinLacunarity
    , perlinOctaves :: Int
perlinOctaves     = Int
_perlinOctaves
    , perlinPersistence :: Double
perlinPersistence = Double
_perlinPersistence
    , perlinSeed :: Int
perlinSeed        = Int
_perlinSeed
    }

-- | One-dimensional Perlin noise.
perlin1 :: PerlinParameters -> Double -> Double
perlin1 :: PerlinParameters -> Double -> Double
perlin1 PerlinParameters
params Double
x = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
0 (Perlin -> (Double, Double, Double) -> Maybe Double
forall n.
NoiseClass n =>
n -> (Double, Double, Double) -> Maybe Double
Perlin.getValue (PerlinParameters -> Perlin
marshalPP PerlinParameters
params) (Double
x, Double
0, Double
0))

-- | Two-dimensional Perlin noise.
perlin2 :: PerlinParameters -> Vec2 -> Double
perlin2 :: PerlinParameters -> Vec2 -> Double
perlin2 PerlinParameters
params (Vec2 Double
x Double
y) = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
0 (Perlin -> (Double, Double, Double) -> Maybe Double
forall n.
NoiseClass n =>
n -> (Double, Double, Double) -> Maybe Double
Perlin.getValue (PerlinParameters -> Perlin
marshalPP PerlinParameters
params) (Double
x, Double
y, Double
0))

-- | Three-dimensional Perlin noise.
perlin3 :: PerlinParameters -> Double -> Double -> Double -> Double
perlin3 :: PerlinParameters -> Double -> Double -> Double -> Double
perlin3 PerlinParameters
params Double
x Double
y Double
z = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
0 (Perlin -> (Double, Double, Double) -> Maybe Double
forall n.
NoiseClass n =>
n -> (Double, Double, Double) -> Maybe Double
Perlin.getValue (PerlinParameters -> Perlin
marshalPP PerlinParameters
params) (Double
x, Double
y, Double
z))