Skip to content

Instantly share code, notes, and snippets.

@silky
Forked from sordina/field.hs
Created June 5, 2014 02:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save silky/2709a7801dceb479503c to your computer and use it in GitHub Desktop.
Save silky/2709a7801dceb479503c to your computer and use it in GitHub Desktop.
{-# LANGUAGE BangPatterns #-}
-- Preview on Youtube: http://www.youtube.com/watch?v=bK01Bgh32Sc
import Data.Complex
type C = Complex Float
type Color = (Float,Float,Float)
type Point = (Float,Float)
main :: IO ()
main = flip mapM_ [0 :: Float, 0.1 .. 5] $ \t -> do -- 125 = 1 period
print t
let output = renderer (2000,1000) (-1.2,-1.5) (0.5,0.6) function t
writeFile ("temp/field/testimage_" ++ show t ++ ".ppm") output
function :: Float -> Point -> Color
function !t' !(x',y') = c2c $ n $ tc ** pc
where
pc = x :+ y
tc = 8 * (n $ t ** x :+ (y - t))
x = x' + 0.6
y = y' + 0.3
t = 40 * (sin (t'/20) + 1)
c2c :: Complex Float -> Color
c2c !p@(r :+ i) = (r, i, (magnitude p))
n :: C -> C
n !(x :+ y) = nf sin x :+ nf cos y
nf :: Fractional a => (t -> a) -> t -> a
nf !fun !x = (fun x + 1) / 2
-- ppm
renderer :: (Int, Int) -> (Float, Float) -> (Float, Float) -> (Float -> Point -> Color) -> Float -> String
renderer !size !lowbound !highbound !fun !time = header size body
where
xs = steps (fst lowbound) (fst highbound) (fst size)
ys = steps (snd lowbound) (snd highbound) (snd size)
body = unlines $ map line ys
line y = decolor . point fun time y =<< xs
header :: (Show a, Show a1) => (a, a1) -> [Char] -> [Char]
header !(w,h) x = "P3\n" ++ show w ++ " " ++ show h ++ "\n255\n" ++ x
steps :: Float -> Float -> Int -> [Float]
steps !l !h !p = take p [l, l + (h - l) / fromIntegral p .. h]
point :: (t1 -> (t2, t3) -> t) -> t1 -> t3 -> t2 -> t
point !f !t !y !x = f t (x,y)
decolor :: Color -> String
decolor !(r,g,b) = ' ' : unwords [sf r, sf g, sf b]
-- The mod here is intentional, as part of the cool look comes from overflowing the bounds of the color values.
sf :: Float -> String
sf = (show :: Int -> String) . flip mod 255 . floor . (*255)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment