Advertisement
neuronix

3DSoftEngine

Dec 10th, 2017
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.87 KB | None | 0 0
  1. --debug
  2. local debug = false
  3. --debug
  4.  
  5. local RGB = unpack
  6. local abs = math.abs
  7.  
  8. local defaultColor = { 0, 0, 0 }
  9.  
  10. local screen = platform.window
  11.  
  12. function def(var)
  13.     return (var ~= nil)
  14. end
  15.  
  16. function undef(var)
  17.     return (var == nil)
  18. end
  19.  
  20. function addToGC(name, func)
  21.     local gct = platform.withGC(getmetatable)
  22.     gct[name] = func
  23. end
  24.  
  25. function setPixel(gc, x, y)
  26.     gc:drawLine(x, y, x, y)
  27. end
  28.  
  29. addToGC("setPixel", setPixel)
  30.  
  31. --moteur 2D
  32. --point 2D
  33.  
  34. Point2D = class()
  35.  
  36. function Point2D:init(x, y, ...)
  37.     self.x = x
  38.     self.y = y
  39.     local args = { ... }
  40.     if def(args[1]) then
  41.         self.color = args[1] else self.color = defaultColor
  42.     end
  43.     self.inscreen = true
  44. end
  45.  
  46. function Point2D:changeColor(newcolor)
  47.     self.color = newcolor
  48. end
  49.  
  50. function Point2D:isInScreen()
  51.     self.inscreen = (self.x >= 0 and self.x <= screen:width() and self.y >= 0 and self.y <= screen:height())
  52.     return self.inscreen
  53. end
  54.  
  55. function Point2D:move(x,y)
  56.     self.x = self.x + x
  57.     self.y = self.y + y
  58. end
  59.  
  60. function Point2D:disp(gc)
  61.     if self:isInScreen() then
  62.         gc:setColorRGB(RGB(self.color))
  63.         if debug then gc:drawString("Disp Point2D", 0, 0, "top") end
  64.         gc:setPixel(self.x, self.y)
  65.     end
  66. end
  67.  
  68. --ligne 2D
  69.  
  70. Line2D = class()
  71.  
  72. --Line2D(Point2D,Point2D[,color]) or Line2D(Point1x,Point1y,Point2x,Point2y[,color,...])
  73.  
  74. function Line2D:init(point1orx, point2or1y, ...)
  75.     local args = { ... }
  76.     if def(args[2]) then
  77.         if def(args[3]) then
  78.             self.color = args[3]
  79.         else
  80.             self.color = defaultColor
  81.         end
  82.         self.point1 = Point2D(point1orx, point2or1y, self.color)
  83.         self.point2 = Point2D(args[1], args[2], self.color)
  84.     else
  85.         if def(args[1]) then
  86.             self.color = args[1]
  87.         else
  88.             self.color = defaultColor
  89.         end
  90.         self.point1 = point1orx
  91.         self.point2 = point2or1y
  92.         self.point1:changeColor(self.color)
  93.         self.point2:changeColor(self.color)
  94.     end
  95. end
  96.  
  97. function Line2D:changeColor(newcolor)
  98.     self.point1:changeColor(newcolor)
  99.     self.point2:changeColor(newcolor)
  100.     self.color = newcolor
  101. end
  102.  
  103. function Line2D:move(x,y)
  104.     self.point1:move(x,y)
  105.     self.point2:move(x,y)
  106. end
  107.  
  108. function Line2D:disp(gc)
  109.     if debug then gc:drawString("disp Line2D",0,0,"top") end
  110.     local dx, dy, sx, sy, err, e2, ptemp
  111.     dx = abs(self.point2.x - self.point1.x)
  112.     sx = (self.point1.x < self.point2.x) and 1 or -1
  113.     dy = -abs(self.point2.y - self.point1.y)
  114.     sy = (self.point1.y < self.point2.y) and 1 or -1
  115.     err = dx + dy
  116.     ptemp = self.point1
  117.     ptemp:disp(gc)
  118.     while ptemp.x ~= self.point2.x or ptemp.y ~= self.point2.y do
  119.         e2 = 2 * err
  120.         if e2 >= dy then
  121.             err = err + dy
  122.             ptemp.x = ptemp.x + sx
  123.         end
  124.         if e2 <= dx then
  125.             err = err + dx
  126.             ptemp.y = ptemp.y + sy
  127.         end
  128.         ptemp:disp(gc)
  129.     end
  130.     --gc:drawLine(self.point1.x,self.point1.y,self.point2.x,self.point2.y)
  131. end
  132.  
  133. --moteur 3D
  134. --point 3D
  135.  
  136. Point3D = class()
  137.  
  138. function Point3D:init(x, y, z, ...)
  139.     self.x = x
  140.     self.y = y
  141.     self.z = z
  142.     local args = { ... }
  143.     if ... then
  144.         self.color = args[1]
  145.     else
  146.         self.color = defaultColor
  147.     end
  148.     self.inscreen = true
  149.     self.proj2d = Point2D(0, 0, self.color)
  150. end
  151.  
  152. function Point3D:changeColor(newcolor)
  153.     self.color = newcolor
  154.     self.proj2d:changeColor()
  155. end
  156.  
  157. function Point3D:projection()
  158.     local tan35 = 0.70020753820970977945852271944483
  159.     local f = (screen:width() / 2) / tan35
  160.     self.proj2d.x = math.floor(self.x * f / (self.z + 5) + (screen:width() / 2))
  161.     self.proj2d.y = math.floor((screen:height() / 2) - (self.y * f / (self.z + 5)))
  162.     return self.proj2d
  163. end
  164.  
  165. function Point3D:isInScreen()
  166.     self:projection()
  167.     self.inscreen = ((0 <= self.proj2d.x <= screen:width()) and (0 <= self.proj2d.y <= screen:height()))
  168.     return self.inscreen
  169. end
  170.  
  171. function Point3D:move(x,y,z)
  172.     self.x = self.x + x
  173.     self.y = self.y + y
  174.     self.z = self.z + z
  175. end
  176.  
  177. function Point3D:disp(gc)
  178.     if self:isInScreen() then
  179.         if debug then gc:drawString("disp Point3D",0,0,"top") end
  180.         self.proj2d:disp(gc)
  181.     end
  182. end
  183.  
  184. --ligne 3D
  185.  
  186. Line3D = class()
  187.  
  188. function Line3D:init(point1orx, point2or1y, ...)
  189.     local args = { ... }
  190.     if def(args[4]) then
  191.         if def(args[5]) then
  192.             self.color = args[5]
  193.         else
  194.             self.color = defaultColor
  195.         end
  196.         self.point1 = Point3D(point1orx, point2or1y, args[1], self.color)
  197.         self.point2 = Point3D(args[2], args[3], args[4], self.color)
  198.     else
  199.         if def(args[1]) then
  200.             self.color = args[1]
  201.         else
  202.             self.color = defaultColor
  203.         end
  204.         self.point1 = point1orx
  205.         self.point2 = point2or1y
  206.         self.point1:changeColor(self.color)
  207.         self.point2:changeColor(self.color)
  208.     end
  209.     self.proj2d = Line2D(Point2D(0, 0), Point2D(0, 0), self.color)
  210. end
  211.  
  212. function Line3D:changeColor(newcolor)
  213.     self.point1:changeColor(newcolor)
  214.     self.point2:changeColor(newcolor)
  215.     self.proj2d:changeColor(newcolor)
  216.     self.color = newcolor
  217. end
  218.  
  219. function Line3D:projection()
  220.     self.point1:projection()
  221.     self.point2:projection()
  222.     self.proj2d = Line2D(self.point1.proj2d, self.point2.proj2d, self.color)
  223. end
  224.  
  225. function Line3D:move(x,y,z)
  226.     self.point1:move(x,y,z)
  227.     self.point2:move(x,y,z)
  228. end
  229.  
  230. function Line3D:disp(gc)
  231.     if debug then gc:drawString("disp Line3D",0,0,"top") end
  232.     self:projection()
  233.     self.proj2d:disp(gc)
  234. end
  235.  
  236. --objet
  237. --triangle 3D
  238.  
  239. Triangle = class()
  240.  
  241. function Triangle:init(point1, point2, point3, ...)
  242.     local args = {...}
  243.     if def(args[1]) then
  244.         self.color = args[1]
  245.     else
  246.         self.color = defaultColor
  247.     end
  248.     self.point1 = point1
  249.     self.point2 = point2
  250.     self.point3 = point3
  251.     self.point1:changeColor(self.color)
  252.     self.point2:changeColor(self.color)
  253.     self.point3:changeColor(self.color)
  254.     self.proj2d1 = Point2D(0,0,self.color)
  255.     self.proj2d2 = Point2D(0,0,self.color)
  256.     self.proj2d3 = Point2D(0,0,self.color)
  257. end
  258.  
  259. function Triangle:changeColor(newcolor)
  260.     self.point1:changeColor(newcolor)
  261.     self.point2:changeColor(newcolor)
  262.     self.point3:changeColor(newcolor)
  263.     self.proj2d1:changeColor(newcolor)
  264.     self.proj2d2:changeColor(newcolor)
  265.     self.proj2d3:changeColor(newcolor)
  266.     self.color = newcolor
  267. end
  268.  
  269. function Triangle:projection()
  270.     self.point1:projection()
  271.     self.point2:projection()
  272.     self.point3:projection()
  273.     self.proj2d1 = self.point1.proj2d
  274.     self.proj2d2 = self.point2.proj2d
  275.     self.proj2d3 = self.point3.proj2d
  276. end
  277.  
  278. function Triangle:move(x,y,z)
  279.     self.point1:move(x,y,z)
  280.     self.point2:move(x,y,z)
  281.     self.point3:move(x,y,z)
  282. end
  283.  
  284. local function torad(a) return (a * 180 / math.pi) end
  285.  
  286. function Triangle:rotationX(mat) -- pour la rotation dans le plan (y,z)
  287.     local cosAngle,sinAngle = math.cos(torad(mat[3])),math.sin(torad(mat[3]))
  288.     local newy = self.point3.y * cosAngle - self.point3.z * sinAngle
  289.     local newz = self.point3.z * cosAngle + self.point3.y * sinAngle
  290.     self.point3.y = self.point3.y + newy
  291.     self.point3.z = self.point3.z + newz
  292.     local cosAngle,sinAngle = math.cos(torad(mat[2])),math.sin(torad(mat[2]))
  293.     local newy = self.point2.y * cosAngle - self.point2.z * sinAngle
  294.     local newz = self.point2.z * cosAngle + self.point2.y * sinAngle
  295.     self.point2.y = self.point2.y + newy
  296.     self.point2.z = self.point2.z + newz
  297.     local cosAngle,sinAngle = math.cos(torad(mat[1])),math.sin(torad(mat[1]))
  298.     local newy = self.point1.y * cosAngle - self.point1.z * sinAngle
  299.     local newz = self.point1.z * cosAngle + self.point1.y * sinAngle
  300.     self.point1.y = self.point1.y + newy
  301.     self.point1.z = self.point1.z + newz
  302. end
  303.  
  304. function Triangle:rotationY(mat) -- pour la rotation dans le plan (x,z)
  305.     local cosAngle,sinAngle = math.cos(torad(mat[3])),math.sin(torad(mat[3]))
  306.     local newx = self.point3.x * cosAngle - self.point3.z * sinAngle
  307.     local newz = self.point3.z * cosAngle + self.point3.x * sinAngle
  308.     self.point3.x = self.point3.x + newx
  309.     self.point3.z = self.point3.z + newz
  310.     local cosAngle,sinAngle = math.cos(torad(mat[2])),math.sin(torad(mat[2]))
  311.     local newx = self.point2.x * cosAngle - self.point2.z * sinAngle
  312.     local newz = self.point2.z * cosAngle + self.point2.x * sinAngle
  313.     self.point2.x = self.point2.x + newx
  314.     self.point2.z = self.point2.z + newz
  315.     local cosAngle,sinAngle = math.cos(torad(mat[1])),math.sin(torad(mat[1]))
  316.     local newx = self.point1.x * cosAngle - self.point1.z * sinAngle
  317.     local newz = self.point1.z * cosAngle + self.point1.x * sinAngle
  318.     self.point1.x = self.point1.x + newx
  319.     self.point1.z = self.point1.z + newz
  320. end
  321.  
  322. function Triangle:rotationZ(mat) -- pour la rotation dans le plan (x,y)
  323.     local cosAngle,sinAngle = math.cos(torad(mat[3])),math.sin(torad(mat[3]))
  324.     local newx = self.point3.x * cosAngle - self.point3.y * sinAngle
  325.     local newy = self.point3.y * cosAngle + self.point3.x * sinAngle
  326.     self.point3.x = self.point3.x + newx
  327.     self.point3.y = self.point3.y + newy
  328.     local cosAngle,sinAngle = math.cos(torad(mat[2])),math.sin(torad(mat[2]))
  329.     local newx = self.point2.x * cosAngle - self.point2.y * sinAngle
  330.     local newy = self.point2.y * cosAngle + self.point2.x * sinAngle
  331.     self.point2.x = self.point2.y + newx
  332.     self.point2.y = self.point2.y + newy
  333.     local cosAngle,sinAngle = math.cos(torad(mat[1])),math.sin(torad(mat[1]))
  334.     local newx = self.point1.x * cosAngle - self.point1.y * sinAngle
  335.     local newy = self.point1.y * cosAngle + self.point1.x * sinAngle
  336.     self.point1.x = self.point1.x + newx
  337.     self.point1.y = self.point1.y + newy
  338. end
  339.  
  340. function Triangle:fillBottomFlatTriangle(gc,v1,v2,v3,color)
  341.     local invslope1 = (v2.x - v1.x) / (v2.y - v1.y)
  342.     local invslope2 = (v3.x - v1.x) / (v3.y - v1.y)
  343.  
  344.     local curx1 = v1.x
  345.     local curx2 = v1.x
  346.  
  347.     local scanlineY,line
  348.     for scanlineY = v1.y, v2.y do
  349.         line = Line2D(curx1,scanlineY,curx2,scanlineY,color)
  350.         line:disp(gc)
  351.         curx1 = curx1 + invslope1
  352.         curx2 = curx2 + invslope2
  353.     end
  354. end
  355.  
  356. function Triangle:fillTopFlatTriangle(gc,v1,v2,v3,color)
  357.     local invslope1 = (v3.x - v1.x) / (v3.y - v1.y)
  358.     local invslope2 = (v3.x - v2.x) / (v3.y - v2.y)
  359.  
  360.     local curx1 = v3.x
  361.     local curx2 = v3.x
  362.  
  363.     local scanlineY,line
  364.     for scanlineY = v3.y, (v1.y + 1), -1 do
  365.         line = Line2D(curx1,scanlineY,curx2,scanlineY,color)
  366.         line:disp(gc)
  367.         curx1 = curx1 - invslope1
  368.         curx2 = curx2 - invslope2
  369.     end
  370. end
  371.  
  372. function Triangle:fillTriangle(gc,color)
  373.     self.point1:projection()
  374.     self.point2:projection()
  375.     self.point3:projection()
  376.  
  377.     local v1,v2,v3 = self.proj2d1,self.proj2d2,self.proj2d3
  378.     local i = {v1,v2,v3}
  379.     local f = function(a1,a2) return (a1.y >= a2.y) end
  380.     i = table.sort(i, f)
  381.  
  382.     v1,v2,v3 = i[1],i[2],i[3]
  383.  
  384.     v1:changeColor(color)
  385.     v2:changeColor(color)
  386.     v3:changeColor(color)
  387.  
  388.     if v2.y == v3.y then
  389.         self:fillBottomFlatTriangle(gc,v1,v2,v3,color)
  390.     elseif v1.y == v2.y then
  391.         self:fillTopFlatTriangle(gc,v1,v2,v3,color)
  392.     else
  393.         local v4 = Point2D(math.floor(v1.x + (v2.y - v1.y) / (v3.y - v1.y) * (v3.x - v1.x)),v2.y,color)
  394.         self:fillBottomFlatTriangle(gc,v1,v2,v4,color)
  395.         self:fillTopFlatTriangle(gc,v2,v4,v3,color)
  396.     end
  397. end
  398.  
  399. function Triangle:disp(gc)
  400.     if debug then gc:drawString("disp Triangle",0,0,"top") end
  401.     local line1, line2, line3
  402.     line1 = Line3D(self.point1,self.point2,self.color)
  403.     line2 = Line3D(self.point2,self.point3,self.color)
  404.     line3 = Line3D(self.point1,self.point3,self.color)
  405.     line1:disp(gc)
  406.     line2:disp(gc)
  407.     line3:disp(gc)
  408. end
  409.  
  410. --main
  411.  
  412. local k = Triangle(Point3D(-1,-1,-1),Point3D(-1,1,-1),Point3D(1,-1,-1),{255,0,0})
  413. local k1 = Triangle(Point3D(-1,1,-1),Point3D(1,1,-1),Point3D(1,-1,-1),{0,0,255})
  414.  
  415. function on.paint(gc)
  416.     if debug then gc:drawString("test",0,0,"top") end
  417.     k:fillTriangle(gc, {255,0,0})
  418.     --k1:fillTriangle(gc, k1.color)
  419.     k:disp(gc)
  420.     k1:disp(gc)
  421. end
  422.  
  423. function on.charIn(ch)
  424.     if ch == '+' then
  425.         k:move(0,0,-1)
  426.         k1:move(0,0,-1)
  427.     elseif ch == '-' then
  428.         k:move(0,0,1)
  429.         k1:move(0,0,1)
  430.     elseif ch == '6' then
  431.         k:rotationY(5)
  432.         k1:rotationY(5)
  433.     elseif ch == '4' then
  434.         k:rotationY(-5)
  435.         k1:rotationY(-5)
  436.     end
  437.     screen:invalidate()
  438. end
  439.  
  440. function on.arrowLeft()
  441.     k:move(-1,0,0)
  442.     screen:invalidate()
  443. end
  444.  
  445. function on.arrowRight()
  446.     k:move(1,0,0)
  447.     screen:invalidate()
  448. end
  449.  
  450. function on.arrowUp()
  451.     k:move(0,1,0)
  452.     screen:invalidate()
  453. end
  454.  
  455. function on.arrowDown()
  456.     k:move(0,-1,0)
  457.     screen:invalidate()
  458. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement