ADS Lighting Class

I refactored my lighting class, you have to tell it up front whether you are 1) colored 2) textured or 3) textured and bumpmapped as it now splits assumptions for performance based on these.

https://gist.github.com/sp4cemonkey/5112117

A demo of the modes is this tweaked version of @xavier’s 3d tile based (use below code with the class in another tab or imported)


--# Main


-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
function setup()
    stick = Stick()

    pylon = Wall("Cargo Bot:Crate Red 2", true, true)
    wall = Wall("Cargo Bot:Crate Yellow 2", true, false)
    floor = Floor("Cargo Bot:Crate Green 2", false, false)

    world = World()
    hero = Hero(3,3)

    TO_DEG = 180/math.pi
end

-- This function gets called once every frame
function draw()
    --output.clear()
    print(1/DeltaTime)
    --print(ElapsedTime)
    background(0)
    local TO_DEG = TO_DEG
    local hero = hero

    perspective(60)
    camera(hero.x, 3, 1 + hero.z, hero.x, 0, hero.z, 0, 1, 0)

    eye = vec3(hero.x, 3, 1 + hero.z)
    --fixed light
    --light = vec3(7, 3, 7)
    --light just above the hero's head
    light = vec3(hero.x, 0.5, hero.z)
    
-- Draw world
    pushMatrix()
    world:draw(eye, light)
    popMatrix()

-- Draw hero
    translate(hero.x, hero.y, hero.z)
    rotate(stick.direction*TO_DEG, 0, 1, 0)

    -- roll animation
    if stick.active then
        rotate(-ElapsedTime*10*TO_DEG, 0, 0, 1)
    end

    scale(.25, .25, .25)
    hero:draw(eye, light)

-- Restore orthographic projection
    ortho()
    viewMatrix(matrix())
    resetMatrix()

    -- fade out overlay
    --sprite("Cargo Bot:Background Fade", WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
    if stick.active then
        local ceil = math.ceil
        stick:draw()

        -- move hero based on stick direction
        local mvtx = math.cos(stick.direction)/50*stick.dist
        local mvtz = -math.sin(stick.direction)/50*stick.dist
        hero.x = hero.x + mvtx
        hero.z = hero.z + mvtz

        -- convert to table coordinates
        hero.px = ceil(hero.x - .5)
        hero.py = ceil(hero.z - .5)

        -- lazy collision check
        if world.data[hero.py][hero.px] ~= 0 then
            hero.x = hero.x - mvtx
            hero.z = hero.z - mvtz
            hero.px = ceil(hero.x - .5)
            hero.py = ceil(hero.z - .5)
        end
    end

end

function touched(touch)
    stick:touched(touch)
end

--# World
World = class()

function World:init()

    -- define the world
    self.data =
    {
        {1, 1, 1, 1, 1, 1, 1, 1},
        {1, 2, 0, 0, 0, 0, 2, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 1, 2, 0, 0, 1},
        {1, 0, 0, 2, 1, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 2, 0, 0, 0, 0, 2, 1},
        {1, 1, 1, 1, 1, 1, 1, 1}
    }
end

function World:draw(eye, light)
    local floor, wall, pylon = floor, wall, pylon
    local offSet = 3
    local px, py = hero.px, hero.py

    -- look around the hero to draw whatever is around him
    translate(px - offSet, 0, py - offSet)
    for y = py - offSet, py + offSet do
        for x = px - offSet, px + offSet do
            if self.data[y] then
                local val = self.data[y][x]
                if val == 0 then
                    floor:draw(eye, light)
                elseif val == 1 then
                    wall:draw(eye, light)
                elseif val == 2 then
                    pylon:draw(eye, light)
                end
            end
            translate(1,0,0)
        end
        translate(-(1 + 2 * offSet), 0, 1)
    end
end


--# Hero
Hero = class()

function Hero:init(x, z)
    self.x, self.y, self.z = x,0,z
    self.px, self.py = math.ceil(.5+x), math.ceil(.5+z)

    self.mdl = Wall("Cargo Bot:Crate Blue 2", true, false)
end

function Hero:draw(eye, light)
    self.mdl:draw(eye, light)
end


--# Wall
Wall = class()


function Wall:init(tex, isTextured, isBump)
    -- all the unique vertices that make up a cube
    local vertices =
    {
        vec3(-0.5, -0.5,  0.5), -- Left  bottom front
        vec3( 0.5, -0.5,  0.5), -- Right bottom front
        vec3( 0.5,  0.5,  0.5), -- Right top    front
        vec3(-0.5,  0.5,  0.5), -- Left  top    front
        vec3(-0.5, -0.5, -0.5), -- Left  bottom back
        vec3( 0.5, -0.5, -0.5), -- Right bottom back
        vec3( 0.5,  0.5, -0.5), -- Right top    back
        vec3(-0.5,  0.5, -0.5), -- Left  top    back
    }

    -- now construct a cube out of the vertices above
    local verts =
    {
        -- Front
        vertices[1], vertices[2], vertices[3],
        vertices[1], vertices[3], vertices[4],
        -- Right
        vertices[2], vertices[6], vertices[7],
        vertices[2], vertices[7], vertices[3],
        -- Back
        vertices[6], vertices[5], vertices[8],
        vertices[6], vertices[8], vertices[7],
        -- Left
        vertices[5], vertices[1], vertices[4],
        vertices[5], vertices[4], vertices[8],
        -- Top
        vertices[4], vertices[3], vertices[7],
        vertices[4], vertices[7], vertices[8],
       -- Bottom
        vertices[5], vertices[6], vertices[2],
        vertices[5], vertices[2], vertices[1]
    }

    -- all the unique texture positions needed
    local texvertices =
    {
        vec2(0.02,0.02),
        vec2(0.98,0.02),
        vec2(0.02,0.98),
        vec2(0.98,0.98)
    }

    -- apply the texture coordinates to each triangle
    local texCoords =
    {
        -- Front
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Right
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Back
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Left
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Top
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Bottom
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3]
    }

    self.model = LitMesh(isTextured, isBump)
    self.model.litMesh.vertices = verts
    if isTextured == true then
        theTexture = readImage(tex)
        self.model.litMesh.texCoords = texCoords
        self.model:setTexture(theTexture)
    end   
    self.model:deriveVertexNTB()
    if isBump == true then
        local tempText = readImage(tex)
        theBumpMap = self.model:generateTextureBumpMap(tempText,0.007)
        self.model:setBumpMap(theBumpMap)
    end
