Download
199 lines 6.6 KiBLuaModified 2017-10-28 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
local Noise = require "hill_noise"
local Histogram = require 'histogram'
local DRAW_RES = love.window.toPixels(4)
local SCALE = 100
local DRAW_HISTOGRAMS = false
local DRAW_GRADIENTS = false

local decay = function(x) return .15^x end
local n1,g1 = Noise.make1d{resolution=5, distribution=decay, seed=1}
local n2,g2 = Noise.make2d{resolution=7, distribution=decay, seed=1}
local n3,g3 = Noise.make3d{resolution=9, distribution=decay, seed=1}
local s1,s1g = Noise.make1dShader{resolution=10, distribution=decay, seed=1, draw_outline=true}
local s2,s2g = Noise.make2dShader{resolution=15, distribution=decay, seed=1}
local s3,s3g = Noise.make3dShader{resolution=20, distribution=decay, seed=1}

lg = love.graphics
W,H = lg.getDimensions()
local cw,ch = W/2,H/3
local canv = lg.newCanvas(cw,ch)
local font = lg.newFont(love.window.toPixels(24))

function love.load()
    xOffset = 0
    yOffset = 0
    t0 = love.timer.getTime()
    love.mouse.setCursor(love.mouse.getSystemCursor("hand"))
end

function love.mousepressed()
    love.mouse.setCursor(love.mouse.getSystemCursor("sizeall"))
end

function love.mousereleased()
    love.mouse.setCursor(love.mouse.getSystemCursor("hand"))
end

function love.draw()
    if DRAW_HISTOGRAMS then
        lg.setColor(0,100,0)
        histogram1:draw()
        lg.setColor(0,0,150)
        histogram2:draw()
        lg.setColor(125,0,0)
        histogram3:draw()
    end

    lg.setColor(255,255,255)
    lg.setLineWidth(love.window.toPixels(2))
    lg.setLineJoin("none")
    local p1 = {}
    for x=0,W-H/3,DRAW_RES do
        table.insert(p1,x)
        table.insert(p1,n1(x/SCALE+xOffset)*H/3)
    end
    lg.line(p1)
    do -- Draw tangent line
        local mx = love.mouse.getX()
        local y, dydx = n1(mx/SCALE + xOffset), g1(mx/SCALE + xOffset)
        y = y * H/3
        dydx = dydx * H/3 / SCALE
        local h = 50/math.sqrt(1+dydx^2)
        lg.setColor(255,255,0)
        lg.line(mx-h, y - h*dydx, mx + h, y + h*dydx)
        lg.setColor(255,255,255)
    end

    local p2 = {}
    local t = love.timer.getTime()-t0
    for x=0,W-H/3,DRAW_RES do
        table.insert(p2,x)
        table.insert(p2,(1+n2(x/SCALE+xOffset,t))*H/3)
    end
    lg.line(p2)
    do -- Draw tangent line
        local mx = love.mouse.getX()
        local y = n2(mx/SCALE + xOffset, t)
        local dydx, dydz = g2(mx/SCALE + xOffset, t)
        y = (1+y) * H/3
        dydx = dydx * H/3 / SCALE
        local h = 50/math.sqrt(1+dydx^2)
        lg.setColor(255,255,0)
        lg.line(mx-h, y - h*dydx, mx + h, y + h*dydx)
        lg.setColor(255,255,255)
    end

    for y=0,H/6*1.2,2*DRAW_RES do
        local p3 = {}
        for x=0,W-H/3,DRAW_RES do
            table.insert(p3,x)
            table.insert(p3,2/3*H+H/6*(1-n3(x/SCALE+xOffset,y/SCALE+yOffset,t))+y)
        end
        lg.line(p3)
    end
    for x=-H/6,W-H/3,DRAW_RES*2 do
        local p3 = {}
        local slant = .5
        for y=0,H/6*1.2,2*DRAW_RES do
            local x2 = x + slant*y
            if x2 < -2*DRAW_RES then goto continue end
            table.insert(p3,x2)
            table.insert(p3,2/3*H+H/6*(1-n3(x2/SCALE+xOffset,y/SCALE+yOffset,t))+y)
            if x2 > W/2 then break end
            ::continue::
        end
        if #p3 > 2 then
            lg.line(p3)
        end
    end
    --[[ 3D tangent lines not working
    do -- Draw tangent line
        local mx = love.mouse.getX()
        local my = love.mouse.getY()/2 - 1/3*H
        if my < 1/6*H then my = 1/6*H end
        mx = mx + .5*my
        local y = 2/3*H+H/6*(1-n3(mx/SCALE + xOffset, my/SCALE + yOffset, t))+my
        local dydx, dydz, _ = g3(mx/SCALE + xOffset, my/SCALE + yOffset, t)
        dydx = dydx * H/3 / SCALE
        local h = 50/math.sqrt(1+dydx^2)
        lg.setColor(255,255,0)
        lg.line(mx-h, y - h*dydx, mx + h, y + h*dydx)
        lg.setColor(255,255,255)
    end
    ]]

    local shader
    shader = DRAW_GRADIENTS and s1g or s1
    lg.setShader(shader)
    shader:send("range_min", xOffset)
    shader:send("range_max", xOffset+2*cw/SCALE)
    lg.draw(canv,W-cw,0)
    shader = DRAW_GRADIENTS and s2g or s2
    lg.setShader(shader)
    shader:send("range_min", {xOffset,yOffset})
    shader:send("range_max", {xOffset+2*cw/SCALE,yOffset+2*ch/SCALE})
    lg.draw(canv,W-cw,ch)
    shader = DRAW_GRADIENTS and s3g or s3
    lg.setShader(shader)
    shader:send("range_min", {xOffset,yOffset})
    shader:send("range_max", {xOffset+2*cw/SCALE,yOffset+2*ch/SCALE})
    shader:send('z', t)
    lg.draw(canv,W-cw,2*ch)
    lg.setShader(nil)

    lg.setColor(0,0,0,175)
    lg.rectangle('fill',0,0,W,font:getHeight()+love.window.toPixels(5))
    lg.rectangle('fill',0,H/3,W,font:getHeight()+love.window.toPixels(5))
    lg.rectangle('fill',0,2*H/3,W,font:getHeight()+love.window.toPixels(5))
    lg.setColor(255,230,50)
    lg.setFont(font)
    lg.printf("1D_Noise(x)", 5,5, W)
    lg.printf("2D_Noise(x,time)", 5,5+H/3, W)
    lg.printf("3D_Noise(x,y,time)", 5,5+2*H/3, W)
    lg.printf("1D_Noise_Shader(x)", 0,5, W-5, 'right')
    lg.printf("2D_Noise_Shader(x,y)", 0,5+H/3, W-5, 'right')
    lg.printf("3D_Noise_Shader(x,y,time)", 0,5+2*H/3, W-5, 'right')

    lg.setColor(20,200,20)
    lg.printf("'h': toggle histograms, 'g': toggle gradients", 5,5, W-5, 'center')
