Advertisement
SquidDev

Lua3D

Nov 14th, 2015
217
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
Advertisement