|
Post by Tag365 on Jun 30, 2015 17:54:22 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","Example3.lua":"Example1 = true\nrequire \"main\"\nlocal Ren = Renderer.new()\nlocal Map\nlocal rotatemode = 0\nlocal zoom = 1\nlocal rx, ry, rz = -32, 90, 0\n\nlocal buttonTitles = {\n \"Reset Camera\",\n}\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dCamX, dCamY, dCamZ = -248, 1171, 0\nlocal dRx, dRy, dRz = rx, ry, rz\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\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)\n--Ren: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\n -- Check button tapped\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 1 then\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\n -- Draw the frame\n --Ren.setCameraAngle(math.random()*100, 0, 0)\n draw.beginframe()\n draw.clear(draw.black)\n local size = 138\n local r = 1\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\n\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\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\n -- Draw info about the current camera mode.\n local camMode = \"Fixed Mode (Angle: \"..(zoom*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\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","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","ProjectionSpeed.lua":"Example1 = true\nrequire \"main\"\n\nlocal Ren = Renderer.new()\nlocal random = math.random\n\nlocal Random = function(value)\n return (random() - .5)*value*2\nend\n\ndraw.setscreen(0)\nprint(\"Performing test...\")\nlocal oldtime = sys.gettime()\nlocal Project3D = Renderer.Project3D\nfor ilteration = 1, 100000 do\n Project3D(Ren, Random(20000), Random(20000), Random(20000))\nend\nlocal newtime = sys.gettime()\n\nprint(\"Test completed in \"..(newtime - oldtime)..\" seconds.\")","Example5.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\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 = BasicMeshes.newCube(48)--ExampleMesh.new(10, 0, 0, 0)\nlocal Mesh2 = BasicMeshes.newCube(48)\nCubeMesh:AttachPoint(Mesh2, 2, 1, 2, 1)\nMesh2:Shift(0, 48, 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:setCameraFOV(angle*45)\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)\n--Ren:setAntiAlias(true)\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\n-- Start an intentional infinite loop\nwhile true do\n -- Update the frame counter.\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\n -- Check which button was 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), 1+ (tappedSide*.1), 1 + (tappedSide*.1))\n elseif buttonTapped == 3 then\n CubeMesh = BasicMeshes.newCube(48)\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\n -- If needed, shift the cube.\n if shiftX or shiftY or shiftZ then\n CubeMesh:Shift(shiftX*.1, shiftY*.1, shiftZ*.1)\n end\n\n -- Draw the frame\n color = 1\n draw.beginframe()\n draw.clear(draw.black)\n\n -- Start drawing 3D elements.\n -- Draw the cube to the screen.\n CubeMesh:Draw(Ren)\n\n -- Draw a floor.\n drawFloor(256, 0, 0, 0, draw.green)\n\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\n -- Draw an image located in a 3D world.\n --Ren:DrawSprite(\"@resources\/SomeTile.png\", Vector3.new(0, 20, 600), 24)\n\n -- Draw a string above a 3D point.\n Ren:DrawString(\"Tap the screen to change camera mode\", Vector3.new(0, 100, 0), 16, draw.blue)\n\n -- Now we have to actually draw to the screen using the DrawQueueToScreen function.\n if (framesLastSecond or framesThisSecond) == 0 then\n local tab = Ren:DrawQueueToScreen()\n print(\"-- Drawing... --\")\n for k, v in pairs(tab) do\n print(v..\" \"..k..\" objects\")\n end\n else\n Ren:DrawQueueToScreen()\n end\n\n -- Draw the buttons to the screen.\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\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\n -- Draw info about 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\n -- Finally, draw the current Frames Per Second.\n draw.string(\"FPS: \"..(framesLastSecond or framesThisSecond)..\" frames\", 0, 128, draw.white)\n draw.string(\"RAM used: \".. collectgarbage(\"count\")*1024 ..\" bytes\", 0, 180, draw.white)\n draw.endframe()\n\n\n framesThisSecond = framesThisSecond + 1\nend","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 checkValidArgType(Color, {\"Color\", \"Texture\"}, 2)\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 checkValidArgType(x, \"number\", 1)\n checkValidArgType(z, \"number\", 2)\n checkValidArgType(Height, \"number\", 3)\n checkValidArgType(Material, \"number\", 4)\n self.heightmap[x][z] = {Height, Material}\nend\n\n-- Sets a region of cells to the height and material.\nfunction Heightmap:SetCells(x1, z1, x2, z2, Height, Material)\n checkValidArgType(x1, \"number\", 1)\n checkValidArgType(z1, \"number\", 2)\n checkValidArgType(x2, \"number\", 3)\n checkValidArgType(z2, \"number\", 4)\n checkValidArgType(Height, \"number\", 5)\n checkValidArgType(Material, \"number\", 6)\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 checkValidArgType(Height, \"number\", 1)\n checkValidArgType(Material, \"number\", 2)\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 checkValidArgType(low, \"number\", 1)\n checkValidArgType(high, \"number\", 2)\n seed = seed or (sys.gettime()*2000)\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 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 end\n end\n end\n end\n end\nend\n\n-- This function draws the heightmap.\nfunction Heightmap:Draw(Ren)\n checkValidArgType(Ren, \"Renderer\", 1)\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\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 = BasicMeshes.newCube(48)--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:setCameraFOV(angle*45)\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)\n--Ren:setAntiAlias(true)\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\n-- Start an intentional infinite loop\nwhile true do\n -- Update the frame counter.\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\n -- Check which button was 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), 1+ (tappedSide*.1), 1 + (tappedSide*.1))\n elseif buttonTapped == 3 then\n CubeMesh = BasicMeshes.newCube(48)\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\n -- If needed, shift the cube.\n if shiftX or shiftY or shiftZ then\n CubeMesh:Shift(shiftX*.1, shiftY*.1, shiftZ*.1)\n end\n\n -- Draw the frame\n color = 1\n draw.beginframe()\n draw.clear(draw.black)\n\n -- Start drawing 3D elements.\n -- Draw the cube to the screen.\n CubeMesh:Draw(Ren)\n\n -- Draw a floor.\n drawFloor(256, 0, 0, 0, draw.green)\n\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\n -- Draw an image located in a 3D world.\n --Ren:DrawSprite(\"@resources\/SomeTile.png\", Vector3.new(0, 20, 600), 24)\n\n -- Draw a string above a 3D point.\n Ren:DrawString(\"Tap the screen to change camera mode\", Vector3.new(0, 100, 0), 16, draw.blue)\n\n -- Now we have to actually draw to the screen using the DrawQueueToScreen function.\n if (framesLastSecond or framesThisSecond) == 0 then\n local tab = Ren:DrawQueueToScreen()\n print(\"-- Drawing... --\")\n for k, v in pairs(tab) do\n print(v..\" \"..k..\" objects\")\n end\n else\n Ren:DrawQueueToScreen()\n end\n\n -- Draw the buttons to the screen.\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\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\n -- Draw info about 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\n -- Finally, draw the current Frames Per Second.\n draw.string(\"FPS: \"..(framesLastSecond or framesThisSecond)..\" frames\", 0, 128, draw.white)\n draw.string(\"RAM used: \".. collectgarbage(\"count\")*1024 ..\" bytes\", 0, 180, draw.white)\n draw.endframe()\n\n\n framesThisSecond = framesThisSecond + 1\nend","3DRenderer.lua":"if not Example1 then require \"Example1\" end\nlocal 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\nlocal max, min, rad, floor = math.max, math.min, math.rad, math.floor\nlocal cos, sin = math.cos, math.sin\nlocal pairs, ipairs = pairs, ipairs\nlocal type = type\nlocal setmetatable = setmetatable\nlocal insert = table.insert\n\n-- Returns a new renderer object.\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.textureResolution = 16\n self.textureDetail = 480\n self.render = {}\n self.lastRenderCache = {}\n self.perspective = true\n return self\nend\n\nlocal camorx, camory, camorz = 0, 0, 0\ncamorx, camory, camorz = rad(camorx), rad(camory), rad(camorz)\nlocal camvx, camvy, camvz = sin(camorx), cos(camory), camorz\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 = cos(zangle)\nlocal zsin = sin(zangle)\n\n-- Sets the maximum render distance of the\n-- camera. This will cut off the rendering of\n-- polygons farther away than this point.\nfunction Renderer:setCameraRenderDistance(value)\n checkValidArgType(value, \"number\", 1)\n self.maxRange = max(value, 0)\nend\n\n-- Sets the Anti-Alias feature of the renderer.\n-- By default Anti-Alias is disabled.\nfunction Renderer:setAntiAlias(value)\n checkValidArgType(value, \"boolean\", 1)\n self.antialiased = value\nend\n\n-- Sets the camera into Perspective or\n-- Graph mode.\nfunction Renderer:setDrawMode(value)\n if string.lower(tostring(value)) == \"perspective\" then\n value = true\n end\n self.perspective = value\nend\n\n-- Sets the camera zoom.\nfunction Renderer:setCameraZoom(value)\n checkValidArgType(value, \"number\", 1)\n self.unit = value\nend\n\n-- Sets the camera's field of view angle.\nfunction Renderer:setCameraFOV(value)\n checkValidArgType(value, \"number\", 1)\n self.angle = max(value\/45, 1\/90)\nend\n\n-- Sets the position of the camera.\nfunction Renderer:setCameraPosition(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n -- Set the camera position\n self.camx, self.camy, self.camz = x, y, z\nend\n\n-- Sets the camera rotation.\nfunction Renderer.setCameraRotation(self, x, y, z)\n if type(self) ~= Renderer.classtype then\n x, y, z = self, x, y\n self = nil\n end\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n\n if self then\n self.camrotx, self.camroty, self.camrotz = x, y, z\n end\n -- Set the camera rotation\n camorx, camory, camorz = rad(x), rad(y), rad(z)\n camvx, camvy, camvz = sin(camorx), cos(camory), camorz\n\n cosx, cosy, cosz = cos(camorx), cos(camory), cos(camorz)\n sinx, siny, sinz = sin(camorx), sin(camory), sin(camorz)\nend\n\n-- Returns the current camera position.\nfunction Renderer:GetCameraRotation()\n return camorx, camory, camorz\nend\n\n-- Transforms a 3D position to the renderer's viewpoint.\nfunction Renderer:Transform3D(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n -- Transform the value.\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\n -- Transform the 3D position.\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\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 return dx, dy, 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-- 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\n -- Transform the 3D position.\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\n\n -- Determine if the camera is perspective or not.\n if self.perspective then\n -- Use the perspective drawing mode\n local complex = cosy*zs + siny*(sinz*ys + cosz*xs)\n local dx = cosy*(sinz*ys + cosz*xs) - siny*zs\n local dy = sinx*(complex) + cosx*(cosz*ys - sinz*xs)\n local dz = cosx*(complex) - sinx*(cosz*ys - sinz*xs)\n local ezdivdz = ez\/dz\n\n -- Calculate position to draw at\n local bx = ezdivdz*dx - ex\n local by = ezdivdz*dy - ey\n local bz = ezdivdz*(ez - dz)\n return bx + (width*.5 + (self.angle*10)), 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\n-- polygon to be drawn to the screen. To draw\n-- queued 3D elements call\n-- 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\n-- drawn by the renderer.\nfunction Renderer:DrawTriangle(point1, point2, point3, color, outline)\n self.render[#self.render + 1] = {outline and \"TriangleOutline\" or \"Triangle\", 0, point1, point2, point3, color}\nend\n\n-- Queues a three dimensional line to be drawn.\nfunction Renderer:DrawLine(point1, point2, color, width)\n self.render[#self.render + 1] = {\"Line\", width or 2, 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\/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\n-- Localize some variables for faster operation\nlocal filltriangle = draw.filltriangle\nlocal triangle = draw.triangle\nlocal Project3D = Renderer.Project3D\n\n-- This function draws queued 3D elements to the screen.\nfunction Renderer:DrawQueueToScreen()\n local minz, maxz = 240*self.angle, self.angle*self.maxRange\n local objectsDrawn = {}\n local order = {}\n\n -- Set up queued elements.\n for k, v in ipairs(self.render) do\n --objectsDrawn[v[1]] = (objectsDrawn[v[1]] or 0) + 1\n if v[1] == \"Polygon\" or v[1] == \"PolygonOutline\" then\n -- Draw two triangles.\n -- Get the ordered points of this\n -- polygon.\n local p1, p2, p3, p4 = v[3], v[4], v[5], v[6]\n -- Transform the coordinates of this\n -- polygon.\n local x1, y1, zvalue = Project3D(self, p1:raw())\n --if zvalue <= minz then goto SkipElement end\n local x2, y2, zvalue2 = Project3D(self, p2:raw())\n local x3, y3, zvalue3 = Project3D(self, p3:raw())\n local x4, y4, zvalue4 = Project3D(self, p4:raw())\n -- Determine the Z value of this\n -- polygon.\n local zvalueLow = min(zvalue, zvalue2, zvalue3, zvalue4)\n local zvalueHigh = max(zvalue, zvalue2, zvalue3, zvalue4)\n zvalue = zvalueLow + ((zvalueHigh - zvalueLow)*.75)\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 if v[7].classtype == \"Color\" and self.FogEnabled then\n v[7] = v[7]*min((96 + p1.y)\/128, 1)*min((maxz - zvalueLow)\/(.5*maxz), 1)\n end\n order[zvalue][#order[zvalue] + 1] = {v[1], x1, y1, x2, y2, x3, y3, x4, y4, v[7]}--, v[7]*min((p1.y + 96)\/128, 1)*min((maxz - zvalueHigh)\/(maxz \/ 2), 1)}\n end\n elseif v[1] == \"Triangle\" or v[1] == \"TriangleOutline\" then\n -- Draw a triangle.\n local p1, p2, p3 = v[3], v[4], v[5]\n local x1, y1, zvalue = Project3D(self, p1:raw())\n local x2, y2, zvalue2 = Project3D(self, p2:raw())\n local x3, y3, zvalue3 = Project3D(self, p3:raw())\n local zvalueLow = min(zvalue, zvalue2, zvalue3)\n local zvalueHigh = max(zvalue, zvalue2, zvalue3)\n zvalue = zvalueLow + (.75*(zvalueHigh - zvalueLow))\n if zvalueLow > minz and zvalueHigh <= maxz then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n -- Add fog to the color\n if v[6].classtype == \"Color\" and self.FogEnabled then\n v[6] = v[6]*min((96 + p1.y)\/128, 1)*min((maxz - zvalueLow)\/(.5*maxz), 1)\n end\n order[zvalue][#order[zvalue] + 1] = {v[1], x1, y1, x2, y2, x3, y3, v[6]}\n end\n elseif v[1] == \"Sprite\" then\n -- Draw a two dimensional sprite.\n local p1 = v[3]\n local x1, y1, zvalue = Project3D(self, 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 - (.05*zvalue)*v[4])\/96}\n end\n elseif v[1] == \"String\" then\n -- Draw a string.\n local p1 = v[3]\n local x1, y1, zvalue = Project3D(self, p1:raw())\n if zvalue > minz 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\n -- Draw a line.\n local p1, p2 = v[3], v[4]\n local x1, y1, zvalue = Project3D(self, p1:raw())\n local x2, y2, zvalue2 = Project3D(self, p2:raw())\n local zvalueLow = min(zvalue, zvalue2)\n local zvalueHigh = 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], v[2]}\n end\n end\n --::SkipElement::\n end\n draw.setantialias(self.antialiased or false)\n\n -- Draw queued elements to screen.\n local dOrder = {}\n local sOrder = {}\n -- We must create a sorted table, otherwise\n -- ipairs will not work.\n -- We can't use pairs because it will\n -- ilterate in a jacked up order that is not\n -- perspective correct.\n for k, v in pairs(order) do\n if #sOrder == 0 then\n sOrder[1] = k\n else\n local inserted = false\n for k2, v2 in ipairs(sOrder) do\n if k > v2 then\n insert(sOrder, k2, k)\n inserted = true\n break\n end\n end\n if not inserted then\n sOrder[#sOrder + 1] = k\n end\n end\n end\n for k = 1, #sOrder do\n dOrder[k] = order[sOrder[k]]\n end\n\n -- We now will actually draw elements to the\n -- screen.\n --for k, v in ipairs(dOrder) do\n for k = 1, #dOrder do\n --for k2, v2 in ipairs(v) do\n for k2, v2 in ipairs(dOrder[k]) 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 col.classtype == \"Texture\" then\n res = max(floor(self.textureResolution), 1)\n draw.texturedTriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n draw.texturedTriangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], col)\n else\n filltriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n filltriangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], col)\n if self.antialiased then\n triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n 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 triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[10])\n triangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], v2[10])\n elseif v2[1] == \"Triangle\" then\n filltriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[8])\n elseif v2[1] == \"TriangleOutline\" then\n triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[8])\n elseif v2[1] == \"Sprite\" then\n --[==[if not imageCache[v2[2]] then\n imageCache[v2[2]] = {draw.cacheimage(v2[2])}\n end]==]\n local x, y = imageCache[v2[2]][1], imageCache[v2[2]][2]\n if v2[3] + v2[5]*x > 0 and v2[3] - v2[5]*x < width and v2[4] + v2[5]*y > 0 and v2[4] - v2[5]*y < height then\n draw.transformedimage(v2[2], v2[3], v2[4], v2[5], camorz)\n end\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(v2[7], \"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.lastRenderCache = self.render\n self.render = {}\n return objectsDrawn\nend\n\nfunction Renderer:GetTappedVector3(x, y)\n local range = 20\n for key, v in ipairs(self.lastRenderCache) do\n if v[1] == \"Polygon\" then\n local p1, p2, p3, p4 = v[3], v[4], v[5], v[6]\n local x1, y1 = self:Project3D(p1:raw())\n local x2, y2 = self:Project3D(p2:raw())\n local x3, y3 = self:Project3D(p3:raw())\n local x4, y4 = self:Project3D(p4:raw())\n if math.abs(x - x1) < range and math.abs(y - y1) < range then\n return p1\n end\n if math.abs(x - x2) < range and math.abs(y - y2) < range then\n return p2\n end\n if math.abs(x - x3) < range and math.abs(y - y3) < range then\n return p3\n end\n if math.abs(x - x4) < range and math.abs(y - y4) < range then\n return p4\n end\n end\n end\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 angle = 1\nlocal rx, ry, rz = 0, 0, 0\n\nlocal buttonTitles = {\n \"Reset Camera\",\n}\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dCamX, dCamY, dCamZ = 10, 10, 32\nlocal dRx, dRy, dRz = rx, ry, rz\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\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*.2, oldy + my*.2\n elseif rotatemode == 2 then\n Ren.camx, Ren.camz = oldx + mx*.2, oldz + my*.2\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*45\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*45)\nRen.setCameraRotation(rx, ry, rz)\nRen:setCameraPosition(dCamX, dCamY, dCamZ)\nRen:setDrawMode(true)\nRen:setAntiAlias(false)\n\n-- Set up the Terrain object.\nTerrain:SetSavingLocation()\nTerrain:LoadChunk(0,0,0)\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\nlocal ok, err = xpcall(function() while 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\n -- Check button tapped\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 1 then\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\n -- Draw the frame\n draw.beginframe()\n draw.clear(draw.black)\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 if not Terrain:GetChunk(-math.floor(Ren.camx+2\/4), -math.floor(Ren.camy+2\/4), -math.floor(Ren.camz+2\/4)) then\n Terrain:LoadChunk(-math.floor(Ren.camx+2\/4), -math.floor(Ren.camy+2\/4), -math.floor(Ren.camz+2\/4))\n end\n Terrain:Draw(Ren, -math.floor(Ren.camx+2\/4), -math.floor(Ren.camy+2\/4), -math.floor(Ren.camz+2\/4))\n Ren:DrawQueueToScreen()\n\n\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\n\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\n -- Draw info about the current camera mode.\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\n\n draw.string(\"Frame Rate: \"..(framesLastSecond or framesThisSecond), 0, 128, draw.white)\n draw.string(camMode or \"\", 0, 160, draw.white)\n if Terrain:IsGeneratingTerrain() then\n draw.string(\"Generating terrain\"..string.rep(\".\", (os.clock()*4)%3), 0, 192, draw.blue)\n end\n draw.endframe()\n framesThisSecond = framesThisSecond + 1\n end\nend, function(str)\n return str..\"\\n\"..debug.traceback()\nend)\nerror(err, 0)","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\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\nfunction Color.random(alpha)\n return Color.new(math.random()*255, math.random()*255, math.random()*255, alpha or 255)\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 if self.alpha < 1 then\n return \"Color: red \"..math.floor(self.red*255)..\", green \"..math.floor(self.green*255)..\", blue \"..math.floor(self.blue*255)..\", opacity \"..math.floor(self.alpha*255)\n else\n return \"Color: red \"..math.floor(self.red*255)..\", green \"..math.floor(self.green*255)..\", blue \"..math.floor(self.blue*255)\n end\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)\n return setmetatable({red = self.red*other.red, green = self.green*other.green, blue = self.blue*other.blue, alpha = self.alpha}, Color)\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 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","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 mesh.\nMesh.new = function()\n local self = setmetatable({}, Mesh)\n self.mesh = {}\n self.attachedPoints = {}\n self.defaultColor = draw.blue\n self.shift = Vector3.new(0, 0, 0)\n self.rotation = 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) ~= \"Color\" and type(Color) ~= \"Texture\" 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\n-- Adds a filled cube to the mesh.\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\n-- Adds a holow tube of faces to the mesh.\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.\n-- Arguments: number PolygonID.\nfunction Mesh:RemovePolygon(PolygonID)\n checkValidArgType(PolygonID, \"number\", 1)\n table.remove(self.mesh, PolygonID)\nend\n\n-- Sets the color of a polygon.\n-- Arguments: number PolygonID, color color.\nfunction Mesh:SetPolygonColor(PolygonID, color)\n self.mesh[PolygonID][5] = color\nend\n\n-- Scales the mesh.\n-- Arguments: Vector3 or numbers x, y, z\nfunction Mesh:Scale(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n\n -- Scale the mesh.\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's position.\n-- Arguments: Vector3 or numbers x, y, z.\nfunction Mesh:Shift(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n -- Add the shift by value to this mesh.\n self.shift = self.shift + Vector3.new(x, y, z)\n local move = Vector3.new(x, y, z)\n -- Move all of the mesh's points.\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n v = v + move\n end\n end\nend\n\n-- Moves the mesh to a selected point.\n-- Arguments: Vector3 or numbers x, y, z.\nfunction Mesh:MoveTo(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n local shift = Vector3.new(x, y, z) - self.shift\n -- Shift the mesh using the shift function\n self:Shift(shift)\nend\n\n-- Rotates the mesh on the XY axis.\nfunction Mesh:RotateXY(degrees)\n checkValidArgType(degrees, \"number\", 1)\n -- Shift the mesh to the center of the\n -- world.\n local x, y, z = self.shift:raw()\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n -- Rotate the polygons on the mesh.\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 -- Return the mesh to the correct position.\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n -- Update the rotation vector.\n self.rotation.x = self.rotation.x + degrees\nend\n\n-- Rotates the mesh on the XZ axis.\n-- Arguments: number degrees\nfunction Mesh:RotateXZ(degrees)\n checkValidArgType(degrees, \"number\", 1)\n -- Shift the mesh to the center of the\n -- world.\n local x, y, z = self.shift:raw()\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n -- Rotate the polygons on the mesh.\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 -- Return the mesh to the correct position.\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n self.rotation.y = self.rotation.y + degrees\nend\n\n-- Rotates the mesh on the YZ axis.\nfunction Mesh:RotateYZ(degrees)\n checkValidArgType(degrees, \"number\", 1)\n -- Shift the mesh to the center of the\n -- world.\n local x, y, z = self.shift:raw()\n x, y, z = -x, -y, -z\n self:Shift(x, y, z)\n -- Rotate the polygons on the mesh.\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 -- Return the mesh to the correct position.\n x, y, z = -x, -y, -z\n shift:Shift(x, y, z)\n self.rotation.z = self.rotation.z + degrees\nend\n\nfunction Mesh:AttachPoint(OtherMesh, PolygonID1, Point1, PolygonID2, Point2)\n self.attachedPoints[#self.attachedPoints + 1] = {OtherMesh, PolygonID1, Point1, PolygonID2, Point2}\nend\n\n-- Draws a mesh.\nfunction Mesh:Draw(Renderer)\n checkValidArgType(Renderer, \"Renderer\", 1)\n for k, v in ipairs(self.attachedPoints) do\n local otherMesh = v[1]\n self.mesh[v[2]][v[3]] = otherMesh.mesh[v[4]][v[5]]\n end\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\n-- Gets the closest point.\nfunction Mesh:GetClosestPoint(Vector)\n local closestDistance = 2000\n local closePoint\n for k, v in pairs(self.mesh) do\n for i=1, 4 do\n local distance = v - Vector\n if closestDistance < distance:magnitude() then\n closepoint = {k, i}\n end\n end\n end\n if closepoint then\n return closepoint[1], closepoint[2]\n end\n return false\nend\n\nreturn Mesh","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","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, math.sin\nlocal rad = math.rad\nlocal setmetatable = setmetatable\nlocal type = type\n\n-- This function constructs a new object of this type.\nVector3.new = function(x, y, z)\n return setmetatable({x = x, y = y, z = z}, Vector3)\nend\n\nlocal new = Vector3.new\n\n-- Adds a vector to this vector.\nfunction Vector3:AddVectorToVector(vector2)\n return new(self.x + vector2.x, self.y + vector2.y, self.z + vector2.z)\nend\n\n-- Subtracts a vector from this vector.\nfunction Vector3:SubtractVectorFromVector(vector2)\n return new(self.x - vector2.x, self.y - vector2.y, self.z - vector2.z)\nend\n\n-- Multiplies a vector by this vector.\nfunction Vector3:MultiplyVectorByVector(vector2)\n return new(self.x * vector2.x, self.y * vector2.y, self.z * vector2.z)\nend\n\n-- Divides a vector by this vector.\nfunction Vector3:DivideVectorByVector(vector2)\n return new(self.x \/ vector2.x, self.y \/ vector2.y, self.z \/ vector2.z)\nend\n\n-- Gets the magnitude of a Vector3.\nfunction Vector3:magnitude()\n return self.x + self.y + self.z\nend\n\n-- Gets the unit of a Vector3.\nfunction Vector3:unit()\n local maxv = math.max(self.x, self.y, self.z)\n return new(self.x\/maxv, self.y\/maxv, self.z\/maxv)\nend\n\n-- Gets the mass of a Vector3.\nfunction Vector3:mass(vector3)\n vector3 = vector3 or new(0, 0, 0)\n return (vector3.x - self.x)*(vector3.y - self.y)*(vector3.z - self.z)\nend\n\n-- The rotation functions should return a vector.\n\n-- Rotates a vector around all three dimensions.\nfunction Vector3:rotate(vector3)\n local output = new(self.x, self.y, self.z)\n output = output:rotateXY(vector3.x)\n output = output:rotateYZ(vector3.y)\n return output:rotateXZ(vector3.z)\nend\n\n-- Rotates a vector around the XY plane.\nfunction Vector3:rotateXY(degrees)\n local output = new(self.x, self.y, self.z)\n local radians = 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(degrees)\n local output = new(self.x, self.y, self.z)\n local radians = 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(degrees)\n local output = new(self.x, self.y, self.z)\n local radians = 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(s0, s1, s2)\n local output = 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()\n return self.x, self.y, self.z\nend\n\n-- Set up metatables.\nVector3.__tostring = function(self)\n if self.x then\n return \"Vector3: x \"..(math.floor(self.x*100000)\/100000)..\", y \"..(math.floor(self.y*100000)\/100000)..\", z \"..(math.floor(self.z*100000)\/100000)\n end\n return self.classtype\nend\nVector3.__concat = function(self, other)\n return (\"Vector3: x \"..(math.floor(self.x*100000)\/100000)..\", y \"..(math.floor(self.y*100000)\/100000)..\", z \"..(math.floor(self.z*100000)\/100000))..other\nend\n\n-- Math functions.\nVector3.__add = function(self, other)\n if type(other) == \"number\" then\n return new(self.x + other, self.y + other, self.z + other)\n elseif GetObjectType(other) ~= \"Vector3\" then\n return self\n end\n return self:AddVectorToVector(other)\nend\nVector3.__sub = function(self, other)\n if type(other) == \"number\" then\n return new(self.x - other, self.y - other, self.z - other)\n elseif 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 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 new(self.x\/other, self.y\/other, self.z\/other)\n end\n return self\n end\n return self:DivideVectorByVector(other)\nend\nVector3.__pow = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n if type(other) == \"number\" then\n return new(self.x^other, self.y^other, self.z^other)\n end\n return self\n end\n return new(self.x^other.x, self.y^other.y, self.z^other.z)\nend\nVector3.__mod = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n if type(other) == \"number\" then\n return new(self.x%other, self.y%other, self.z%other)\n end\n return self\n end\n return new(self.x%other.x, self.y%other.y, self.z%other.z)\nend\nVector3.__unm = function(self)\n return new(-self.x, -self.y, -self.z)\nend\n\nVector3.__len = function(self)\n return self.x + self.y + self.z\nend\n\n-- Comparison functions.\nVector3.__eq = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return false\n end\n return (self.x == other.x and self.y == other.y and self.z == other.z) or false\nend\nVector3.__lt = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return false\n end\n return (self.x < other.x and self.y < other.y and self.z < other.z) or false\nend\nVector3.__le = function(self, other)\n if GetObjectType(other) ~= \"Vector3\" then\n return false\n end\n return (self.x <= other.x and self.y <= other.y and self.z <= other.z) or false\nend\n\nreturn Vector3","Export.lua":"print('Generating Installer Stubs!')\nlocal FileTable = {}\n\nfunction requireFromRoot(File)\n local Handle, err = io.open(\"..\/\"..File..\".lua\")\n local String, Funct = \"\", nil\n if Handle then\n String = \"require = requireFromRoot\\n\"..Handle:read(\"*a\")\n Handle:close()\n Funct = load(String)\n end\n --local Funct, err = loadfile(\"..\"..File..\".lua\")\n if Funct then\n local var1 = Funct()\n require = Require\n return var1 or true\n else\n print(err)\n end\nend\n\nlfs = require \"lfs\"\n\nJSON = require(\"JSON\")\nlocal files = sys.dir()\n\nfunction lfs.isDirectory(Path)\n return lfs.attributes(Path, \"mode\") == \"directory\"\nend\n\nfor k, v in ipairs(files) do\n if v ~= \".\" and v ~= \"..\" and v ~= \"InstallStub\" and v~= \"SavedData\" then\n if lfs.isDirectory(v) then\n local sub = sys.dir(v)\n for k2, v2 in ipairs(sub) do\n if v2 ~= \".\" and v2 ~= \"..\" and string.sub(v, -8)~=\"stub.lua\" then\n files[#files + 1] = v..\"\/\"..v2\n end\n end\n end\n end\nend\n\nfor k, v in ipairs(files) do\n if v ~= \".\" and v ~= \"..\" and string.sub(v, -8)~=\"stub.lua\" then\n local file = io.open(v)\n if file then\n FileTable[v] = file:read(\"*a\")\n file:close()\n end\n end\nend\n\n\nlocal String = JSON.EncodeJSON(FileTable)\nprint(#String..\" bytes\")\n\nif not lfs.isDirectory(\"InstallStub\") then\n lfs.mkdir(\"InstallStub\")\nend\n\nprint(\"Saving...\")\nlocal Chunk = 8192*16\nfor i=1, math.ceil(#String\/Chunk) do\n file = io.open(\"InstallStub\/Lua3D\".. i..\"stub.lua\", \"w\")\n file:write(string.sub(String, ((i - 1)*Chunk) + 1, math.min(i*Chunk, #String)))\n file:close()\nend\nprint(\"Done!\")","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","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","main.lua":"Lua3D = {Version = 1.10, VersionStr = \"1.1.0\"}\nif not imageCache then imageCache = {} end\nlocal oldType = type\ndraw.setscreen(1)\nwidth, height = draw.getport()\n\n-- Replace the original type with something that will also return the type of an object.\nfunction GetObjectType(object)\n if oldType(object) ~= \"table\" then\n return oldType(object)\n elseif not object.classtype then\n return oldType(object)\n end\n return object.classtype\nend\ntype = GetObjectType\nrawtype = oldType\n\nfunction checkValidArgType(value, types, num)\n local throwError = true\n if type(types) == \"table\" then\n for k, v in ipairs(types) do\n if type(value) == v then\n throwError = false\n break\n end\n end\n else\n throwError = type(value) ~= types\n end\n -- If we need to throw an error do it\n -- similar to how lua functions error\n if throwError then\n local tab = debug.getinfo(2,\"n\")\n tab.name = tab.name or \"function\"\n local str = \"bad argument #\"..num..\" to '\"..tab.name..\"' (\"\n if type(types) == \"table\" then\n local lastType = types[#types]\n types[#types] = nil\n if #types > 1 then\n str = str..table.concat(types, \",\")..\",\"\n elseif #types > 0 then\n str = str..types[1]\n else\n str = str..lastType\n end\n if #types > 0 then\n str = str..\" or \"..lastType\n end\n else\n str = str..types\n end\n str = str..\" expected, got \"..type(value)..\")\"\n error(str, 3)\n end\nend\n\nColor = require \"Color\"\nVector3 = require \"Vector3\"\nRegion3 = require \"Region3\"\nRenderer = require \"3DRenderer\"\nMesh = require \"3DMesh\"\nObject3D = require \"3DObject\"\nBasicMeshes = require \"BasicMeshes\"\nHeightmap = require \"TerrainHeightmap\"\nTerrainMesh = require \"TerrainMesh\"\n\nRenderer.maxRange = 18000\nHeightmap.LODTable = {2, 4, 8, 16, 32, 64}\nlocal doNothing = function() end\n\nif not pcall(draw.tracktouches, doNothing, doNothing, doNothing) then\n function draw.tracktouches(x, y, z)\n draw.touchbegan = function(d)\n for k = 1, #d do\n x(d[k].x, d[k].y)\n end\n end\n draw.touchmoved = function(d)\n for k = 1, #d do\n y(d[k].x, d[k].y)\n end\n end\n draw.touchended = function(d)\n for k = 1, #d do\n z(d[k].x, d[k].y)\n end\n end\n end\nend\nprint(\"Lua3D Version \"..Lua3D.VersionStr..\" loaded.\")","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\"\n\nTerrain.savePath = \"TerrainData\/\"\nlocal defExt = 33554432\nlocal chunkSize = 4\n\nlocal lfs = require \"lfsplus\"\n\n-- Variables\nlocal nCellMaterial = 1\nlocal nCellBlock = 2\nlocal nCellOrientation = 3\n\n-- Default Terrain Materials --\nTerrain.Materials = {}\n\nTerrain.Liquids = {}\n\nlocal yield = function(...)\n local args = {pcall(coroutine.yield, ...)}\n table.remove(args, 1)\n return table.unpack(args)\nend\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.renderDegraded = {}\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 self:CreateNewMaterial(2, draw.blue)\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[#self.materials + 1] = 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\nfunction Terrain:File(x, y, z)\n return self.savePath..\"X\"..x..\"Y\"..y..\"Z\"..z\nend\n\n-- Terrain Teraforming Functions --\nfunction Terrain:GenerateHeightmap(x, z)\n local heightmap = {}\n for xb = 1, chunkSize do\n heightmap[xb] = {}\n for zb = 1, chunkSize do\n heightmap[xb][zb] = math.random(0, 8)\n end\n end\n return heightmap\nend\n\n-- This function is used to generate a chunk of terrain.\nfunction Terrain:GenerateChunk(x, y, z)\n local chunk = {}\n local heightmap = self:GenerateHeightmap(x, z)\n for yb = 1, chunkSize do\n chunk[yb] = {}\n for xb = 1, chunkSize do\n chunk[yb][xb] = {}\n for zb = 1, chunkSize do\n chunk[yb][xb][zb] = {\n ((yb + y*chunkSize) > heightmap[xb][zb] and math.random (1, 3)) or 0, 1, 0}\n end\n end\n end\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] = chunk\n return chunk\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 = self:GetChunk(x\/chunkSize, y\/chunkSize, z\/chunkSize)\n x, y, z = x - (math.floor(x\/chunkSize)*chunkSize) + 1, y - (math.floor(y\/chunkSize)*chunkSize) + 1, z - (math.floor(z\/chunkSize)*chunkSize) + 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 = self:GetChunk(x\/chunkSize, y\/chunkSize, z\/chunkSize)\n x, y, z = x - (math.floor(x\/chunkSize)*chunkSize) + 1, y - (math.floor(y\/chunkSize)*chunkSize) + 1, z - (math.floor(z\/chunkSize)*chunkSize) + 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\nfunction Terrain:GetChunkCorner(x, y, z)\n return x*chunkSize + 1, y*chunkSize + 1, z*chunkSize + 1\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 if not self.chunks[y][x][z] then\n self:LoadChunkRaw(x, y, z)\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 if not self.chunks then\n error(\"This can only be used on objects\", 2)\n end\n local Chunk = self:GetChunk(x\/chunkSize, y\/chunkSize, z\/chunkSize)\n if not Chunk then return 0,0,0 end\n local CellY = Chunk[y - (math.floor(y\/chunkSize)*chunkSize) + 1]\n local CellX = CellY[x - (math.floor(x\/chunkSize)*chunkSize) + 1]\n local Cell = CellX[z - (math.floor(z\/chunkSize)*chunkSize) + 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 = self:GetChunk(x\/chunkSize, y\/chunkSize, z\/chunkSize)\n local CellY = Chunk[y - (math.floor(y\/chunkSize)*chunkSize) + 1]\n local CellX = CellY[x - (math.floor(x\/chunkSize)*chunkSize) + 1]\n local Cell = CellX[z - (math.floor(z\/chunkSize)*chunkSize) + 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 --\nfunction sortTable(val1, val2)\n return val2[1] > val1[1]\nend\n\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] = {} self.renderDegraded[y] = {} end\n if not self.render[y][x] then self.render[y][x] = {} self.renderDegraded[y][x] = {} end\n local drawChunk = {}\n local commonMaterials = {}\n local cx, cy, cz = x*chunkSize, y*chunkSize, z*chunkSize\n -- Build a renderer table.\n for yk=1, chunkSize do\n for xk=1, chunkSize do\n for zk=1, chunkSize do\n local dx, dy, dz = cx + xk, cy + yk, cz + zk\n local Cell = chunk[yk][xk][zk]\n if not commonMaterials[Cell[1]] then\n commonMaterials[Cell[1]] = {1, Cell[1]}\n else\n commonMaterials[Cell[1]][1] = commonMaterials[Cell[1]][1] + 1\n end\n if Cell[1] > 0 then\n local material, block, orientation = Cell[nCellMaterial], Cell[nCellBlock], Cell[nCellOrientation]\n local tfl, tfr, tbl, tbr, bfl, bfr, bbl, bbr = 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[nCellMaterial] == 0 then\n table.insert(drawChunk, {tfl, tfr, tbr, tbl, self:GetMaterialColor(Cell[nCellMaterial])})\n end\n if bot[nCellMaterial] == 0 then\n table.insert(drawChunk, {bfl, bfr, bbr, bbl, self:GetMaterialColor(Cell[nCellMaterial])})\n end\n if rig[nCellMaterial] == 0 then\n table.insert(drawChunk, {tfr, tbr, bbr, bfr, self:GetMaterialColor(material)})\n end\n if left[nCellMaterial] == 0 then\n table.insert(drawChunk, {tfl, tbl, bbl, bfl, self:GetMaterialColor(material)})\n end\n if fro[nCellMaterial] == 0 then\n table.insert(drawChunk, {tfl, tfr, bfr, bfl, self:GetMaterialColor(material)})\n end\n if bac[nCellMaterial] == 0 then\n table.insert(drawChunk, {tbl, tbr, bbr, bbl, self:GetMaterialColor(material)})\n end\n elseif block == 2 then -- Ramp\n\n end\n end\n end\n end\n -- Yield\n yield()\n end\n -- Do the low quality render\n table.sort(commonMaterials, sortTable)\n if commonMaterials[1] then\n local commonMaterial = commonMaterials[1][1]\n local color = self:GetMaterialColor(material)\n local degraded = {}\n local dx, dy, dz = cx, cy, cz\n local tfl, tfr, tbl, tbr, bfl, bfr, bbl, bbr = Vector3.new(dx, dy, dz), Vector3.new(dx + chunkSize, dy, dz), Vector3.new(dx, dy, dz + chunkSize), Vector3.new(dx + chunkSize, dy, dz + chunkSize), Vector3.new(dx, dy + chunkSize, dz), Vector3.new(dx + chunkSize, dy + chunkSize, dz), Vector3.new(dx, dy + chunkSize, dz + chunkSize), Vector3.new(dx + chunkSize, dy + chunkSize, dz + chunkSize)\n if commonMaterial > 0 then\n table.insert(degraded, {tfl, tfr, tbr, tbl, color})\n table.insert(degraded, {bfl, bfr, bbr, bbl, color})\n end\n end\n self.renderDegraded[y][x][z] = degraded or {}\n self.render[y][x][z] = drawChunk\nend\n\nfunction Terrain:DrawChunk(Ren, x, y, z, degra)\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, v = (degra and self.renderDegraded[y][x][z]) or self.render[y][x][z]\n for k = 1, (#render < 2000 and #render) or 2000 do\n v = render[k]\n Ren:DrawPolygon(v[1], v[2], v[3], v[4], v[5])\n end\nend\n\n-- This function draws a terrain object.\nfunction Terrain:Draw(Ren, x, y, z)\n x,y,z = x or 0, y or 0, z or 0\n self:DrawChunk(Ren, x, y, z)\n local range = 0\n for x1 = x - range, x + range do\n for y1 = y - range, y + range do\n for z1 = z - range, z + range do\n if x1 ~= x or y1 ~= y or z1 ~= z then\n self:DrawChunk(Ren, x1, y1, z1, true)\n end\n end\n end\n end\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 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, chunkSize do\n for xk=1, chunkSize do\n for zk=1, chunkSize 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 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, chunkSize do\n for xk=1, chunkSize do\n local line = file:read()\n if line then\n for zk=1, chunkSize 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*chunkSize + xk, y*chunkSize + yk, z*chunkSize + 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","RenderSpeed.lua":"Example1 = true\nrequire \"main\"\nlocal Ren = Renderer.new()\nlocal Map\nlocal rotatemode = 0\nlocal zoom = 1\nlocal rx, ry, rz = -32, 90, 0\n\nRenderer.maxRange = 24000\nHeightmap.LODTable = {256}\n\n-- Set up defaults.\nlocal dZoom = zoom\nlocal dCamX, dCamY, dCamZ = 12000, 8000, 0\nlocal dRx, dRy, dRz = rx, ry, rz\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)\nfor x = 96, 2, -2 do\n pcall(Map.SetCells, Map, -x, -x, x - 1, x - 1, x*(x*.5), 2)\nend\n\nlocal startTime = sys.gettime()\nprint(\"Drawing...\")\ndraw.setscreen(1)\ndraw.disablerefresh()\ndo\n -- Draw the frame\n --draw.beginframe()\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.settitle(\"Rendering...\")\n Map:Draw(Ren)\n draw.enablerefresh()\n draw.setrefresh(60)\n draw.settitle(\"Drawing...\")\n Ren:DrawQueueToScreen()\n --draw.endframe()\nend\nlocal endTime = sys.gettime()\nprint(\"Rendering took \"..endTime - startTime..\" seconds.\")","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","3DRendererOld.lua":"if not Example1 then require \"ProjectionSpeed\" end\nlocal 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-- Returns a new renderer object.\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.textureResolution = 16\n self.textureDetail = 480\n self.render = {}\n self.lastRenderCache = {}\n self.perspective = true\n return self\nend\n\nlocal max, min, rad, floor = math.max, math.min, math.rad, math.floor\nlocal cos, sin = math.cos, math.sin\nlocal pairs, ipairs = pairs, ipairs\n\nlocal camorx, camory, camorz = 15, 15, 15\ncamorx, camory, camorz = rad(camorx), rad(camory), rad(camorz)\nlocal camvx, camvy, camvz = sin(camorx), cos(camory), camorz\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 = cos(zangle)\nlocal zsin = sin(zangle)\n\n-- Sets the maximum render distance of the\n-- camera. This will cut off the rendering of\n-- polygons farther away than this point.\nfunction Renderer:setCameraRenderDistance(value)\n checkValidArgType(value, \"number\", 1)\n self.maxRange = max(value, 0)\nend\n\n-- Sets the Anti-Alias feature of the renderer.\n-- By default Anti-Alias is disabled.\nfunction Renderer:setAntiAlias(value)\n checkValidArgType(value, \"boolean\", 1)\n self.antialiased = value\nend\n\n-- Sets the camera into Perspective or\n-- Graph mode.\nfunction Renderer:setDrawMode(value)\n if string.lower(tostring(value)) == \"perspective\" then\n value = true\n end\n self.perspective = value\nend\n\n-- Sets the camera zoom.\nfunction Renderer:setCameraZoom(value)\n checkValidArgType(value, \"number\", 1)\n self.unit = value\nend\n\n-- Sets the camera's field of view angle.\nfunction Renderer:setCameraFOV(value)\n checkValidArgType(value, \"number\", 1)\n self.angle = max(value\/45, 1\/90)\nend\n\n-- Sets the position of the camera.\nfunction Renderer:setCameraPosition(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n -- Set the camera position\n self.camx, self.camy, self.camz = x, y, z\nend\n\n-- Sets the camera rotation.\nfunction Renderer.setCameraRotation(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n -- Set the camera rotation\n camorx, camory, camorz = rad(x), rad(y), rad(z)\n camvx, camvy, camvz = sin(camorx), cos(camory), camorz\n\n cosx, cosy, cosz = cos(camorx), cos(camory), cos(camorz)\n sinx, siny, sinz = sin(camorx), sin(camory), sin(camorz)\nend\n\n-- Returns the current camera position.\nfunction Renderer:GetCameraRotation()\n return camorx, camory, camorz\nend\n\n-- Transforms a 3D position to the renderer's viewpoint.\nfunction Renderer:Transform3D(x, y, z)\n -- Check if the argument type is valid\n checkValidArgType(x, {\"Vector3\", \"number\"}, 1)\n if type(x) == \"number\" then\n checkValidArgType(y, \"number\", 2)\n checkValidArgType(z, \"number\", 3)\n end\n -- Convert a Vector3 to raw variables.\n if type(x) == \"Vector3\" then\n x, y, z = x:raw()\n end\n -- Transform the value.\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\n -- Transform the 3D position.\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\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 return dx, dy, 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-- 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\n -- Transform the 3D position.\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\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 -- 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 + (self.angle*10)), 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\n-- polygon to be drawn to the screen. To draw\n-- queued 3D elements call\n-- 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\n-- drawn by the renderer.\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, width)\n self.render[#self.render + 1] = {\"Line\", width or 2, 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\/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\nlocal filltriangle = draw.filltriangle\nlocal triangle = draw.triangle\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 objectsDrawn = {}\n local order = {}\n -- Set up queued elements.\n for k, v in ipairs(self.render) do\n objectsDrawn[v[1]] = (objectsDrawn[v[1]] or 0) + 1\n if v[1] == \"Polygon\" or v[1] == \"PolygonOutline\" then\n -- Draw two triangles.\n -- Get the ordered points of this\n -- polygon.\n local p1, p2, p3, p4 = v[3], v[4], v[5], v[6]\n -- Transform the coordinates of this\n -- polygon.\n local x1, y1, zvalue = self:Project3D(p1:raw())\n --if zvalue <= minz then goto SkipElement end\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\n -- polygon.\n local zvalueLow = min(zvalue, zvalue2, zvalue3, zvalue4)\n local zvalueHigh = max(zvalue, zvalue2, zvalue3, zvalue4)\n zvalue = zvalueLow + ((zvalueHigh - zvalueLow)*.75)\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 if v[7].classtype == \"Color\" then\n v[7] = v[7]*min((p1.y + 96)\/128, 1)*min((maxz - zvalueLow)\/(maxz \/ 2), 1)\n end\n order[zvalue][#order[zvalue] + 1] = {v[1], x1, y1, x2, y2, x3, y3, x4, y4, v[7]}--, v[7]*min((p1.y + 96)\/128, 1)*min((maxz - zvalueHigh)\/(maxz \/ 2), 1)}\n end\n elseif v[1] == \"Triangle\" or v[1] == \"TriangleOutline\" then\n -- 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 = min(zvalue, zvalue2, zvalue3)\n local zvalueHigh = max(zvalue, zvalue2, zvalue3)\n zvalue = zvalueLow + (.75*(zvalueHigh - zvalueLow))\n if zvalueLow > minz and zvalueHigh <= maxz then\n if not order[zvalue] then\n order[zvalue] = {}\n end\n -- Add fog to the color\n if v[6].classtype == \"Color\" then\n v[6] = v[6]*min((p1.y + 96)\/128, 1)*min((maxz - zvalueLow)\/(maxz \/ 2), 1)\n end\n order[zvalue][#order[zvalue] + 1] = {v[1], x1, y1, x2, y2, x3, y3, v[6]}\n end\n elseif v[1] == \"Sprite\" then\n -- 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\n -- Draw a string.\n local p1 = v[3]\n local x1, y1, zvalue = self:Project3D(p1:raw())\n if zvalue > minz 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\n -- 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 = min(zvalue, zvalue2)\n local zvalueHigh = 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], v[2]}\n end\n end\n --::SkipElement::\n end\n draw.setantialias(self.antialiased or false)\n -- Draw queued elements to screen.\n local dOrder = {}\n local sOrder = {}\n -- We must create a sorted table, otherwise\n -- ipairs will not work.\n -- We can't use pairs because it will\n -- ilterate in a jacked up order that is not\n -- perspective correct.\n for k, v in pairs(order) do\n if #sOrder == 0 then\n sOrder[1] = k\n else\n local inserted = false\n for k2, v2 in ipairs(sOrder) do\n if k > v2 then\n table.insert(sOrder, k2, k)\n inserted = true\n break\n end\n end\n if not inserted then\n sOrder[#sOrder + 1] = k\n end\n end\n end\n for k, v in ipairs(sOrder) do\n dOrder[k] = order[v]\n end\n -- We now will actually draw elements to the\n -- screen.\n for k, v in ipairs(dOrder) 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 col.classtype == \"Texture\" then\n res = max(floor(self.textureResolution), 1)\n draw.texturedTriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n draw.texturedTriangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], col)\n else\n filltriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n filltriangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], col)\n if self.antialiased then\n triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], col)\n 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 triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[10])\n triangle(v2[2], v2[3], v2[6], v2[7], v2[8], v2[9], v2[10])\n elseif v2[1] == \"Triangle\" then\n filltriangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[8])\n elseif v2[1] == \"TriangleOutline\" then\n triangle(v2[2], v2[3], v2[4], v2[5], v2[6], v2[7], v2[8])\n elseif v2[1] == \"Sprite\" then\n if not imageCache[v2[2]] then\n imageCache[v2[2]] = {draw.cacheimage(v2[2])}\n end\n local x, y = imageCache[v2[2]][1], imageCache[v2[2]][2]\n if v2[3] + v2[5]*x > 0 and v2[3] - v2[5]*x < width and v2[4] + v2[5]*y > 0 and v2[4] - v2[5]*y < height then\n draw.transformedimage(v2[2], v2[3], v2[4], v2[5], camorz)\n end\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(v2[7], \"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.lastRenderCache = self.render\n self.render = {}\n return objectsDrawn\nend\n\nfunction Renderer:GetTappedVector3(x, y)\n local range = 20\n for key, v in ipairs(self.lastRenderCache) do\n if v[1] == \"Polygon\" then\n local p1, p2, p3, p4 = v[3], v[4], v[5], v[6]\n local x1, y1 = self:Project3D(p1:raw())\n local x2, y2 = self:Project3D(p2:raw())\n local x3, y3 = self:Project3D(p3:raw())\n local x4, y4 = self:Project3D(p4:raw())\n if math.abs(x - x1) < range and math.abs(y - y1) < range then\n return p1\n end\n if math.abs(x - x2) < range and math.abs(y - y2) < range then\n return p2\n end\n if math.abs(x - x3) < range and math.abs(y - y3) < range then\n return p3\n end\n if math.abs(x - x4) < range and math.abs(y - y4) < range then\n return p4\n end\n end\n end\nend\n\nreturn Renderer","Example2.lua":"Example1 = true\nrequire \"main\"\nlocal Ren = Renderer.new()\nlocal rotatemode = 0\nlocal zoom = 1\nlocal rx, ry, rz = -32, 270, 0\nlocal shiftX, shiftY, shiftZ = 0, 0, 0\nlocal color = 1\n\nlocal buttonTitles = {\n \"Reset Simulation\",\n \"Shift X\",\n \"Shift Y\",\n \"Shift 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\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(\"Perspective\")\n--Ren:setAntiAlias(true)\n\nlocal lastSecond = sys.gettime()\nlocal framesThisSecond = 0\nlocal framesLastSecond\nwhile true do\n -- Update the frame counter.\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\n -- Check which button was tapped.\n buttonTapped = 0\n draw.doevents()\n if buttonTapped == 1 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 == 2 then\n shiftX = (shiftX or 0) + (tappedSide)*10\n elseif buttonTapped == 3 then\n shiftY = (shiftY or 0) + (tappedSide)*10\n elseif buttonTapped == 4 then\n shiftZ = (shiftZ or 0) + (tappedSide)*10\n end\n\n -- Start to draw the frame to the screen.\n draw.beginframe()\n draw.clear(draw.black)\n\n -- Start drawing 3D elements to the screen.\n TerrainMesh:Draw(Ren)\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 if (framesLastSecond or framesThisSecond) == 0 then\n local tab = Ren:DrawQueueToScreen()\n print(\"-- Drawing... --\")\n for k, v in pairs(tab) do\n print(v..\" \"..k..\" objects\")\n end\n else\n Ren:DrawQueueToScreen()\n end\n\n -- Start drawing the Hud.\n -- Draw the buttons on the screen.\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\n -- Draw the current 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\n -- Draw info about the current camera mode.\n local camMode = \"Fixed Mode (Angle: \"..(zoom*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\n -- Finally, draw the current Frames Per Second.\n draw.string(\"FPS: \"..(framesLastSecond or framesThisSecond)..\" frames\", 0, 128, draw.white)\n draw.endframe()\n\n\n framesThisSecond = framesThisSecond + 1\nend","Warp.lua":"local vector = Vector3.new\nmath.randomseed(sys.gettime()*2000)\nlocal maxPrecision = .01\nlocal maxRand = 8\nVector3.new = function(x, y, z)\n maxPrecision = maxPrecision*1.0001 + .001\n x, y, z = x + (math.random()*maxRand)-(maxRand*.5), y + (math.random()*maxRand)-(maxRand*.5), z + (math.random()*maxRand)-(maxRand*.5)\n return vector(math.floor(x\/maxPrecision)*maxPrecision, math.floor(y\/maxPrecision)*maxPrecision, math.floor(z\/maxPrecision)*maxPrecision)\nend"}
|
|