packages feed

hfractal (empty) → 0.1.0

raw patch · 8 files changed

+282/−0 lines, 8 filesdep +GLUTdep +OpenGLdep +arraysetup-changed

Dependencies added: GLUT, OpenGL, array, base, data-accessor, data-accessor-template, gd

Files

+ Bindings.hs view
@@ -0,0 +1,36 @@+module Bindings+  where++import Graphics.UI.GLUT+import Data.IORef+import System.Exit++import FracState+import FracImg++--TODO. Clean up by using Data.Accessor+keyboardAct :: IORef Mandstate -> Key -> KeyState -> IO ()+keyboardAct ms (SpecialKey KeyLeft) Down = do+  modifyIORef ms (\m@Mandstate{xmid=x,range=r} -> m{xmid=x - 0.1*r})+keyboardAct ms (SpecialKey KeyRight) Down = do+  modifyIORef ms (\m@Mandstate{xmid=x,range=r} -> m{xmid=x + 0.1*r})+keyboardAct ms (SpecialKey KeyUp) Down = do+  modifyIORef ms (\m@Mandstate{ymid=y,range=r} -> m{ymid=y + 0.1*r})+keyboardAct ms (SpecialKey KeyDown) Down = do+  modifyIORef ms (\m@Mandstate{ymid=y,range=r} -> m{ymid=y - 0.1*r})+keyboardAct ms (Char '+') Down = do+  modifyIORef ms (\m@Mandstate{range=r} -> m{range=r/rangemul})+keyboardAct ms (Char '-') Down = do+  modifyIORef ms (\m@Mandstate{range=r} -> m{range=r*rangemul})+keyboardAct ms (Char 'a') Down = do+  modifyIORef ms (\m@Mandstate{colourmul=cm} -> m{colourmul=cm*cmul})+keyboardAct ms (Char 's') Down = do+  modifyIORef ms (\m@Mandstate{colourmul=cm} -> m{colourmul=cm/cmul})+keyboardAct ms (Char 'p') Down = do+  ms' <- readIORef ms+  imagAt "frac.png" ms'+keyboardAct ms (Char 'o') Down = do+  ms' <- readIORef ms+  print ms'+keyboardAct _ (Char '\27') _ = exitWith ExitSuccess+keyboardAct _ _ _ = return ()
+ FracComp.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE BangPatterns #-}+module FracComp+  where++import Graphics.UI.GLUT+import Data.Array.IO++import FracState++type Pix = IOUArray Int Double+-- Number of iterations to escape+mandPoint :: Int -> Double -> Double -> Double -> Double -> Double+mandPoint !n !x !y cx cy | n > maxIter		= 0.0+					     | (x2 + y2) > 4.0  = 1.0 - logBase 2 (0.5 * logBase 2 (x2 + y2)) + fromIntegral n+					     | otherwise		= mandPoint (n+1) (x2 - y2 + cx) (2.0*x*y + cy) cx cy where+	x2 = x*x  --This CSE saves a few cycles+	y2 = y*y++compPoints :: Double -> Double -> Double -> Sz -> Pix -> IO ()+compPoints xm ym rng sz@(Sz width height) arr = go 0 0 where+	go !x !y | y == height  = return () +			 | x == width   = go 0 (y+1)+			 | otherwise = do +		writeArray arr k (mandPoint 0 0.0 0.0 cx cy)+		go (x+1) y where+			k = x + y*width+			fi = fromIntegral+			cx = rng * (fi x - fi w2) / fi w2 + xm :: Double+			cy = rng * (fi y - fi h2) / fi h2 + ym :: Double+			(w2, h2) = (width `div` 2, height `div` 2)++-- Colour a vertex+colourMand :: Double -> Double -> Color3 GLdouble+colourMand 0.0 _ = fmap realToFrac $ Color3 0.0 0.0 0.0+colourMand m cm = fmap realToFrac $ Color3 r g b where+	r = 0.5 + 0.5 * cos (m * cm) +	g = 0.5 + 0.5 * cos ((m + 16.0) * cm)+	b = 0.5 + 0.5 * cos ((m + 32.0) * cm)++-----------------------------------------+--QuickCheck Properties+-----------------------------------------+--TODO: Conjure up some more properties++prop_reflection :: Double -> Double -> Bool+prop_reflection x y = mandPoint 0 0.0 0.0 x y == mandPoint 0 0.0 0.0 x (-y)
+ FracImg.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE BangPatterns #-}+module FracImg+	where++import FracComp+import FracState++import Graphics.GD+import Data.Array.IO hiding (range)+import System.IO+import Graphics.Rendering.OpenGL++w = 1600+h = 1600+filepath = "." :: FilePath++convColour :: Color3 GLdouble -> Graphics.GD.Color+convColour (Color3 r g b) = rgb (f r) (f g) (f b) where+	f = (floor . (* 256))++--pixel ::  Image -> Double -> (Int, Double) -> IO ()+pixelWrite im (Sz w h) cm pixarr = go 0 0 where+	go !x !y | y == h = return ()+			 | x == w = go 0 (y+1)+			 | otherwise = do+		p <- readArray pixarr (x + y*w)+		setPixel (x,y) (convColour $ colourMand p cm) im+		go (x+1) y++imagAt ::  FilePath -> Mandstate -> IO ()+imagAt fp Mandstate{xmid=xm, ymid=ym, range=rng, colourmul=cm} = do+	pixarr <- newArray (0, w*h-1) 0.0 :: IO Pix+	im <- newImage (w, h)+	compPoints xm ym rng (Sz w h) pixarr+	pixelWrite im (Sz w h) cm pixarr +	savePngFile fp im++{-+imgrange :: Double-> Double-> Double-> Double-> Double-> Int-> [Char]-> IO ()+imgrange xm ym cm initrange scale num rootfp = mapM_ (\(fn, r) -> imagAt fn xm ym cm r) $ zip fns ranges where+	fns = map (\s -> rootfp ++ show (100000 + s) ++ ".png") [1..num]+	ranges = take num $ iterate (/scale) initrange+-}
+ FracState.hs view
@@ -0,0 +1,27 @@+module FracState+  where++maxIter, maxWidth, maxHeight :: Int+maxIter = 500+(maxWidth, maxHeight) = (1200,1200)++--Keep the indicies as a global list so they aren't recopmuted every rendering+indicies :: [Int]+indicies = [0 .. (maxWidth-1)*(maxHeight-1)]++rangemul, cmul :: Double+rangemul = 1.02+cmul     = 1.3++data Mandstate = Mandstate {+  xmid :: Double,+  ymid :: Double,+  range :: Double,+  colourmul :: Double } deriving (Eq, Show)++data Sz = Sz Int Int deriving (Eq, Show)++data Options = Options+	{ size :: Sz,+	  ms   :: Mandstate   +	} deriving (Eq, Show)
+ Hfractal.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE BangPatterns #-}+import Graphics.UI.GLUT+import Data.IORef+import Data.Array.IO hiding (range)+import System.Console.GetOpt+import System.Environment (getArgs)++import Bindings+import FracState+import FracComp++inializeScreen opts@Options{size=Sz w h} = do+	(progname,_) <- getArgsAndInitialize+	initialDisplayMode $= [DoubleBuffered]+	lineSmooth  $= Enabled+	blendFunc   $= (SrcAlpha, OneMinusSrcAlpha)+	createWindow "HFractal"+	windowSize $= Size (fromIntegral (w-2)) (fromIntegral (h-1))+	--clearColor $= Color4 0 0 0 0+	matrixMode $= Projection+	ortho2D 0.0 (fromIntegral (w-1)) 0.0 (fromIntegral (h-1)) +	matrixMode $= Modelview 0++setCallBacks opts@Options{size=s@(Sz w h), ms=state} = do+	--Create the state and pixel array+	ms <- newIORef state+	pixarr <- newArray (0, w*h-1) 0.0 :: IO Pix+	--Set the callbacks+	reshapeCallback $= Just (reshape opts)+	idleCallback $= Just idle+	keyboardMouseCallback $= Just (keyboardMouse ms)+	displayCallback $= display ms s pixarr++----------------------------------------+--Display Callback and related functions+----------------------------------------++display ms sz@(Sz w h) pixarr = do+	clear [ColorBuffer]+	loadIdentity+	Mandstate{xmid=x, ymid=y, range=r, colourmul=cm} <- get ms+	compPoints x y r sz pixarr+	preservingMatrix $ do+		renderPrimitive Points $ displayPix sz cm pixarr+	swapBuffers++displayPix :: Sz -> Double -> IOUArray Int Double -> IO ()+displayPix sz@(Sz width height) cm pixarr = go 0 0 where+	go !x !y | y == height = return ()+	         | x == width  = go 0 (y+1)	+			 | otherwise   = do+		dk <- readArray pixarr (x + y*width)+		color (colourMand dk cm)+		vertex $ Vertex2 (fromIntegral x) (fromIntegral y :: GLfloat)+		go (x+1) y++-----------------------------------------+--Other Callbacks+-----------------------------------------++idle ::  IO ()+idle = do+	postRedisplay Nothing++reshape opts s'@(Size w h) = do+	viewport $= (Position 0 0, s')+	--setCallBacks opts{size=Sz (fromIntegral w) (fromIntegral h)} --Reset the callbacks so that the pixarr is recreated+	postRedisplay Nothing++keyboardMouse ms key state _ _ = do+	keyboardAct ms key state++-----------------------------------------+--Option Parsing and Main loop+----------------------------------------++zeroState, state1 :: Mandstate+zeroState = Mandstate {xmid = 0.0, ymid = 0.0, range = 2.0, colourmul = 0.05}+state1    = Mandstate {xmid = 0.001643721971153, ymid = 0.822467633298876, range = 0.05, colourmul = 0.0625}+state = state1++defOpts = Options {size=Sz 400 400, ms=state}++--TODO: Tidy up the option parser with Data.Accessor(.Template)+options :: [OptDescr (Options -> Options)]+options = [ +	Option ['w'] ["width"] (ReqArg (\x opt -> opt {size = sx (size opt) (r x)} ) "WIDTH") "Set width of rendering window", +	Option ['h'] ["height"] (ReqArg (\y opt -> opt {size = sy (size opt) (r y)} ) "HEIGHT") "Set height of rendering window"] where +	--Options ['x'] ["x-mid"] (NoArg (\x opt -> opt { ms {xmid = read x} }))+	sx (Sz x y) x' = (Sz x' y)+	sy (Sz x y) y' = (Sz x y')+	r = read++getOpts :: [String] -> IO Options+getOpts argv = case getOpt Permute options argv of+	(o, [], []) -> return $ foldl (flip ($)) defOpts o+	(_, _, errs) -> ioError (userError (concat errs ++ usageInfo header options))+	where header = "Usage: hfractal [OPTION...]"++main :: IO()+main = do+	opts <- getOpts =<< getArgs+	inializeScreen opts +	setCallBacks opts+	mainLoop
+ README view
@@ -0,0 +1,7 @@+OpenGL Fractal renderer. Currently only renders the Mandelbrot set, but can (and will) be easily extened to other fractals.++Controls:+Arrow keys   -    Movement++/-          -    Zoom in/out+a/s          -    Alter colouring gradient+p            -    Print a hi-res image of the current location in the working direction
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hfractal.cabal view
@@ -0,0 +1,16 @@+name:                hfractal+version:             0.1.0+cabal-version:		 >= 1.2+synopsis:            OpenGL fractal renderer+category:            Graphics+license:             BSD3+author:              Chris Holdsworth+maintainer:          chrisholdsworth@gmail.com+build-type:          Simple+extra-source-files:  README++Executable hfractal+    main-is:            Hfractal.hs+    build-depends:      base >=4 && <= 4.1, array, data-accessor, data-accessor-template, gd, OpenGL, GLUT+    other-Modules:      FracComp, FracState, FracImg, Bindings+    ghc-options:        -O2