-- Copyright (c) 2011, Colin Hill


-- | Implementation of Perlin noise.

--

-- Example of use:

--

-- @

--main = putStrLn (\"Noise value at (1, 2, 3): \" ++ show x)

--    where seed        = 1

--          octaves     = 5

--          scale       = 0.05

--          persistance = 0.5

--          perlinNoise = perlin seed octaves scale persistance

--          x           = noiseValue perlinNoise (1, 2, 3)

-- @

module Numeric.Noise.Perlin (
    Perlin,
    perlin,
    noiseValue
) where

import Numeric.Noise

-- | A Perlin noise function.

data Perlin = Perlin Seed Int Double Double

instance Noise Perlin where
    noiseValue :: Perlin -> Point -> Double
noiseValue Perlin
perlinNoise Point
xyz = forall a. Ord a => a -> a -> a -> a
clamp Double
noise (-Double
1) Double
1
        where Perlin Int
_ Int
octs Double
_ Double
_ = Perlin
perlinNoise
              noise :: Double
noise             = Perlin -> Int -> Double -> Double -> Point -> Double
perlinNoiseValue Perlin
perlinNoise Int
octs Double
1 Double
1 Point
xyz

-- | Constructs a Perlin noise function given a seed, number of octaves, scale, and persistance.

perlin :: Seed -> Int -> Double -> Double -> Perlin
perlin :: Int -> Int -> Double -> Double -> Perlin
perlin = Int -> Int -> Double -> Double -> Perlin
Perlin

-- | Evaluates a given number of octaves of perlin noise holding the frequency and amplitude in 

-- the arguments.

perlinNoiseValue :: Perlin -> Int -> Double -> Double -> Point -> Double
perlinNoiseValue :: Perlin -> Int -> Double -> Double -> Point -> Double
perlinNoiseValue Perlin
_           Int
0   Double
_    Double
_   Point
_   = Double
0
perlinNoiseValue Perlin
perlinNoise Int
oct Double
freq Double
amp Point
xyz = Double
noise forall a. Num a => a -> a -> a
+ Double
noise'
    where Perlin Int
seed Int
_ Double
scale Double
pers = Perlin
perlinNoise
          oct' :: Int
oct'   = Int
oct forall a. Num a => a -> a -> a
- Int
1
          freq' :: Double
freq'  = Double
freq forall a. Num a => a -> a -> a
* Double
2
          amp' :: Double
amp'   = Double
amp forall a. Num a => a -> a -> a
* Double
pers
          xyz' :: Point
xyz'   = (Double -> Double) -> Point -> Point
pmap (forall a. Num a => a -> a -> a
* (Double
scale forall a. Num a => a -> a -> a
* Double
freq)) Point
xyz
          noise :: Double
noise  = Int -> Point -> Double
coherentNoise Int
seed Point
xyz' forall a. Num a => a -> a -> a
* Double
amp
          noise' :: Double
noise' = Perlin -> Int -> Double -> Double -> Point -> Double
perlinNoiseValue Perlin
perlinNoise Int
oct' Double
freq' Double
amp' Point
xyz