end

function Wall:draw(eye, light)
    self.model:setLight(light, 0.2, 1.0, 1.0, color(255))
    self.model:setEye(eye)
    self.model:draw()
end
--# Floor
Floor = class()

function Floor:init(tex, isTextured, isBump)
    -- all the unique vertices that make up a cube
    local vertices =
    {
        vec3( 0.5,  -0.5,  0.5), -- Right top    front
        vec3(-0.5,  -0.5,  0.5), -- Left  top    front
        vec3( 0.5,  -0.5, -0.5), -- Right top    back
        vec3(-0.5,  -0.5, -0.5), -- Left  top    back
    }


    -- now construct a cube out of the vertices above
    local verts =
    {
        -- Bottom
        vertices[3], vertices[4], vertices[2],
        vertices[3], vertices[2], vertices[1],
    }

    -- all the unique texture positions needed
    local texvertices =
    {
        vec2(0.02,0.02),
        vec2(0.98,0.02),
        vec2(0.02,0.98),
        vec2(0.98,0.98)
    }

    -- apply the texture coordinates to each triangle
    local texCoords =
    {
        -- Bottom
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
    }

    self.model = LitMesh(isTextured, isBump)

    self.model.litMesh.vertices = verts
    self.model.litMesh:setColors(255,200,150,255)
    if isTextured == true then
        theTexture = readImage(tex)
        self.model.litMesh.texCoords = texCoords
        self.model:setTexture(theTexture)
    end 
    self.model:deriveVertexNTB()  
    if isBump == true then
        local tempText = readImage(tex)
        theBumpMap = self.model:generateTextureBumpMap(tempText,0.007)
        self.model:setBumpMap(theBumpMap)
    end
end

function Floor:draw(eye, light)
    self.model:setLight(light, 0.2, 1.0, 0.6, color(255))
    self.model:setEye(eye)
    self.model:draw()
end

--# Stick
Stick = class()

function Stick:init()
    self.direction = 0
    self.dist = 0

    self.active = false
    self.origin = vec2(150, 150)
    self.center = self.origin
    self.pos = self.origin

    self.stick_bg = readImage("Small World:Dialog Icon")
    self.stick = readImage("Small World:Bush")

   -- self.stick_bg = readImage("Space Art:Eclipse")
  --  self.stick = readImage("Space Art:UFO")

end

function Stick:draw()
    sprite(self.stick_bg, self.center.x, self.center.y)
    sprite(self.stick, self.pos.x, self.pos.y)
end

function Stick:touched(touch)
    if touch.state == BEGAN then
        self.center = vec2(touch.x, touch.y)
        self.active = true
    end

    self.pos = vec2(touch.x, touch.y)
    self.direction = math.atan2(self.pos.y - self.center.y, self.pos.x - self.center.x)

    self.dist = math.min(2, self.pos:dist(self.center)/32)

    if touch.state == ENDED then
        self.center = self.origin
        self.pos = self.center
        self.active = false
    end


end