SquidDev

Lua3D

Nov 14th, 2015
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 23.79 KB | None | 0 0
  1. local function _W(f) local e=setmetatable({}, {__index = _ENV or getfenv()}) if setfenv then setfenv(f, e) end return f(e) or e end
  2. local colors=_W(function(_ENV, ...)
  3. local pairs = pairs
  4. local colors = colors or setmetatable({}, {__index = function() return 1 end})
  5. local termSets = {
  6.     [colors.white] = {240, 240, 240},
  7.     [colors.orange] = {242, 178, 51},
  8.     [colors.magenta] = {229, 127, 216},
  9.     [colors.lightBlue] = {153, 178, 242},
  10.     [colors.yellow] = {222, 222, 108},
  11.     [colors.lime] = {127, 204, 25},
  12.     [colors.pink] = {242, 178, 204},
  13.     [colors.gray] = {76, 76, 76},
  14.     [colors.lightGray] = {153, 153, 153},
  15.     [colors.cyan] = {76, 153, 178},
  16.     [colors.purple] = {178, 102, 229},
  17.     [colors.blue] = {37, 49, 146},
  18.     [colors.brown] = {127, 102, 76},
  19.     [colors.green] = {5, 122, 100},
  20.     [colors.red] = {204, 76, 76},
  21.     [colors.black] = {0, 0, 0},
  22. }
  23.  
  24. local strSets = {
  25.     ["0"] = {240, 240, 240},
  26.     ["1"] = {242, 178, 51},
  27.     ["2"] = {229, 127, 216},
  28.     ["3"] = {153, 178, 242},
  29.     ["4"] = {222, 222, 108},
  30.     ["5"] = {127, 204, 25},
  31.     ["6"] = {242, 178, 204},
  32.     ["7"] = {76, 76, 76},
  33.     ["8"] = {153, 153, 153},
  34.     ["9"] = {76, 153, 178},
  35.     ["a"] = {178, 102, 229},
  36.     ["b"] = {37, 49, 146},
  37.     ["c"] = {127, 102, 76},
  38.     ["d"] = {5, 122, 100},
  39.     ["e"] = {204, 76, 76},
  40.     ["f"] = {0, 0, 0},
  41. }
  42.  
  43. local function findClosestColor(colors, r, g, b)
  44.     local smallestDifference = nil
  45.     local smallestColor = nil
  46.     for id, rgb in pairs(colors) do
  47.         local diff = (r - rgb[1])^2 + (g - rgb[2])^2 + (b - rgb[3])^2
  48.  
  49.         if not smallestDifference or diff < smallestDifference then
  50.             smallestColor = id
  51.             smallestDifference = diff
  52.         end
  53.     end
  54.  
  55.     return smallestColor
  56. end
  57.  
  58. local closestCache = {}
  59.  
  60. --- Find the closest colour using a cache to store the results.
  61. -- This is because findClosestColor is not the fastest code.
  62. -- However, this could grow to be 256 ^ 3 bytes large (over 14MiB) which isn't great.
  63. local function findClosestCached(colors, r, g, b)
  64.     local cache = closestCache[colors]
  65.     if not cache then
  66.         cache = {}
  67.         closestCache[colors] = cache
  68.     end
  69.  
  70.     local index = r * 65536 + g * 256 + b
  71.     local result = cache[index]
  72.     if not result then
  73.         result = findClosestColor(colors, r, g, b)
  74.         cache[index] = result
  75.     end
  76.  
  77.     return result
  78. end
  79.  
  80. return {
  81.     findClosestColor = findClosestColor,
  82.     findClosestCached = findClosestCached,
  83.     termSets = termSets,
  84.     strSets = strSets,
  85. }
  86. end)
  87. local graphics=_W(function(_ENV, ...)
  88. local width, height if term then width, height = term.getSize() else width, height = 400, 300 end
  89. local buffer = (function(...)
  90. local width, height = ...
  91. local colours, export = {}, {}
  92. local function clearColour(colour) colour = colour or {0, 0, 0, 255} for i = 1, width * height do colours[i] = colour end end
  93. export.clearColour = clearColour
  94. clearColour({0, 0, 0, 255})
  95. local depth, testDepth, inf = {}, true, math.huge
  96. local function clearDepth(colour) for i = 1, width * height do depth[i] = inf end end
  97. export.clearColour = clearColour
  98. clearDepth()
  99. export.clear = function(colour)
  100. clearColour(colour)
  101. clearDepth()
  102. end
  103. local function pixel(x, y, z, colour)
  104. if x < 1 or x > width or y < 1 or y > height or (z > 1 or z < -1) then return end
  105. local index = width * (y - 1) + x
  106. if z < depth[index] then
  107. depth[index] = z
  108. colours[index] = colour
  109. end
  110. end
  111. export.pixel = pixel
  112. export.love = function(love, oX, oY)
  113. local setPoint, setColour = love.graphics.point, love.graphics.setColor
  114. oX = oX or 0
  115. oY = oY or 0
  116.  
  117. for y = 1, height do
  118. local offset = (y - 1) * width
  119. for x = 1, width do
  120. local colour = colours[offset + x]
  121. setColour(colour[1], colour[2], colour[3], colour[4])
  122. setPoint(oX + x, oY + y)
  123. end
  124. end
  125. end
  126. local blit_fore = ("0"):rep(width)
  127. local blit_text = (" "):rep(width)
  128. local closest, cols = colors.findClosestCached, colors.strSets
  129. local insert, concat = table.insert, table.concat
  130. export.cc = function(term, x, y)
  131. local blit, set = term.blit, term.setCursorPos
  132. for y = 1, height do
  133. local offset = (y - 1) * width
  134. local back = {}
  135. for x = 1 , width do
  136. local colour = colours[offset + x]
  137. insert(back, closest(cols, colour[1], colour[2], colour[3]))
  138. end
  139.  
  140. set(1, y)
  141. blit(blit_text, blit_fore, concat(back))
  142. end
  143. end
  144.  
  145. export.silica = function(term, x, y)
  146. local blit, set = term.blit, term.setCursorPos
  147. for y = 1, height do
  148. local offset = (y - 1) * width
  149. local back = {}
  150.  
  151. for x = 1 , width do
  152. local colour = colours[offset + x]
  153. insert(back, closest(cols, colour[1], colour[2], colour[3]))
  154. end
  155.  
  156. set(1, y)
  157. blit(concat(back))
  158. end
  159. end
  160. export.loveDepth = function(love, oX, oY)
  161. local setPoint, setColour = love.graphics.point, love.graphics.setColor
  162. oX = oX or 0
  163. oY = oY or 0
  164.  
  165. for y = 1, height do
  166. local offset = (y - 1) * width
  167. for x = 1, width do
  168. if depth[offset + x] ~= inf then
  169. local color = 255 - ((depth[offset + x] + 1) / 2 * 255)
  170. setColour(color, color, color, 255)
  171. setPoint(oX + x + width, oY + y)
  172. end
  173. end
  174. end
  175. end
  176. export.size = function() return width, height end
  177. return export
  178.  
  179. end)(width, height)
  180. buffer.line = (function(...)
  181. local pixel, width, height = ...
  182. local floor, abs = math.floor, math.abs
  183. return function(x1, y1, var1_1, x2, y2, var2_1, uniform_1)
  184. if (x1 < 1 and x2 < 1) or (x1 > width and x2 > width) or (y1 < 1 and y2 < 1) or (y1 > height and y2 > height)  or (var1_1<-1 and var2_1<-1) or (var1_1>1 and var2_1>1) then return end
  185.         x1, x2 = floor(x1), floor(x2)
  186.         y1, y2 = floor(y1), floor(y2)
  187.  
  188.         local ndx, ndy = x2 - x1, y2 - y1
  189.         local dx, dy = abs(ndx), abs(ndy)
  190.         local steep = dy > dx
  191.         if steep then
  192.             dy, dx = dx, dy
  193.         end
  194.  
  195.         local e = 2 * dy - dx
  196.         local x, y = x1, y1
  197.  
  198.         local signy, signx = 1, 1
  199.         if ndx < 0 then signx = -1 end
  200.         if ndy < 0 then signy = -1 end
  201.     local var_1, dvar_1 = var1_1, (var2_1 - var11) / dx
  202.  
  203. for i = 1, dx do
  204. pixel(x, y, var, uniform_1)
  205.     while e >= 0 do
  206.         if steep then
  207.             x = x + signx
  208.         else
  209.             y = y + signy
  210.         end
  211.         e = e - 2 * dx
  212.     end
  213.  
  214.     if steep then
  215.         y = y + signy
  216.     else
  217.         x = x + signx
  218.     end
  219.     e = e + 2 * dy
  220.     var_1 = var_1 + dvar_1
  221. end
  222. pixel(x2, y2, var2_1, uniform_1)
  223. end
  224.  
  225. end)(buffer.pixel, width, height)
  226. buffer.lineBlended = (function(...)
  227. local pixel, width, height = ...
  228. local floor, abs = math.floor, math.abs
  229. return function(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2)
  230. if (x1 < 1 and x2 < 1) or (x1 > width and x2 > width) or (y1 < 1 and y2 < 1) or (y1 > height and y2 > height)  or (var1_1<-1 and var2_1<-1) or (var1_1>1 and var2_1>1) then return end
  231.         x1, x2 = floor(x1), floor(x2)
  232.         y1, y2 = floor(y1), floor(y2)
  233.  
  234.         local ndx, ndy = x2 - x1, y2 - y1
  235.         local dx, dy = abs(ndx), abs(ndy)
  236.         local steep = dy > dx
  237.         if steep then
  238.             dy, dx = dx, dy
  239.         end
  240.  
  241.         local e = 2 * dy - dx
  242.         local x, y = x1, y1
  243.  
  244.         local signy, signx = 1, 1
  245.         if ndx < 0 then signx = -1 end
  246.         if ndy < 0 then signy = -1 end
  247.     local var_1, dvar_1 = var1_1, (var2_1 - var11) / dx
  248. local var_2_1 = var1_2[1] local dvar_2_1 = (var2_2[1] - var_2_1) / dx
  249. local var_2_2 = var1_2[2] local dvar_2_2 = (var2_2[2] - var_2_2) / dx
  250. local var_2_3 = var1_2[3] local dvar_2_3 = (var2_2[3] - var_2_3) / dx
  251. local var_2_4 = var1_2[4] local dvar_2_4 = (var2_2[4] - var_2_4) / dx
  252.  
  253. for i = 1, dx do
  254. pixel(x, y, var, {var, var, var, var, })
  255.     while e >= 0 do
  256.         if steep then
  257.             x = x + signx
  258.         else
  259.             y = y + signy
  260.         end
  261.         e = e - 2 * dx
  262.     end
  263.  
  264.     if steep then
  265.         y = y + signy
  266.     else
  267.         x = x + signx
  268.     end
  269.     e = e + 2 * dy
  270.     var_1 = var_1 + dvar_1
  271. var_2_1 = var_2_1 + dvar_2_1
  272. var_2_2 = var_2_2 + dvar_2_2
  273. var_2_3 = var_2_3 + dvar_2_3
  274. var_2_4 = var_2_4 + dvar_2_4
  275. end
  276. pixel(x2, y2, var2_1, var2_2)
  277. end
  278.  
  279. end)(buffer.pixel, width, height)
  280. buffer.triangle = (function(...)
  281. local pixel, width, height = ...
  282. local floor, ceil, abs = math.floor, math.ceil, math.abs
  283. local bottom = function(x1, y1, var1_1, x2, y2, var2_1, x3, y3, var3_1, uniform_1)
  284.             local xStart, xEnd = x1, x1 + 0.5
  285.             local dy2, dy3 = y2 - y1, y3 - y1
  286.             local dx2, dx3 = (x2 - x1) / dy2, (x3 - x1) / dy3
  287.         local varStart_1, varEnd_1 = var1_1, var1_1
  288. local dVar2_1, dVar3_1 = (var2_1 - var1_1) / dy2, (var3_1 - var1_1) / dy3
  289.  
  290. if dx3 < dx2 then
  291. dx2, dx3 = dx3, dx2
  292. dVar2_1, dVar3_1 = dVar3_1, dVar2_1
  293. end
  294.  
  295. for y = y1, y2 do
  296. if y >= 1 and y <= height then
  297. for x = ceil(xStart), xEnd do
  298. local t = (x - xStart) / (xEnd - xStart)
  299. local tInv = 1 - t
  300. pixel(x, y, tInv * varStart_1 + t * varEnd_1, uniform_1)
  301. end
  302. end
  303. xStart, xEnd = xStart + dx2, xEnd + dx3
  304. varStart_1, varEnd_1 = varStart_1 + dVar2_1, varEnd_1 + dVar3_1
  305. end
  306. end
  307.  
  308. local top = function(x1, y1, var1_1, x2, y2, var2_1, x3, y3, var3_1, uniform_1)
  309.             local xStart, xEnd = x3, x3 + 0.5
  310.             local dy1, dy2 = y3 - y1, y3 - y2
  311.             local dx1, dx2 = (x3 - x1) / dy1, (x3 - x2) / dy2
  312.         local varStart_1, varEnd_1 = var3_1, var3_1
  313. local dVar1_1, dVar2_1 = (var3_1 - var1_1) / dy1, (var3_1 - var2_1) / dy2
  314.  
  315. if dx1 < dx2 then
  316. dx1, dx2 = dx2, dx1
  317. dVar1_1, dVar2_1 = dVar2_1, dVar1_1
  318. end
  319.  
  320. for y = y3, y1, -1 do
  321. xStart, xEnd = xStart - dx1, xEnd - dx2
  322. varStart_1, varEnd_1 = varStart_1 - dVar1_1, varEnd_1 - dVar2_1
  323. if y >= 1 and y <= height then
  324. for x = ceil(xStart), xEnd do
  325. local t = (x - xStart) / (xEnd - xStart)
  326. local tInv = 1 - t
  327. pixel(x, y, tInv * varStart_1 + t * varEnd_1, uniform_1)
  328. end
  329. end
  330. end
  331. end
  332. return function(x1, y1, var1_1, x2, y2, var2_1, x3, y3, var3_1, uniform_1)
  333. if (x1 < 1 and x2 < 1) or (x1 > width and x2 > width) or (y1 < 1 and y2 < 1) or (y1 > height and y2 > height)  or (var1_1<-1 and var2_1<-1 and var3_1<-1) or (var1_1>1 and var2_1>1 and var3_1>1) then return end
  334. x1, x2, x3 = floor(x1), floor(x2), floor(x3)
  335. y1, y2, y3 = floor(y1), floor(y2), floor(y3)
  336. if y1 > y2 then
  337. x1, x2 = x2, x1
  338. y1, y2 = y2, y1
  339. var1_1, var2_1 = var2_1, var1_1
  340. end
  341. if y1 > y3 then
  342. x1, x3 = x3, x1
  343. y1, y3 = y3, y1
  344. var1_1, var3_1 = var3_1, var1_1
  345. end
  346. if y2 > y3 then
  347. x2, x3 = x3, x2
  348. y2, y3 = y3, y2
  349. var2_1, var3_1 = var3_1, var2_1
  350. end
  351. if y2 == y3 then
  352. return bottom(x1, y1, var1_1, x2, y2, var2_1, x3, y3, var3_1, uniform_1)
  353. elseif y1 == y2 then
  354. return top(x1, y1, var1_1, x2, y2, var2_1, x3, y3, var3_1, uniform_1)
  355. else            local delta = (y2 - y1) / (y3 - y1)
  356.             local x = floor(x1 + delta * (x3 - x1))
  357.         local var_1 = var1_1 + delta * (var3_1 - var1_1)
  358. bottom(x1, y1, var1_1, x2, y2, var2_1, x, y2, var_1, uniform_1)
  359. top(x2, y2, var2_1, x, y2, var_1, x3, y3, var3_1, uniform_1)
  360. end
  361. end
  362. end)(buffer.pixel, width, height)
  363. buffer.triangleBlended = (function(...)
  364. local pixel, width, height = ...
  365. local floor, ceil, abs = math.floor, math.ceil, math.abs
  366. local bottom = function(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2, x3, y3, var3_1, var3_2)
  367.             local xStart, xEnd = x1, x1 + 0.5
  368.             local dy2, dy3 = y2 - y1, y3 - y1
  369.             local dx2, dx3 = (x2 - x1) / dy2, (x3 - x1) / dy3
  370.         local varStart_1, varEnd_1 = var1_1, var1_1
  371. local dVar2_1, dVar3_1 = (var2_1 - var1_1) / dy2, (var3_1 - var1_1) / dy3
  372. local varStart_2_1 = var1_2[1] local varEnd_2_1 = varStart_2_1
  373. local dVar2_2_1, dVar3_2_1 = (var2_2[1] - varStart_2_1) / dy2, (var3_2[1] - varStart_2_1) / dy3
  374. local varStart_2_2 = var1_2[2] local varEnd_2_2 = varStart_2_2
  375. local dVar2_2_2, dVar3_2_2 = (var2_2[2] - varStart_2_2) / dy2, (var3_2[2] - varStart_2_2) / dy3
  376. local varStart_2_3 = var1_2[3] local varEnd_2_3 = varStart_2_3
  377. local dVar2_2_3, dVar3_2_3 = (var2_2[3] - varStart_2_3) / dy2, (var3_2[3] - varStart_2_3) / dy3
  378. local varStart_2_4 = var1_2[4] local varEnd_2_4 = varStart_2_4
  379. local dVar2_2_4, dVar3_2_4 = (var2_2[4] - varStart_2_4) / dy2, (var3_2[4] - varStart_2_4) / dy3
  380.  
  381. if dx3 < dx2 then
  382. dx2, dx3 = dx3, dx2
  383. dVar2_1, dVar3_1 = dVar3_1, dVar2_1
  384. dVar2_2_1, dVar3_2_1 = dVar3_2_1, dVar2_2_1
  385. dVar2_2_2, dVar3_2_2 = dVar3_2_2, dVar2_2_2
  386. dVar2_2_3, dVar3_2_3 = dVar3_2_3, dVar2_2_3
  387. dVar2_2_4, dVar3_2_4 = dVar3_2_4, dVar2_2_4
  388. end
  389.  
  390. for y = y1, y2 do
  391. if y >= 1 and y <= height then
  392. for x = ceil(xStart), xEnd do
  393. local t = (x - xStart) / (xEnd - xStart)
  394. local tInv = 1 - t
  395. pixel(x, y, tInv * varStart_1 + t * varEnd_1, {tInv * varStart_2_1 + t * varEnd_2_1, tInv * varStart_2_2 + t * varEnd_2_2, tInv * varStart_2_3 + t * varEnd_2_3, tInv * varStart_2_4 + t * varEnd_2_4, })
  396. end
  397. end
  398. xStart, xEnd = xStart + dx2, xEnd + dx3
  399. varStart_1, varEnd_1 = varStart_1 + dVar2_1, varEnd_1 + dVar3_1
  400. varStart_2_1, varEnd_2_1 = varStart_2_1 + dVar2_2_1, varEnd_2_1 + dVar3_2_1
  401. varStart_2_2, varEnd_2_2 = varStart_2_2 + dVar2_2_2, varEnd_2_2 + dVar3_2_2
  402. varStart_2_3, varEnd_2_3 = varStart_2_3 + dVar2_2_3, varEnd_2_3 + dVar3_2_3
  403. varStart_2_4, varEnd_2_4 = varStart_2_4 + dVar2_2_4, varEnd_2_4 + dVar3_2_4
  404. end
  405. end
  406.  
  407. local top = function(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2, x3, y3, var3_1, var3_2)
  408.             local xStart, xEnd = x3, x3 + 0.5
  409.             local dy1, dy2 = y3 - y1, y3 - y2
  410.             local dx1, dx2 = (x3 - x1) / dy1, (x3 - x2) / dy2
  411.         local varStart_1, varEnd_1 = var3_1, var3_1
  412. local dVar1_1, dVar2_1 = (var3_1 - var1_1) / dy1, (var3_1 - var2_1) / dy2
  413. local varStart_2_1 = var3_2[1] local varEnd_2_1 = varStart_2_1
  414. local dVar1_2_1, dVar2_2_1 = (varStart_2_1 - var1_2[1]) / dy1, (varStart_2_1 - var2_2[1]) / dy2
  415. local varStart_2_2 = var3_2[2] local varEnd_2_2 = varStart_2_2
  416. local dVar1_2_2, dVar2_2_2 = (varStart_2_2 - var1_2[2]) / dy1, (varStart_2_2 - var2_2[2]) / dy2
  417. local varStart_2_3 = var3_2[3] local varEnd_2_3 = varStart_2_3
  418. local dVar1_2_3, dVar2_2_3 = (varStart_2_3 - var1_2[3]) / dy1, (varStart_2_3 - var2_2[3]) / dy2
  419. local varStart_2_4 = var3_2[4] local varEnd_2_4 = varStart_2_4
  420. local dVar1_2_4, dVar2_2_4 = (varStart_2_4 - var1_2[4]) / dy1, (varStart_2_4 - var2_2[4]) / dy2
  421.  
  422. if dx1 < dx2 then
  423. dx1, dx2 = dx2, dx1
  424. dVar1_1, dVar2_1 = dVar2_1, dVar1_1
  425. dVar1_2_1, dVar2_2_1 = dVar2_2_1, dVar1_2_1
  426. dVar1_2_2, dVar2_2_2 = dVar2_2_2, dVar1_2_2
  427. dVar1_2_3, dVar2_2_3 = dVar2_2_3, dVar1_2_3
  428. dVar1_2_4, dVar2_2_4 = dVar2_2_4, dVar1_2_4
  429. end
  430.  
  431. for y = y3, y1, -1 do
  432. xStart, xEnd = xStart - dx1, xEnd - dx2
  433. varStart_1, varEnd_1 = varStart_1 - dVar1_1, varEnd_1 - dVar2_1
  434. varStart_2_1, varEnd_2_1 = varStart_2_1 - dVar1_2_1, varEnd_2_1 - dVar2_2_1
  435. varStart_2_2, varEnd_2_2 = varStart_2_2 - dVar1_2_2, varEnd_2_2 - dVar2_2_2
  436. varStart_2_3, varEnd_2_3 = varStart_2_3 - dVar1_2_3, varEnd_2_3 - dVar2_2_3
  437. varStart_2_4, varEnd_2_4 = varStart_2_4 - dVar1_2_4, varEnd_2_4 - dVar2_2_4
  438. if y >= 1 and y <= height then
  439. for x = ceil(xStart), xEnd do
  440. local t = (x - xStart) / (xEnd - xStart)
  441. local tInv = 1 - t
  442. pixel(x, y, tInv * varStart_1 + t * varEnd_1, {tInv * varStart_2_1 + t * varEnd_2_1, tInv * varStart_2_2 + t * varEnd_2_2, tInv * varStart_2_3 + t * varEnd_2_3, tInv * varStart_2_4 + t * varEnd_2_4, })
  443. end
  444. end
  445. end
  446. end
  447. return function(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2, x3, y3, var3_1, var3_2)
  448. if (x1 < 1 and x2 < 1) or (x1 > width and x2 > width) or (y1 < 1 and y2 < 1) or (y1 > height and y2 > height)  or (var1_1<-1 and var2_1<-1 and var3_1<-1) or (var1_1>1 and var2_1>1 and var3_1>1) then return end
  449. x1, x2, x3 = floor(x1), floor(x2), floor(x3)
  450. y1, y2, y3 = floor(y1), floor(y2), floor(y3)
  451. if y1 > y2 then
  452. x1, x2 = x2, x1
  453. y1, y2 = y2, y1
  454. var1_1, var2_1 = var2_1, var1_1
  455. var1_2, var2_2 = var2_2, var1_2
  456. end
  457. if y1 > y3 then
  458. x1, x3 = x3, x1
  459. y1, y3 = y3, y1
  460. var1_1, var3_1 = var3_1, var1_1
  461. var1_2, var3_2 = var3_2, var1_2
  462. end
  463. if y2 > y3 then
  464. x2, x3 = x3, x2
  465. y2, y3 = y3, y2
  466. var2_1, var3_1 = var3_1, var2_1
  467. var2_2, var3_2 = var3_2, var2_2
  468. end
  469. if y2 == y3 then
  470. return bottom(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2, x3, y3, var3_1, var3_2)
  471. elseif y1 == y2 then
  472. return top(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2, x3, y3, var3_1, var3_2)
  473. else            local delta = (y2 - y1) / (y3 - y1)
  474.             local x = floor(x1 + delta * (x3 - x1))
  475.         local var_1 = var1_1 + delta * (var3_1 - var1_1)
  476. local var_2 = {
  477. var1_2[1] + delta * (var3_2[1] - var1_2[1]),
  478. var1_2[2] + delta * (var3_2[2] - var1_2[2]),
  479. var1_2[3] + delta * (var3_2[3] - var1_2[3]),
  480. var1_2[4] + delta * (var3_2[4] - var1_2[4]),
  481. }
  482. bottom(x1, y1, var1_1, var1_2, x2, y2, var2_1, var2_2, x, y2, var_1, var_2)
  483. top(x2, y2, var2_1, var2_2, x, y2, var_1, var_2, x3, y3, var3_1, var3_2)
  484. end
  485. end
  486. end)(buffer.pixel, width, height)
  487. return buffer
  488. end)
  489. local matrix=_W(function(_ENV, ...)
  490. return {
  491. matrix = function(l, r)
  492. local l_1_1=l[1]
  493. local l_2_1=l[2]
  494. local l_3_1=l[3]
  495. local l_4_1=l[4]
  496. local l_1_2=l[5]
  497. local l_2_2=l[6]
  498. local l_3_2=l[7]
  499. local l_4_2=l[8]
  500. local l_1_3=l[9]
  501. local l_2_3=l[10]
  502. local l_3_3=l[11]
  503. local l_4_3=l[12]
  504. local l_1_4=l[13]
  505. local l_2_4=l[14]
  506. local l_3_4=l[15]
  507. local l_4_4=l[16]
  508. local r_1_1=r[1]
  509. local r_2_1=r[2]
  510. local r_3_1=r[3]
  511. local r_4_1=r[4]
  512. local r_1_2=r[5]
  513. local r_2_2=r[6]
  514. local r_3_2=r[7]
  515. local r_4_2=r[8]
  516. local r_1_3=r[9]
  517. local r_2_3=r[10]
  518. local r_3_3=r[11]
  519. local r_4_3=r[12]
  520. local r_1_4=r[13]
  521. local r_2_4=r[14]
  522. local r_3_4=r[15]
  523. local r_4_4=r[16]
  524. return {
  525. l_1_1*r_1_1 + l_1_2*r_2_1 + l_1_3*r_3_1 + l_1_4*r_4_1,
  526. l_2_1*r_1_1 + l_2_2*r_2_1 + l_2_3*r_3_1 + l_2_4*r_4_1,
  527. l_3_1*r_1_1 + l_3_2*r_2_1 + l_3_3*r_3_1 + l_3_4*r_4_1,
  528. l_4_1*r_1_1 + l_4_2*r_2_1 + l_4_3*r_3_1 + l_4_4*r_4_1,
  529. l_1_1*r_1_2 + l_1_2*r_2_2 + l_1_3*r_3_2 + l_1_4*r_4_2,
  530. l_2_1*r_1_2 + l_2_2*r_2_2 + l_2_3*r_3_2 + l_2_4*r_4_2,
  531. l_3_1*r_1_2 + l_3_2*r_2_2 + l_3_3*r_3_2 + l_3_4*r_4_2,
  532. l_4_1*r_1_2 + l_4_2*r_2_2 + l_4_3*r_3_2 + l_4_4*r_4_2,
  533. l_1_1*r_1_3 + l_1_2*r_2_3 + l_1_3*r_3_3 + l_1_4*r_4_3,
  534. l_2_1*r_1_3 + l_2_2*r_2_3 + l_2_3*r_3_3 + l_2_4*r_4_3,
  535. l_3_1*r_1_3 + l_3_2*r_2_3 + l_3_3*r_3_3 + l_3_4*r_4_3,
  536. l_4_1*r_1_3 + l_4_2*r_2_3 + l_4_3*r_3_3 + l_4_4*r_4_3,
  537. l_1_1*r_1_4 + l_1_2*r_2_4 + l_1_3*r_3_4 + l_1_4*r_4_4,
  538. l_2_1*r_1_4 + l_2_2*r_2_4 + l_2_3*r_3_4 + l_2_4*r_4_4,
  539. l_3_1*r_1_4 + l_3_2*r_2_4 + l_3_3*r_3_4 + l_3_4*r_4_4,
  540. l_4_1*r_1_4 + l_4_2*r_2_4 + l_4_3*r_3_4 + l_4_4*r_4_4,
  541. }
  542. end,
  543. vector = function(l, r)
  544. local l_1_1=l[1]
  545. local l_2_1=l[2]
  546. local l_3_1=l[3]
  547. local l_4_1=l[4]
  548. local l_1_2=l[5]
  549. local l_2_2=l[6]
  550. local l_3_2=l[7]
  551. local l_4_2=l[8]
  552. local l_1_3=l[9]
  553. local l_2_3=l[10]
  554. local l_3_3=l[11]
  555. local l_4_3=l[12]
  556. local l_1_4=l[13]
  557. local l_2_4=l[14]
  558. local l_3_4=l[15]
  559. local l_4_4=l[16]
  560. local r_1_1=r[1]
  561. local r_2_1=r[2]
  562. local r_3_1=r[3]
  563. local r_4_1=r[4]
  564. return {
  565. l_1_1*r_1_1 + l_1_2*r_2_1 + l_1_3*r_3_1 + l_1_4*r_4_1,
  566. l_2_1*r_1_1 + l_2_2*r_2_1 + l_2_3*r_3_1 + l_2_4*r_4_1,
  567. l_3_1*r_1_1 + l_3_2*r_2_1 + l_3_3*r_3_1 + l_3_4*r_4_1,
  568. l_4_1*r_1_1 + l_4_2*r_2_1 + l_4_3*r_3_1 + l_4_4*r_4_1,
  569. }
  570. end,
  571. }
  572. end)
  573. local transform=_W(function(_ENV, ...)
  574. --[[
  575.     Handles matrix transformations
  576.  
  577.     Several references:
  578.         - https://open.gl/transformations
  579.         - http://www.songho.ca/opengl/gl_transform.html
  580.         - https://github.com/g-truc/glm/blob/master/glm/gtc/matrix_transform.inl
  581.         - http://www.codinglabs.net/article_world_view_projection_matrix.aspx
  582. ]]
  583. local sin, cos, tan = math.sin, math.cos, math.tan
  584.  
  585. local function translate(x, y, z)
  586.     return {
  587.         1, 0, 0, 0,
  588.         0, 1, 0, 0,
  589.         0, 0, 1, 0,
  590.         x, y, z, 1,
  591.     }
  592. end
  593.  
  594. local function scale(x, y, z)
  595.     return {
  596.         x, 0, 0, 0,
  597.         0, y, 0, 0,
  598.         0, 0, z, 0,
  599.         0, 0, 0, 1,
  600.     }
  601. end
  602.  
  603. local function rotateX(a)
  604.     local c, s = cos(a), sin(a)
  605.     return {
  606.         1,  0, 0, 0,
  607.         0,  c, s, 0,
  608.         0, -s, c, 0,
  609.         0,  0, 0, 1
  610.     }
  611. end
  612.  
  613. local function rotateY(a)
  614.     local c, s = cos(a), sin(a)
  615.     return {
  616.          c, 0, s, 0,
  617.          0, 1, 0, 0,
  618.         -s, 0, c, 0,
  619.          0, 0, 0, 1
  620.     }
  621. end
  622.  
  623. local function rotateZ(a)
  624.     local c, s = cos(a), sin(a)
  625.     return {
  626.         c, -s, 0, 0,
  627.         s,  c, 0, 0,
  628.         0,  0, 1, 0,
  629.         0,  0, 0, 1,
  630.     }
  631. end
  632.  
  633. local function orthographic(left, right, bottom, top, zNear, zFar)
  634.     local invRL, invTB, invFN = 1 / (right - left), 1 / (top - bottom), 1 / (zNear - zFar)
  635.  
  636.     return {
  637.         2 * invRL, 0,         0,          0,
  638.         0,         2 * invTB, 0,          0,
  639.         0,         0,         -2 * invFN, 0,
  640.  
  641.         -- Translate
  642.         (-right + left) * invRL, -(top + bottom) * invTB, -(zFar + zNear) * invFN, 1,
  643.     }
  644. end
  645.  
  646. local function perspective(fovy, aspect, zNear, zFar)
  647.     local tanHalfFovy = tan(fovy / 2)
  648.  
  649.     -- Diagonals
  650.     return {
  651.         1 / (aspect * tanHalfFovy), 0, 0, 0,
  652.         0, 1 / tanHalfFovy, 0, 0,
  653.         0, 0, -(zFar + zNear) / (zFar - zNear), -1,
  654.         0, 0, -(2 * zNear * zFar) / (zFar - zNear), 0,
  655.     }
  656. end
  657.  
  658. return {
  659.     translate = translate,
  660.     scale = scale,
  661.     rotateX = rotateX,
  662.     rotateY = rotateY,
  663.     rotateZ = rotateZ,
  664.  
  665.     orthographic = orthographic,
  666.     perspective = perspective,
  667. }
  668. end)
  669. local verticies = {
  670.     {  3,  3, -3, 1 },
  671.     {  3, -3, -3, 1 },
  672.     { -3, -3, -3, 1 },
  673.     { -3,  3, -3, 1 },
  674.     {  3,  3,  3, 1 },
  675.     {  3, -3,  3, 1 },
  676.     { -3, -3,  3, 1 },
  677.     { -3,  3,  3, 1 },
  678. }
  679.  
  680. local colours = {
  681.     { 255, 0,   0,   100 },
  682.     { 0,   255, 0,   100 },
  683.     { 0,   0,   255, 100 },
  684.     { 0,   255, 255, 100 },
  685.     { 255, 255, 0,   100 },
  686.     { 255, 0,   255, 100 },
  687.     { 255, 128, 0,   100 },
  688.     { 128, 255, 0,   100 },
  689. }
  690.  
  691. local indexes = {
  692.     {1,2,3, 1},
  693.     {1,3,4, 1},
  694.     {7,6,8, 2},
  695.     {8,6,5, 2},
  696.  
  697.     {3,7,4, 3}, -- Left
  698.     {4,7,8, 3},
  699.     {5,6,2, 4},
  700.     {2,1,5, 4},
  701.  
  702.     {5,1,4, 5}, -- Top
  703.     {4,8,5, 5},
  704.     {2,6,3, 6},
  705.     {6,7,3, 6},
  706. }
  707.  
  708.  
  709. local g = graphics
  710. local debug = cclite and cclite.log or print
  711. local clock, format = os.clock, string.format
  712. local function profile(section, time) debug(format("[%.2f] %s: %.5f", clock(), section, time)) end
  713.  
  714. local dispWidth, dispHeight = g.size()
  715. local projection = transform.perspective(math.pi / 2, 1, 0.1, 6.0)
  716.  
  717. local function compose(...)
  718.     local result, items = ..., {select(2, ...)}
  719.     for _, item in pairs(items) do
  720.         result = matrix.matrix(result, item)
  721.     end
  722.  
  723.     return result
  724. end
  725.  
  726. local function normalise(coord)
  727.     coord[1] = (coord[1] + 1) * dispWidth / 2
  728.     coord[2] = (coord[2] + 1) * dispHeight / 2
  729.     coord[3] = (coord[3] + 1) / 2
  730.  
  731.     return coord
  732. end
  733.  
  734. local function draw(g, v, group)
  735.     local a, b, c = v[group[1]], v[group[2]], v[group[3]]
  736.     g.triangle(
  737.         a[1], a[2], a[3], -- colours[group[1]],
  738.         b[1], b[2], b[3], -- colours[group[2]],
  739.         c[1], c[2], c[3], colours[group[4]]
  740.     )
  741. end
  742.  
  743. local rotX, rotY = 0, 0
  744. local x, y, z = 0, 0, 8
  745.  
  746. local function refreshMatrix()
  747.     local start
  748.  
  749.     start = clock()
  750.     local view = compose(unpack {
  751.         transform.scale(1/20, 1/20, 1/20),
  752.         transform.translate(-x, -y, -z),
  753.         transform.rotateX(rotX),
  754.         transform.rotateY(rotY),
  755.     })
  756.     local mvp = compose(projection, view)
  757.     profile("Preparing MVP", clock() - start)
  758.  
  759.     g.clear()
  760.  
  761.     start = clock()
  762.     local p = {}
  763.     for k, v in pairs(verticies) do
  764.         local coord = matrix.vector(mvp, v)
  765.         if coord[4] == 0 then coord[4] = 1 print("SOMETHING IS 0", coord[3]) end
  766.         coord[1] = coord[1] / coord[4]
  767.         coord[2] = coord[2] / coord[4]
  768.         p[k] = normalise(coord)
  769.     end
  770.     profile("Preparing Verticies", clock() - start)
  771.  
  772.     start = clock()
  773.     for _, group in pairs(indexes) do
  774.         draw(g, p, group)
  775.     end
  776.     profile("Drawing", clock() - start)
  777. end
  778.  
  779. refreshMatrix()
  780. local rotSpeed, speed = 0.01, 0.1
  781.  
  782. local changed = false
  783. local function pressed(key)
  784.     if key == "a" then
  785.         rotY = (rotY + rotSpeed) % (2 * math.pi)
  786.     elseif key == "d" then
  787.         rotY = (rotY - rotSpeed) % (2 * math.pi)
  788.     elseif key == "w" then
  789.         rotX = (rotX + rotSpeed) % (2 * math.pi)
  790.     elseif key == "s" then
  791.         rotX = (rotX - rotSpeed) % (2 * math.pi)
  792.     elseif key == "u" then
  793.         z = z + speed
  794.     elseif key == "p" then
  795.         z = z - speed
  796.     elseif key == "j" then
  797.         x = x + speed
  798.     elseif key == "l" then
  799.         x = x - speed
  800.     elseif key == "i" then
  801.         y = y + speed
  802.     elseif key == "k" then
  803.         y = y - speed
  804.     elseif key == "r" then
  805.         rotY = 0
  806.         rotX = 0
  807.     end
  808.  
  809.     changed = true
  810. end
  811.  
  812. if term then
  813.     g.silica(term.native())
  814.     local fps = 30
  815.     local id = os.startTimer(1 / fps)
  816.     while true do
  817.         local e, arg = os.pullEvent()
  818.         if e == "char" then
  819.             pressed(arg)
  820.         elseif e == "timer" and arg == id then
  821.             id = os.startTimer(1 / fps)
  822.             if not changed then
  823.                 rotY = rotY + 0.05
  824.                 changed = true
  825.             end
  826.             if changed then
  827.                 local vStart = clock()
  828.                 refreshMatrix()
  829.                 changed = false
  830.  
  831.                 local start = clock()
  832.                 g.silica(term.native())
  833.                 profile("Blitting", clock() - start)
  834.                 profile("TOTAL", clock() - vStart)
  835.                 debug("FPS: " .. (1 / (clock() - vStart)))
  836.             end
  837.         end
  838.     end
  839. elseif love then
  840.     love.keypressed = pressed
  841.  
  842.     function love.draw()
  843.         if changed then
  844.             refreshMatrix()
  845.             changed = false
  846.         end
  847.         g.love(love)
  848.         g.loveDepth(love, dispWidth)
  849.     end
  850. else
  851.     error("Requires running in silica of Love")
  852. end
Advertisement
Add Comment
Please, Sign In to add comment