Advertisement
Xelostar

ThreeD_API_v0.5.1

Jul 22nd, 2018
653
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 24.10 KB | None | 0 0
  1.  
  2. -- Made by Xelostar: https://www.youtube.com/channel/UCDE2STpSWJrIUyKtiYGeWxw
  3.  
  4. local function round(number)
  5.     return math.floor(number + 0.5)
  6. end
  7.  
  8. local function sortPolygons(polygons, objectX, objectY, objectZ, cameraX, cameraY, cameraZ)
  9.     local sortedPolygons = {}
  10.  
  11.     for i = 1, #polygons do
  12.         local polygon = polygons[i]
  13.  
  14.         local avgX = (math.min(polygon[1] + objectX, polygon[4] + objectX, polygon[7] + objectX) + math.max(polygon[1] + objectX, polygon[4] + objectX, polygon[7] + objectX)) * 0.5
  15.         local avgY = (math.min(polygon[2] + objectY, polygon[5] + objectY, polygon[8] + objectY) + math.max(polygon[2] + objectY, polygon[5] + objectY, polygon[8] + objectY)) * 0.5
  16.         local avgZ = (math.min(polygon[3] + objectZ, polygon[6] + objectZ, polygon[9] + objectZ) + math.max(polygon[3] + objectZ, polygon[6] + objectZ, polygon[9] + objectZ)) * 0.5
  17.  
  18.         local dX = cameraX - avgX
  19.         local dY = cameraY - avgY
  20.         local dZ = cameraZ - avgZ
  21.  
  22.         local distance = math.pow(dX*dX + dY*dY + dZ*dZ, 0.5)
  23.  
  24.         polygon[14] = distance
  25.         sortedPolygons[#sortedPolygons+1] = polygon
  26.     end
  27.    
  28.     table.sort(sortedPolygons, function(a, b) return a[14] > b[14] end)
  29.    
  30.     return sortedPolygons
  31. end
  32.  
  33. local function loadModel(modelName, modelsDir)
  34.     local modelFile = fs.open(modelsDir.."/"..modelName, "r")
  35.     content = modelFile.readAll()
  36.     modelFile.close()
  37.  
  38.     local model = textutils.unserialise(content)
  39.  
  40.     return model
  41. end
  42.  
  43. local function rotatePolygon(x, y, z, rotationY)
  44.     local x = x + 0.0000001
  45.     local y = y + 0.0000001
  46.     local z = z + 0.0000001
  47.     local hAlpha = math.deg(math.atan(x / z))
  48.     if (z < 0) then
  49.         if (x < 0) then
  50.             hAlpha = hAlpha - 180
  51.         else
  52.             hAlpha = hAlpha + 180
  53.         end
  54.     else
  55.         hAlpha = hAlpha
  56.     end
  57.  
  58.     local hAlpha2 = hAlpha + rotationY
  59.     if (hAlpha2 > 180) then
  60.         while (hAlpha2 > 180) do
  61.             hAlpha2 = hAlpha2 - 360
  62.         end
  63.     elseif (hAlpha2 < -180) then
  64.         while (hAlpha2 < -180) do
  65.             hAlpha2 = hAlpha2 + 360
  66.         end
  67.     end
  68.  
  69.     local hDistance = x / math.sin(math.rad(hAlpha))
  70.  
  71.     local x = hDistance * math.sin(math.rad(hAlpha2))
  72.     local z = hDistance * math.cos(math.rad(hAlpha2))
  73.  
  74.     return x, y, z
  75. end
  76.  
  77. local function rotateModel(model, rotationY)
  78.     if (rotationY ~= 0) then
  79.         local rotatedModel = {}
  80.  
  81.         for _, polygon in pairs(model) do
  82.             local x1, y1, z1 = rotatePolygon(polygon[1], polygon[2], polygon[3], rotationY)
  83.             local x2, y2, z2 = rotatePolygon(polygon[4], polygon[5], polygon[6], rotationY)
  84.             local x3, y3, z3 = rotatePolygon(polygon[7], polygon[8], polygon[9], rotationY)
  85.  
  86.             rotatedModel[#rotatedModel+1] = {x1, y1, z1, x2, y2, z2, x3, y3, z3}
  87.             rotatedModel[#rotatedModel][10] = polygon[10]
  88.             rotatedModel[#rotatedModel][11] = polygon[11]
  89.             rotatedModel[#rotatedModel][12] = polygon[12]
  90.             rotatedModel[#rotatedModel][13] = polygon[13]
  91.         end
  92.  
  93.         return rotatedModel
  94.     else
  95.         return model
  96.     end
  97. end
  98.  
  99. local function sortObjects(objects, cameraX, cameraY, cameraZ, renderDistance)
  100.     local sortedObjects = {}
  101.  
  102.     for i = 1, #objects do
  103.         local object = objects[i]
  104.         local dX = cameraX - object.x
  105.         local dY = cameraY - object.y
  106.         local dZ = cameraZ - object.z
  107.         local distance = math.pow(dX*dX + dY*dY + dZ*dZ, 0.5)
  108.         if (distance <= renderDistance) then
  109.             object.distance = distance
  110.             sortedObjects[#sortedObjects+1] = object
  111.         end
  112.     end
  113.    
  114.     table.sort(sortedObjects, function (a, b) return a.distance > b.distance end)
  115.    
  116.     return sortedObjects
  117. end
  118.  
  119. local function rotate90(vector)
  120.     local newVector = {x = -vector.y, y = vector.x}
  121.     return newVector
  122. end
  123.  
  124. local function dot(a, b)
  125.     return (a.x * b.x + a.y * b.y)
  126. end
  127.  
  128. local function isFacingCamera(pointA, pointB, pointC)
  129.     local dirAB = {}
  130.     dirAB.x = pointB.x - pointA.x
  131.     dirAB.y = pointB.y - pointA.y
  132.  
  133.     local dirBC = {}
  134.     dirBC.x = pointC.x - pointB.x
  135.     dirBC.y = pointC.y - pointB.y
  136.  
  137.     if (dot(rotate90(dirAB), dirBC) < 0) then
  138.         return true
  139.     end
  140.  
  141.     return false
  142. end
  143.  
  144. local function linear(x1, y1, x2, y2)
  145.     local dy = y2 - y1
  146.     local dx = x2 - x1
  147.  
  148.     local a = math.pow(10, 99)
  149.     if (dx ~= 0) then
  150.         a = dy / dx
  151.     end
  152.     local b = y1 - a * x1
  153.  
  154.     return a, b
  155. end
  156.  
  157. local function isInLine(checkX, checkY, x1, y1, x2, y2, framex1, framey1, framex2, framey2)
  158.     local a, b = linear(x1, y1, x2, y2)
  159.  
  160.     if (x2 >= x1) then
  161.         local start = x1>1 and x1 or 1
  162.         for x = start, x2 do
  163.             if (x == checkX) then
  164.                 local y = a * x + b
  165.                 if (y == checkY) then
  166.                     return true
  167.                 end
  168.             end
  169.  
  170.             if (x > framex2 - framex1 + 6) then
  171.                 break
  172.             end
  173.         end
  174.     else
  175.         local start = x2>1 and x2 or 1
  176.         for x = start, x1 do
  177.             if (x == checkX) then
  178.                 local y = a * x + b
  179.                 if (y == checkY) then
  180.                     return true
  181.                 end
  182.             end
  183.  
  184.             if (x > framex2 - framex1 + 6) then
  185.                 break
  186.             end
  187.         end
  188.     end
  189.  
  190.     if (y2 >= y1) then
  191.         local start = y1>1 and y1 or 1
  192.         for y = start, y2 do
  193.             if (y == checkY) then
  194.                 local x = (y - b) / a
  195.                 if (x == checkX) then
  196.                     return true
  197.                 end
  198.             end
  199.  
  200.             if (y > framey2 - framey1 + 6) then
  201.                 break
  202.             end
  203.         end
  204.     else
  205.         local start = y2>1 and y2 or 1
  206.         for y = start, y1 do
  207.             if (y == checkY) then
  208.                 local x = (y - b) / a
  209.                 if (x == checkX) then
  210.                     return true
  211.                 end
  212.             end
  213.  
  214.             if (y > framey2 - framey1 + 6) then
  215.                 break
  216.             end
  217.         end
  218.     end
  219.  
  220.     return false
  221. end
  222.  
  223. local function isInHorLine(checkX, checkY, a1, b1, a2, b2, startY, endY, framex1, framey1, framex2, framey2)
  224.     if (startY < 0) then startY = 0
  225.     elseif (startY > framey2 - framey1 + 2) then startY = framey2 - framey1 + 2 end
  226.     if (endY < 0) then endY = 0
  227.     elseif (endY > framey2 - framey1 + 2) then endY = framey2 - framey1 + 2 end
  228.  
  229.     for y = startY, endY do
  230.         if (y == checkY) then
  231.             local y2 = y
  232.             if (y ~= startY and y ~= endY) then
  233.                 y2 = round(y)
  234.             end
  235.  
  236.             local x1 = round((round(y2 - 0.5) - b1) / a1)
  237.             local x2 = round((round(y2 - 0.5) - b2) / a2)
  238.  
  239.             if (x1 < 0) then x1 = 0
  240.             elseif (x1 > framex2 - framex1 + 2) then x1 = framex2 - framex1 + 2 end
  241.             if (x2 < 0) then x2 = 0
  242.             elseif (x2 > framex2 - framex1 + 2) then x2 = framex2 - framex1 + 2 end
  243.  
  244.             if (x1 < x2) then
  245.                 for x = x1, x2 do
  246.                     if (x == checkX) then
  247.                         return true
  248.                     end
  249.                 end
  250.             else
  251.                 for x = x2, x1 do
  252.                     if (x == checkX) then
  253.                         return true
  254.                     end
  255.                 end
  256.             end
  257.         end
  258.     end
  259.  
  260.     return false
  261. end
  262.  
  263. local function sign(p1, p2, p3)
  264.     return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y)
  265. end
  266.  
  267. local function isInTriangle(checkX, checkY, x1, y1, x2, y2, x3, y3, framex1, framey1, framex2, framey2, alternative)
  268.     if (not alternative) then
  269.         local a1, b1 = linear(x1, y1, x2, y2)
  270.         local a2, b2 = linear(x2, y2, x3, y3)
  271.         local a3, b3 = linear(x1, y1, x3, y3)
  272.  
  273.         if (y1 <= y2 and y1 <= y3) then
  274.             if (y2 <= y3) then
  275.                 if (a1 ~= 0) then
  276.                     if (isInHorLine(checkX, checkY, a1, b1, a3, b3, y1, y2, framex1, framey1, framex2, framey2)) then
  277.                         return true
  278.                     end
  279.                 end
  280.                 if (a2 ~= 0) then
  281.                     if (isInHorLine(checkX, checkY, a2, b2, a3, b3, y2, y3, framex1, framey1, framex2, framey2)) then
  282.                         return true
  283.                     end
  284.                 end
  285.             else
  286.                 if (a3 ~= 0) then
  287.                     if (isInHorLine(checkX, checkY, a1, b1, a3, b3, y1, y3, framex1, framey1, framex2, framey2)) then
  288.                         return true
  289.                     end
  290.                 end
  291.                 if (a2 ~= 0) then
  292.                     if (isInHorLine(checkX, checkY, a1, b1, a2, b2, y3, y2, framex1, framey1, framex2, framey2)) then
  293.                         return true
  294.                     end
  295.                 end
  296.             end
  297.         elseif (y2 <= y1 and y2 <= y3) then
  298.             if (y1 <= y3) then
  299.                 if (a1 ~= 0) then
  300.                     if (isInHorLine(checkX, checkY, a1, b1, a2, b2, y2, y1, framex1, framey1, framex2, framey2)) then
  301.                         return true
  302.                     end
  303.                 end
  304.                 if (a3 ~= 0) then
  305.                     if (isInHorLine(checkX, checkY, a2, b2, a3, b3, y1, y3, framex1, framey1, framex2, framey2)) then
  306.                         return true
  307.                     end
  308.                 end
  309.             else
  310.                 if (a2 ~= 0) then
  311.                     if (isInHorLine(checkX, checkY, a1, b1, a2, b2, y2, y3, framex1, framey1, framex2, framey2)) then
  312.                         return true
  313.                     end
  314.                 end
  315.                 if (a3 ~= 0) then
  316.                     if (isInHorLine(checkX, checkY, a1, b1, a3, b3, y3, y1, framex1, framey1, framex2, framey2)) then
  317.                         return true
  318.                     end
  319.                 end
  320.             end
  321.         else
  322.             if (y1 <= y2) then
  323.                 if (a3 ~= 0) then
  324.                     if (isInHorLine(checkX, checkY, a2, b2, a3, b3, y3, y1, framex1, framey1, framex2, framey2)) then
  325.                         return true
  326.                     end
  327.                 end
  328.                 if (a1 ~= 0) then
  329.                     if (isInHorLine(checkX, checkY, a1, b1, a2, b2, y1, y2, framex1, framey1, framex2, framey2)) then
  330.                         return true
  331.                     end
  332.                 end
  333.             else
  334.                 if (a2 ~= 0) then
  335.                     if (isInHorLine(checkX, checkY, a2, b2, a3, b3, y3, y2, framex1, framey1, framex2, framey2)) then
  336.                         return true
  337.                     end
  338.                 end
  339.                 if (a1 ~= 0) then
  340.                     if (isInHorLine(checkX, checkY, a1, b1, a3, b3, y2, y1, framex1, framey1, framex2, framey2)) then
  341.                         return true
  342.                     end
  343.                 end
  344.             end
  345.         end
  346.  
  347.         if (isInLine(checkX, checkY, x1, y1, x2, y2, framex1, framey1, framex2, framey2)) then
  348.             return true
  349.         elseif (isInLine(checkX, checkY, x2, y2, x3, y3, framex1, framey1, framex2, framey2)) then
  350.             return true
  351.         elseif (isInLine(checkX, checkY, x3, y3, x1, y1, framex1, framey1, framex2, framey2)) then
  352.             return true
  353.         end
  354.  
  355.         return false
  356.     else -- alternative (faster but doesn't exactly match the triangles that are drawn)
  357.         local b1 = sign({x = checkX, y = checkY}, {x = x1, y = y1}, {x = x2, y = y2}) < 0
  358.         local b2 = sign({x = checkX, y = checkY}, {x = x2, y = y2}, {x = x3, y = y3}) < 0
  359.         local b3 = sign({x = checkX, y = checkY}, {x = x3, y = y3}, {x = x1, y = y1}) < 0
  360.  
  361.         return ((b1 == b2) and (b2 == b3))
  362.     end
  363. end
  364.  
  365. local pi = math.pi
  366. local doublepi = 2 * math.pi
  367. local halfpi = 0.5 * math.pi
  368.  
  369. function newFrame(x1, y1, x2, y2, FoV, cameraX, cameraY, cameraZ, cameraDirZ, cameraDirY, modelsDir, oldModelsDir)
  370.     if (x1 == nil or y1 == nil or x2 == nil or y2 == nil) then
  371.         error("When creating a new frame, the size must be specified!")
  372.     end
  373.  
  374.     local frame = {}
  375.     frame.modelsDir = oldModelsDir or modelsDir or "/models"
  376.     frame.models = {}
  377.     frame.modelsSorted = {}
  378.     frame.saveSortedModelsBool = false
  379.  
  380.     frame.frameX1 = x1
  381.     frame.frameY1 = y1
  382.     frame.frameX2 = x2
  383.     frame.frameY2 = y2
  384.  
  385.     frame.buffer = bufferAPI.newBuffer(x1, y1, x2, y2)
  386.     frame.buffer:clear(colors.white)
  387.  
  388.     frame.blittleOn = false
  389.     frame.pixelratio = 1.5
  390.  
  391.     frame.renderDistance = math.huge
  392.     frame.FoV = FoV or 90
  393.     frame.d = 0.2
  394.     frame.t = math.tan(math.rad(frame.FoV / 2)) * 2 * frame.d
  395.  
  396.     frame.cameraDirZ = 0
  397.     if (cameraDirZ) then
  398.         frame.cameraDirZ = math.rad(cameraDirZ)
  399.     end
  400.     frame.cameraDirY = 0
  401.     if (cameraDirY) then
  402.         frame.cameraDirY = math.rad(cameraDirY)
  403.     end
  404.  
  405.     frame.cameraX = cameraX or 0
  406.     frame.cameraY = cameraY or 0
  407.     frame.cameraZ = cameraZ or 0
  408.  
  409.     frame.loadedBackgroundColor = false
  410.  
  411.     function frame:setSize(x1, y1, x2, y2)
  412.         self.frameX1 = x1
  413.         self.frameY1 = y1
  414.         self.frameX2 = x2
  415.         self.frameY2 = y2
  416.  
  417.         if (not self.blittleOn) then
  418.             self.buffer:setBufferSize(x1, y1, x2, y2)
  419.             self.width = x2 - x1 + 1
  420.             self.height = y2 - y1 + 1
  421.             self.pixelratio = 1.5
  422.         else
  423.             self.buffer:setBufferSize(x1 * 2, y1 * 3, x2 * 2, y2 * 3)
  424.             self.width = (x2 - x1 + 1) * 2
  425.             self.height = (y2 - y1 + 1) * 3
  426.             self.pixelratio = 1
  427.         end
  428.     end
  429.  
  430.     function frame:useBLittle(use)
  431.         self.blittleOn = use
  432.         if (use) then
  433.             self.buffer:setBufferSize((self.frameX1 - 1) * 2 + 1, (self.frameY1 - 1) * 3 + 1, (self.frameX2) * 2, (self.frameY2 + 1) * 3)
  434.             self.width = (self.frameX2 - self.frameX1 + 1) * 2
  435.             self.height = (self.frameY2 - self.frameY1 + 1) * 3
  436.             self.pixelratio = 1
  437.         else
  438.             self.buffer:setBufferSize(self.frameX1, self.frameY1, self.frameX2, self.frameY2)
  439.             self.width = self.frameX2 - self.frameX1 + 1
  440.             self.height = self.frameY2 - self.frameY1 + 1
  441.             self.pixelratio = 1.5
  442.         end
  443.     end
  444.  
  445.     function frame:setCamera(cameraX, cameraY, cameraZ, cameraDirY, cameraDirZ, FoV)
  446.         self.cameraX = cameraX + 0.001
  447.         self.cameraY = cameraY + 0.001
  448.         self.cameraZ = cameraZ + 0.001
  449.  
  450.         if (cameraDirY ~= nil) then
  451.             self.cameraDirY = math.rad(cameraDirY) + 0.001
  452.         end
  453.         if (cameraDirZ ~= nil) then
  454.             self.cameraDirZ = math.rad(cameraDirZ) + 0.001
  455.         end
  456.         if (FoV ~= nil) then
  457.             self.FoV = FoV
  458.         end
  459.     end
  460.  
  461.     function frame:setRenderDistance(renderDistance)
  462.         self.renderDistance = renderDistance
  463.     end
  464.  
  465.     function frame:loadModel(modelName, model)
  466.         local transformedModel = {}
  467.         for plyNr, polygon in pairs(model) do
  468.             transformedModel[#transformedModel+1] = {}
  469.             transformedModel[#transformedModel][1] = polygon.x1
  470.             transformedModel[#transformedModel][2] = polygon.y1
  471.             transformedModel[#transformedModel][3] = polygon.z1
  472.             transformedModel[#transformedModel][4] = polygon.x2
  473.             transformedModel[#transformedModel][5] = polygon.y2
  474.             transformedModel[#transformedModel][6] = polygon.z2
  475.             transformedModel[#transformedModel][7] = polygon.x3
  476.             transformedModel[#transformedModel][8] = polygon.y3
  477.             transformedModel[#transformedModel][9] = polygon.z3
  478.             transformedModel[#transformedModel][10] = polygon.forceRender
  479.             transformedModel[#transformedModel][11] = polygon.c
  480.             transformedModel[#transformedModel][12] = polygon.char
  481.             transformedModel[#transformedModel][13] = polygon.charc
  482.         end
  483.         self.models[modelName] = transformedModel
  484.     end
  485.  
  486.     function frame:getModel(modelName)
  487.         local model = self.models[modelName]
  488.         local transformedModel = {}
  489.         for key, polygon in pairs(model) do
  490.             transformedModel[key] = {x1 = polygon[1], y1 = polygon[2], z1 = polygon[3], x2 = polygon[4], y2 = polygon[5], z2 = polygon[6], x3 = polygon[7], y3 = polygon[8], z3 = polygon[9], forceRender = polygon[10], c = polygon[11], char = polygon[12], charc = polygon[13]}
  491.         end
  492.  
  493.         return transformedModel
  494.     end
  495.  
  496.     function frame:saveSortedModels(c)
  497.         self.saveSortedModelsBool = c
  498.     end
  499.  
  500.     function frame:findPointOnScreen(oX, oY, oZ)
  501.         local dX = oX - self.cameraX
  502.         local dY = oY - self.cameraY
  503.         local dZ = oZ - self.cameraZ
  504.  
  505.         -- Horizontal rotation
  506.  
  507.         local hAlpha = math.atan(dX / dZ)
  508.         if (dZ < 0) then
  509.             if (dX < 0) then
  510.                 hAlpha = hAlpha - pi
  511.             else
  512.                 hAlpha = hAlpha + pi
  513.             end
  514.         end
  515.  
  516.         local hAlpha2 = hAlpha + self.cameraDirY
  517.         if (hAlpha2 > pi) then
  518.                 hAlpha2 = hAlpha2 - doublepi
  519.         elseif (hAlpha2 < -pi) then
  520.                 hAlpha2 = hAlpha2 + doublepi
  521.         end
  522.  
  523.         local hDistance = dX / math.sin(hAlpha)
  524.  
  525.         local dX = hDistance * math.sin(hAlpha2)
  526.         local dZ = hDistance * math.cos(hAlpha2)
  527.  
  528.         -- Vertical rotation
  529.  
  530.         local vAlpha = math.atan(dY / dX)
  531.  
  532.         if (dX < 0) then
  533.             if (dY < 0) then
  534.                 vAlpha = vAlpha - pi
  535.             else
  536.                 vAlpha = vAlpha + pi
  537.             end
  538.         end
  539.  
  540.         local vAlpha2 = vAlpha - self.cameraDirZ
  541.         if (vAlpha2 > pi) then
  542.             vAlpha2 = vAlpha2 - doublepi
  543.         elseif (hAlpha2 < -pi) then
  544.             vAlpha2 = vAlpha2 + doublepi
  545.         end
  546.  
  547.         if (vAlpha2 >= halfpi or vAlpha2 <= -halfpi) then
  548.             return 0, 0, false
  549.         end
  550.  
  551.         local vDistance = dX / math.cos(vAlpha)
  552.  
  553.         local dY = vDistance * math.sin(vAlpha2)
  554.         local dX = vDistance * math.cos(vAlpha2)
  555.        
  556.         -- Recalculating horizontal angle after vertical rotation
  557.  
  558.         local hAlpha3 = math.atan(dX / dZ)
  559.         if (dZ < 0) then
  560.             if (dX < 0) then
  561.                 hAlpha3 = hAlpha3 - pi
  562.             else
  563.                 hAlpha3 = hAlpha3 + pi
  564.             end
  565.         end
  566.  
  567.         -- Using the angles to calculate the coordinates on the screen
  568.  
  569.         local tx = 0
  570.         if (hAlpha3 > 0 and hAlpha3 < halfpi) then
  571.             tx = self.d / math.tan(hAlpha3)
  572.         elseif (hAlpha3 >= halfpi and hAlpha3 < pi) then
  573.             tx = self.d * -math.tan(hAlpha3 - halfpi)
  574.         end
  575.  
  576.         if (hAlpha3 >= pi or hAlpha3 <= 0) then
  577.             return 0, 0, false
  578.         end
  579.  
  580.         local x = tx / self.t * self.width + math.floor(self.width * 0.5) + 1
  581.         local y = -self.d * math.tan(vAlpha2) * self.width / (self.t * self.height * self.pixelratio) * self.height + math.floor(self.height * 0.5)
  582.         if (y ~= y) then
  583.             y = math.floor(self.height * 0.5)
  584.         end
  585.  
  586.         return x, y, true
  587.     end
  588.  
  589.     function frame:loadObject(object)
  590.         local x = object.x
  591.         local y = object.y
  592.         local z = object.z
  593.  
  594.         local oX, oY, onScreen = self:findPointOnScreen(x, y, z)
  595.  
  596.         if (oX ~= nil) then
  597.             local modelName = object.model
  598.             if (modelName == "flip") then
  599.                 local oWidth = object.width
  600.                 local oHeight = object.height
  601.  
  602.                 local x1, y1 = self:findPointOnScreen(x, y - 0.5 + oHeight, z)
  603.                 local x2, y2 = self:findPointOnScreen(x, y - 0.5, z)
  604.  
  605.                 local height = math.abs(y2 - y1)
  606.                 local width = 1
  607.                 if (self.blittleOn) then
  608.                     width = math.abs(height * oWidth / oHeight)
  609.                 else
  610.                     width = math.abs(height * oWidth / oHeight * 1.5)
  611.                 end
  612.  
  613.                 height = math.floor(height)
  614.                 width = math.floor(width)
  615.  
  616.                 local color = object.color
  617.  
  618.                 if (x1 ~= nil and y1 ~= nil and x2 ~= nil and y2 ~= nil) then
  619.                     self.buffer:loadBox(x1 - (0.5 * width), y1, x2 + (0.5 * width), y2, color, color, " ")
  620.                 end
  621.             else
  622.                 local model = {}
  623.                 if (self.models[modelName] == nil) then
  624.                     self:loadModel(modelName, loadModel(modelName, self.modelsDir))
  625.                 end
  626.                 model = self.models[modelName]
  627.  
  628.                 local rotatedModel = object.rotationY ~= nil and object.rotationY ~= 0 and rotateModel(model, object.rotationY) or model
  629.                 local sortedPolygons = sortPolygons(rotatedModel, x, y, z, self.cameraX, self.cameraY, self.cameraZ)
  630.  
  631.                 if (self.saveSortedModelsBool) then
  632.                     if (object.rotationY == nil or object.rotationY == 0) then
  633.                         if (self.modelsSorted[modelName] == nil) then
  634.                             self.models[modelName] = sortedPolygons
  635.                             self.modelsSorted[modelName] = true
  636.                         end
  637.                     end
  638.                 end
  639.  
  640.                 for i = 1, #sortedPolygons do
  641.                     local polygon = sortedPolygons[i]
  642.                    
  643.                     local x1, y1, onScreen1 = self:findPointOnScreen(x + polygon[1], y + polygon[2], z + polygon[3])
  644.                     if (onScreen1) then
  645.                         local x2, y2, onScreen2 = self:findPointOnScreen(x + polygon[4], y + polygon[5], z + polygon[6])
  646.                         if (onScreen2) then
  647.                             local x3, y3, onScreen3 = self:findPointOnScreen(x + polygon[7], y + polygon[8], z + polygon[9])
  648.                             if (onScreen3) then
  649.                                 if (polygon[10] or isFacingCamera({x = x1, y = y1}, {x = x2, y = y2}, {x = x3, y = y3})) then
  650.                                     self.buffer:loadTriangle(round(x1), round(y1), round(x2), round(y2), round(x3), round(y3), polygon[11], polygon[12], polygon[13])
  651.                                 end
  652.                             end
  653.                         end
  654.                     end
  655.                 end
  656.             end
  657.         end
  658.     end
  659.  
  660.     function frame:loadObjects(objects)
  661.         if (not self.loadedBackgroundColor) then
  662.             self.buffer:clear(colors.white)
  663.         end
  664.  
  665.         local sortedObjects = sortObjects(objects, self.cameraX, self.cameraY, self.cameraZ, self.renderDistance)
  666.  
  667.         self.modelsSorted = {}
  668.         for i = 1, #sortedObjects do
  669.             self:loadObject(sortedObjects[i])
  670.         end
  671.  
  672.         self.loadedBackgroundColor = false
  673.  
  674.         return sortedObjects
  675.     end
  676.  
  677.     function frame:drawBuffer()
  678.         self.buffer:drawBuffer(self.blittleOn)
  679.     end
  680.  
  681.     function frame:loadGround(color, char, charc)
  682.         local distance = 10
  683.         local gX = distance * math.cos(self.cameraDirY) + self.cameraX
  684.         local gZ = distance * math.sin(self.cameraDirY) + self.cameraZ
  685.         local x, y = self:findPointOnScreen(gX, self.cameraY - 0.01, gZ)
  686.  
  687.         if (y < 0) then y = 0 end
  688.         if (y > (self.frameY2 - self.frameY1 + 2) * 3) then y = (self.frameY2 - self.frameY1 + 2) * 3 end
  689.  
  690.         if (not self.blittleOn) then
  691.             self.buffer:loadBox(1, y, self.frameX2 - self.frameX1 + 1, self.frameY2 - self.frameY1 + 2, charc or color, color, char or " ")
  692.         else
  693.             self.buffer:loadBox(1, y, (self.frameX2 - self.frameX1 + 1) * 2, (self.frameY2 - self.frameY1 + 2) * 3, charc or color, color, char or " ")
  694.         end
  695.  
  696.         self.loadedBackgroundColor = true
  697.     end
  698.  
  699.     function frame:loadSky(color, char, charc)
  700.         local distance = 10
  701.         local gX = distance * math.cos(self.cameraDirY) + self.cameraX
  702.         local gZ = distance * math.sin(self.cameraDirY) + self.cameraZ
  703.         local x, y = self:findPointOnScreen(gX, self.cameraY - 0.01, gZ)
  704.  
  705.         if (y < 0) then y = 0 end
  706.         if (y > (self.frameY2 - self.frameY1 + 2) * 3) then y = (self.frameY2 - self.frameY1 + 2) * 3 end
  707.        
  708.         if (not self.blittleOn) then
  709.             self.buffer:loadBox(1, 1, self.frameX2 - self.frameX1 + 1, y, charc or color, color, char or " ")
  710.         else
  711.             self.buffer:loadBox(1, 1, (self.frameX2 - self.frameX1 + 1) * 2, y, charc or color, color, char or " ")
  712.         end
  713.  
  714.         self.loadedBackgroundColor = true
  715.     end
  716.  
  717.     function frame:getObjectIndexTrace(objects, x, y, alternative)
  718.         local solutions = {}
  719.         if (self.blittleOn) then
  720.             x = x * 2
  721.             y = y * 3
  722.         end
  723.  
  724.         for i = 1, #objects do
  725.             local object = objects[i]
  726.  
  727.             local model = {}
  728.             if (self.models[object.model] ~= nil) then
  729.                 model = self.models[object.model]
  730.             else
  731.                 model = loadModel(object.model, self.modelsDir)
  732.                 self.models[object.model] = model
  733.             end
  734.  
  735.             local rotatedModel = object.rotationY ~= nil and object.rotationY ~= 0 and rotateModel(model, object.rotationY) or model
  736.  
  737.             for j = 1, #rotatedModel do
  738.                 local polygon = rotatedModel[j]
  739.                
  740.                 local x1, y1, onScreen1 = self:findPointOnScreen(object.x + polygon[1], object.y + polygon[2], object.z + polygon[3])
  741.                 local x2, y2, onScreen2 = self:findPointOnScreen(object.x + polygon[4], object.y + polygon[5], object.z + polygon[6])
  742.                 local x3, y3, onScreen3 = self:findPointOnScreen(object.x + polygon[7], object.y + polygon[8], object.z + polygon[9])
  743.  
  744.                 if (polygon[10] or isFacingCamera({x = x1, y = y1}, {x = x2, y = y2}, {x = x3, y = y3})) then
  745.                     if (onScreen1 and onScreen2 and onScreen3) then
  746.                         if (not self.blittleOn) then
  747.                             if (isInTriangle(x, y, round(x1), round(y1), round(x2), round(y2), round(x3), round(y3), self.frameX1, self.frameY1, self.frameX2, self.frameY2, alternative)) then
  748.                                 solutions[#solutions+1] = {objectIndex = i, polygonIndex = j}
  749.                             end
  750.                         else
  751.                             if (isInTriangle(x, y, round(x1), round(y1), round(x2), round(y2), round(x3), round(y3), (self.frameX1 - 1) * 2 + 1, (self.frameY1 - 1) * 3 + 1, (self.frameX2) * 2, (self.frameY2 + 1) * 3, alternative)) then
  752.                                 solutions[#solutions+1] = {objectIndex = i, polygonIndex = j}
  753.                             end
  754.                         end
  755.                     end
  756.                 end
  757.             end
  758.         end
  759.  
  760.         if (#solutions <= 0) then
  761.             return
  762.         end
  763.  
  764.         local objectSolution = {}
  765.  
  766.         local closestObject = -1
  767.         local closestObjectDistance = math.huge
  768.         for i = 1, #solutions do
  769.             local object = objects[solutions[i].objectIndex]
  770.  
  771.             local dX = self.cameraX - object.x
  772.             local dY = self.cameraY - object.y
  773.             local dZ = self.cameraZ - object.z
  774.             local distance = math.pow(dX*dX + dY*dY + dZ*dZ, 0.5)
  775.  
  776.             if (distance < closestObjectDistance) then
  777.                 closestObjectDistance = distance
  778.                 closestObject = solutions[i].objectIndex
  779.             end
  780.         end
  781.         for i = 1, #solutions do
  782.             local object = objects[solutions[i].objectIndex]
  783.  
  784.             local dX = self.cameraX - object.x
  785.             local dY = self.cameraY - object.y
  786.             local dZ = self.cameraZ - object.z
  787.             local distance = math.pow(dX*dX + dY*dY + dZ*dZ, 0.5)
  788.  
  789.             if (distance == closestObjectDistance) then
  790.                 objectSolution[#objectSolution+1] = solutions[i].polygonIndex
  791.             end
  792.         end
  793.  
  794.         local object = objects[closestObject]
  795.         local model = {}
  796.         if (self.models[object.model] ~= nil) then
  797.             model = self.models[object.model]
  798.         else
  799.             model = loadModel(object.model, self.modelsDir)
  800.             self.models[object.model] = model
  801.         end
  802.  
  803.         local closestPolygon = -1
  804.         local closestPolygonDistance = math.huge
  805.  
  806.         for i = 1, #objectSolution do
  807.             local polygon = model[objectSolution[i]]
  808.  
  809.             local avgX = (math.min(unpack({polygon[1] + object.x, polygon[4] + object.x, polygon[7] + object.x})) + math.max(unpack({polygon[1] + object.x, polygon[4] + object.x, polygon[7] + object.x}))) / 2
  810.             local avgY = (math.min(unpack({polygon[2] + object.y, polygon[5] + object.y, polygon[8] + object.y})) + math.max(unpack({polygon[2] + object.y, polygon[5] + object.y, polygon[8] + object.y}))) / 2
  811.             local avgZ = (math.min(unpack({polygon[3] + object.z, polygon[6] + object.z, polygon[9] + object.z})) + math.max(unpack({polygon[3] + object.z, polygon[6] + object.z, polygon[9] + object.z}))) / 2
  812.  
  813.             local dX = self.cameraX - avgX
  814.             local dY = self.cameraY - avgY
  815.             local dZ = self.cameraZ - avgZ
  816.  
  817.             local distance = math.pow(dX*dX + dY*dY + dZ*dZ, 0.5)
  818.  
  819.             if (distance < closestPolygonDistance) then
  820.                 closestPolygonDistance = distance
  821.                 closestPolygon = objectSolution[i]
  822.             end
  823.         end
  824.  
  825.         return closestObject, closestPolygon
  826.     end
  827.  
  828.     return frame
  829. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement