|
Post by Tag365 on Jun 13, 2015 15:06:23 GMT
{"Region3.lua":"local Region3 = {}\nRegion3.__index = Region3 -- This is a class table, set the index to itself so that all instances of it can use its functions and variables.\nRegion3.classtype = \"Region3\"\n\n-- This function constructs a new object of this type.\nRegion3.new = function(vector1, vector2)\n local self = setmetatable({}, Region3)\n self.vector1 = Vector3.new(math.min(vector1.x, vector2.x), math.min(vector1.y, vector2.y), math.min(vector1.z, vector2.z))\n self.vector2 = Vector3.new(math.max(vector1.x, vector2.x), math.max(vector1.y, vector2.y), math.max(vector1.z, vector2.z))\n return self\nend\n\n-- Returns a vector3 with the total size of the region.\nfunction Region3:getSize()\n return self.vector2:subtractVectorFromVector(self.vector1)\nend\n\n-- Returns the volume of this vector.\nfunction Region3:getVolume()\n local vector = Region3:getSize()\n return vector.x*vector.y*vector.z\nend\n\n-- Returns the center.of this region.\nfunction Region3:getCenter()\n local size = Region3:getSize()\n return self.vector1 + (size*.5)\nend\n\n-- This function gets all of the points with positions that are valid positions for terrain cells.\nfunction Region3:GetIntegerPoints()\n local integerPoints = {}\n local X1, Y1, Z1 = self.vector1:raw()\n local X2, Y2, Z2 = self.vector2:raw()\n for Y=Y1, Y2 do\n for X=X1, X2 do\n for Z=Z1, Z2 do\n integerPoints[#integerPoints + 1] = {X, Y, Z}\n end\n end\n end\n return integerPoints\nend\n\n-- This function returns the terrain cells inside this region.\nfunction Region3:GetTerrainCellsInsideRegion(terrain)\n local Points = self:GetIntegerPoints()\n local Cells = {}\n for k, v in ipairs(Points) do\n local x, y, z = v[1], v[2], v[3]\n if not Cells[y] then\n Cells[y] = {}\n end\n if not Cells[y][x] then\n Cells[y][x] = {}\n end\n Cells[y][x][z] = {terrain:GetCell(x, y, z)}\n end\n return Cells\nend\n\n-- This function returns the terrain cells inside this region.\nfunction Region3:CopyTerrainRegion(terrain)\n local Points = self:GetIntegerPoints()\n local newTerrain = Terrain.new()\n for k, v in ipairs(Points) do\n local x, y, z = v[1], v[2], v[3]\n if not Cells[y] then\n Cells[y] = {}\n end\n if not Cells[y][x] then\n Cells[y][x] = {}\n end\n if not terrain:GetLiquidCell(x, y, z) then\n newTerrain:SetCell(x, y, z, terrain:GetCell(x, y, z))\n else\n local isLiquid, material, force, direction = terrain:GetLiquidCell(x, y, z)\n newTerrain:SetLiquidCell(x, y, z, material, force, direction)\n end\n end\n return newTerrain\nend\n\nreturn Region3","Object.lua":"local Object = {}\nObject.__index = Object -- This is a class table, set the index to itself so that all instances of it can use its functions and variables.\nObject.classtype = \"Object\"\n\n-- This function constructs a new object of this type.\nObject.new = function()\n local self = setmetatable({}, Object)\n return self\nend\n\nreturn Object","BasicMeshes.lua":"local BasicMeshes = {}\n\n-- Generate Cube Mesh\nfunction BasicMeshes.GetCubeVectors(s)\n return Vector3.new(-s, s, -s), Vector3.new(s, s, -s), Vector3.new(s, s, s), Vector3.new(-s, s, s), Vector3.new(-s, -s, -s), Vector3.new(s, -s, -s), Vector3.new(s, -s, s), Vector3.new(-s, -s, s)\nend\n\nfunction BasicMeshes.newCube(size, c)\n local p1, p2, p3, p4, p5, p6, p7, p8 = BasicMeshes.GetCubeVectors(size or 1)\n local CubeMesh = Mesh.new()\n CubeMesh:AddPolygon(p1, p2, p3, p4, c or draw.green)\n CubeMesh:AddPolygon(p1, p2, p6, p5, c or draw.red)\n CubeMesh:AddPolygon(p2, p3, p7, p6, c or draw.blue)\n CubeMesh:AddPolygon(p3, p4, p8, p7, c or draw.magenta)\n CubeMesh:AddPolygon(p4, p1, p5, p8, c or draw.cyan)\n CubeMesh:AddPolygon(p5, p6, p7, p8, c or draw.yellow)\n return CubeMesh\nend\n\nreturn BasicMeshes","TerrainHeightmap.lua":"if not Example1 then require \"Example3\" end\nlocal Heightmap = {}\nHeightmap.__index = Heightmap -- This is a class table, set the index to itself so that all instances of it can use its functions and variables.\nHeightmap.classtype = \"TerrainHeightmap\"\n\n\n-- This function constructs a new object of this type.\nHeightmap.new = function(size)\n local self = setmetatable({}, Heightmap)\n self.sizeOfGrid = size or 64\n self.sizeOfCell = 128\n self.heightmap = {}\n -- Set up default materials. --\n self.materials = {}\n self:AddNewMaterial(\"Water\", Color.new(0, 128, 255, 64))\n self:AddNewMaterial(\"Grass\", Color.new(0, 255, 0))\n self:AddNewMaterial(\"Dark Grass\", Color.new(0, 128, 0))\n self:AddNewMaterial(\"Dirt\", Color.new(164, 96, 0))\n self:AddNewMaterial(\"Dark Dirt\", Color.new(96, 64, 0))\n return self\nend\n\n-- Heightmap Terraforming functions --\n\n-- This function sets a new material for the heightmap.\nfunction Heightmap:AddNewMaterial(Name, Color)\n local tab = {}\n tab.name = Name\n tab.color = Color\n self.materials[#self.materials + 1] = tab\n return #self.materials\nend\n\n-- This function sets a cell of the terrain heightmap.\nfunction Heightmap:SetCell(x, z, Height, Material)\n self.heightmap[x][z] = {Height, Material}\nend\n\nfunction Heightmap:SetCells(x1, z1, x2, z2, Height, Material)\n for x=x1, x2 do\n for z=z1, z2 do\n self.heightmap[x][z] = {Height, Material}\n end\n end\nend\n\n-- This function resets the heightmap.\nfunction Heightmap:Reset(Height, Material)\n for x=-self.sizeOfGrid, self.sizeOfGrid do\n self.heightmap[x] = {}\n for z=-self.sizeOfGrid, self.sizeOfGrid do\n self.heightmap[x][z] = {Height, Material}\n end\n end\nend\n\n-- This function randomizes the height of terrain.\nfunction Heightmap:RandomizeHeight(low, high, seed)\n seed = seed or (sys.gettime()*10)\n for x=-self.sizeOfGrid, self.sizeOfGrid do\n for z=-self.sizeOfGrid, self.sizeOfGrid do\n if not self.heightmap[x][z] then\n self.heightmap[x][z] = {0, 1}\n end\n math.randomseed((x\/z)*seed)\n self.heightmap[x][z][1] = low + (math.random()*(high - low))\n end\n end\nend\n\n-- This function warps the height of water.\nfunction Heightmap:Warp()\n times = (times or 0) + 1\n if math.floor(times\/20) == times\/20 then\n for x=-self.sizeOfGrid, self.sizeOfGrid do\n for z=-self.sizeOfGrid, self.sizeOfGrid do\n if (self.heightmap[x][z]) or (times > 5) then\n if not self.heightmap[x][z] then\n self.heightmap[x][z] = {0, 1}\n end\n math.randomseed(x*z*sys.gettime())\n self.heightmap[x][z] = {(self.heightmap[x][z][1] or 0) + math.random()*128 - 64, 1}\n end\n end\n end\n end\nend\n\n-- This function draws a level of detail version of the heightmap.\nfunction Heightmap:DrawLOD(Ren, LOD, Hole, X1, Z1, X2, Z2, cx, cz)\n local size = self.sizeOfCell\n X1, X2 = math.min(X1, X2), math.max(X1, X2)\n Z1, Z2 = math.min(Z1, Z2), math.max(Z1, Z2)\n for x=X1, X2, LOD do\n local cellX = self.heightmap[x]\n local cellX2 = self.heightmap[x + LOD]\n if cellX and cellX2 then\n for z=Z1, Z2, LOD do\n if (x > (Hole + cx) - LOD or x < -Hole + cx) or (z > Hole + cz - LOD or z < - Hole + cz) then\n local cellZ = self.heightmap[x][z]\n local cellZ2 = self.heightmap[x + LOD][z]\n local cellZ3 = self.heightmap[x][z + LOD]\n local cellZ4 = self.heightmap[x + LOD][z + LOD]\n if cellZ and cellZ2 and cellZ4 then\n local h1, h2, h3, h4 = cellZ[1], cellZ2[1], cellZ3[1], cellZ4[1]\n --[[if x <= X1 then\n h1 = cellZ[1] + ((cellZ[1] - self.heightmap[x + LOD][z][1])*(z\/(LOD*2)))\n h3 = 100 --cellZ3[1] + ((cellZ3[1] - self.heightmap[math.floor((x + LOD)\/LOD)*LOD][z + LOD][1])*(z\/(LOD*2)))\n --[[elseif x == X2 then\n h2 = cellZ2[1] + ((cellZ2[1] - self.heightmap[x + (LOD*2)][z][1])*(z\/(LOD*2)))\n elseif z == Z1 then\n h3 = cellZ3[1] + ((cellZ3[1] - self.heightmap[x][z - LOD][1])*(x\/(LOD*4)))\n elseif z == Z2 then\n h4 = cellZ4[1] + ((cellZ4[1] - self.heightmap[x][z + (LOD*2)][1])*(x\/(LOD*4)))\n end]]\n Ren:DrawPolygon(Vector3.new(x*size, h1, z*size), Vector3.new((x + LOD)*size, h2, z*size), Vector3.new((x + LOD)*size, h4, (z + LOD)*size), Vector3.new(x*size, h3, (z + LOD)*size), self.materials[cellZ[2]].color)\n --Ren:DrawPolygon(Vector3.new(x*size, cellZ[1], z*size), Vector3.new((x + LOD)*size, cellZ2[1], z*size), Vector3.new((x + LOD)*size, cellZ4[1], (z + LOD)*size), Vector3.new(x*size, cellZ3[1], (z + LOD)*size), Color.new(0, 0, LOD*16)) -- self.materials[cellZ[2]].color, true)\n end\n end\n end\n end\n end\nend\n\n-- This function draws the heightmap.\nfunction Heightmap:Draw(Ren)\n local cx, cz = math.floor((Ren.camx\/self.sizeOfCell)), math.floor((Ren.camz\/self.sizeOfCell))\n local LODTable = self.LODTable\n local lasthole = 0\n for k, v in ipairs(LODTable) do\n if k > 1 then\n local v1 = LODTable[k - 1]\n if v > v1 then\n local loss = 2^(k - 1)\n lasthole = lasthole + (v - v1)\n self:DrawLOD(Ren, loss, v1, cx - v, cz - v, cx + v - 1, cz + v - 1, cx, cz)\n end\n else\n self:DrawLOD(Ren, 1, 0, cx - v, cz - v, cx + v - 1, cz + v - 1, cx, cz)\n end\n end\nend\n\nreturn Heightmap","3DCamera.lua":"local Camera = {}\nCamera.__index = Camera -- failed table lookups on the instances should fallback to the class table, to get methods\nCamera.classtype = \"Camera\"\n\nCamera.new = function()\n local self = setmetatable({}, Camera)\n self.position = Vector3.new(0, 0, 0)\n self.minX, self.maxX = 0, screenWidth\n self.minY, self.maxY = 0, screenHeight\n self.minZ, self.maxZ = 0, 10\n self.objectsInWorld = {}\n return self\nend\n\n-- Draws all shown objects to the screen.\nfunction Camera.drawScene(self)\n draw.beginframe()\n draw.clear()\n for x, v in ipairs(self.objectsInWorld) do\n if v.classtype == \"Point\" then\n -- Do the current rendering code\n if v.x > self.minX and v.x < self.maxX then\n if v.y > self.minY and v.y < self.maxY then\n if v.z > self.minZ and v.z < self.maxZ then\n v:drawPoint()\n end\n end\n end\n elseif v.classtype == \"LineSegment\" then\n for p, v2 in pairs(v:returnPointsInSegment()) do\n v2:drawPoint()\n end\n end\n end\n draw.endframe()\nend\n\nreturn Camera","Example1.lua":"Example1 = true\nrequire \"main\"\nlocal Ren = Renderer.new()\nlocal rotatemode = 0\nlocal angle = 1\nlocal zoom = 1\nlocal rx, ry, rz = -32, -180, 0 -- -84, 0, 0\nlocal shiftX, shiftY, shiftZ = 0, 0, 0\nlocal color = 1\n\nlocal colors = {draw.red, draw.blue, draw.green, draw.purple, draw.orange, draw.cyan, draw.gray, draw.yellow}\nlocal buttonTitles = {\n \"Rotate Model\",\n \"Change Size\",\n \"Reset\",\n \"Move X\",\n \"Move Y\",\n \"Move Z\"\n}\n\n-- Set up the cube mesh.\nlocal CubeMesh = ExampleMesh.new(10, 0, 0, 0)\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dAngle = angle\nlocal dCamX, dCamY, dCamZ = 0, 260, -260\nlocal dRx, dRy, dRz = rx, ry, rz\nlocal dShiftX, dShiftY, dShiftZ = shiftX, shiftY, shiftZ\n\n-- Set up Functions. --\n\n-- This function draws a button to the screen.\nfunction drawButton(text, x1, y1, x2, y2)\n draw.fillroundedrect(x1, y1, x2, y2, 8, draw.white)\n draw.roundedrect(x1, y1, x2, y2, 8, draw.blue)\n draw.stringinrect(text, x1, y1, x2, y2, draw.black)\nend\n\n-- This function draws a floor.\nfunction drawFloor(size, x, y, z, mycolor)\n local point1 = Vector3.new(x - size, y, z - size)\n local point2 = Vector3.new(x + size, y, z - size)\n local point3 = Vector3.new(x + size, y, z + size)\n local point4 = Vector3.new(x - size, y, z + size)\n Ren:DrawPolygon(point1, point2, point3, point4, mycolor or colors)\n if not mycolor then\n color = (color + 1 <= #colors and color + 1) or 1\n end\nend\n\nfunction none() end\n\n-- This function is called when the user first touches the screen.\nfunction touchBegan(tx, ty)\n originX, originY = tx, ty\n oldx, oldy, oldz = Ren.camx, Ren.camy, Ren.camz\n oldangle = angle\n oldzoom = zoom\n oldrotx, oldroty, oldrotz = rx, ry, rz\nend\n\n-- This function is called on touch position movement.\nfunction touchMoved(tx, ty)\n if not (tx > width - 96) then\n local mx, my = (tx - originX), (ty - originY)\n local deadZone = 12\n if rotatemode >= 3 and rotatemode <= 4 then\n deadZone = 32\n end\n if not (mx > deadZone or mx < -deadZone) then\n mx = 0\n elseif mx > 0 then\n mx = mx - (deadZone - 1)\n else\n mx = mx + (deadZone)\n end\n if not (my > deadZone or my < -deadZone) then\n my = 0\n elseif my > 0 then\n my = my - (deadZone - 1)\n else\n my = my + (deadZone)\n end\n if rotatemode == 1 then\n Ren.camx, Ren.camy = oldx + mx, oldy + my\n elseif rotatemode == 2 then\n Ren.camx, Ren.camz = oldx + mx, oldz + my\n elseif rotatemode == 3 then\n mx, my = mx*.5, my*.5\n rx, ry = oldrotx + mx, oldroty + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 4 then\n mx, my = mx*.5, my*.5\n rx, rz = oldrotx + mx, oldrotz + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 5 then\n angle = math.max(oldangle - (my*.01), .01)\n Ren.angle = angle\n elseif rotatemode == 6 then\n zoom = math.max(oldzoom - (my*.01), .01)\n Ren.unit = zoom\n end\n end\nend\n\n-- This function is called on the touch ending.\nfunction checkButtonTapped(tx, ty)\n if tx > width - 96 then\n buttonTapped = math.floor(ty\/48)\n if tx > width - 48 then\n tappedSide = 1\n else\n tappedSide = -1\n end\n else\n local mx, my = (tx - originX)*.1, (ty - originY)*.1\n if not (mx > 1 or mx < -1) and not (my > 1 or my < -1) then\n rotatemode = rotatemode + 1\n if rotatemode > 5 then\n rotatemode = 0\n end\n end\n end\nend\n\ndraw.tracktouches(touchBegan, touchMoved, checkButtonTapped)\n\n-- Set up the renderer.\nRen:setCameraZoom(zoom)\nRen.setCameraRotation(rx, ry, rz)\nRen:setCameraPosition(dCamX, dCamY, dCamZ)\nRen:setDrawMode(true)\nRen:setAntiAlias(true)\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\n-- Start an intentional infinite loop\nwhile true do\n if sys.gettime() > lastSecond + 1 then\n framesLastSecond = framesThisSecond\n framesThisSecond = 0\n lastSecond = sys.gettime()\n elseif sys.gettime() < lastSecond then\n lastSecond = sys.gettime()\n end\n -- Check button tapped\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 1 then\n CubeMesh:RotateXZ(45*tappedSide)\n elseif buttonTapped == 2 then\n CubeMesh:Scale(1 + (tappedSide*.1))\n elseif buttonTapped == 3 then\n CubeMesh = ExampleMesh.new(10, 0, 0, 0) -- BasicMeshes.newCube(10, draw.blue)\n shiftX, shiftY, shiftZ = dShiftX, dShiftY, dShiftZ\n rx, ry, rz = dRx, dRy, dRz\n zoom = dZoom\n angle = dAngle\n Ren.unit = zoom\n Ren.angle = angle\n Ren:setCameraPosition(dCamX, dCamY, dCamZ)\n Ren.setCameraRotation(rx, ry, rz)\n elseif buttonTapped == 4 then\n shiftX = (shiftX or 0) + (tappedSide)*10\n elseif buttonTapped == 5 then\n shiftY = (shiftY or 0) + (tappedSide)*10\n elseif buttonTapped == 6 then\n shiftZ = (shiftZ or 0) + (tappedSide)*10\n end\n -- Shift the cube\n if shiftX or shiftY or shiftZ then\n CubeMesh:Shift(shiftX*.1, shiftY*.1, shiftZ*.1)\n end\n -- Draw the frame\n color = 1\n draw.beginframe()\n draw.clear(draw.black)\n -- Draw the cube to the screen.\n CubeMesh:Draw(Ren)\n -- Draw a floor.\n --drawFloor(256, 0, 0, 0, draw.green)\n -- Draw an axis.\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(1000, 0, 0), draw.red)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 1000, 0), draw.blue)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 0, 1000), draw.green)\n -- Draw an image located in a 3D world.\n --Ren:DrawSprite(\"@resources\/SomeTile.png\", Vector3.new(400, 20, 0), 24)\n -- Draw a string above a 3D point.\n --Ren:DrawString(\"Tap the screen to change camera mode\", Vector3.new(100, 60, 0), 16, draw.blue)\n -- Now we have to actually draw to the screen using the DrawQueueToScreen function.\n Ren:DrawQueueToScreen()\n draw.setfont(\"Arial\", 16)\n -- Draw the buttons to the screen.\n for k, v in ipairs(buttonTitles) do\n drawButton(v, width - 96, k*48, width, (k + 1)*48)\n end\n -- Draw the camera position and rotation.\n draw.string(\"Camera Position: \", 0, 24, draw.white)\n draw.string(\"X: \"..Ren.camx, 0, 40, draw.white)\n draw.string(\"Y: \"..Ren.camy, 128, 40, draw.white)\n draw.string(\"Z: \"..Ren.camz, 256, 40, draw.white)\n draw.string(\"Camera Rotation: \", 0, 64, draw.white)\n draw.string(\"X: \"..rx, 0, 80, draw.white)\n draw.string(\"Y: \"..ry, 128, 80, draw.white)\n draw.string(\"Z: \"..rz, 256, 80, draw.white)\n -- Show the current camera mode.\n local camMode = \"Fixed Mode (Angle: \"..(angle*45)..\")\"\n if rotatemode > 5 then\n camMode = \"Zoom Mode (Zoom: \"..zoom..\")\"\n elseif rotatemode > 4 then\n camMode = \"Angle Mode (Angle: \"..(angle*45)..\")\"\n elseif rotatemode > 3 then\n camMode = \"Rotation Mode XZ\"\n elseif rotatemode > 2 then\n camMode = \"Rotation Mode XY\"\n elseif rotatemode > 1 then\n camMode = \"Movement Mode XZ\"\n elseif rotatemode > 0 then\n camMode = \"Movement Mode XY\"\n end\n draw.string(camMode, 0, 160, draw.white)\n -- Finally, draw the current Frames Per Second.\n draw.string(\"FPS: \"..(framesLastSecond or framesThisSecond)..\" frames\", 0, 128, draw.white)\n draw.endframe()\n framesThisSecond = framesThisSecond + 1\nend","3DRenderer.lua":"local Renderer = {}\nRenderer.__index = Renderer -- failed table lookups on the instances should fallback to the class table, to get methods\nRenderer.classtype = \"Renderer\"\nRenderer.maxRange = 2048\n\n-- This function constructs a new object of this type.\nRenderer.new = function(x, y, z)\n local self = setmetatable({}, Renderer)\n self.camx, self.camy, self.camz = 0, 0, 0\n self.angle = 1\n self.unit = 2\n self.render = {}\n return self\nend\n\nlocal camorx, camory, camorz = 15, 15, 15\ncamorx, camory, camorz = math.rad(camorx), math.rad(camory), math.rad(camorz)\nlocal camvx, camvy, camvz = math.sin(camorx), math.cos(camory), camorz\nlocal cos, sin = math.cos, math.sin\nlocal cosx, cosy, cosz = cos(camorx), cos(camory), cos(camorz)\nlocal sinx, siny, sinz = sin(camorx), sin(camory), sin(camorz)\n\nlocal zangle = 35 \/ 180 * math.pi*1\nlocal zcos = math.cos(zangle)\nlocal zsin = math.sin(zangle)\n\nfunction Renderer:setAntiAlias(value)\n self.antialiased = value\nend\n\n-- Sets the camera into graphic mode.\nfunction Renderer:setDrawMode(value)\n self.perspective = value\nend\n\n-- Sets the camera zoom.\nfunction Renderer:setCameraZoom(value)\n self.unit = value\nend\n\n-- Sets the camera position.\nfunction Renderer:setCameraPosition(x, y, z)\n self.camx, self.camy, self.camz = x, y, z\nend\n\n-- Sets the camera rotation.\nfunction Renderer.setCameraRotation(x, y, z)\n camorx, camory, camorz = x, y, z\n camorx, camory, camorz = math.rad(camorx), math.rad(camory), math.rad(camorz)\n camvx, camvy, camvz = math.sin(camorx), math.cos(camory), camorz\n cos, sin = math.cos, math.sin\n cosx, cosy, cosz = cos(camorx), cos(camory), cos(camorz)\n sinx, siny, sinz = sin(camorx), sin(camory), sin(camorz)\nend\n\n-- Transforms a 3D position.\nfunction Renderer:Transform3D(x, y, z)\n local unit = self.unit\n if x ~= 0 then\n x = x*unit\n end\n if y ~= 0 then\n y = y*unit\n end\n if z ~= 0 then\n z = z*unit\n end\n local xs, ys, zs = x - camx, y - camy, z - camz\n local dx = cosy*(sinx*ys + cosx*xs) - siny*zs\n local dy = sinx*(cosy*zs + siny*(sinz*ys + cosz*xs)) + cosx*(cosz*ys - sinz*x)\n local dz = cosx*(cosy*zs + siny*(sinz*ys + cosz*xs)) - sinx*(cosz*ys - sinz*x)\n return dx, dy, dz\nend\n\n-- Transforms a 3D position into a two dimensional point on the screen.\nfunction Renderer:Project3D(x, y, z)\n -- Determine the current camera position\n local camx, camy, camz = self.camx, self.camy, self.camz\n local angle = self.angle\n local unit = self.unit\n -- Warp the position to avoid Touch Lua crashing\n --[[math.randomseed(x*y*z)\n while math.floor(x) == x do\n x = x + (math.random()*.01) -.005\n math.randomseed(x*y*z + math.random())\n end\n math.randomseed(x*y*z)\n while math.floor(y) == y do\n y = y + (math.random()*.01) -.005\n math.randomseed(x*y*z + math.random())\n end\n math.randomseed(x*y*z)\n while math.floor(z) == z do\n z = z + (math.random()*.01) -.005\n math.randomseed(x*y*z + math.random())\n end]]\n\n -- Transform the 3D position.\n --x, y, z = x*unit, y*unit, z*unit\n local xs, ys, zs = (x - camx)*unit, (y - camy)*unit, (z - camz)*unit\n local ex, ey, ez = 10*angle, 10*angle, 240*angle-- width, height, z - camz--xs, ys, zs\n\n -- Determine if the camera is perspective or not.\n if self.perspective then\n -- Use the perspective drawing mode\n local dx = cosy*(sinz*ys + cosz*xs) - siny*zs\n local dy = sinx*(cosy*zs + siny*(sinz*ys + cosz*xs)) + cosx*(cosz*ys - sinz*xs)\n local dz = cosx*(cosy*zs + siny*(sinz*ys + cosz*xs)) - sinx*(cosz*ys - sinz*xs)\n\n -- Calculate position to draw at\n local bx = (ez\/dz)*dx - ex\n local by = (ez\/dz)*dy - ey\n local bz = ((ez\/dz))*(ez - dz)\n --return bx + width*.5, by + height*.5\n --return bx, by\n return bx + width*.5, by + height*.5, ez - dz\n else\n -- Use the graphical drawing mode\n ys = -ys\n return (width*.5) + (xs * unit - zs * unit * cosz)*.5, (height*.5) + (ys * unit + zs * unit * zsin)*.5, zs * unit + zs * unit * zsin\n end\nend\n\n-- This function queues a three dimensional polygon to be drawn to the screen. To draw queued 3D elements call Renderer.DrawQueueToScreen.\nfunction Renderer:DrawPolygon(point1, point2, point3, point4, color, outline)\n if outline then\n self.render[#self.render + 1] = {\"PolygonOutline\", 0, point1, point2, point3, point4, color}\n else\n self.render[#self.render + 1] = {\"Polygon\", 0, point1, point2, point3, point4, color}\n end\nend\n\n-- Queues a three dimensional triangle to be drawn.\nfunction Renderer:DrawTriangle(point1, point2, point3, color)\n self.render[#self.render + 1] = {\"Triangle\", 0, point1, point2, point3, color}\nend\n\n-- Queues a three dimensional line to be drawn.\nfunction Renderer:DrawLine(point1, point2, color)\n self.render[#self.render + 1] = {\"Line\", 0, point1, point2, color}\nend\n\n-- Queues a sprite to be drawn on the screen.\nfunction Renderer:DrawSprite(image, vector3, size)\n if not imageCache[image] then\n imageCache[image] = {draw.cacheimage(image)}\n end\n local imgsize = imageCache[image]\n self.render[#self.render + 1] = {\"Sprite\", image, vector3, size\/math.max(imgsize[1], imgsize[2])}\nend\n\n-- Queues a string of text to be drawn on the screen.\nfunction Renderer:DrawString(text, vector3, size, color)\n self.render[#self.render + 1] = {\"String\", text, vector3, size, color}\nend\n\nfunction Fix(p1, p2, p3, p4)\n local x1, y1, z1 = p1:raw()\n local x2, y2, z2 = p2:raw()\n local x3, y3, z3 = p3:raw()\n local x4, y4, z4 = p4:raw()\n local r1, r2, r3, r4 = p1, p2, p3, p4\n --[[if y1 < y3 then\n r1, r2, r3, r4 = p3, p4, p1, p2\n end\n if x1 > x2 then\n r1, r2 = p2, p1\n end\n if x3 < x4 then\n r3, r4 = p4, p3\n end]]\n return r1, r2, r3, r4\nend\n\n-- This function draws queued 3D elements to the screen.\nfunction Renderer:DrawQueueToScreen()\n local minz, maxz = self.angle*240, self.angle*self.maxRange\n local order = {}\n -- Set up queued elements.\n for k, v in ipairs(self.render) do\n if v[1] == \"Polygon\" or v[1] == \"PolygonOutline\" then -- Draw two triangles.\n -- Get the ordered points of this polygon.\n local p1, p2, p3, p4 = Fix(v[3], v[4], v[5], v[6])\n -- Transform the coordinates of this polygon.\n local x1, y1, zvalue = self:Project3D(p1:raw())\n local x2, y2, zvalue2 = self:Project3D(p2:raw())\n local x3, y3, zvalue3 = self:Project3D(p3:raw())\n local x4, y4, zvalue4 = self:Project3D(p4:raw())\n -- Determine the Z value of this polygon.\n local zvalueLow = math.min(zvalue, zvalue2, zvalue3, zvalue4)\n local zvalueHigh = math.max(zvalue, zvalue2, zvalue3, zvalue4)\n zvalue = zvalueLow + ((zvalueHigh - zvalueLow)*.1)\n -- If the zvalue is in range, draw it.\n if zvalueLow > minz and zvalueHigh <= maxz then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n order[zvalue][#order[zvalue] + 1] = {v[1], x1, y1, x2, y2, x3, y3, x4, y4, v[7]*math.min((p1.y + 96)\/128, 1)*math.min((maxz - zvalueLow)\/(maxz \/ 2), 1)}--, v[7]*math.min((p1.y + 96)\/128, 1)*math.min((maxz - zvalueHigh)\/(maxz \/ 2), 1)}\n end\n elseif v[1] == \"Triangle\" then -- Draw a triangle.\n local p1, p2, p3 = v[3], v[4], v[5]\n local x1, y1, zvalue = self:Project3D(p1:raw())\n local x2, y2, zvalue2 = self:Project3D(p2:raw())\n local x3, y3, zvalue3 = self:Project3D(p3:raw())\n local zvalueLow = math.min(zvalue, zvalue2, zvalue3)\n local zvalueHigh = math.max(zvalue, zvalue2, zvalue3)\n zvalue = zvalueLow + ((zvalueHigh - zvalueLow)*.1)\n if zvalueLow > minz then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n order[zvalue][#order[zvalue] + 1] = {\"Triangle\", x1, y1, x2, y2, x3, y3, v[6]*zvalue}\n end\n elseif v[1] == \"Sprite\" then -- Draw a two dimensional sprite.\n local p1 = v[3]\n local x1, y1, zvalue = self:Project3D(p1:raw())\n if zvalue > minz*2 and zvalue <= maxz then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n order[zvalue][#order[zvalue] + 1] = {\"Sprite\", v[2], x1, y1, (minz - (zvalue*.05)*v[4])\/96}\n end\n elseif v[1] == \"String\" then -- Draw a string.\n local p1 = v[3]\n local x1, y1, zvalue = self:Project3D(p1:raw())\n if zvalue > minz*2 then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n order[zvalue][#order[zvalue] + 1] = {\"String\", v[2], x1, y1, v[4], v[5]}\n end\n elseif v[1] == \"Line\" then -- Draw a line.\n local p1, p2 = v[3], v[4]\n local x1, y1, zvalue = self:Project3D(p1:raw())\n local x2, y2, zvalue2 = self:Project3D(p2:raw())\n local zvalueLow = math.min(zvalue, zvalue2)\n local zvalueHigh = math.max(zvalue, zvalue2)\n zvalue = zvalueLow + ((zvalueHigh - zvalueLow)*.1)\n if zvalueLow > minz then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n order[zvalue][#order[zvalue] + 1] = {\"Line\", x1, y1, x2, y2, v[5]}\n end\n end\n end\n draw.setantialias(self.antialiased or false)\n -- Draw queued elements to screen.\n for k, v in pairs(order) do\n for k2, v2 in ipairs(v) do\n if v2[1] == \"Polygon\" then\n --[[if math.min(v2[2], v2[4], v2[6], v2[8]) > -256 and math.max(v2[2], v2[4], v2[6], v2[8]) < width + 256 then\n if math.min(v2[3], v2[5], v2[7], v2[9]) > -256 and math.max(v2[3], v2[5], v2[7], v2[9]) < height + 256 then]]\n local col = v2[10]\n --[[if self.gradientsEnabled then\n drawTriangle(v2[6], v2[7], v2[4], v2[5], v2[2], v2[3], col, v2[11])\n else]]\n draw.filltriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n draw.filltriangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], col) -- {k\/2048, k\/256, 1, 1})\n if self.antialiased then\n draw.triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n draw.triangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], col)\n --end\n end\n --[[end\n end]]\n elseif v2[1] == \"PolygonOutline\" then\n draw.triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[10])\n draw.triangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], v2[10]) -- {k\/2048, k\/256, 1, 1})\n elseif v2[1] == \"Triangle\" then\n draw.filltriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[8])\n elseif v2[1] == \"Sprite\" then\n draw.transformedimage(v2[2], v2[3], v2[4], v2[5], -camory)\n elseif v2[1] == \"String\" then\n draw.setantialias(true)\n draw.setfont(\"Arial\", v2[5])\n local sizeX, sizeY = draw.stringsize(v2[2])\n draw.stringinrect(v2[2], v2[3] - (sizeX*.5), v2[4] - (sizeY*.5), v2[3] + (sizeX*.5), v2[4] + (sizeY*.5), v2[6])\n draw.setantialias(self.antialiased or false)\n elseif v2[1] == \"Line\" then\n draw.setantialias(true)\n --draw.setlinestyle(4, \"butt\")\n draw.line(v2[2], v2[3], v2[4], v2[5], v2[6])\n --draw.setlinestyle(1, \"butt\")\n draw.setantialias(self.antialiased or false)\n end\n end\n end\n draw.setantialias(true)\n self.render = {}\nend\n\nreturn Renderer","Example4.lua":"Example1 = true\nrequire \"main\"\nTerrainVoxel = require \"TerrainVoxel\"\nlocal Ren = Renderer.new()\nlocal Terrain = TerrainVoxel.new()\nlocal rotatemode = 0\nlocal zoom = 1\nlocal rx, ry, rz = -32, 90, 0\nlocal shiftX, shiftY, shiftZ = 0, 0, 0\nlocal color = 1\n\nlocal colors = {draw.red, draw.blue, draw.green, draw.purple, draw.orange, draw.cyan, draw.gray, draw.yellow}\nlocal buttonTitles = {\n \"Reset Camera\",\n}\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dCamX, dCamY, dCamZ = -248, 1171, 0 --260, 0\nlocal dRx, dRy, dRz = rx, ry, rz\nlocal dShiftX, dShiftY, dShiftZ = shiftX, shiftY, shiftZ\n\n-- Set up Functions. --\n\n-- This function draws a button to the screen.\nfunction drawButton(text, x1, y1, x2, y2)\n draw.fillroundedrect(x1, y1, x2, y2, 8, draw.white)\n draw.roundedrect(x1, y1, x2, y2, 8, draw.blue)\n draw.stringinrect(text, x1, y1, x2, y2, draw.black)\nend\n\n-- This function draws a floor.\nfunction drawFloor(size, x, y, z, color1)\n local point1 = Vector3.new(x - size, y, z - size)\n local point2 = Vector3.new(x + size, y, z - size)\n local point3 = Vector3.new(x + size, y, z + size)\n local point4 = Vector3.new(x - size, y, z + size)\n Ren:DrawPolygon(point1, point2, point3, point4, color1 or colors)\n if not color1 then\n color = (color + 1 <= #colors and color + 1) or 1\n end\nend\n\nfunction none() end\n\n-- This function is called when the user first touches the screen.\nfunction touchBegan(tx, ty)\n originX, originY = tx, ty\n oldx, oldy, oldz = Ren.camx, Ren.camy, Ren.camz\n oldzoom = zoom\n oldrotx, oldroty, oldrotz = rx, ry, rz\nend\n\n-- This function is called on touch position movement.\nfunction touchMoved(tx, ty)\n if not (tx > width - 96) then\n local mx, my = (tx - originX), (ty - originY)\n local deadZone = 12\n if rotatemode >= 3 and rotatemode <= 4 then\n deadZone = 32\n end\n if not (mx > deadZone or mx < -deadZone) then\n mx = 0\n elseif mx > 0 then\n mx = mx - (deadZone - 1)\n else\n mx = mx + (deadZone)\n end\n if not (my > deadZone or my < -deadZone) then\n my = 0\n elseif my > 0 then\n my = my - (deadZone - 1)\n else\n my = my + (deadZone)\n end\n if rotatemode == 1 then\n Ren.camx, Ren.camy = oldx + mx, oldy + my\n elseif rotatemode == 2 then\n Ren.camx, Ren.camz = oldx + mx, oldz + my\n elseif rotatemode == 3 then\n mx, my = mx*.5, my*.5\n rx, ry = oldrotx + mx, oldroty + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 4 then\n mx, my = mx*.5, my*.5\n rx, rz = oldrotx + mx, oldrotz + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 5 then\n zoom = math.max(oldzoom - (my*.01), .01)\n Ren.angle = zoom\n end\n end\nend\n\n-- This function is called on the touch ending.\nfunction checkButtonTapped(tx, ty)\n if tx > width - 96 then\n buttonTapped = math.floor(ty\/48)\n if tx > width - 48 then\n tappedSide = 1\n else\n tappedSide = -1\n end\n else\n local mx, my = (tx - originX)*.1, (ty - originY)*.1\n if not (mx > 1 or mx < -1) and not (my > 1 or my < -1) then\n rotatemode = rotatemode + 1\n if rotatemode > 5 then\n rotatemode = 0\n end\n end\n end\nend\n\ndraw.tracktouches(touchBegan, touchMoved, checkButtonTapped)\n\n-- Set up the renderer.\nRen:setCameraZoom(zoom)\nRen.setCameraRotation(rx, ry, rz)\nRen:setCameraPosition(dCamX, dCamY, dCamZ)\nRen:setDrawMode(true)\nRen:setAntiAlias(true)\n\n-- Set up the Terrain.\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\nwhile true do\n if sys.gettime() > lastSecond + 1 then\n framesLastSecond = framesThisSecond\n framesThisSecond = 0\n lastSecond = sys.gettime()\n elseif sys.gettime() < lastSecond then\n lastSecond = sys.gettime()\n end\n -- Check button tapped\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 1 then\n shiftX, shiftY, shiftZ = dShiftX, dShiftY, dShiftZ\n rx, ry, rz = dRx, dRy, dRz\n zoom = dZoom\n Ren.angle = zoom\n Ren:setCameraPosition(dCamX, dCamY, dCamZ)\n Ren.setCameraRotation(rx, ry, rz)\n end\n -- Shift the cube\n if shiftX or shiftY or shiftZ then\n --CubeMesh:Shift(shiftX*.1, shiftY*.1, shiftZ*.1)\n --Ren:setCameraPosition(shiftX, shiftY, shiftZ)\n end\n -- Draw the frame\n color = 1\n --Ren.setCameraAngle(math.random()*100, 0, 0)\n draw.beginframe()\n draw.clear(draw.black)\n --CubeMesh:Draw(Ren)\n local size = 256\n local r = 4\n -- Draw the axis\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(1000, 0, 0), draw.red)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 1000, 0), draw.blue)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 0, 1000), draw.green)\n -- Draw the Terrain object to the screen.\n Terrain:Draw(Ren)\n Ren:DrawQueueToScreen()\n draw.setfont(\"Arial\", 16)\n for k, v in ipairs(buttonTitles) do\n drawButton(v, width - 96, k*48, width, (k + 1)*48)\n end\n draw.string(\"Camera Position: \", 0, 24, draw.white)\n draw.string(\"X: \"..Ren.camx, 0, 40, draw.white)\n draw.string(\"Y: \"..Ren.camy, 128, 40, draw.white)\n draw.string(\"Z: \"..Ren.camz, 256, 40, draw.white)\n draw.string(\"Camera Rotation: \", 0, 64, draw.white)\n draw.string(\"X: \"..rx, 0, 80, draw.white)\n draw.string(\"Y: \"..ry, 128, 80, draw.white)\n draw.string(\"Z: \"..rz, 256, 80, draw.white)\n if rotatemode > 5 then\n camMode = \"Zoom Mode (Zoom: \"..zoom..\")\"\n elseif rotatemode > 4 then\n camMode = \"Angle Mode (Angle: \"..(angle*45)..\")\"\n elseif rotatemode > 3 then\n camMode = \"Rotation Mode XZ\"\n elseif rotatemode > 2 then\n camMode = \"Rotation Mode XY\"\n elseif rotatemode > 1 then\n camMode = \"Movement Mode XZ\"\n elseif rotatemode > 0 then\n camMode = \"Movement Mode XY\"\n end\n draw.string(\"Frame Rate: \"..(framesLastSecond or framesThisSecond), 0, 128, draw.white)\n draw.endframe()\n framesThisSecond = framesThisSecond + 1\nend","Vector3.lua":"local Vector3 = {}\nVector3.__index = Vector3 -- failed table lookups on the instances should fallback to the class table, to get methods\nVector3.classtype = \"Vector3\"\n\nlocal cos, sin = math.cos(1), math.sin(1)\n\n-- This function constructs a new object of this type.\nVector3.new = function(x, y, z)\n local self = setmetatable({}, Vector3)\n self.x = x\n self.y = y\n self.z = z\n return self\nend\n\n-- Adds a vector to this vector.\nfunction Vector3.addVectorToVector(self, vector2)\n local output = Vector3.new(self.x, self.y, self.z)\n output.x = self.x + vector2.x\n output.y = self.y + vector2.y\n output.z = self.z + vector2.z\n return output\nend\n\n-- Subtracts a vector from this vector.\nfunction Vector3.subtractVectorFromVector(self, vector2)\n local output = Vector3.new(self.x, self.y, self.z)\n output.x = self.x - vector2.x\n output.y = self.y - vector2.y\n output.z = self.z - vector2.z\n return output\nend\n\n-- Multiplies a vector by this vector.\nfunction Vector3.multiplyVectorByVector(self, vector2)\n local output = Vector3.new(self.x, self.y, self.z)\n output.x = self.x * vector2.x\n output.y = self.y * vector2.y\n output.z = self.z * vector2.z\n return output\nend\n\n-- Divides a vector by this vector.\nfunction Vector3.divideVectorByVector(self, vector2)\n local output = Vector3.new(self.x, self.y, self.z)\n output.x = self.x \/ vector2.x\n output.y = self.y \/ vector2.y\n output.z = self.z \/ vector2.z\n return output\nend\n\n-- The rotation functions should return a vector.\n\n-- Rotates a vector around the XY plane.\nfunction Vector3.rotateXY(self, degrees)\n local output = Vector3.new(self.x, self.y, self.z)\n local cos, sin = math.cos, math.sin\n local radians = math.rad(degrees)\n output.x = cos(radians)*self.x + -sin(radians)*output.y\n output.y = sin(radians)*self.x + cos(radians)*self.y\n output.z = self.z\n return output\nend\n\n-- Rotates a vector around the YZ plane.\nfunction Vector3.rotateYZ(self, degrees)\n local output = Vector3.new(self.x, self.y, self.z)\n local cos, sin = math.cos, math.sin\n local radians = math.rad(degrees)\n output.x = self.x\n output.y = cos(radians)*self.y + -sin(radians)*output.z\n output.z = sin(radians)*self.y + cos(radians)*self.z\n return output\nend\n\n-- Rotates a vector around the XZ plane.\nfunction Vector3.rotateXZ(self, degrees)\n local output = Vector3.new(self.x, self.y, self.z)\n local cos, sin = math.cos, math.sin\n local radians = math.rad(degrees)\n output.x = cos(radians)*self.x + sin(radians)*self.z\n output.y = self.y\n output.z = -sin(radians)*self.x + cos(radians)*self.z\n return output\nend\n\n-- Scales a vector using the scaling 3-tuple and returns an output vector that is scaled.\nfunction Vector3.scale(self, s0, s1, s2)\n local output = Vector3.new(self.x, self.y, self.z)\n output.x = output.x * s0\n output.y = output.y * s1\n output.z = output.z * s2\n return output\nend\n\n-- Returns the raw position for this vector.\nfunction Vector3.raw(self)\n return self.x, self.y, self.z\nend\n\n-- Set up metatables\nVector3.__tostring = function(self)\n return self.x..\", \"..self.y..\", \"..self.z\nend\nVector3.__add = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return self\n end\n return self:addVectorToVector(other)\nend\nVector3.__sub = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return self\n end\n return self:subtractVectorFromVector(other)\nend\nVector3.__mul = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n if type(other) == \"number\" then\n return Vector3.new(self.x*other, self.y*other, self.z*other)\n end\n return self\n end\n return self:multiplyVectorByVector(other)\nend\nVector3.__div = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n if type(other) == \"number\" then\n return Vector3.new(self.x\/other, self.y\/other, self.z\/other)\n end\n return self\n end\n return self:divideVectorByVector(other)\nend\n\nVector3.__eq = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return false\n end\n if self.x == other.x and self.y == other.y and self.z == other.z then\n return true\n end\n return false\nend\nVector3.__lt = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return false\n end\n if self.x < other.x and self.y < other.y and self.z < other.z then\n return true\n end\n return false\nend\nVector3.__le = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return false\n end\n if self.x <= other.x and self.y <= other.y and self.z <= other.z then\n return true\n end\n return false\nend\n\nreturn Vector3","Example3.lua":"Example1 = true\nrequire \"main\"\nlocal Ren = Renderer.new()\nlocal Map = Heightmap.new()\nlocal rotatemode = 0\nlocal zoom = 1\nlocal rx, ry, rz = -32, 90, 0\nlocal shiftX, shiftY, shiftZ = 0, 0, 0\nlocal color = 1\n\nlocal colors = {draw.red, draw.blue, draw.green, draw.purple, draw.orange, draw.cyan, draw.gray, draw.yellow}\nlocal buttonTitles = {\n \"Reset Camera\",\n}\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dCamX, dCamY, dCamZ = -248, 1171, 0 --260, 0\nlocal dRx, dRy, dRz = rx, ry, rz\nlocal dShiftX, dShiftY, dShiftZ = shiftX, shiftY, shiftZ\n\n-- Set up Functions. --\n\n-- This function draws a button to the screen.\nfunction drawButton(text, x1, y1, x2, y2)\n draw.fillroundedrect(x1, y1, x2, y2, 8, draw.white)\n draw.roundedrect(x1, y1, x2, y2, 8, draw.blue)\n draw.stringinrect(text, x1, y1, x2, y2, draw.black)\nend\n\n-- This function draws a floor.\nfunction drawFloor(size, x, y, z, color1)\n local point1 = Vector3.new(x - size, y, z - size)\n local point2 = Vector3.new(x + size, y, z - size)\n local point3 = Vector3.new(x + size, y, z + size)\n local point4 = Vector3.new(x - size, y, z + size)\n Ren:DrawPolygon(point1, point2, point3, point4, color1 or colors)\n if not color1 then\n color = (color + 1 <= #colors and color + 1) or 1\n end\nend\n\nfunction none() end\n\n-- This function is called when the user first touches the screen.\nfunction touchBegan(tx, ty)\n originX, originY = tx, ty\n oldx, oldy, oldz = Ren.camx, Ren.camy, Ren.camz\n oldzoom = zoom\n oldrotx, oldroty, oldrotz = rx, ry, rz\nend\n\n-- This function is called on touch position movement.\nfunction touchMoved(tx, ty)\n if not (tx > width - 96) then\n local mx, my = (tx - originX), (ty - originY)\n local deadZone = 12\n if rotatemode >= 3 and rotatemode <= 4 then\n deadZone = 32\n end\n if not (mx > deadZone or mx < -deadZone) then\n mx = 0\n elseif mx > 0 then\n mx = mx - (deadZone - 1)\n else\n mx = mx + (deadZone)\n end\n if not (my > deadZone or my < -deadZone) then\n my = 0\n elseif my > 0 then\n my = my - (deadZone - 1)\n else\n my = my + (deadZone)\n end\n if rotatemode == 1 then\n Ren.camx, Ren.camy = oldx + mx, oldy + my\n elseif rotatemode == 2 then\n Ren.camx, Ren.camz = oldx + mx, oldz + my\n elseif rotatemode == 3 then\n mx, my = mx*.5, my*.5\n rx, ry = oldrotx + mx, oldroty + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 4 then\n mx, my = mx*.5, my*.5\n rx, rz = oldrotx + mx, oldrotz + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 5 then\n zoom = math.max(oldzoom - (my*.01), .01)\n Ren.angle = zoom\n end\n end\nend\n\n-- This function is called on the touch ending.\nfunction checkButtonTapped(tx, ty)\n if tx > width - 96 then\n buttonTapped = math.floor(ty\/48)\n if tx > width - 48 then\n tappedSide = 1\n else\n tappedSide = -1\n end\n else\n local mx, my = (tx - originX)*.1, (ty - originY)*.1\n if not (mx > 1 or mx < -1) and not (my > 1 or my < -1) then\n rotatemode = rotatemode + 1\n if rotatemode > 5 then\n rotatemode = 0\n end\n end\n end\nend\n\ndraw.tracktouches(touchBegan, touchMoved, checkButtonTapped)\n\n-- Set up the renderer.\nRen:setCameraZoom(zoom)\nRen.setCameraRotation(rx, ry, rz)\nRen:setCameraPosition(dCamX, dCamY, dCamZ)\nRen:setDrawMode(true)\nRen:setAntiAlias(true)\n\n-- Set up the heightmap.\nMap = Heightmap.new(64)\nMap:Reset(256, 5)\nMap:RandomizeHeight(-64, 1024)\nMap:SetCells(-8, -8, 7, 7, 16, 4)\nMap:SetCells(-4, -4, 3, 3, 4, 3)\nMap:SetCells(-2, -2, 1, 1, 0, 2)\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\nwhile true do\n if sys.gettime() > lastSecond + 1 then\n framesLastSecond = framesThisSecond\n framesThisSecond = 0\n lastSecond = sys.gettime()\n elseif sys.gettime() < lastSecond then\n lastSecond = sys.gettime()\n end\n -- Check button tapped\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 1 then\n shiftX, shiftY, shiftZ = dShiftX, dShiftY, dShiftZ\n rx, ry, rz = dRx, dRy, dRz\n zoom = dZoom\n Ren.angle = zoom\n Ren:setCameraPosition(dCamX, dCamY, dCamZ)\n Ren.setCameraRotation(rx, ry, rz)\n end\n -- Shift the cube\n if shiftX or shiftY or shiftZ then\n --CubeMesh:Shift(shiftX*.1, shiftY*.1, shiftZ*.1)\n --Ren:setCameraPosition(shiftX, shiftY, shiftZ)\n end\n -- Draw the frame\n color = 1\n --Ren.setCameraAngle(math.random()*100, 0, 0)\n draw.beginframe()\n draw.clear(draw.black)\n --CubeMesh:Draw(Ren)\n local size = 256\n local r = 4\n for x=-r, r do\n for z=-4, r do\n drawFloor(size, Ren.camx + (x*size), 128, Ren.camz + (z*size), Color.new(0, 88, 255, 128))\n end\n end\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(1000, 0, 0), draw.red)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 1000, 0), draw.blue)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 0, 1000), draw.green)\n Map:Draw(Ren)\n Ren:DrawQueueToScreen()\n draw.setfont(\"Arial\", 16)\n for k, v in ipairs(buttonTitles) do\n drawButton(v, width - 96, k*48, width, (k + 1)*48)\n end\n draw.string(\"Camera Position: \", 0, 24, draw.white)\n draw.string(\"X: \"..Ren.camx, 0, 40, draw.white)\n draw.string(\"Y: \"..Ren.camy, 128, 40, draw.white)\n draw.string(\"Z: \"..Ren.camz, 256, 40, draw.white)\n draw.string(\"Camera Rotation: \", 0, 64, draw.white)\n draw.string(\"X: \"..rx, 0, 80, draw.white)\n draw.string(\"Y: \"..ry, 128, 80, draw.white)\n draw.string(\"Z: \"..rz, 256, 80, draw.white)\n if rotatemode > 5 then\n camMode = \"Zoom Mode (Zoom: \"..zoom..\")\"\n elseif rotatemode > 4 then\n camMode = \"Angle Mode (Angle: \"..(angle*45)..\")\"\n elseif rotatemode > 3 then\n camMode = \"Rotation Mode XZ\"\n elseif rotatemode > 2 then\n camMode = \"Rotation Mode XY\"\n elseif rotatemode > 1 then\n camMode = \"Movement Mode XZ\"\n elseif rotatemode > 0 then\n camMode = \"Movement Mode XY\"\n end\n draw.string(\"Frame Rate: \"..(framesLastSecond or framesThisSecond), 0, 128, draw.white)\n draw.endframe()\n framesThisSecond = framesThisSecond + 1\nend","3DObject.lua":"local Object3D = {}\nObject3D.__index = Object3D -- This is a class table, set the index to itself so that all instances of it can use its functions and variables.\nObject3D.classtype = \"Object3D\"\n\n-- This function constructs a new object of this type.\nObject3D.new = function(position, ...)\n local self = setmetatable({}, Object3D)\n self.position = position or Vector3.new(0,0,0)\n self.rotation = Vector3.new(0,0,0)\n self.meshes = {...}\n return self\nend\n\n-- General Functions --\n\n--\nfunction Object3D:rescale()\n\nend\n\n--\nfunction Object3D:rotate()\n\nend\n\nfunction Object3D:draw()\n for k, v in ipairs(self.meshes) do\n v:draw()\n end\nend\n\nreturn Object3D","ExampleMesh.lua":"if not Example1 then require \"Example1\" end\nlocal ExampleMesh1 = {}\nlocal ExampleMesh2 = {}\n\n--[[255255255000\n000000000255\n255255255255\n031084255255\n000000064255\n225225255255\n082038000255\n048000000255]]\nfunction ExampleMesh1.new()\n local Mesh = Mesh.new()\n local color1, color2, color3, color4 = Color.new(31, 84, 255), Color.new(244, 244, 255), Color.new(0, 0, 12)\n -- Make Legs\n local l1, l2, l3, l4, l5, l6, l7, l8 = Vector3.new(-32, 0, -44), Vector3.new(-8, 0, -48), Vector3.new(-8, 0, -8), Vector3.new(-32, 0, -8),\n Vector3.new(-32, 6, -44), Vector3.new(-8, 6, -48), Vector3.new(-8, 7, -8), Vector3.new(-32, 6, -8)\n Mesh:AddCube(l1, l2, l3, l4, l5, l6, l7, l8, color1)\n\n -- Make Arms\n\n\n -- Make Body\n local h1, h2, h3 = 64, 128, 160\n local w1, w2 = 40, 32\n local l1, l2 = 32, 24\n local bl1, bl2 = 32, 24\n local p1, p2, p3, p4, p5, p6 = Mesh:AddCube(Vector3.new(-w1, h1, -l1), Vector3.new(w1, h1, -l1), Vector3.new(w1, h1, bl1), Vector3.new(-w1, h1, bl1), Vector3.new(-w1, h2, -l1), Vector3.new(w1, h2, -l1), Vector3.new(w1, h2, bl1), Vector3.new(-w1, h2, bl1), color1)\n Mesh:SetPolygonColor(p2, color2)\n Mesh:RemovePolygon(p6)\n p1, p2, p3, p4, p5, p6 = Mesh:AddCube(Vector3.new(-w1, h2, -l1), Vector3.new(w1, h2, -l1), Vector3.new(w1, h2, bl1), Vector3.new(-w1, h2, bl1), Vector3.new(-w2, h3, -l2), Vector3.new(w2, h3, -l2), Vector3.new(w2, h3, bl2), Vector3.new(-w2, h3, bl2), color1)\n Mesh:SetPolygonColor(p2, color2)\n --Mesh:SetPolygonColor(p1, color2)\n Mesh:RemovePolygon(p1)\n\n -- Make Neck\n --[[h1, h2 = 160, 180\n local w, l = 18, 18\n Mesh:AddTube(Vector3.new(-w, h1, -l), Vector3.new(w, h1, -l), Vector3.new(w, h1, l), Vector3.new(-w, h1, l), Vector3.new(-w, h2, -l), Vector3.new(w, h2, -l), Vector3.new(w, h2, l), Vector3.new(-w, h2, l), color1)]]\n\n -- Make Head\n local h1, h2, h3, h4 = 180, 200, 206, 230\n local w1, w2, w3 = 28, 27, 24\n local l1, l2, l3 = 28, 24, 22\n local bl1, bl2, bl3 = 24, 23.5, 20\n p1, p2, p3, p4, p5, p6 = Mesh:AddCube(Vector3.new(-w1, h1, -l1), Vector3.new(w1, h1, -l1), Vector3.new(w1, h1, bl1), Vector3.new(-w1, h1, bl1), Vector3.new(-w1, h2, -l1), Vector3.new(w1, h2, -l1), Vector3.new(w1, h2, bl1), Vector3.new(-w1, h2, bl1), color1)\n Mesh:RemovePolygon(p6)\n Mesh:AddTube(Vector3.new(-w1, h2, -l1), Vector3.new(w1, h2, -l1), Vector3.new(w1, h2, bl1), Vector3.new(-w1, h2, bl1), Vector3.new(-w2, h3, -l2), Vector3.new(w2, h3, -l2), Vector3.new(w2, h3, bl2), Vector3.new(-w2, h3, bl2), color1)\n Mesh:AddCube(Vector3.new(-w2, h3, -l2), Vector3.new(w2, h3, -l2), Vector3.new(w2, h3, bl2), Vector3.new(-w2, h3, bl2), Vector3.new(-w3, h4, -l3), Vector3.new(w3, h4, -l3), Vector3.new(w3, h4, bl3), Vector3.new(-w3, h4, bl3), color1)\n --Mesh:AddPolygon(Vector3.new(-32, h1, -32), Vector3.new(32, h1, -32), Vector3.new(32, h1, 32), Vector3.new(-32, h1, 32), color1)\n return Mesh\nend\n\nfunction WarpValue(mult, x, z)\n math.randomseed(x*z*.1)\n return (math.random()*2 - 1)*mult\nend\n\na = math.abs\n\nfunction MakeRandomTerrain(Mesh, xc, zc)\n local tab = {}\n local cells, size, height = 4, 40, 64\n xc, zc = xc*cells, zc*cells\n for x=-cells, cells do\n tab[x] = {}\n for z=-cells, cells do\n if a(x) == cells and a(z) == cells then\n tab[x][z] = Vector3.new(x*size, WarpValue(height, x, z), z*size)\n elseif a(x) == cells then\n tab[x][z] = Vector3.new(x*size, WarpValue(height, x, z), z*size + WarpValue(size, x, z))\n elseif a(z) == cells then\n tab[x][z] = Vector3.new(x*size + WarpValue(size, x, z), WarpValue(height, x, z), z*size)\n else\n local corner = tab[x - 1][z - 1]\n tab[x][z] = Vector3.new(x*size + WarpValue(size, x, z), WarpValue(height, x, z), z*size + WarpValue(size, x, z))\n end\n end\n end\n for x, xval in pairs(tab) do\n if x < cells then\n local xval2 = tab[x + 1]\n for z, zval in pairs(xval) do\n --if z < cells then\n local zval2 = xval[z + 1]\n local zval3 = xval2[z]\n local zval4 = xval2[z + 1]\n if zval and zval2 and zval3 then\n Mesh:AddPolygon(zval, zval2, zval4, zval3, draw.blue)\n end\n end\n end\n end\nend\n\nfunction ExampleMesh2.new(x, z, height)\n local Mesh = Mesh.new()\n local size = 120\n --[[local l1, l2, l3, l4 = Vector3.new(-size, 0, -size), Vector3.new(size, 0, -size), Vector3.new(size, 0, size), Vector3.new(-size, 0, size)\n Mesh:AddPolygon(l1, l2, l3, l4, draw.blue)]]\n MakeRandomTerrain(Mesh, x, z, height)\n return Mesh\nend\n\nreturn ExampleMesh1","main.lua":"draw.setscreen(1)\ndraw.settitle(\"Three Dimensional Graphics Screen\")\nwidth, height = draw.getport()\nif not imageCache then imageCache = {} end\n\nfunction GetObjectType(object)\n if type(object) ~= \"table\" then\n return false\n elseif not object.classtype then\n return false\n end\n return object.classtype\nend\n\nColor = require \"Color\"\nVector3 = require \"Vector3\"\nRegion3 = require \"Region3\"\nRenderer = require \"3DRenderer\"\nMesh = require \"3DMesh\"\nObject3D = require \"3DObject\"\nBasicMeshes = require \"BasicMeshes\"\nExampleMesh = require \"ExampleMesh\"\nHeightmap = require \"TerrainHeightmap\"\nTerrainMesh = require \"TerrainMesh\"\n\nRenderer.maxRange = 18000\nHeightmap.LODTable = {2, 4, 8, 16, 32, 64}","TerrainVoxel.lua":"if not Example1 then require \"Example4\" end\nlocal Terrain = {}\nTerrain.__index = Terrain -- This is a class table, set the index to itself so that all instances of it can use its functions and variables.\nTerrain.classtype = \"TerrainVoxel\"\nlocal defExt = 33554432\n\n-- Variables\nlocal nCellMaterial = 1\nlocal nCellBlock = 2\nlocal nCellOrientation = 3\n\n-- Default Terrain Materials --\nTerrain.Materials = {}\n\nTerrain.Liquids = {}\n\n-- Terrain Configuration Functions --\n-- This function constructs a new object of this type.\nTerrain.new = function()\n local self = setmetatable({}, Terrain)\n self.chunks = {}\n self.render = {}\n self.maxExtents = Region3.new(Vector3.new(-defExt, -defExt, -defExt), Vector3.new(defExt-1, defExt-1, defExt-1))\n self.materials = {}\n self:CreateNewMaterial(1, draw.green)\n -- Coroutine setup\n self.coroutines = {}\n self.saveProgress = {}\n self.loadProgress = {}\n self.genProgress = {}\n return self\nend\n\n-- Material functions --\nfunction Terrain:CreateNewMaterial(id, color)\n local material = {color = color}\n self.materials[material] = material\nend\n\nfunction Terrain:GetMaterialColor(material)\n if self.materials[material] then\n return self.materials[material][\"color\"]\n end\n return draw.blue\nend\n\n-- Coroutine management functions --\nfunction Terrain:CreateCoroutine(funct, priority, ...)\n local roTab = {coroutine = coroutine.create(funct)}\n local ok, errString = coroutine.resume(roTab.coroutine, ...)\n if not ok then\n print(errString)\n else\n self.coroutines[#self.coroutines + 1] = roTab\n end\nend\n\n-- This function resumes the recently running coroutine.\nfunction Terrain:ResumeCoroutine()\n local tab = self.coroutines[1]\n if tab then\n local routine = tab.coroutine\n if coroutine.status(routine) == \"dead\" then\n table.remove(self.coroutines, 1)\n return false\n end\n local ok, err = coroutine.resume(routine)\n if not ok then\n print(err)\n return false\n end\n return true\n end\n return false\nend\n\n-- This function is used to set a saving location for chunks.\nfunction Terrain:SetSavingLocation(path)\n self.savePath = path\nend\n\nfunction Terrain:SetSaveType(type)\n self.saveType = type\nend\n\n-- Terrain Teraforming Functions --\n-- This function is used to generate a chunk of terrain.\nfunction Terrain:GenerateTerrain()\n\nend\n\n-- This function is used to set a cube cell of terrain.\nfunction Terrain:SetCell(x, y, z, material, block, orientation)\n local Cell = {}\n Cell[nCellMaterial] = math.abs(material)\n Cell[nCellBlock] = block\n Cell[nCellOrientation] = orientation\n local Chunk = Terrain:GetChunk(x\/16, y\/16, z\/16)\n x, y, z = x - (math.floor(x\/16)*16) + 1, y - (math.floor(y\/16)*16) + 1, z - (math.floor(z\/16)*16) + 1\n if not Chunk[y] then\n Chunk[y] = {}\n end\n if not Chunk[y][x] then\n Chunk[y][x] = {}\n end\n Chunk[y][x][z] = Cell\nend\n\n-- This function is used to set a liquid cell.\nfunction Terrain:SetLiquidCell(x, y, z, material, force, direction)\n local Cell = {}\n Cell[nCellMaterial] = -math.abs(material)\n Cell[nCellBlock] = force\n Cell[nCellOrientation] = direction\n local Chunk = Terrain:GetChunk(x\/16, y\/16, z\/16)\n x, y, z = x - (math.floor(x\/16)*16) + 1, y - (math.floor(y\/16)*16) + 1, z - (math.floor(z\/16)*16) + 1\n if not Chunk[y] then\n Chunk[y] = {}\n end\n if not Chunk[y][x] then\n Chunk[y][x] = {}\n end\n Chunk[y][x][z] = Cell\nend\n\nfunction Terrain.SetCellsCoroutine(self, region, material, block, orientation)\n local points = region:GetIntegerPoints()\n local stepsBeforeYielding = 2500\n local steps = 0\n for k, v in ipairs(points) do\n local x, y, z = v[1], v[2], v[3]\n self:SetCell(x, y, z, material, block, orientation)\n steps = steps + 1\n if steps >= stepsBeforeYielding then\n steps = 0\n coroutine.yield()\n --stepsBeforeYielding = self.cr.stepTime*2500\n end\n end\nend\n\n-- This function is used to set a region of terrain cells.\nfunction Terrain:SetCells(region, material, block, orientation)\n self:CreateCoroutine(self.SetCellsCoroutine, 1, region, material, block, orientation)\n --[[local coro = coroutine.create(self.setCellsCoroutine)\n coroutine.resume(coro, self, region, material, block, orientation)\n self.cr.routines[#self.cr.routines + 1] = coro]]\nend\n\n-- This function is used to obtain a whole chunk.\nfunction Terrain:GetChunk(x, y, z)\n x, y, z = math.floor(x), math.floor(y), math.floor(z)\n if not self.chunks[y] then\n self.chunks[y] = {}\n end\n if not self.chunks[y][x] then\n self.chunks[y][x] = {}\n end\n return self.chunks[y][x][z]\nend\n\n-- This function returns the material, type, and orientation of a grid cell.\nfunction Terrain:GetCell(x, y, z)\n local Chunk = Terrain:GetChunk(x\/16, y\/16, z\/16)\n local CellY = Chunk[y - (math.floor(y\/16)*16) + 1]\n local CellX = CellY[x - (math.floor(x\/16)*16) + 1]\n local Cell = CellX[z - (math.floor(z\/16)*16) + 1]\n return Cell[nCellMaterial], Cell[nCellBlock], Cell[nCellOrientation]\nend\n\n-- This function returns the material, water force, and water direction of a grid cell.\nfunction Terrain:GetLiquidCell(x, y, z)\n local Chunk = Terrain:GetChunk(x\/16, y\/16, z\/16)\n local CellY = Chunk[y - (math.floor(y\/16)*16) + 1]\n local CellX = CellY[x - (math.floor(x\/16)*16) + 1]\n local Cell = CellX[z - (math.floor(z\/16)*16) + 1]\n return (Cell[nCellMaterial] < 0), math.abs(Cell[nCellMaterial]), Cell[nCellBlock], Cell[nCellOrientation]\nend\n\n-- This function calls the Region3's CopyTerrainRegion.\nfunction Terrain:CopyRegion(region3)\n return region3:CopyTerrainRegion(self)\nend\n\n-- Drawing Functions --\n-- This function rebuilds a chunk polygon table.\nfunction Terrain:RepairDrawingTable(x, y, z)\n local chunk = self:GetChunk(x, y, z)\n if not chunk then return false end\n if not self.render[y] then self.render[y] = {} end\n if not self.render[y][x] then self.render[y][x] = {} end\n local drawChunk = {}\n local cx, cy, cz = x*16, y*16, z*16\n -- Save the chunk data\n for yk=1, 16 do\n for xk=1, 16 do\n for zk=1, 16 do\n local dx, dy, dz = cx + xk, cy + yk, cz + zk\n local Cell = chunk[yk][xk][zk]\n local material, block, orientation = Cell[nCellMaterial], Cell[nCellBlock], Cell[nCellOrientation]\n local tfl, tfr, tbl, tbr, bfl, bfr, bll, blr = Vector3:new(dx, dy, dz), Vector3:new(dx + 1, dy, dz), Vector3:new(dx, dy, dz + 1), Vector3:new(dx + 1, dy, dz + 1), Vector3:new(dx, dy + 1, dz), Vector3:new(dx + 1, dy + 1, dz), Vector3:new(dx, dy + 1, dz + 1), Vector3:new(dx + 1, dy + 1, dz + 1)\n local top, bot, left, rig, fro, bac = self:GetCell(dx, dy - 1, dz), self:GetCell(dx, dy + 1, dz), self:GetCell(dx - 1, dy, dz),self:GetCell(dx + 1, dy, dz),self:GetCell(dx, dy, dz + 1),self:GetCell(dx, dy, dz - 1)\n if block == 1 then -- Solid block\n if top[nCellBlock] ~= 1 then\n table.insert(drawChunk, {tfl, tfr, tbr, tbl, self:getMaterialColor(Cell[nCellMaterial])})\n end\n if bot[nCellBlock] ~= 1 then\n table.insert(drawChunk, {bfl, bfr, bbr, bbl, self:getMaterialColor(Cell[nCellMaterial])})\n end\n end\n end\n end\n -- Yield\n coroutine.yield()\n end\n self.render[y][x][z] = drawChunk\nend\n\nfunction Terrain:DrawChunk(Ren, x, y, z)\n if not self.render[y] then return self:RepairDrawingTable(x, y, z) end\n if not self.render[y][x] then return self:RepairDrawingTable(x, y, z) end\n if not self.render[y][x][z] then return self:RepairDrawingTable(x, y, z) end\n local render = self.render[y][x][z]\n for k, v in ipairs(render) do\n\n end\nend\n\n-- This function draws a terrain object.\nfunction Terrain:Draw(Ren)\n self:DrawChunk(Ren, 0,0,0)\nend\n\n-- Terrain Persistance Functions --\n-- This function is used to reset a chunk of terrain.\nfunction Terrain:ResetChunk(x, y, z)\n if not self.chunks[y] then\n self.chunks[y] = {}\n end\n if not self.chunks[y][x] then\n self.chunks[y][x] = {}\n end\n self.chunks[y][x][z] = {}\nend\n\nfunction string.padnum(num, digits)\n local str = tostring(num)\n str = string.rep(\"0\", digits - #str)..str\n return str\nend\n\nfunction Terrain:SaveChunkRaw(x, y, z)\n local id = #self.coroutines + 1\n local progress = 0\n self.saveProgress[id] = progress\n coroutine.yield(progress)\n -- After coroutine is resumed\n local file, err = io.open(self:File(x, y, z), \"w\")\n if file then\n local chunk = self:GetChunk(x, y, z)\n -- Save the chunk data\n for yk=1, 16 do\n for xk=1, 16 do\n for zk=1, 16 do\n local Cell = chunk[yk][xk][zk]\n local material, block, orientation = Cell[nCellMaterial] + 500, Cell[nCellBlock], Cell[nCellOrientation]\n file:write(string.padnum(material, 3))\n file:write(string.padnum(block, 2))\n file:write(string.padnum(orientation, 2))\n end\n file:write(\"\\n\")\n end\n --file:write(\"\\n\")\n -- Yield\n self.saveProgress[id] = progress\n coroutine.yield(progress)\n end\n file:close()\n print(\"Saved Chunk \"..x..\",\"..y..\",\"..z..\"!\")\n else\n print(err)\n end\n self.saveProgress[id] = true\n return true\nend\n\nfunction Terrain:LoadChunkRaw(x, y, z)\n local id = #self.coroutines + 1\n local progress = 0\n self.loadProgress[id] = progress\n coroutine.yield(progress)\n -- After coroutine is resumed\n local file = io.open(self:File(x, y, z))\n local x1, y1, z1 = self:GetChunkCorner(x, y, z)\n if file then\n local chunk = self:GetChunk(x, y, z)\n -- Save the chunk data\n for yk=1, 16 do\n for xk=1, 16 do\n local line = file:read()\n if line then\n for zk=1, 16 do\n local num1, num2, num3 = string.sub(line, (zk - 1)*7 + 1, (zk - 1)*7 + 3), string.sub(line, (zk - 1)*7 + 4, (zk - 1)*7 + 5), string.sub(line, (zk - 1)*7 + 6, (zk - 1)*7 + 7),\n self:SetCell(x*16 + xk, y*16 + yk, z*16 + zk, (num1*256) + num2, x1 + xk - 1, y1 + yk - 1, z1 + zk - 1)\n end\n end\n end\n -- Yield\n self.saveProgress[id] = progress\n coroutine.yield(progress)\n end\n file:close()\n return true\n end\nend\n\n-- This function saves a chunk.\nfunction Terrain:SaveChunk(x, y, z)\n self:CreateCoroutine(self.SaveChunkRaw, 1, self, x, y, z)\nend\n\n-- This function loads a chunk.\nfunction Terrain:LoadChunkFromDisk(x, y, z)\n self:CreateCoroutine(self.LoadChunkRaw, 1, self, x, y, z)\nend\n\n-- This function loads a chunk into RAM.\nfunction Terrain:LoadChunk(x, y, z)\n if lfs.isFile(self:File(x, y, z)) then\n self:LoadChunkFromDisk(x, y, z)\n else\n self:GenerateChunk(x, y, z)\n end\nend\n\nfunction Terrain:IsSavingTerrain()\n for k, v in pairs(self.saveProgress) do\n if type(v) ~= \"boolean\" then\n return true\n end\n end\n return false\nend\n\nfunction Terrain:IsLoadingTerrain()\n for k, v in pairs(self.loadProgress) do\n if type(v) ~= \"boolean\" then\n return true\n end\n end\n return false\nend\n\nfunction Terrain:IsGeneratingTerrain()\n for k, v in pairs(self.genProgress) do\n if type(v) ~= \"boolean\" then\n return true\n end\n end\n return false\nend\n\n-- Terrain Update Functions --\n-- This function is called every frame to both update terrain and handle coroutines.\nfunction Terrain:Update()\n self:ResumeCoroutine()\nend\n\nreturn Terrain","Color.lua":"local Color = {}\nColor.__index = Color -- failed table lookups on the instances should fallback to the class table, to get methods\nColor.classtype = \"Color\"\n\nlocal cos, sin = math.cos(1), math.sin(1)\n\n-- This function constructs a new object of this type.\nColor.new = function(red, green, blue, alpha, dontdivide)\n local self = setmetatable({}, Color)\n if dontdivide then\n self.red = red\n self.green = green\n self.blue = blue\n self.alpha = alpha or 1\n else\n self.red = red\/255\n self.green = green\/255\n self.blue = blue\/255\n self.alpha = (alpha or 255)\/255\n end\n return self\nend\n\n-- Adds a vector to this color.\nfunction Color.addColorToColor(self, vector2)\n local output = Color.new(self.red, self.green, self.blue, self.alpha)\n output.red = self.red + vector2.red\n output.green = self.green + vector2.green\n output.blue = self.blue + vector2.blue\n output.alpha = self.alpha + vector2.alpha\n return output\nend\n\n-- Subtracts a vector from this vector.\nfunction Color.subtractColorFromColor(self, vector2)\n local output = Color.new(self.red, self.green, self.blue, self.alpha)\n output.red = self.red - vector2.red\n output.green = self.green - vector2.green\n output.blue = self.blue - vector2.blue\n output.alpha = self.alpha - vector2.alpha\n return output\nend\n\n-- Multiplies a vector by this vector.\nfunction Color.multiplyColorByColor(self, vector2)\n local output = Color.new(self.red, self.green, self.blue, self.alpha)\n output.red = self.red * vector2.red\n output.green = self.green * vector2.green\n output.blue = self.blue * vector2.blue\n output.alpha = self.alpha * vector2.alpha\n return output\nend\n\n-- Divides a vector by this vector.\nfunction Color.divideColorByColor(self, vector2)\n local output = Color.new(self.red, self.green, self.blue, self.alpha)\n output.red = self.red \/ vector2.red\n output.green = self.green \/ vector2.green\n output.blue = self.blue \/ vector2.blue\n output.alpha = self.alpha \/ vector2.alpha\n return output\nend\n\n-- Returns the raw values for this color.\nfunction Color.raw(self)\n return self.red, self.green, self.blue, self.alpha\nend\n\n-- Set up metatables\nColor.__tostring = function(self)\n return self.red..\", \"..self.green..\", \"..self.blue..\", \"..self.alpha\nend\nColor.__add = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n if type(other) == \"number\" then\n return Color.new(self.red+other, self.green+other, self.blue+other, self.alpha+other)\n end\n return self\n end\n return self:addColorToColor(other)\nend\nColor.__sub = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n if type(other) == \"number\" then\n return Color.new((self.red*255)-other, (self.green*255)-other, (self.blue*255)-other, (self.alpha*255)-other)\n end\n return self\n end\n return self:subtractColorFromColor(other)\nend\nColor.__mul = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n if type(other) == \"number\" then\n return Color.new(self.red*other, self.green*other, self.blue*other, self.alpha, true)\n end\n return self\n end\n return self:multiplyColorByColor(other)\nend\nColor.__div = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n if type(other) == \"number\" then\n return Color.new((self.red)\/other, (self.green)\/other, (self.blue)\/other, self.alpha, true)\n end\n return self\n end\n return self:divideColorByColor(other)\nend\n\nColor.__eq = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n return false\n end\n if self.red == other.red and self.green == other.green and self.blue == other.blue then\n return true\n end\n return false\nend\nColor.__lt = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n return false\n end\n if self.red < other.red and self.green < other.green and self.blue < other.blue then\n return true\n end\n return false\nend\nColor.__le = function(self, other)\n if GetObjectType(other) ~= \"Color\" then\n return false\n end\n if self.red <= other.red and self.green <= other.green and self.blue <= other.blue then\n return true\n end\n return false\nend\n\n-- Enhance default draw colors table\nfor k, v in pairs(draw) do\n if type(v) == \"table\" then\n --print(\"Table \"..k)\n if v.red then\n draw[k] = Color.new(v.red, v.green, v.blue, v.alpha, true)\n end\n end\nend\n\nreturn Color","Configuration.lua":"draw.setscreen(1)\nlocal width, height = draw.getport()\nlocal config = {}\nlocal configFile = \"Config.txt\"\n\n-- This function loads a configuration.\nlocal function loadConfiguration()\n for line in io.lines(configFile) do\n local sep = string.find(line, \"#\")\n local key, value = line:sub(0, sep), line:sub(sep + 1)\n config[key] = value\n end\nend\n\n-- This function saves a configuration.\nlocal function saveConfiguration()\n local file = io.open(configFile, \"w\")\n if file then\n for k, v in pairs(config) do\n file:write(k..\"#\"..v..\"\\n\")\n end\n file:close()\n end\nend\n\n-- Set up layout\nlocal layout = {\n [\"Main\"] = {\n controls = {\n {\n type = \"Slider\",\n x = 1,\n y = 1,\n xsize = 98,\n ysize = 16,\n value = 0,\n valueChanged = 5\n }\n }\n }\n}\nlocal currentPage = \"Main\"\n\nlocal drawCont = {}\n\n-- This function draws a slider.\ndrawCont[\"Slider\"] = function(x, y, xsize, ysize, value)\n -- Draw background\n draw.fillroundedrect(x + 4, y + 4, x + 4 + ((xsize - 8)*value), y + (ysize - 4), 8, draw.blue)\n draw.roundedrect(x + 4, y + 4, x + (xsize - 4), y + (ysize - 4), 8, draw.black)\n -- Draw slider rectangle\n draw.roundedrect(x - 4 + ((xsize - 8)*value), y + 4, x + 8 + ((xsize - 8)*value), y + (ysize - 4), 4, draw.black)\nend\n\nfunction drawPage(pageID)\n local width, height = width*.01, (height - 48)*.01\n local page = layout[pageID]\n for k, v in pairs(page.controls) do\n local x, y, xsize, ysize = v.x*width, (v.y*height) + 48, v.xsize*width, v.ysize*height\n if drawCont[v.type] then\n drawCont[v.type](x, y, xsize, ysize, v.value, v.text)\n end\n end\nend\n\n-- This function draws the tabs on the top of the screen.\nfunction drawTabs()\n local tabWidth = 128\n local Key = 0\n for pageKey, pageTable in pairs(layout) do\n Key = Key + 1\n if currentPage == pageKey then\n\n else\n draw.fillroundedrect((Key - 1)*tabWidth, 0, Key*tabWidth, 64, 8, draw.gray)\n end\n draw.roundedrect((Key - 1)*tabWidth, 0, Key*tabWidth, 64, 8, draw.black)\n draw.stringinrect(pageKey, (Key - 1)*tabWidth, 16, Key*tabWidth, 48, draw.black)\n end\n drawPage(currentPage)\nend\n\nwhile true do\n draw.beginframe()\n draw.clear()\n drawTabs()\n draw.endframe()\nend","3DMesh.lua":"local Mesh = {}\nMesh.__index = Mesh -- failed table lookups on the instances should fallback to the class table, to get methods\nMesh.classtype = \"Mesh\"\n\n-- This function constructs a new object of this type.\nMesh.new = function()\n local self = setmetatable({}, Mesh)\n self.mesh = {}\n self.defaultColor = draw.blue\n self.shift = Vector3.new(0, 0, 0)\n return self\nend\n\n-- Adds a polygon to the mesh.\nfunction Mesh:AddPolygon(Point1, Point2, Point3, Point4, Color)\n if type(Color) ~= \"table\" then\n Color = draw.blue\n end\n local id = #self.mesh + 1\n self.mesh[id] = {Point1, Point2, Point3, Point4, Color or draw.blue}\n return id\nend\n\nfunction Mesh:AddCube(p1, p2, p3, p4, p5, p6, p7, p8, Color)\n local pl1 = self:AddPolygon(p1, p2, p3, p4, Color)\n local pl2 = self:AddPolygon(p1, p2, p6, p5, Color)\n local pl3 = self:AddPolygon(p2, p3, p7, p6, Color)\n local pl4 = self:AddPolygon(p3, p4, p8, p7, Color)\n local pl5 = self:AddPolygon(p4, p1, p5, p8, Color)\n local pl6 = self:AddPolygon(p5, p6, p7, p8, Color)\n return pl1, pl2, pl3, pl4, pl5, pl6\nend\n\nfunction Mesh:AddTube(p1, p2, p3, p4, p5, p6, p7, p8, Color)\n local pl1 = self:AddPolygon(p1, p2, p6, p5, Color)\n local pl2 = self:AddPolygon(p2, p3, p7, p6, Color)\n local pl3 = self:AddPolygon(p3, p4, p8, p7, Color)\n local pl4 = self:AddPolygon(p4, p1, p5, p8, Color)\n return pl1, pl2, pl3, pl4\nend\n\n-- Removes a polygon from the mesh.\nfunction Mesh:RemovePolygon(PolygonID)\n table.remove(self.mesh, PolygonID)\nend\n\nfunction Mesh:SetPolygonColor(PolygonID, color)\n self.mesh[PolygonID][5] = color\nend\n\n-- Scales a mesh.\nfunction Mesh:Scale(x, y, z)\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n v = v:scale(x, y or x, z or x)\n end\n end\nend\n\n-- Shifts a mesh by a certain value.\nfunction Mesh:Shift(x, y, z)\n self.shift = self.shift:addVectorToVector(Vector3.new(x, y, z))\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n v.x = v.x + x\n v.y = v.y + y\n v.z = v.z + z\n end\n end\nend\n\nfunction Mesh:RotateXY(degrees)\n local x, y, z = self.shift:raw()\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n v = v:rotateXY(degrees)\n end\n end\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\nend\n\nfunction Mesh:RotateXZ(degrees)\n local x, y, z = self.shift:raw()\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n v = v:rotateXZ(degrees)\n end\n end\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\nend\n\nfunction Mesh:RotateYZ(degrees)\n local x, y, z = self.shift:raw()\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n v = v:rotateYZ(degrees)\n end\n end\n x, y, z = -x, -y, -z\n shift:Shift(x, y, z)\nend\n\n-- Draws a mesh.\nfunction Mesh:Draw(Renderer)\n for k, v in pairs(self.mesh) do\n Renderer:DrawPolygon(v[1], v[2], v[3], v[4], v[5] or self.defaultColor)\n end\nend\n\nreturn Mesh","TerrainMesh.lua":"local TerrainMesh = {}\nTerrainMesh.__index = TerrainMesh -- This is a class table, set the index to itself so that all instances of it can use its functions and variables.\nTerrainMesh.classtype = \"TerrainMesh\"\n\n-- This function constructs a new object of this type.\nTerrainMesh.new = function(size)\n local self = setmetatable({}, TerrainMesh)\n math.randomseed(sys.gettime()*2000)\n self.floor = 48\n self.seed = 8 or (math.random()*2048*2048)\n self.chunks = {}\n self:GenerateChunk(0,0)\n return self\nend\n\n-- Generation functions --\nlocal function WarpValue(mult, x, z, seed)\n math.randomseed(x*z*seed)\n return (math.random()*2 - 1)*mult\nend\n\nlocal a = math.abs\n\nlocal function ChunkMesh(Mesh, xc, zc, seed)\n local tab = {}\n local cells, size, height = 4, 128, 128\n xc, zc = xc*cells, zc*cells\n for x=-cells, cells do\n tab[x] = {}\n for z=-cells, cells do\n if a(x) == cells - 1 and a(z) == cells then\n tab[x][z] = Vector3.new(x*size, WarpValue(height, x, z, seed), z*size)\n elseif a(x) == cells then\n tab[x][z] = Vector3.new(x*size, WarpValue(height, x, z, seed), z*size + WarpValue(size, x, z, seed))\n elseif a(z) == cells then\n tab[x][z] = Vector3.new(x*size + WarpValue(size, x, z, seed), WarpValue(height, x, z, seed), z*size)\n else\n local corner = tab[x - 1][z - 1]\n tab[x][z] = Vector3.new(x*size + WarpValue(size, x, z, seed), WarpValue(height, x, z, seed), z*size + WarpValue(size, x, z, seed))\n end\n end\n end\n for x, xval in pairs(tab) do\n if x < cells then\n local xval2 = tab[x + 1]\n for z, zval in pairs(xval) do\n --if z < cells then\n local zval2 = xval[z + 1]\n local zval3 = xval2[z]\n local zval4 = xval2[z + 1]\n if zval and zval2 and zval3 then\n Mesh:AddPolygon(zval, zval2, zval4, zval3, draw.blue)\n end\n end\n end\n end\n return Mesh\nend\n\nfunction TerrainMesh:GenerateChunk(x, z)\n local seed = self.seed\n local mesh = ChunkMesh(Mesh.new(), x, z, seed)\n mesh:RotateXY(0)\n mesh:Shift(x*512, self.floor, z*512)\n if not self.chunks[x] then\n self.chunks[x] = {}\n end\n self.chunks[x][z] = mesh\nend\n\n-- Draw Functions --\n\nfunction TerrainMesh:DrawChunk(Ren, x, z)\n if self.chunks[x] then\n if self.chunks[x][z] then\n self.chunks[x][z]:Draw(Ren)\n else\n self:GenerateChunk(x, z)\n end\n else\n self:GenerateChunk(x, z)\n end\nend\n\nfunction TerrainMesh:Draw(Ren)\n local rx, rz = 0,0 --math.floor((Ren.camx + Ren.camy)\/512), math.floor(Ren.camz\/512)\n local zone = 0\n for x=rx - zone, rx + zone do\n for z=rz - zone, rz + zone do\n self:DrawChunk(Ren, x, z)\n end\n end\nend\n\nreturn TerrainMesh","Example2.lua":"Example1 = true\nrequire \"main\"\nlocal Ren = Renderer.new()\n--local Map = Heightmap.new()\nlocal rotatemode = 0\nlocal zoom = 1\nlocal rx, ry, rz = -32, 270, 0 -- -84, 0, 0\nlocal shiftX, shiftY, shiftZ = 0, 0, 0\nlocal color = 1\n\nlocal colors = {draw.red, draw.blue, draw.green, draw.purple, draw.orange, draw.cyan, draw.gray, draw.yellow}\nlocal buttonTitles = {\n \"Rotate Model\",\n \"Change Size\",\n \"Reset\",\n \"Move X\",\n \"Move Y\",\n \"Move Z\"\n}\n\n-- Set up the cube mesh.\nlocal TerrainMesh = TerrainMesh.new()\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dCamX, dCamY, dCamZ = -248, 260, 0\nlocal dRx, dRy, dRz = rx, ry, rz\nlocal dShiftX, dShiftY, dShiftZ = shiftX, shiftY, shiftZ\n\n-- Set up Functions. --\n\n-- This function draws a button to the screen.\nfunction drawButton(text, x1, y1, x2, y2)\n draw.fillroundedrect(x1, y1, x2, y2, 8, draw.white)\n draw.roundedrect(x1, y1, x2, y2, 8, draw.blue)\n draw.stringinrect(text, x1, y1, x2, y2, draw.black)\nend\n\n-- This function draws a floor.\nfunction drawFloor(size, x, y, z)\n local point1 = Vector3.new(x - size, y, z - size)\n local point2 = Vector3.new(x + size, y, z - size)\n local point3 = Vector3.new(x + size, y, z + size)\n local point4 = Vector3.new(x - size, y, z + size)\n Ren:DrawPolygon(point1, point2, point3, point4, colors)\n color = (color + 1 <= #colors and color + 1) or 1\nend\n\nfunction none() end\n\n-- This function is called when the user first touches the screen.\nfunction touchBegan(tx, ty)\n originX, originY = tx, ty\n oldx, oldy, oldz = Ren.camx, Ren.camy, Ren.camz\n oldzoom = zoom\n oldrotx, oldroty, oldrotz = rx, ry, rz\nend\n\n-- This function is called on touch position movement.\nfunction touchMoved(tx, ty)\n if not (tx > width - 96) then\n local mx, my = (tx - originX), (ty - originY)\n local deadZone = 12\n if rotatemode >= 3 and rotatemode <= 4 then\n deadZone = 32\n end\n if not (mx > deadZone or mx < -deadZone) then\n mx = 0\n elseif mx > 0 then\n mx = mx - (deadZone - 1)\n else\n mx = mx + (deadZone)\n end\n if not (my > deadZone or my < -deadZone) then\n my = 0\n elseif my > 0 then\n my = my - (deadZone - 1)\n else\n my = my + (deadZone)\n end\n if rotatemode == 1 then\n Ren.camx, Ren.camy = oldx + mx, oldy + my\n elseif rotatemode == 2 then\n Ren.camx, Ren.camz = oldx + mx, oldz + my\n elseif rotatemode == 3 then\n mx, my = mx*.5, my*.5\n rx, ry = oldrotx + mx, oldroty + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 4 then\n mx, my = mx*.5, my*.5\n rx, rz = oldrotx + mx, oldrotz + my\n Ren.setCameraRotation(rx, ry, rz)\n elseif rotatemode == 5 then\n zoom = math.max(oldzoom - (my*.01), .01)\n Ren.angle = zoom\n end\n end\nend\n\n-- This function is called on the touch ending.\nfunction checkButtonTapped(tx, ty)\n if tx > width - 96 then\n buttonTapped = math.floor(ty\/48)\n if tx > width - 48 then\n tappedSide = 1\n else\n tappedSide = -1\n end\n else\n local mx, my = (tx - originX)*.1, (ty - originY)*.1\n if not (mx > 1 or mx < -1) and not (my > 1 or my < -1) then\n rotatemode = rotatemode + 1\n if rotatemode > 5 then\n rotatemode = 0\n end\n end\n end\nend\n\ndraw.tracktouches(touchBegan, touchMoved, checkButtonTapped)\n\n-- Set up the renderer.\nRen:setCameraZoom(zoom)\nRen.setCameraRotation(rx, ry, rz)\nRen:setCameraPosition(dCamX, dCamY, dCamZ)\nRen:setDrawMode(true)\nRen:setAntiAlias(true)\n\n-- Set up the heightmap.\n--[[Map:Reset(64, 5)\nMap:RandomizeHeight(-48, 48)\nMap:SetCells(-8, -8, 7, 7, 16, 4)\nMap:SetCells(-4, -4, 3, 3, 4, 3)\nMap:SetCells(-2, -2, 1, 1, 0, 2)]]\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\nwhile true do\n if sys.gettime() > lastSecond + 1 then\n framesLastSecond = framesThisSecond\n framesThisSecond = 0\n lastSecond = sys.gettime()\n elseif sys.gettime() < lastSecond then\n lastSecond = sys.gettime()\n end\n -- Check button tapped\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 3 then\n TerrainMesh = TerrainMesh.new(10)\n shiftX, shiftY, shiftZ = dShiftX, dShiftY, dShiftZ\n rx, ry, rz = dRx, dRy, dRz\n zoom = dZoom\n Ren.angle = zoom\n Ren:setCameraPosition(dCamX, dCamY, dCamZ)\n Ren.setCameraRotation(rx, ry, rz)\n elseif buttonTapped == 4 then\n shiftX = (shiftX or 0) + (tappedSide)*10\n elseif buttonTapped == 5 then\n shiftY = (shiftY or 0) + (tappedSide)*10\n elseif buttonTapped == 6 then\n shiftZ = (shiftZ or 0) + (tappedSide)*10\n end\n -- Shift the cube\n -- Draw the frame\n color = 1\n --Ren.setCameraAngle(math.random()*100, 0, 0)\n draw.beginframe()\n draw.clear(draw.black)\n TerrainMesh:Draw(Ren)\n --drawFloor(20, Ren.camx, Ren.camy - 24, Ren.camz)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(1000, 0, 0), draw.red)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 1000, 0), draw.blue)\n Ren:DrawLine(Vector3.new(0, 0, 0), Vector3.new(0, 0, 1000), draw.green)\n --Map:Draw(Ren)\n --Ren:DrawSprite(\"@resources\/SomeTile.png\", Vector3.new(1000, 20, 0), 24)\n --Ren:DrawString(\"3D String Is Drawn\", Vector3.new(-100, 10, -10), .1, draw.white)\n Ren:DrawQueueToScreen()\n draw.setfont(\"Arial\", 16)\n for k, v in ipairs(buttonTitles) do\n drawButton(v, width - 96, k*48, width, (k + 1)*48)\n end\n draw.string(\"Camera Position: \", 0, 24, draw.white)\n draw.string(\"X: \"..Ren.camx, 0, 40, draw.white)\n draw.string(\"Y: \"..Ren.camy, 128, 40, draw.white)\n draw.string(\"Z: \"..Ren.camz, 256, 40, draw.white)\n draw.string(\"Camera Rotation: \", 0, 64, draw.white)\n draw.string(\"X: \"..rx, 0, 80, draw.white)\n draw.string(\"Y: \"..ry, 128, 80, draw.white)\n draw.string(\"Z: \"..rz, 256, 80, draw.white)\n if rotatemode > 4 then\n draw.string(\"Zoom Mode (Zoom: \"..zoom..\")\", 0, 160, draw.white)\n elseif rotatemode > 2 then\n draw.string(\"Rotation Mode \"..(rotatemode - 2), 0, 160, draw.white)\n elseif rotatemode > 0 then\n draw.string(\"Movement Mode \"..(rotatemode), 0, 160, draw.white)\n else\n draw.string(\"Fixed Mode (Zoom: \"..zoom..\")\", 0, 160, draw.white)\n end\n draw.string(\"Frames Drawn Last Second: \"..(framesLastSecond or framesThisSecond), 0, 128, draw.white)\n draw.endframe()\n framesThisSecond = framesThisSecond + 1\nend"}
|
|