Advertisement
jig487

PlumDrawing

Nov 11th, 2021 (edited)
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.31 KB | None | 0 0
  1. --Draws a line from x1,y1 to x2,y2 with given color, using name of wrapped AR controller
  2. local function drawLineAR(wrapper,x1,y1,x2,y2,color)
  3.     color = 0x000000 --Overriding color to black. Comment out to use custom colors
  4.     local dx = x2 - x1
  5.     local dy = y2 - y1
  6.     local length = math.floor(math.sqrt((dx^2)+(dy^2)))
  7.     for i = 1, length do
  8.         local nextY = y1 + dy * (i / length)
  9.         local nextX = x1 + dx * (i / length)
  10.         wrapper.horizontalLine(nextX, nextX, nextY, color)
  11.     end
  12. end
  13.  
  14. --Draws an object with an indexList which points to a list x/y points, using name of wrapped AR controller
  15. local function drawWireObj(wrapper,vL) --vL == vertice list. cL == color list
  16.     local cL = vL.colorList
  17.     for i = 1, #vL, 12 do --Draws a whole triangle per loop
  18.         local i1,i2 = i+1, i+2
  19.         local col = cL[(i+2)/3]
  20.         drawLineAR(wrapper, vL[i],   vL[i+1], vL[i+4], vL[i+5], col) --vert 1 to 2
  21.         drawLineAR(wrapper, vL[i+4], vL[i+5], vL[i+8], vL[i+9], col) --vert 2 to 3
  22.         drawLineAR(wrapper, vL[i+8], vL[i+9], vL[i],   vL[i+1], col) --vert 3 to 1
  23.     end
  24. end
  25.  
  26. --Basically a line function with cutoffs for anything < 0.
  27. local function drawFlatTriangle(wrapper,px1,px2,y,color)
  28.     local xStart = math.ceil(px1 - 0.5)
  29.     local xEnd =   math.ceil(px2 - 0.5)
  30.  
  31.     if xEnd > 0 then
  32.         if xStart < 0 then xStart = 0 end
  33.         for x = xStart, xEnd do
  34.             wrapper.horizontalLine(x, x, y, color)
  35.         end
  36.     end
  37. end
  38.  
  39. --Basically a line function with cutoffs for anything < 0.
  40. local function drawFlatTriangleTerm(wrapper,px1,px2,y,color)
  41.     local xStart = math.ceil(px1 - 0.5)
  42.     local xEnd =   math.ceil(px2 - 0.5)
  43.  
  44.     if xEnd > 0 then
  45.         if xStart < 0 then xStart = 0 end
  46.         for x = xStart, xEnd do
  47.             term.setCursorPos(x,y)
  48.             term.write(" ")
  49.         end
  50.     end
  51. end
  52.  
  53. --Both draw flat top and bottom draw an entire line at a time instead of each pixel individually b/c performance. Will add individual pixel support later.
  54. local function drawFlatTopTriangle( wrapper,vec1,vec2,vec3,color )
  55.     --Calculate slopes in screen space
  56.     --Run over rise so we don't get infinite slopes
  57.     local m1 = (vec3.x - vec1.x) / (vec3.y - vec1.y)
  58.     local m2 = (vec3.x - vec2.x) / (vec3.y - vec2.y)
  59.  
  60.     --Calculate start and end scanlines
  61.     local yStart = math.ceil(vec1.y - 0.5)
  62.     local yEnd =   math.ceil(vec3.y - 0.5)-1 --the scanline AFTER the last line drawn, which is why it's offset by -1
  63.  
  64.     if yEnd > 0 then
  65.         if yStart < 0 then yStart = 0 end
  66.         for y = yStart, yEnd do
  67.             --calculate start and end x's
  68.             --Add 0.5 because we're calculating based on pixel centers
  69.             local px1 = m1 * (y + 0.5 - vec1.y) + vec1.x
  70.             local px2 = m2 * (y + 0.5 - vec2.y) + vec2.x
  71.  
  72.             drawFlatTriangleTerm( wrapper,px1,px2,y,color )
  73.         end
  74.     end
  75.     term.setBackgroundColour(colors.black)
  76. end
  77.  
  78. local function drawFlatBottomTriangle( wrapper,vec1,vec2,vec3,color )
  79.     --Calculate slopes in screen space
  80.     local m1 = (vec2.x - vec1.x) / (vec2.y - vec1.y)
  81.     local m2 = (vec3.x - vec1.x) / (vec3.y - vec1.y)
  82.  
  83.     --Calculate start and end scanlines
  84.     local yStart = math.ceil(vec1.y-0.5)
  85.     local yEnd =   math.ceil(vec3.y-0.5)-1 --the scanline AFTER the last line drawn, which is why we need to subtract 1 otherwise we get visual bugs
  86.  
  87.     if yEnd > 0 then
  88.         if yStart < 0 then yStart = 0 end
  89.         for y = yStart, yEnd do
  90.             --calculate start and end points (x/z coords)
  91.             --Add 0.5 because we're calculating based on pixel centers
  92.             local px1 = m1 * (y + 0.5 - vec1.y) + vec1.x
  93.             local px2 = m2 * (y + 0.5 - vec1.y) + vec1.x
  94.  
  95.             drawFlatTriangleTerm( wrapper,px1,px2,y,color )
  96.         end
  97.     end
  98. end
  99.  
  100. --Draws a solid triangle from 3 vectors
  101. local function drawSolidTriangle( wrapper,pv1,pv2,pv3,color )
  102.     --Sort vertices by y
  103.     if pv2.y < pv1.y then pv1,pv2 = pv2,pv1 end
  104.     if pv3.y < pv2.y then pv2,pv3 = pv3,pv2 end
  105.     if pv2.y < pv1.y then pv1,pv2 = pv2,pv1 end
  106.  
  107.     if pv1.y == pv2.y then --Natural flat top
  108.         --Sort top vertice by x
  109.         if pv2.x < pv1.x then pv1,pv2 = pv2,pv1 end
  110.         drawFlatTopTriangle(wrapper,pv1,pv2,pv3,color )
  111.     elseif pv2.y == pv3.y then --Natural flat bottom
  112.         --Sort bottom vertice by x
  113.         if pv3.x < pv2.x then pv3,pv2 = pv2,pv3 end
  114.         drawFlatBottomTriangle(wrapper,pv1,pv2,pv3,color )
  115.     else --General triangle
  116.         local alphaSplit  = (pv2.y-pv1.y)/(pv3.y-pv1.y)
  117.         local zAlphaSplit = (pv2.z-pv1.z)/(pv3.z-pv1.z)
  118.         local wAlphaSplit = (pv2.w-pv1.w)/(pv3.w-pv1.w) --maybe redundant
  119.         local vi = {
  120.             x = pv1.x + ((pv3.x - pv1.x) * alphaSplit),      
  121.             y = pv1.y + ((pv3.y - pv1.y) * alphaSplit),
  122.             z = pv1.z + ((pv3.z - pv1.z) * zAlphaSplit),
  123.             w = pv1.w + ((pv3.w - pv1.w) * wAlphaSplit)
  124.         }
  125.         if pv2.x < vi.x then --Major right
  126.             drawFlatBottomTriangle(wrapper,pv1,pv2,vi,color)
  127.             drawFlatTopTriangle(wrapper,pv2,vi,pv3,color)
  128.         else --Major left
  129.             drawFlatBottomTriangle(wrapper,pv1,vi,pv2,color)
  130.             drawFlatTopTriangle(wrapper,vi,pv2,pv3,color)
  131.         end
  132.     end
  133. end
  134.  
  135. --Draw an entire object one triangle at a time
  136. --Converts points from the 1D table to vectors b/c I'm lazy and it's easier to process this way
  137. local function drawSolidObj( wrapper, vL ) --vL == index List. cL == color list
  138.     term.setBackgroundColour(colors.white)
  139.     local cL = vL.colorList
  140.         --OPTIMIZATION here?. Probably should convert to 1D at least for full optimization
  141.     for i = 1, #vL, 12 do
  142.         local v1 = vector.new( vL[i],   vL[i+1], vL[i+2]  )
  143.         local v2 = vector.new( vL[i+4], vL[i+5], vL[i+6]  )
  144.         local v3 = vector.new( vL[i+8], vL[i+9], vL[i+10] )
  145.         v1.w = vL[i+3]
  146.         v2.w = vL[i+7]
  147.         v3.w = vL[i+11]
  148.         drawSolidTriangle( wrapper, v1, v2, v3, cL[(i+2)/3] )
  149.     end
  150.     term.setBackgroundColour(colors.black)
  151. end
  152. -- + || 0, 1, 2, 3, || 4, 5, 6, 7, || 8, 9,  10, 11
  153. -- = || 1, 2, 3, 4, || 5, 6, 7, 8, || 9, 10, 11, 12
  154. -- K || x, y, z, w, || x, y, z, w, || x, y,  z,  w
  155.  
  156. --Expose functions
  157. return
  158. {
  159.     drawWireObj = drawWireObj,
  160.     drawSolidObj = drawSolidObj,
  161. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement