Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

3D Wave using Perlin noise

in Examples Posts: 116

I was inspired by these terrain generators(writen by me)
http://codea.io/talk/discussion/6808/a-big-collection-of-mountain-fractals-terrain-generation-in-3d-and-2d-useless-bonus

Now i wrote a dynamic wave using noise values and i want to share this with you.

function setup()
    displayMode(FULLSCREEN)
    btns = {
    exit = Button("Tyrian Remastered:Super Brain","Tyrian Remastered:Explosion Huge",35, HEIGHT-35)
    }
    btns.exit.action = function() close() end
    size = 25
    ms = mesh()
    ms:setColors(255,255,255,255)
    parameter.number("noiseScale", 0.01,2,0.07)
    field = 40
    noisePos = vec2(0,0)
    heights = {}
    for i=1, field do
        table.insert(heights,{})
        for a=1, field do
            table.insert(heights[i],0)
        end
    end

    parameter.action("LookAtCenter",function()cam:lookAt(vec3(0,0,0))end)
    parameter.color("basecol", color(0,0,127,255), function() col = true end)

    col = false
    tex1D = false
    tex2D = false
    rndTex = false

    parameter.action(".col", function() col = true draw() col = false end)
    parameter.action(".tex1D", function() tex1D = true draw() tex1D = false end)
    parameter.action(".tex2D", function() tex2D = true draw() tex2D = false end)
    parameter.action(".rndTex", function() rndTex = true draw() rndTex = false end)
    --[[
    parameter.boolean("col", false)
    parameter.boolean("tex1D", false)
    parameter.boolean("tex2D", true)
    parameter.boolean("rndTex", true)
      ]]
    touches = {}
    cam = Camera()
    cam.crosshair = false
    cam.dist = 1400
    cam.fix = true
    ls,rs = Stick(10),Stick(3,WIDTH-120)
end

function draw()
    next()
    background(54, 54, 54, 255)
    perspective()

    cam:draw()

    cam.angH = cam.angH + rs.x
    cam.angV = cam.angV + rs.y

    cam:movement(ls.y,ls.x)

    pushMatrix()
    strokeWidth(1)
    rotate(90,1,0,0)
    popMatrix()
    translate(-size*field/2, 0, -size*field/2)
    ms:draw()
    ortho()
    viewMatrix(matrix())
    resetMatrix()
    ls:draw()
    rs:draw()
    strokeWidth(1)
    for k, btn in pairs(btns) do
        btn:draw()
    end
end
function touched(touch)
    for k, btn in pairs(btns) do
        btn:touched(touch)
    end
     if touch.state == ENDED then
        touches[touch.id] = nil
    else
        touches[touch.id] = touch
    end
end

function next()
    size = 25
    --noiseScale = 0.07
noisePos = noisePos + vec2(0.01,0.01)
    for r, row in pairs(heights) do
        for i, h in pairs(row) do
            row[i]= noise(i * noiseScale + noisePos.x, r * noiseScale + noisePos.y)*size*10
        end
    end
    setVrt()
    if col then
        setColVrt()
    end
    if tex2D then
        set2DVrt()
    elseif rndTex then
        setRndVrt()
    elseif tex1D then
        set1DVrt()
    end
end
function setVrt()
    msvrt = {}
    for y, row in pairs(heights) do
        if y >1 then
            for x, pt in pairs(row) do
                if x+1 <= #row then
                    table.insert(msvrt,vec3(x*size,pt,y*size))--tri vertices
                    table.insert(msvrt,vec3(x*size,heights[y-1][x],(y-1)*size))
                    table.insert(msvrt,vec3((x+1)*size,heights[y-1][x+1],(y-1)*size))
                end 
                if x>1 then
                table.insert(msvrt,vec3(x*size,pt,y*size))--tri vertices
                table.insert(msvrt,vec3(x*size,heights[y-1][x],(y-1)*size))
                table.insert(msvrt,vec3((x-1)*size,heights[y][x-1],y*size))
                end
            end
        end
    end
    ms.vertices = msvrt
end
function mid(values)
    result = 0
    for i, value in ipairs(values) do
        result = result + value
        num = i
    end
    return result/num
end
function set1DVrt()
    tx = {}
    for i, val in pairs(msvrt) do
        table.insert(tx, vec2(i/#msvrt,i/#msvrt))
    end
    ms.texture = "Documents:Water"
    ms.texCoords = tx
end
function set2DVrt()
    tx = {}
    for i, val in pairs(msvrt) do
        table.insert(tx, vec2(val.x/size/field, val.z/size/field))
    end
    ms.texture = "Documents:Water"
    ms.texCoords = tx
end
function setColVrt()
    cl = {}
    for i, val in pairs(msvrt) do
        table.insert(cl, color(basecol.r,basecol.g,basecol.b+size*10/(255-basecol.b)*val.y,basecol.a))
    end
    ms.colors = cl
end
function setRndVrt()
    tx = {}
    math.randomseed(8063777880817693033805)
    tx = {}
        for i, val in pairs(msvrt) do
            table.insert(tx, vec2(math.random(1,999)/1000,math.random(1,999)/1000))
        end
    ms.texture = "Documents:Water"
    ms.texCoords = tx
end
--# Camera

Camera = class()

function Camera:init(eX,eY,eZ,lX,lY,lZ,uX,uY,uZ)
    self.eye = vec3(eX or 0, eY or 0, eZ or 400)
    self.lat = vec3(lX or 0, lY or 0, lZ or 0)
    self.upV = vec3(uX or 0, uY or 1, uZ or 0)
    self.dist = self.lat:dist(self.eye)
    self.angH = 90
    self.angV = -90
    self.fix = false
    self.crosshair = false
end

function Camera:draw()
    if self.fix then
        self.eye = -self:rotatePoint() + self.lat
    else
        self.lat =  self:rotatePoint() + self.eye
    end
    camera(
    self.eye.x, self.eye.y, self.eye.z,
    self.lat.x, self.lat.y, self.lat.z,
    self.upV.x, self.upV.y, self.upV.z)
    if self.crosshair then self:drawCrosshair(50) end
end

function Camera:movement(z,x)
    if z and z ~= 0 then
        local zVel = (self.lat-self.eye):normalize() * z
        self.eye = self.eye + zVel
        self.lat = self.lat + zVel
    end
    if x and x ~= 0 then
        local xVel = (self.lat-self.eye):cross(vec3(0,1,0)):normalize() * x
        self.eye = self.eye + xVel
        self.lat = self.lat + xVel
    end
end

function Camera:rotatePoint()
    -- calculate y and z from angV at set distance
    local y = math.cos(math.rad(self.angV))*self.dist
    local O = math.sin(math.rad(self.angV))*self.dist
    -- calculate x and z from angH using O as the set distance
    local x = math.cos(math.rad(self.angH))*O
    local z = math.sin(math.rad(self.angH))*O
    return vec3(x,y,z)
end

function Camera:updateAngles()
    self.angH = math.deg(math.atan2(self.lat.z-self.eye.z,self.lat.x-self.eye.x))+180
    self.angV = -math.deg(math.acos((self.lat.y-self.eye.y)/self.dist))
end

function Camera:lookAt(target)
    self.dist = self.eye:dist(target)
    self.lat = target
    self:updateAngles()
end

function Camera:drawCrosshair(w)
    pushMatrix()pushStyle()
    translate(self.lat.x,self.lat.y, self.lat.z)
    strokeWidth(2)
    line(-w/2,0,w/2,0)
    line(0,-w/2,0,w/2) rotate(90,1,0,0)
    line(0,-w/2,0,w/2)
    popMatrix()popStyle()
end
--# Stick

Stick = class()

function Stick:init(ratio,x,y)
    self.ratio = ratio or 1
    self.i = vec2(x or 120,y or 120)-- initial pos
    self.v = vec2(0,0) -- stick pos relative to initial pos
    self.b = b or 180  -- base diameter
    self.s = s or 100  -- stick diameter
    self.d = d or 50  -- dead zone diameter
    self.a = 0         -- stick angle relative to initial pos
    self.touchId = nil
    self.x,self.y = 0,0
end

function Stick:draw()

    if touches[self.touchId] == nil then
        for i,t in pairs(touches) do
            if vec2(t.x,t.y):dist(self.i) < self.b/2 then self.touchId = i end
        end
        self.v = vec2(0,0)
    else
        self.v = vec2(touches[self.touchId].x,touches[self.touchId].y) - self.i
        self.a = math.deg(math.atan2(self.v.y,self.v.x))
    end
    self.t = math.min(self.b/2,self.v:len())
    if self.t >= self.b/2 then
        self.v = vec2(math.cos(math.rad(self.a))*self.b/2,math.sin(math.rad(self.a))*self.b/2)
    end

    fill(127, 127, 127, 150)
    ellipse(self.i.x,self.i.y,self.b)
    ellipse(self.i.x+self.v.x,self.i.y+self.v.y,self.s)

    self.v = self.v/(self.b/2)*self.ratio
    self.t = self.t/(self.b/2)*self.ratio
    self.x,self.y = self.v.x,self.v.y

end
Button = class()

function Button:init(btnNorm,btnSel,x,y)
    self.pos = vec2(x,y)
    self.btnNorm = btnNorm
    self.btnSel = btnSel
    self.selected = false
    self.action = nil
    self.w,self.h = spriteSize(self.btnNorm)
end

function Button:draw()
    if self.selected == true then
        sprite(self.btnSel,self.pos.x,self.pos.y,self.w,self.h)
    elseif self.selected == false then
        sprite(self.btnNorm,self.pos.x,self.pos.y,self.w,self.h)
    end
    if self.selected == true and self.action then
        self.action()
    end
end

function Button:touched(touch)
    if touch.state == BEGAN or touch.state == MOVING then
        if math.abs(self.pos.x - touch.x) <= (self.w/2)
        and math.abs(self.pos.y - touch.y) <= (self.h/2) then
            self.selected = true
        else
            self.selected = false
        end
    elseif touch.state == ENDED then
        self.selected = false
    end
end
Tagged:

Comments

  • IgnatzIgnatz Mod
    Posts: 5,396

    @TimurEke - please put all of these comments in a single thread. All these posts are cluttering the forum.

  • Posts: 116

    I put the comments because character limit was reached. And this should be a independent post, because here are no fractals or mountains

Sign In or Register to comment.