end

function love.update(dt)
    local key = love.keyboard.isDown
    local dx = 400/SCALE*dt*((key('right') and 1 or 0) + (key('left') and -1 or 0))
    local dy = 400/SCALE*dt*((key('down') and 1 or 0) + (key('up') and -1 or 0))
    xOffset = xOffset + dx
    yOffset = yOffset + dy
end

function love.keypressed(key)
    if key == 'escape' then love.event.quit() end
    if key == 'r' then love.load() end
    if key == 'g' then
        DRAW_GRADIENTS = not DRAW_GRADIENTS
    end
    if key == 'h' then
        DRAW_HISTOGRAMS = not DRAW_HISTOGRAMS
        if DRAW_HISTOGRAMS and not histogram1 then
            local data1,data2,data3 = {},{},{}
            for i=1,100000 do
                local x = math.random()*100000
                local y = math.random()*100000
                local z = math.random()*100000
                table.insert(data1, n1(x))
                table.insert(data2, n2(x,y))
                table.insert(data3, n3(x,y,z))
            end
            histogram1 = Histogram:fromList(data1,{pos={x=0,y=0},size={x=W/4,y=H/3},xmin=0,xmax=1,numBuckets=30})
            histogram2 = Histogram:fromList(data2,{pos={x=0,y=H/3},size={x=W/4,y=H/3},xmin=0,xmax=1,numBuckets=30})
            histogram3 = Histogram:fromList(data3,{pos={x=0,y=2*H/3},size={x=W/4,y=H/3},xmin=0,xmax=1,numBuckets=30})
        end
    end
end

function love.mousemoved(x,y,dx,dy)
    if love.mouse.isDown(1) then
        xOffset = xOffset - dx/SCALE
        yOffset = yOffset - dy/SCALE
    end
end