brot/cmd/viewer.lua

local bignum = require "bignum"
local mandelbrot = require "mandelbrot"


local shader = love.graphics.newShader "mandelbrot.glsl"
local canvas = love.graphics.newCanvas(love.graphics.getDimensions())
local redraw = true

local iter = 256
local view_pos = {bignum.float(0), bignum.float(0)}
local zoom = 300
local antialias = 1

local function draw_brot(zoom, x, y)
	love.graphics.setShader(shader)
	shader:send("iterations", iter)
	shader:send("zoom", zoom)
	shader:send("antialias", antialias)
	local orbit = mandelbrot.orbit(iter, x, y)
	shader:send("orbit", unpack(orbit))

	local w, h = love.graphics.getDimensions()
	local ox, oy = -w / 2 / zoom, -h / 2 / zoom
	shader:send("offset", {ox, oy})

	love.graphics.rectangle("fill", 0, 0, love.graphics.getDimensions())
	love.graphics.setShader()

--	love.graphics.push()
--	love.graphics.translate(w / 2, h / 2)
--	love.graphics.scale(zoom)
--	love.graphics.translate(-bignum.tonumber(x), -bignum.tonumber(y))
--	love.graphics.setLineWidth(1 / zoom)
--	love.graphics.setColor(1, 0.1, 1)
--	for i = 2, #orbit do
--		local x1, y1 = unpack(orbit[i - 1])
--		local x2, y2 = unpack(orbit[i])
--		love.graphics.line(x1, y1, x2, y2)
--	end
--	love.graphics.setColor(1, 1, 1)
--	love.graphics.pop()
end

function love.draw()
	local w, h = love.graphics.getDimensions()
	local cw, ch = canvas:getDimensions()
	if cw < w or ch < h then
		canvas:release()
		canvas = love.graphics.newCanvas(w, h)
	end
	if cw ~= w or ch ~= h then
		redraw = true
	end

	if redraw then
		love.graphics.setCanvas(canvas)
		draw_brot(zoom, unpack(view_pos))
		redraw = false
	end

	love.graphics.setShader()
	love.graphics.setCanvas()
	love.graphics.draw(canvas)

	love.graphics.setColor(0, 0, 0, 0.5)
	love.graphics.rectangle("fill", 0, 0, w, 25)
	love.graphics.setColor(1, 1, 1)
	local info = ("p: (%s, %s) z: %s i: %s a: %dX"):format(
		view_pos[1], view_pos[2], zoom, iter, antialias * antialias)
	love.graphics.print(info, 5, 5)
	love.graphics.setColor(1, 1, 1)

	local x, y = unpack(view_pos)
end

function love.mousemoved(x, y, dx, dy)
	if love.mouse.isDown(1) then
		view_pos[1], view_pos[2] =
			view_pos[1] - dx / zoom, view_pos[2] - dy / zoom
		--print("p", unpack(view_pos))
		redraw = true
	end
end

function love.wheelmoved(_, sy)
	local x, y = unpack(view_pos)
	local w, h = love.graphics.getDimensions()
	local mx, my = love.mouse.getPosition()
	mx, my = mx - w / 2, my - h / 2

	x, y = x + mx / zoom, y + my / zoom
	zoom = zoom + sy * (zoom / 15)
	x, y = x - mx / zoom, y - my / zoom
	view_pos[1], view_pos[2] = x, y

	redraw = true
end

function love.keypressed(key)
	if key == "up" then
		if iter < 4096 then
			iter = iter * 2
			redraw = true
		end
	elseif key == "down" then
		if iter > 1 then
			iter = iter / 2
			redraw = true
		end
	elseif key == "a" then
		antialias = 1 + (antialias % 3)
		redraw = true
	end
end