Advertisement
theTANCO

3D Cube

Feb 23rd, 2023 (edited)
923
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.51 KB | None | 0 0
  1. -- This program was made while following this video about programming in Apple II BASIC:
  2. -- https://www.youtube.com/watch?v=PHfKCxjsmos
  3. -- This program renders a 3D cube being rotating along x, y, and z axes at 60fps.
  4. -- This code will only work in ComputerCraft.
  5. local round = function(n)
  6.     return math.floor(n+0.5)
  7. end
  8.  
  9. local wait = (function()
  10.     local ticks = 0
  11.     local startTime = os.clock()
  12.     local frames = {os.clock()}
  13.     local fps = 0
  14.  
  15.     return setmetatable({
  16.         ticks = function() return ticks end,
  17.         frameTime = function(real)
  18.             local time = os.clock()-frames[1]
  19.             if real then return time / fps
  20.             else return round(time / fps * 20) / 20 end
  21.         end,
  22.         startTime = function() return startTime end,
  23.         programClock = function() return os.clock() - startTime end,
  24.         fps = function() return fps end
  25.     }, {
  26.         __call = function(self, n)
  27.             n = tonumber(n) or 20
  28.             if n <= 0 then error("Value out of range, must be greater than 0", 2) end
  29.             ticks = ticks + 1
  30.             frames[#frames+1] = os.clock()
  31.             if n <= 20 then
  32.                 sleep(1/n)
  33.             elseif ticks%round(n/20) == 0 then
  34.                 sleep(0.05)
  35.             end
  36.             while os.clock()-frames[1] > 1 and #frames > 1 do
  37.                 table.remove(frames, 1)
  38.             end
  39.             fps =  #frames / (os.clock() - frames[1]) - (math.floor(n/20)-1)
  40.             return fps
  41.         end
  42.     })
  43. end)()
  44.  
  45. local xSize, ySize = term.getSize()
  46. local winBuffer = {
  47.     [1] = window.create(term.current(), 1, 1, xSize, ySize),
  48.     [2] = window.create(term.current(), 1, 1, xSize, ySize)
  49. }
  50. local cubeSize = ySize*1.4
  51. local xCenter, yCenter = round(xSize/2), round(ySize/2)
  52. local win = 1
  53. local angle = 0
  54. local points = {}
  55.  
  56. for n = 1, 8 do
  57.     local x, y, z = 0, 0, 0
  58.     if n%4 < 2 then x = -1 else x = 1 end
  59.     if (n-1)%4 < 2 then y = -1 else y = 1 end
  60.     if n < 5 then z = -1 else z = 1 end
  61.     points[n] = {
  62.         position = vector.new(x, y, z),
  63.         rotation = {
  64.             x = vector.new(0, 0, 0),
  65.             y = vector.new(0, 0, 0),
  66.             z = vector.new(0, 0, 0)
  67.         },
  68.         projection = vector.new(0, 0, 0)
  69.     }
  70. end
  71.  
  72. local drawLine = function(a, b)
  73.     local x1 = points[a].projection.x * cubeSize + xCenter
  74.     local y1 = points[a].projection.y * cubeSize + yCenter
  75.     local x2 = points[b].projection.x * cubeSize + xCenter
  76.     local y2 = points[b].projection.y * cubeSize + yCenter
  77.     paintutils.drawLine(x1, y1, x2, y2, colors.lime)
  78. end
  79.  
  80. local bufferSwap = function()
  81.     winBuffer[win].setVisible(true)
  82.     if win == 1 then win = 2 else win = 1 end
  83.     winBuffer[win].setVisible(false)
  84.     term.redirect(winBuffer[win])
  85. end
  86.  
  87. local setRotation = function()
  88.     local cs = math.cos(angle)
  89.     local sn = math.sin(angle)
  90.     for n = 1, 8 do
  91.         points[n].rotation.z.x = -cs*points[n].position.x + sn*points[n].position.y
  92.         points[n].rotation.z.y = sn*points[n].position.x + cs*points[n].position.y
  93.         points[n].rotation.z.z = points[n].position.z
  94.  
  95.         points[n].rotation.y.x = cs*points[n].rotation.z.x + sn*points[n].rotation.z.z
  96.         points[n].rotation.y.y = points[n].rotation.z.y
  97.         points[n].rotation.y.z = -sn*points[n].rotation.z.x + cs*points[n].rotation.z.z
  98.  
  99.         points[n].rotation.x.x = points[n].rotation.y.x
  100.         points[n].rotation.x.y = cs*points[n].rotation.y.y - sn*points[n].rotation.y.z
  101.         points[n].rotation.x.z = sn*points[n].rotation.y.y + cs*points[n].rotation.y.z
  102.  
  103.         local z = 1 / (5 - points[n].rotation.x.z)
  104.         points[n].projection.x = points[n].rotation.x.x * z
  105.         points[n].projection.y = points[n].rotation.x.y * z
  106.     end
  107. end
  108.  
  109. local drawCube = function()
  110.     for n = 1, 8 do
  111.         if n%4 > 0 then drawLine(n, n+1)
  112.         else drawLine(n, n-3) end
  113.         if n < 5 then drawLine(n, n+4) end
  114.     end
  115. end
  116.  
  117. while true do
  118.     term.setBackgroundColor(colors.black)
  119.     term.clear()
  120.     term.setCursorPos(1, 1)
  121.     print("FPS: " .. wait.fps())
  122.     print("Start Time: " .. wait.startTime())
  123.     print("Time Since Start: " .. wait.programClock())
  124.     print("Ticks: " .. wait.ticks())
  125.     print("Frametime: " .. wait.frameTime())
  126.     print("Real Frametime: " .. wait.frameTime(true))
  127.     print()
  128.     print("Cube Size: " .. cubeSize)
  129.     print("Angle: " .. round(angle*1000+500)/1000)
  130.     setRotation()
  131.     drawCube()
  132.     angle = angle + 0.005
  133.     bufferSwap()
  134.     wait(60)
  135. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement