3D Drawing Example

<!-- Script Source Terrain = {}

width, height = draw.getport xc = math.floor(width/2) yc = math.floor(height/2)+60 unit = 60 -- Size of block --30 zangle = 45 / 180 * math.pi --35 / 180 * math.pi -- X Angle zcos = math.cos(zangle) -- Y roll zsin = math.sin(zangle) -- Z roll ztan = zsin/zcos

function MapX(x, z)  return xc + x * unit - z * unit * zcos end function MapY(y, z)  return yc - y * unit + z * unit * zsin end

function Fill3D(func, r, color) local d = .25 -- size of each grid local y, mx, my, tx, ty, rx, ry -- drawing positions local nx, ny, nz -- temp for second and third pairs for z = -r, r, d do     -- Setup for drawing local x = -r for x = -r, r, d do        -- First two y = func(x, z)        mx = MapX(x, z)         my = MapY(y, z)         -- Second two nx = x - d        nz = z + d         ny = func(nx, nz) rx = MapX(nx, nz) ry = MapY(ny, nz) -- Third two nx = x + 0 nz = z + d        ny = func(nx, nz) tx = MapX(nx, nz) ty = MapY(ny, nz) -- draw the Plane draw.filltriangle(mx, my, tx, ty, rx, ry, draw.green) -- draw Polygon outlines if DrawMesh then -- line 1 draw.moveto( mx, my) draw.lineto( tx, ty, draw.yellow) -- line 2 draw.moveto( mx, my) draw.lineto( rx, ry, draw.orange) -- line 3 draw.moveto( tx, ty) draw.lineto( rx, ry, draw.lightgray) -- now draw the points draw.point(mx, my, draw.red) draw.point(tx, ty, draw.purple) draw.point(rx, ry, draw.blue) end end end for x = -r, r, d do     -- Setup for drawing local z = -r for z = -r, r, d do        -- First two y = func(x, z)        mx = MapX(x, z)         my = MapY(y, z)         -- Second two nx = x - d        nz = z + d         ny = func(nx, nz) rx = MapX(nx, nz) ry = MapY(ny, nz) -- Third two nx = x - d        nz = z - 0 ny = func(nx, nz) tx = MapX(nx, nz) ty = MapY(ny, nz) -- draw the Plane draw.filltriangle(mx, my, tx, ty, rx, ry, draw.green) -- draw Polygon outlines if DrawMesh then -- line 1 draw.moveto( mx, my) draw.lineto( tx, ty, draw.yellow) -- line 2 draw.moveto( mx, my) draw.lineto( rx, ry, draw.orange) -- line 3 draw.moveto( tx, ty) draw.lineto( rx, ry, draw.lightgray) -- now draw the points draw.point(mx, my, draw.red) draw.point(tx, ty, draw.green) draw.point(rx, ry, draw.blue) end end end end

function Plot3D(func, r, color) local d = .25 local y, mx, my  for z = -r, r, d do      local x = -r y = func(x, z)     mx = MapX(x, z)      my = MapY(y, z)      draw.moveto( mx, my) for x = -r, r, d do        y = func(x, z)         mx = MapX(x, z)         my = MapY(y, z)         draw.lineto( mx, my, draw.cyan) end end for x = -r, r, d do     local z = -r y = func(x, z)     mx = MapX(x, z)      my = MapY(y, z)      draw.moveto( mx, my) for z = -r, r, d do        y = func(x, z)         mx = MapX(x, z)         my = MapY(y, z)         draw.lineto( mx, my, color) end end end

TerTab = {}

function Terrain.CreateBlock(X, Z, Height) local ZTab = TerTab[Z] ZTab[X] = {} local XTab = ZTab[X] ZTab[X] = Height end

local TGrid = 3

function Terrain.Flatten(H) for TZ=0, TGrid, 1 do     if not TerTab[TZ] then TerTab[TZ] = {} end if not TerTab[-TZ] then TerTab[-TZ] = {} end for TX=0, TGrid do        Terrain.CreateBlock(TX, TZ, H)         Terrain.CreateBlock(TX, -TZ, H)         Terrain.CreateBlock(-TX, TZ, H)         Terrain.CreateBlock(-TX, -TZ, H)      end end end

function Terrain.Randomize(H) math.randomseed(1) for TZ=0, TGrid do     if not TerTab[TZ] then TerTab[TZ] = {} end if not TerTab[-TZ] then TerTab[-TZ] = {} end for TX=0, TGrid do        Terrain.CreateBlock(TX, TZ, math.random*H) Terrain.CreateBlock(TX, -TZ, math.random*H) Terrain.CreateBlock(-TX, TZ, math.random*H) Terrain.CreateBlock(-TX, -TZ, math.random*H) end end end

Terrain.Flatten(1) --Terrain.Randomize(1)

function Func(X, Z)  X, Z = math.floor(X), math.floor(Z) local ZTab = TerTab[Z] if ZTab ~= nil then return tonumber(ZTab[X]) or 0 end return 0 -- incase the other one breaks end

draw.setscreen(1) draw.setantialias(true) draw.setlinestyle(1, "butt")

local OldTime = os.clock draw.beginframe draw.clear Fill3D(Func, 3, draw.black) Plot3D(Func, 3, draw.gray) local NewTime = os.clock draw.string(NewTime-OldTime, 2, height-18, draw.black) draw.endframe

draw.waittouch -- Improved by Matthew Cenance from the default 3DPlot script included with TouchLua. -->