packages feed

pure-noise-0.2.0.0: src/Numeric/Noise/OpenSimplex.hs

{-# LANGUAGE Strict #-}

-- |
-- Maintainer: Jeremy Nuttall <jeremy@jeremy-nuttall.com>
-- Stability: experimental
--
-- This module implements a variation of OpenSimplex2 noise derived from FastNoiseLite.
module Numeric.Noise.OpenSimplex (
  -- * 2D Noise
  noise2,
  noise2Base,
) where

import Numeric.Noise.Internal
import Numeric.Noise.Internal.Math

noise2 :: (RealFrac a) => Noise2 a
noise2 = Noise2 noise2Base
{-# INLINE noise2 #-}

noise2Base :: (RealFrac a) => Seed -> a -> a -> a
noise2Base seed xo yo =
  let f2 = 0.5 * (sqrt3 - 1)
      to = (xo + yo) * f2
      x = xo + to
      y = yo + to

      fx = floor x
      fy = floor y
      xi = x - fromIntegral fx
      yi = y - fromIntegral fy

      t = (xi + yi) * g2
      x0 = xi - t
      y0 = yi - t
      i = fx * primeX
      j = fy * primeY

      a = 0.5 - x0 * x0 - y0 * y0
      n0
        | a <= 0 = 0
        | otherwise =
            (a * a)
              * (a * a)
              * gradCoord2 seed i j x0 y0

      n1
        | y0 > x0 =
            let ~x1 = x0 + g2
                ~i1 = i
                ~y1 = y0 + (g2 - 1)
                ~j1 = j + primeY
                ~b = 0.5 - x1 * x1 - y1 * y1
             in if b <= 0
                  then 0
                  else
                    (b * b)
                      * (b * b)
                      * gradCoord2 seed i1 j1 x1 y1
        | otherwise =
            let ~x1 = x0 + (g2 - 1)
                ~i1 = i + primeX
                ~y1 = y0 + g2
                ~j1 = j
                ~b = 0.5 - x1 * x1 - y1 * y1
             in if b <= 0
                  then 0
                  else
                    (b * b)
                      * (b * b)
                      * gradCoord2 seed i1 j1 x1 y1

      c =
        let g2t = 1 - 2 * g2
         in 2 * g2t * (1 / g2 - 2) * t
              + (-2 * g2t * g2t + a)
      n2
        | c <= 0 = 0
        | otherwise =
            let ~x2 = x0 + (2 * g2 - 1)
                ~y2 = y0 + (2 * g2 - 1)
             in (c * c)
                  * (c * c)
                  * gradCoord2 seed (i + primeX) (j + primeY) x2 y2
   in (n0 + n1 + n2) * 99.83685446303647
{-# INLINE noise2Base #-}