Advertisement
neuronix

3DSoftEngine v0.3

Dec 11th, 2017
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.20 KB | None | 0 0
  1. local RGB = unpack
  2. local cos = math.cos
  3. local sin = math.sin
  4. local tan = math.tan
  5.  
  6. local tCos, tSin, tTan = {}, {}, {}
  7.  
  8. local torad = function(a)
  9.     return (a * math.pi / 180)
  10. end
  11.  
  12. local init = function()
  13.     for k = -180, 180 do
  14.         table.insert(tCos, cos(torad(k)))
  15.         table.insert(tSin, sin(torad(k)))
  16.         table.insert(tTan, tan(torad(k)))
  17.     end
  18. end
  19.  
  20. if (#tCos) == 0 then
  21.     init()
  22. end
  23.  
  24. local defaultColor = { 0, 0, 0 }
  25.  
  26. local screen = platform.window
  27.  
  28. function def(var)
  29.     return (var ~= nil)
  30. end
  31.  
  32. function undef(var)
  33.     return (var == nil)
  34. end
  35.  
  36. --moteur 2D
  37. --point 2D
  38.  
  39. Point2D = class()
  40.  
  41. function Point2D:init(x, y, color)
  42.     self.x = x
  43.     self.y = y
  44.     if def(color) then
  45.         self.color = color
  46.     else
  47.         self.color = defaultColor
  48.     end
  49.     self.inscreen = true
  50. end
  51.  
  52. function Point2D:changeColor(newcolor)
  53.     self.color = newcolor
  54. end
  55.  
  56. function Point2D:isInScreen()
  57.     self.inscreen = (self.x >= 0 and self.x <= screen:width() and self.y >= 0 and self.y <= screen:height())
  58.     return self.inscreen
  59. end
  60.  
  61. function Point2D:move(x, y)
  62.     self.x = self.x + x
  63.     self.y = self.y + y
  64. end
  65.  
  66. function Point2D:disp(gc)
  67.     if self:isInScreen() then
  68.         gc:setColorRGB(RGB(self.color))
  69.         gc:setPixel(self.x, self.y)
  70.     end
  71. end
  72.  
  73. --ligne 2D
  74.  
  75. Line2D = class()
  76.  
  77. --Line2D(Point2D,Point2D[,color]) or Line2D(Point1x,Point1y,Point2x,Point2y[,color,...])
  78.  
  79. function Line2D:init(point1orx, point2or1y, ...)
  80.     local args = { ... }
  81.     if def(args[2]) then
  82.         if def(args[3]) then
  83.             self.color = args[3]
  84.         else
  85.             self.color = defaultColor
  86.         end
  87.         self.point1 = Point2D(point1orx, point2or1y, self.color)
  88.         self.point2 = Point2D(args[1], args[2], self.color)
  89.     else
  90.         if def(args[1]) then
  91.             self.color = args[1]
  92.         else
  93.             self.color = defaultColor
  94.         end
  95.         self.point1 = point1orx
  96.         self.point2 = point2or1y
  97.         self.point1:changeColor(self.color)
  98.         self.point2:changeColor(self.color)
  99.     end
  100. end
  101.  
  102. function Line2D:changeColor(newcolor)
  103.     self.point1:changeColor(newcolor)
  104.     self.point2:changeColor(newcolor)
  105.     self.color = newcolor
  106. end
  107.  
  108. function Line2D:move(x, y)
  109.     self.point1:move(x, y)
  110.     self.point2:move(x, y)
  111. end
  112.  
  113. function Line2D:disp(gc)
  114.     gc:drawLine(self.point1.x, self.point1.y, self.point2.x, self.point2.y)
  115. end
  116.  
  117. --moteur 3D
  118. --point 3D
  119.  
  120. local fov = 70
  121.  
  122. Point3D = class()
  123.  
  124. function Point3D:init(x, y, z, color)
  125.     self.x = x
  126.     self.y = y
  127.     self.z = z
  128.     if def(color) then
  129.         self.color = color
  130.     else
  131.         self.color = defaultColor
  132.     end
  133.     self.inscreen = true
  134.     self.proj2d = Point2D(0, 0, self.color)
  135. end
  136.  
  137. function Point3D:changeColor(newcolor)
  138.     self.color = newcolor
  139.     self.proj2d:changeColor()
  140. end
  141.  
  142. function Point3D:projection()
  143.     local f = (screen:width() / 2) / tTan[math.floor(fov / 2) + 181]
  144.     self.proj2d.x = math.floor(self.x * f / (self.z + 5) + (screen:width() / 2))
  145.     self.proj2d.y = math.floor((screen:height() / 2) - (self.y * f / (self.z + 5)))
  146.     return self.proj2d
  147. end
  148.  
  149. function Point3D:isInScreen()
  150.     self:projection()
  151.     self.inscreen = ((0 <= self.proj2d.x <= screen:width()) and (0 <= self.proj2d.y <= screen:height()))
  152.     return self.inscreen
  153. end
  154.  
  155. function Point3D:transform(matrix)
  156.     local newPoint3D = Point3D(0, 0, 0, self.color)
  157.     newPoint3D.x = matrix[1][1] * self.x + matrix[1][2] * self.y + matrix[1][3] * self.z
  158.     newPoint3D.y = matrix[2][1] * self.x + matrix[2][2] * self.y + matrix[2][3] * self.z
  159.     newPoint3D.z = matrix[3][1] * self.x + matrix[3][2] * self.y + matrix[3][3] * self.z
  160.     return newPoint3D
  161. end
  162.  
  163. function Point3D:move(x, y, z)
  164.     self.x = self.x + x
  165.     self.y = self.y + y
  166.     self.z = self.z + z
  167. end
  168.  
  169. function Point3D:rotate(xangle, yangle, zangle)
  170.     local newPoint
  171.  
  172.     local xangle, yangle, zangle = xangle + 181, yangle + 181, zangle + 181
  173.  
  174.     local xmatrix = {
  175.         { 1, 0, 0 },
  176.         { 0, tCos[xangle], -tSin[xangle] },
  177.         { 0, tSin[xangle], tCos[xangle] }
  178.     }
  179.     local ymatrix = {
  180.         { tCos[yangle], 0, tSin[yangle] },
  181.         { 0, 1, 0 },
  182.         { -tSin[yangle], 0, tCos[yangle] }
  183.     }
  184.     local zmatrix = {
  185.         { tCos[zangle], -tSin[zangle], 0 },
  186.         { tSin[zangle], tCos[zangle], 0 },
  187.         { 0, 0, 1 }
  188.     }
  189.  
  190.     newPoint = self:transform(xmatrix)
  191.     newPoint = newPoint:transform(ymatrix)
  192.     newPoint = newPoint:transform(zmatrix)
  193.     self.x = newPoint.x
  194.     self.y = newPoint.y
  195.     self.z = newPoint.z
  196. end
  197.  
  198. function Point3D:disp(gc)
  199.     if self:isInScreen() then
  200.         self.proj2d:disp(gc)
  201.     end
  202. end
  203.  
  204. --ligne 3D
  205.  
  206. Line3D = class()
  207.  
  208. function Line3D:init(point1orx, point2or1y, ...)
  209.     local args = { ... }
  210.     if def(args[4]) then
  211.         if def(args[5]) then
  212.             self.color = args[5]
  213.         else
  214.             self.color = defaultColor
  215.         end
  216.         self.point1 = Point3D(point1orx, point2or1y, args[1], self.color)
  217.         self.point2 = Point3D(args[2], args[3], args[4], self.color)
  218.     else
  219.         if def(args[1]) then
  220.             self.color = args[1]
  221.         else
  222.             self.color = defaultColor
  223.         end
  224.         self.point1 = point1orx
  225.         self.point2 = point2or1y
  226.         self.point1:changeColor(self.color)
  227.         self.point2:changeColor(self.color)
  228.     end
  229.     self.proj2d = Line2D(Point2D(0, 0), Point2D(0, 0), self.color)
  230. end
  231.  
  232. function Line3D:changeColor(newcolor)
  233.     self.point1:changeColor(newcolor)
  234.     self.point2:changeColor(newcolor)
  235.     self.proj2d:changeColor(newcolor)
  236.     self.color = newcolor
  237. end
  238.  
  239. function Line3D:projection()
  240.     self.point1:projection()
  241.     self.point2:projection()
  242.     self.proj2d = Line2D(self.point1.proj2d, self.point2.proj2d, self.color)
  243. end
  244.  
  245. function Line3D:rotate(xangle, yangle, zangle)
  246.     self.point1:rotate(xangle, yangle, zangle)
  247.     self.point2:rotate(xangle, yangle, zangle)
  248. end
  249.  
  250. function Line3D:move(x, y, z)
  251.     self.point1:move(x, y, z)
  252.     self.point2:move(x, y, z)
  253. end
  254.  
  255. function Line3D:disp(gc)
  256.     self:projection()
  257.     self.proj2d:disp(gc)
  258. end
  259.  
  260. --objet
  261. --triangle 3D
  262.  
  263. Triangle = class()
  264.  
  265. function Triangle:init(point1, point2, point3, fill, fillcolor, ...)
  266.     local args = { ... }
  267.     if def(args[1]) then
  268.         self.color = args[1]
  269.     else
  270.         self.color = defaultColor
  271.     end
  272.     self.point1 = point1
  273.     self.point2 = point2
  274.     self.point3 = point3
  275.     self.point1:changeColor(self.color)
  276.     self.point2:changeColor(self.color)
  277.     self.point3:changeColor(self.color)
  278.     self.proj2d1 = Point2D(0, 0, self.color)
  279.     self.proj2d2 = Point2D(0, 0, self.color)
  280.     self.proj2d3 = Point2D(0, 0, self.color)
  281.  
  282.     if def(fill) then
  283.         self.tofill = fill
  284.     else
  285.         self.tofill = false
  286.     end
  287.     if def(fillcolor) then
  288.         self.tofillcolor = fillcolor
  289.     else
  290.         self.tofillcolor = defaultColor
  291.     end
  292. end
  293.  
  294. function Triangle:changeColor(newcolor)
  295.     self.point1:changeColor(newcolor)
  296.     self.point2:changeColor(newcolor)
  297.     self.point3:changeColor(newcolor)
  298.     self.proj2d1:changeColor(newcolor)
  299.     self.proj2d2:changeColor(newcolor)
  300.     self.proj2d3:changeColor(newcolor)
  301.     self.color = newcolor
  302. end
  303.  
  304. function Triangle:projection()
  305.     self.point1:projection()
  306.     self.point2:projection()
  307.     self.point3:projection()
  308.     self.proj2d1 = self.point1.proj2d
  309.     self.proj2d2 = self.point2.proj2d
  310.     self.proj2d3 = self.point3.proj2d
  311. end
  312.  
  313. function Triangle:move(x, y, z)
  314.     self.point1:move(x, y, z)
  315.     self.point2:move(x, y, z)
  316.     self.point3:move(x, y, z)
  317. end
  318.  
  319. function Triangle:rotate(xangle, yangle, zangle)
  320.     self.point1:rotate(xangle, yangle, zangle)
  321.     self.point2:rotate(xangle, yangle, zangle)
  322.     self.point3:rotate(xangle, yangle, zangle)
  323. end
  324. --partie problematique
  325. function Triangle:fillBottomFlatTriangle(v1, v2, v3, color)
  326.     local invslope1 = (v2.x - v1.x) / (v2.y - v1.y)
  327.     local invslope2 = (v3.x - v1.x) / (v3.y - v1.y)
  328.     if undef(color) then
  329.         color = defaultColor
  330.     end
  331.  
  332.     local curx1 = v1.x
  333.     local curx2 = v1.x
  334.  
  335.     for scanlineY = v1.y, v2.y do
  336.         local line = Line2D(curx1, scanlineY, curx2, scanlineY)
  337.         line:disp(gc)
  338.         curx1 = curx1 + invslope1
  339.         curx2 = curx2 + invslope2
  340.     end
  341. end
  342.  
  343. function Triangle:fillTopFlatTriangle(v1, v2, v3, color)
  344.     local invslope1 = (v3.x - v1.x) / (v3.y - v1.y)
  345.     local invslope2 = (v3.x - v2.x) / (v3.y - v2.y)
  346.  
  347.     if undef(color) then
  348.         color = defaultColor
  349.     end
  350.  
  351.     local curx1 = v3.x
  352.     local curx2 = v3.x
  353.  
  354.     for scanlineY = v3.y, (v1.y + 1), -1 do
  355.         local line = Line2D(curx1, scanlineY, curx2, scanlineY, color)
  356.         line:disp(gc)
  357.         curx1 = curx1 - invslope1
  358.         curx2 = curx2 - invslope2
  359.     end
  360. end
  361.  
  362. function Triangle:fillTriangle(color)
  363.     local v1, v2, v3 = self.point1:projection(), self.point2:projection(), self.point3:projection()
  364.  
  365.     if v2.y < v3.y then
  366.         v2, v3 = v3, v2
  367.     end
  368.     if v1.y < v2.y then
  369.         v1, v2 = v2, v1
  370.     end
  371.     if v2.y < v3.y then
  372.         v2, v3 = v3, v2
  373.     end
  374.  
  375.     if v2.y == v3.y then
  376.         self:fillBottomFlatTriangle(v1, v2, v3, color)
  377.     elseif v1.y == v2.y then
  378.         self:fillTopFlatTriangle(v1, v2, v3, color)
  379.     else
  380.         local v4 = Point2D((v1.x + ((v2.y - v1.y) / (v3.y - v1.y)) * (v3.x - v1.x)), v2.y, color)
  381.         self:fillBottomFlatTriangle(v1, v2, v4, color)
  382.         self:fillTopFlatTriangle(v2, v4, v3, color)
  383.     end
  384. end
  385.  
  386. function Triangle:disp(gc)
  387.     local line1, line2, line3
  388.     line1 = Line3D(self.point1, self.point2, self.color)
  389.     line2 = Line3D(self.point2, self.point3, self.color)
  390.     line3 = Line3D(self.point1, self.point3, self.color)
  391.     line1:disp(gc)
  392.     line2:disp(gc)
  393.     line3:disp(gc)
  394.     if self.tofill then
  395.         self:fillTriangle(self.tofillcolor)
  396.     end
  397. end
  398.  
  399. Object3D = class()
  400.  
  401. function Object3D:init(name, listObject, color)
  402.     self.name = name
  403.     self.listObject = listObject
  404.     self.color = color
  405.     self.position = Point3D(0, 0, 0)
  406.     self.rotation = Point3D(0, 0, 0)
  407. end
  408.  
  409. function Object3D:rotate(xangle, yangle, zangle)
  410.     for k = 1, #self.listObject do
  411.         local obj = self.listObject[k]
  412.         obj:rotate(xangle, yangle, zangle)
  413.     end
  414. end
  415.  
  416. function Object3D:move(xmove, ymove, zmove)
  417.     for k = 1, #self.listObject do
  418.         local obj = self.listObject[k]
  419.         if undef(obj.axex) then
  420.             obj:move(xmove, ymove, zmove)
  421.         end
  422.     end
  423. end
  424.  
  425. function Object3D:disp(gc)
  426.     for k = 1, #self.listObject do
  427.         local obj = self.listObject[k]
  428.         if def(obj.name) then
  429.             gc:drawString(obj.name, screen:height(), 0, "bottom")
  430.         end
  431.         obj:disp(gc)
  432.     end
  433. end
  434.  
  435. --axes
  436.  
  437. Axes = class()
  438.  
  439. function Axes:init(posx, posy, posz)
  440.     print("Axes init")
  441.     self.axex = Line3D(Point3D(0, 0, 0), posx, posx.color)
  442.     self.axey = Line3D(Point3D(0, 0, 0), posy, posy.color)
  443.     self.axez = Line3D(Point3D(0, 0, 0), posz, posz.color)
  444. end
  445.  
  446. function Axes:rotate(xangle, yangle, zangle)
  447.     print("Axes rotate")
  448.     self.axex:rotate(xangle, yangle, zangle)
  449.     self.axey:rotate(xangle, yangle, zangle)
  450.     self.axez:rotate(xangle, yangle, zangle)
  451. end
  452.  
  453. function Axes:disp(gc)
  454.     print("Axes disp")
  455.     self.axex:disp(gc)
  456.     self.axey:disp(gc)
  457.     self.axez:disp(gc)
  458.     local pointx, pointy, pointz = self.axex.point2, self.axey.point2, self.axez.point2
  459.     pointx:projection()
  460.     pointy:projection()
  461.     pointz:projection()
  462.     gc:setColorRGB(RGB(self.axex.color))
  463.     gc:drawString("x", pointx.proj2d.x, pointx.proj2d.y)
  464.     gc:setColorRGB(RGB(self.axey.color))
  465.     gc:drawString("y", pointy.proj2d.x, pointy.proj2d.y)
  466.     gc:setColorRGB(RGB(self.axez.color))
  467.     gc:drawString("z", pointz.proj2d.x, pointz.proj2d.y)
  468. end
  469.  
  470. --main
  471. --devant
  472. local face1 = Object3D("face1", { Triangle(Point3D(-1, -1, -1), Point3D(-1, 1, -1), Point3D(1, -1, -1), true, {255,0,0}), Triangle(Point3D(-1, 1, -1), Point3D(1, 1, -1), Point3D(1, -1, -1)) }, { 0, 0, 0 })
  473. --gauche
  474. local face2 = Object3D("face2", { Triangle(Point3D(-1, -1, 1), Point3D(-1, 1, 1), Point3D(-1, -1, -1)), Triangle(Point3D(-1, -1, -1), Point3D(-1, 1, -1), Point3D(-1, 1, 1)) }, { 0, 0, 0 })
  475. --derriere
  476. local face3 = Object3D("face3", { Triangle(Point3D(-1, -1, 1), Point3D(1, 1, 1), Point3D(1, -1, 1)), Triangle(Point3D(-1, -1, 1), Point3D(-1, 1, 1), Point3D(1, 1, 1)) }, { 0, 0, 0 })
  477. --droite
  478. local face4 = Object3D("face4", { Triangle(Point3D(1, -1, -1), Point3D(1, 1, -1), Point3D(1, -1, 1)), Triangle(Point3D(1, -1, 1), Point3D(1, 1, -1), Point3D(1, 1, 1)) }, { 0, 0, 0 })
  479. --haut
  480. local face5 = Object3D("face5", { Triangle(Point3D(-1, 1, -1), Point3D(-1, 1, 1), Point3D(1, 1, -1)), Triangle(Point3D(-1, 1, 1), Point3D(1, 1, 1), Point3D(1, 1, -1)) }, { 0, 0, 0 })
  481. --bas
  482. local face6 = Object3D("face6", { Triangle(Point3D(-1, -1, 1), Point3D(-1, -1, -1), Point3D(1, -1, 1)), Triangle(Point3D(-1, -1, -1), Point3D(1, -1, -1), Point3D(1, -1, 1)) }, { 0, 0, 0 })
  483.  
  484. --axes
  485. local axes = Axes(Point3D(0.5, 0, 0, { 255, 0, 0 }), Point3D(0, 0.5, 0, { 0, 0, 255 }), Point3D(0, 0, 0.5, { 0, 255, 0 }))
  486.  
  487. --cube
  488. local cube = Object3D("cube", { face1, face2, face3, face4, face5, face6, axes })
  489.  
  490. local incx = -5
  491. local incy = -5
  492.  
  493. function on.paint(gc)
  494.     cube:disp(gc)
  495. end
  496.  
  497. function on.charIn(ch)
  498.     if ch == '+' and fov > 0 then
  499.         fov = fov - 5
  500.     elseif ch == '-' and fov < 180 then
  501.         fov = fov + 5
  502.     elseif ch == '8' then
  503.         incx = -5
  504.     elseif ch == '2' then
  505.         incx = 5
  506.     elseif ch == '6' then
  507.         incy = -5
  508.     elseif ch == '4' then
  509.         incy = 5
  510.     elseif ch == 'p' then
  511.         timer.stop()
  512.     elseif ch == 's' then
  513.         timer.start(0.01)
  514.     end
  515.     screen:invalidate()
  516. end
  517.  
  518. function on.timer()
  519.     cube:rotate(incx, incy, 0)
  520.  
  521.     screen:invalidate()
  522. end
  523.  
  524. function on.arrowLeft()
  525.     cube:move(-1, 0, 0)
  526.  
  527.     screen:invalidate()
  528. end
  529.  
  530. function on.arrowRight()
  531.     cube:move(1, 0, 0)
  532.  
  533.     screen:invalidate()
  534. end
  535.  
  536. function on.arrowUp()
  537.     cube:move(0, 1, 0)
  538.  
  539.     screen:invalidate()
  540. end
  541.  
  542. function on.arrowDown()
  543.     cube:move(0, -1, 0)
  544.  
  545.     screen:invalidate()
  546. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement