jig487

JIG3D_AR_Tools_Dev

Aug 23rd, 2021 (edited)
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.98 KB | None | 0 0
  1. -- AR tools API
  2.  
  3. --###  Wireframe drawing functions  ###
  4.  
  5. --Draws a line from x1,y1 to x2,y2 with given color, using name of wrapped AR controller
  6. local function drawLineAR(arController,x1,y1,x2,y2,color)
  7.     color = 0x000000 --Overriding color to black. Comment out to use custom colors
  8.     local dx = x2 - x1 --Distance between x's
  9.     local dy = y2 - y1 --Distance between y's
  10.     local dh = math.sqrt((dx*dx)+(dy*dy))
  11.     for i = 1, dh do
  12.         local nextY = y1 + dy * (i / dh)
  13.         local nextX = x1 + dx * (i / dh)
  14.         if nextY > 0 and nextX > 0 then
  15.             arController.horizontalLine(nextX, nextX, nextY, color)
  16.         end
  17.     end
  18. end
  19.  
  20. --Draws an object with an indexList which points to a list x/y points, using name of wrapped AR controller
  21. --Wireframe is currently about 2x slower than drawing solid objects
  22. local function drawWireObj(arController,vL,cL) --vL == vertice list. cL == color list
  23.     local vList = {}
  24.     for i = 1, #vL, 3 do --Draws a whole triangle per loop
  25.         local i1,i2 = i+1, i+2
  26.         local col = cL[(i+2)/3]
  27.         drawLineAR(arController, vL[i].x,  vL[i].y,  vL[i1].x, vL[i1].y, col) --vert 1 to 2
  28.         drawLineAR(arController, vL[i1].x, vL[i1].y, vL[i2].x, vL[i2].y, col) --vert 2 to 3
  29.         drawLineAR(arController, vL[i2].x, vL[i2].y, vL[i].x,  vL[i].y,  col) --vert 3 to 1
  30.     end
  31. end
  32.  
  33. --###  Solid object drawing functions  ###
  34.  
  35. local function drawFlatTriangle(arController,px1,px2,x,y,color)
  36.     local xStart = math.ceil(px1 - 0.5)
  37.     local xEnd =   math.ceil(px2 - 0.5)
  38.             --To change to individual pixel plotting instead of whole lines, uncomment this `for` loop and replace `(xStart, xEnd, y, color)` with `( x, x, y, color )` in the horizontalLine() function
  39.     for x = xStart, xEnd do
  40.         if y > 0 and x > 0 then
  41.             arController.horizontalLine(x, x, y, color) --Draws a horizontal line. have xStart and xEnd == to the same x val to plot just one pixel
  42.         --elseif y > 0 and xEnd > 0 then
  43.         --    arController.horizontalLine(1, xEnd, y, color)
  44.         end
  45.     end
  46. end
  47.  
  48. --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.
  49. local function drawFlatTopTriangle( arController,vec1,vec2,vec3,color )
  50.     --Calculate slopes in screen space
  51.     --Run over rise so we don't get infinite slopes
  52.     local m1 = (vec3.x - vec1.x) / (vec3.y - vec1.y)
  53.     local m2 = (vec3.x - vec2.x) / (vec3.y - vec2.y)
  54.  
  55.     --Calculate start and end scanlines
  56.     local yStart = math.ceil(vec1.y - 0.5)
  57.     local yEnd =   math.ceil(vec3.y - 0.5)-1 --the scanline AFTER the last line drawn
  58.  
  59.     for y = yStart, yEnd do
  60.         --calculate start and end x's
  61.         --Add 0.5 because we're calculating based on pixel centers
  62.         local px1 = m1 * (y + 0.5 - vec1.y) + vec1.x
  63.         local px2 = m2 * (y + 0.5 - vec2.y) + vec2.x
  64.  
  65.         drawFlatTriangle(arController,px1,px2,y,color)
  66.     end
  67. end
  68.  
  69. local function drawFlatBottomTriangle( arController,vec1,vec2,vec3,color )
  70.     --Calculate slopes in screen space
  71.     local m1 = (vec2.x - vec1.x) / (vec2.y - vec1.y)
  72.     local m2 = (vec3.x - vec1.x) / (vec3.y - vec1.y)
  73.  
  74.     --Calculate start and end scanlines
  75.     local yStart = math.ceil(vec1.y-0.5)
  76.     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
  77.  
  78.     for y = yStart, yEnd do
  79.  
  80.         --calculate start and end points (x coords)
  81.         --Add 0.5 because we're calculating based on pixel centers
  82.         local px1 = m1 * (y + 0.5 - vec1.y) + vec1.x
  83.         local px2 = m2 * (y + 0.5 - vec1.y) + vec1.x
  84.  
  85.         drawFlatTriangle(arController,px1,px2,y,color)
  86.     end
  87. end
  88.  
  89. --Draw an entire object one triangle at a time
  90. --Converts points from the 1D table to vectors b/c I'm lazy
  91. local function drawSolidObj( arController,vL,cL ) --iL == index List. vL == vertex list. cL == color list
  92.         --OPTIMIZATION here?. Probably should convert to 1D at least
  93.     for i = 1, #vL, 3 do --Try to draw a triangle
  94.             --using pointers so we can swap (for sorting purposes) probably don't need this b/c lua? idk
  95.         local pv1 = vL[1]
  96.         local pv2 = vL[2]
  97.         local pv3 = vL[3]
  98.  
  99.         --Sort vertices by y
  100.         if pv2.y < pv1.y then pv1,pv2 = pv2,pv1 end
  101.         if pv3.y < pv2.y then pv2,pv3 = pv3,pv2 end
  102.         if pv2.y < pv1.y then pv1,pv2 = pv2,pv1 end
  103.  
  104.         if pv1.y == pv2.y then --Natural flat top
  105.             --Sort top vertice by x
  106.             if pv2.x < pv1.x then pv1,pv2 = pv2,pv1 end
  107.             drawFlatTopTriangle(arController,pv1,pv2,pv3)
  108.  
  109.         elseif pv2.y == pv3.y then --Natural flat bottom
  110.             --Sort bottom vertice by x
  111.             if pv3.x < pv2.x then pv3,pv2 = pv2,pv3 end
  112.             drawFlatBottomTriangle(arController,pv1,pv2,pv3)
  113.  
  114.         else --General triangle
  115.             local alphaSplit = (pv2.y-pv1.y)/(pv3.y-pv1.y)
  116.             local vi ={
  117.                 x = pv1.x + ((pv3.x - pv1.x) * alphaSplit),      
  118.                 y = pv1.y + ((pv3.y - pv1.y) * alphaSplit), }
  119.             if pv2.x < vi.x then --Major right
  120.                 drawFlatBottomTriangle(arController,pv1,pv2,vi)
  121.                 drawFlatTopTriangle(arController,pv2,vi,pv3)
  122.             else --Major left
  123.                 drawFlatBottomTriangle(arController,pv1,vi,pv2)
  124.                 drawFlatTopTriangle(arController,vi,pv2,pv3)
  125.             end
  126.         end
  127.     end
  128. end
  129.  
  130. --###  Textured drawing functions  ###
  131.  
  132. local function drawFlatTopTriangleTex( arController,vec1,vec2,vec3, texture  )
  133.     --Calculate slopes in screen space
  134.     --Run over rise so we don't get infinite slopes
  135.     local m1 = (vec3.x - vec1.x) / (vec3.y - vec1.y)
  136.     local m2 = (vec3.x - vec2.x) / (vec3.y - vec2.y)
  137.  
  138.     --Calculate start and end scanlines
  139.     local yStart = math.ceil(vec1.y - 0.5)
  140.     local yEnd =   math.ceil(vec3.y - 0.5)-1 --the scanline AFTER the last line drawn
  141.  
  142.     local tWidth = texture.size.x
  143.     local tHeight = texture.size.y
  144.  
  145.     local A = vec3
  146.     local B = vec2
  147.     local C = vec1
  148.  
  149.     for y = yStart, yEnd do
  150.         --calculate start and end x's
  151.         --Add 0.5 because we're calculating based on pixel centers
  152.         local px1 = m1 * (y + 0.5 - vec1.y) + vec1.x
  153.         local px2 = m2 * (y + 0.5 - vec2.y) + vec2.x
  154.  
  155.         local xStart = math.ceil(px1 - 0.5)
  156.         local xEnd =   math.ceil(px2 - 0.5)
  157.  
  158.             --To change to individual pixel plotting instead of whole lines, uncomment this `for` loop and replace `(xStart, xEnd, y, color)` with `( x, x, y, color )` in the horizontalLine() function
  159.         for x = xStart, xEnd do
  160.  
  161.             if y > 0 and x > 0 then
  162.                     --find w1,w2,w3
  163.                 local w1 =
  164.                     (A.x*(C.y - A.y)+(y - A.y)*(C.x - A.x)-x*(C.y - A.y))
  165.                     /((B.y - A.y)*(C.x - A.x))-((B.x - A.x)*(C.y - A.y))
  166.  
  167.                 local w2 = (y - A.y - w1 *(B.y - A.y))/(C.y - A.y)
  168.  
  169.                 local w3 = 1-w1-w2
  170.                     --find
  171.                 local u = (w1*A.u)+(w2*B.u)+(w3*C.u)
  172.                 local v = (w1*A.v)+(w2*B.v)+(w3*C.v)
  173.                     --final target texture uv coordinates
  174.                 local tu = (u * tWidth)
  175.                 local tv = (v * tHeight)
  176.  
  177.                 local color = texture[ (tv*tWidth) + tu ] --Look up the pixel color in the image texture
  178.  
  179.                 arController.horizontalLine(xStart, xEnd, y, color) --Draws a horizontal line. have xStart and xEnd == to the same x val to plot just one pixel
  180.             end
  181.         end
  182.         --drawFlatTriangle(arController,px1,px2,y,color)
  183.     end
  184. end
  185.  
  186. local function drawFlatBottomTriangleTex( arController,vec1,vec2,vec3, texture  )
  187.     --Calculate slopes in screen space
  188.     local m1 = (vec2.x - vec1.x) / (vec2.y - vec1.y)
  189.     local m2 = (vec3.x - vec1.x) / (vec3.y - vec1.y)
  190.  
  191.     --Calculate start and end scanlines
  192.     local yStart = math.ceil(vec1.y-0.5)
  193.     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
  194.  
  195.     local tWidth = texture.size.x
  196.     local tHeight = texture.size.y
  197.  
  198.     local A = vec3
  199.     local B = vec2
  200.     local C = vec1
  201.  
  202.     for y = yStart, yEnd do
  203.  
  204.         --calculate start and end points (x coords)
  205.         --Add 0.5 because we're calculating based on pixel centers
  206.         local px1 = m1 * (y + 0.5 - vec1.y) + vec1.x
  207.         local px2 = m2 * (y + 0.5 - vec1.y) + vec1.x
  208.  
  209.         local xStart = math.ceil(px1 - 0.5)
  210.         local xEnd =   math.ceil(px2 - 0.5)
  211.  
  212.             --To change to individual pixel plotting instead of whole lines, uncomment this `for` loop and replace `(xStart, xEnd, y, color)` with `( x, x, y, color )` in the horizontalLine() function
  213.         for x = xStart, xEnd do
  214.  
  215.             if y > 0 and x > 0 then
  216.                     --find w1,w2,w3
  217.                 local w1 =
  218.                     (A.x*(C.y - A.y)+(y - A.y)*(C.x - A.x)-x*(C.y - A.y))
  219.                     /((B.y - A.y)*(C.x - A.x))-((B.x - A.x)*(C.y - A.y))
  220.  
  221.                 local w2 = (y - A.y - w1 *(B.y - A.y))/(C.y - A.y)
  222.  
  223.                 local w3 = 1-w1-w2
  224.                     --find
  225.                 local u = (w1*A.u)+(w2*B.u)+(w3*C.u)
  226.                 local v = (w1*A.v)+(w2*B.v)+(w3*C.v)
  227.                     --final texture uv coordinates
  228.                 local tu = (u * tWidth)
  229.                 local tv = (v * tHeight)
  230.  
  231.                 local color = texture[ (tv*tWidth) + tu ] --Look up the pixel color in the image texture
  232.  
  233.                 arController.horizontalLine(xStart, xEnd, y, color) --Draws a horizontal line. have xStart and xEnd == to the same x val to plot just one pixel
  234.             end
  235.         end
  236.     end
  237. end
  238.  
  239. local function drawSolidObjTex( arController,vL,objData) --iL == index List. vL == vertex list. cL == color list
  240.         --OPTIMIZATION here?. Probably should convert to 1D at least
  241.     for i = 1, #vL, 3 do --Try to draw a trianglelocal vec3 = { x= vL[ iL[i2] ], y= vL[ iL[i2]+1 ], z= vL[ iL[i2]+2 ] } --Target vertex3's x/y and z
  242.             --using pointers so we can swap (for sorting purposes) probably don't need this b/c lua? idk
  243.         local texData = {}
  244.         if objData.useShader then
  245.             texData = objData.texData
  246.         end
  247.  
  248.         local pv1 = vL[i]
  249.         local pv2 = vL[i+1]
  250.         local pv3 = vL[i+2]
  251.  
  252.             --Sort vertices by y
  253.         if pv2.y < pv1.y then pv1,pv2 = pv2,pv1 end
  254.         if pv3.y < pv2.y then pv2,pv3 = pv3,pv2 end
  255.         if pv2.y < pv1.y then pv1,pv2 = pv2,pv1 end
  256.  
  257.         if pv1.y == pv2.y then --Natural flat top
  258.                 --Sort top vertice by x
  259.             if pv2.x < pv1.x then pv1,pv2 = pv2,pv1 end
  260.             drawFlatTopTriangle(arController,pv1,pv2,pv3,texData)
  261.  
  262.         elseif pv2.y == pv3.y then --Natural flat bottom
  263.                 --Sort bottom vertice by x
  264.             if pv3.x < pv2.x then pv3,pv2 = pv2,pv3 end
  265.             drawFlatBottomTriangle(arController,pv1,pv2,pv3,texData)
  266.  
  267.         else --General triangle
  268.             local alphaSplit = (pv2.y-pv1.y)/(pv3.y-pv1.y)
  269.             local vi ={
  270.                 x = pv1.x + ((pv3.x - pv1.x) * alphaSplit),      
  271.                 y = pv1.y + ((pv3.y - pv1.y) * alphaSplit),
  272.                 z = pv1.z + ((pv3.z - pv1.z) * alphaSplit),
  273.                 u = pv1.u + ((pv3.u - pv1.u) * alphaSplit),
  274.                 v = pv1.v + ((pv3.v - pv1.v) * alphaSplit),
  275.             }
  276.             if pv2.x < vi.x then --Major right
  277.                 drawFlatBottomTriangle(arController,pv1,pv2,vi,texData)
  278.                 drawFlatTopTriangle(arController,pv2,vi,pv3,texData)
  279.             else --Major left
  280.                 drawFlatBottomTriangle(arController,pv1,vi,pv2,texData)
  281.                 drawFlatTopTriangle(arController,vi,pv2,pv3,texData)
  282.             end
  283.         end
  284.     end
  285. end
  286.  
  287. --Expose functions
  288. return
  289. {
  290.     drawWireObj = drawWireObj,
  291.     drawSolidObj = drawSolidObj,
  292.     drawSolidObjTex = drawSolidObjTex,
  293. }
Add Comment
Please, Sign In to add comment