2024-12-05 12:43:06 +01:00

61 lines
2.2 KiB
Haskell

module Math ( mandlebrot ) where
import Graphics.UI.GLUT
import Data.Complex
iterations = 10
x // y = fromIntegral x / fromIntegral y
-- Divides [a] into [[a], [a], ...] with each sublist of length n,
-- except the last sublist which has length <= n
chunkify n [] = []
chunkify n xs = let (xs', rest) = splitAt n xs
in xs' : chunkify n rest
-- Converts a coordinate in screen space to a vertex.
pix2vert (Size w h) (x, y) = Vertex2 ((3 // w * fromIntegral x) - 2.0)
((2 // h * fromIntegral y) - 1.0)
-- List of all the vertices that represent screen pixels.
vertices :: IO [Vertex2 GLfloat]
vertices = get windowSize >>= \(Size w h) -> return $ [pix2vert (Size w h) (x, y) | x <- [0..w-1], y <- [0..h-1]]
-- Gets the color for a number of iterations.
getcolor :: Int -> Color3 Float
getcolor iter | iter == iterations = Color3 0 0 0
| otherwise = Color3 (amt * 0.5) amt (amt * 0.5)
where amt = iter // iterations
-- Returns the number of iterations <= the maximum iterations of the Mandlebrot set at the given vertex
mandel (Vertex2 r i) = length . takeWhile (\z -> magnitude z <= 2) .
take iterations $ iterate (\z -> z^2 + (r :+ i)) 0
-- plots one point.
drawVert v = do color . getcolor $ mandel v
vertex v
-- draws all th vertices in slices (to update the display while drawing).
display' chunks = do mapM_ (\vs -> do renderPrimitive Points $ mapM_ drawVert vs
flush) chunks
displayCallback $= display
display = do clear [ ColorBuffer ]
displayCallback $= (vertices >>= display' . chunkify 256)
get currentWindow >>= postRedisplay
mandlebrot = do
getArgsAndInitialize
initialDisplayMode $= [ SingleBuffered, RGBMode ]
--initialWindowSize $= Size 1200 1024
--initialWindowPosition $= Position 100 100
createWindow "Mandlebrot"
clearColor $= Color4 0 0 0 0
matrixMode $= Projection
loadIdentity
--ortho (-3) 1 (-1) 1 (-1) 1
--ortho (-2) 1 (-1) 1 (-1) 1
ortho (-3) 1 (-1) 1 (-1) 1
displayCallback $= display
mainLoop