Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --debug
- local debug = false
- --debug
- local RGB = unpack
- local abs = math.abs
- local defaultColor = { 0, 0, 0 }
- local screen = platform.window
- function def(var)
- return (var ~= nil)
- end
- function undef(var)
- return (var == nil)
- end
- function addToGC(name, func)
- local gct = platform.withGC(getmetatable)
- gct[name] = func
- end
- function setPixel(gc, x, y)
- gc:drawLine(x, y, x, y)
- end
- addToGC("setPixel", setPixel)
- --moteur 2D
- --point 2D
- Point2D = class()
- function Point2D:init(x, y, ...)
- self.x = x
- self.y = y
- local args = { ... }
- if def(args[1]) then
- self.color = args[1] else self.color = defaultColor
- end
- self.inscreen = true
- end
- function Point2D:changeColor(newcolor)
- self.color = newcolor
- end
- function Point2D:isInScreen()
- self.inscreen = (self.x >= 0 and self.x <= screen:width() and self.y >= 0 and self.y <= screen:height())
- return self.inscreen
- end
- function Point2D:move(x,y)
- self.x = self.x + x
- self.y = self.y + y
- end
- function Point2D:disp(gc)
- if self:isInScreen() then
- gc:setColorRGB(RGB(self.color))
- if debug then gc:drawString("Disp Point2D", 0, 0, "top") end
- gc:setPixel(self.x, self.y)
- end
- end
- --ligne 2D
- Line2D = class()
- --Line2D(Point2D,Point2D[,color]) or Line2D(Point1x,Point1y,Point2x,Point2y[,color,...])
- function Line2D:init(point1orx, point2or1y, ...)
- local args = { ... }
- if def(args[2]) then
- if def(args[3]) then
- self.color = args[3]
- else
- self.color = defaultColor
- end
- self.point1 = Point2D(point1orx, point2or1y, self.color)
- self.point2 = Point2D(args[1], args[2], self.color)
- else
- if def(args[1]) then
- self.color = args[1]
- else
- self.color = defaultColor
- end
- self.point1 = point1orx
- self.point2 = point2or1y
- self.point1:changeColor(self.color)
- self.point2:changeColor(self.color)
- end
- end
- function Line2D:changeColor(newcolor)
- self.point1:changeColor(newcolor)
- self.point2:changeColor(newcolor)
- self.color = newcolor
- end
- function Line2D:move(x,y)
- self.point1:move(x,y)
- self.point2:move(x,y)
- end
- function Line2D:disp(gc)
- if debug then gc:drawString("disp Line2D",0,0,"top") end
- local dx, dy, sx, sy, err, e2, ptemp
- dx = abs(self.point2.x - self.point1.x)
- sx = (self.point1.x < self.point2.x) and 1 or -1
- dy = -abs(self.point2.y - self.point1.y)
- sy = (self.point1.y < self.point2.y) and 1 or -1
- err = dx + dy
- ptemp = self.point1
- ptemp:disp(gc)
- while ptemp.x ~= self.point2.x or ptemp.y ~= self.point2.y do
- e2 = 2 * err
- if e2 >= dy then
- err = err + dy
- ptemp.x = ptemp.x + sx
- end
- if e2 <= dx then
- err = err + dx
- ptemp.y = ptemp.y + sy
- end
- ptemp:disp(gc)
- end
- --gc:drawLine(self.point1.x,self.point1.y,self.point2.x,self.point2.y)
- end
- --moteur 3D
- --point 3D
- Point3D = class()
- function Point3D:init(x, y, z, ...)
- self.x = x
- self.y = y
- self.z = z
- local args = { ... }
- if ... then
- self.color = args[1]
- else
- self.color = defaultColor
- end
- self.inscreen = true
- self.proj2d = Point2D(0, 0, self.color)
- end
- function Point3D:changeColor(newcolor)
- self.color = newcolor
- self.proj2d:changeColor()
- end
- function Point3D:projection()
- local tan35 = 0.70020753820970977945852271944483
- local f = (screen:width() / 2) / tan35
- self.proj2d.x = math.floor(self.x * f / (self.z + 5) + (screen:width() / 2))
- self.proj2d.y = math.floor((screen:height() / 2) - (self.y * f / (self.z + 5)))
- return self.proj2d
- end
- function Point3D:isInScreen()
- self:projection()
- self.inscreen = ((0 <= self.proj2d.x <= screen:width()) and (0 <= self.proj2d.y <= screen:height()))
- return self.inscreen
- end
- function Point3D:move(x,y,z)
- self.x = self.x + x
- self.y = self.y + y
- self.z = self.z + z
- end
- function Point3D:disp(gc)
- if self:isInScreen() then
- if debug then gc:drawString("disp Point3D",0,0,"top") end
- self.proj2d:disp(gc)
- end
- end
- --ligne 3D
- Line3D = class()
- function Line3D:init(point1orx, point2or1y, ...)
- local args = { ... }
- if def(args[4]) then
- if def(args[5]) then
- self.color = args[5]
- else
- self.color = defaultColor
- end
- self.point1 = Point3D(point1orx, point2or1y, args[1], self.color)
- self.point2 = Point3D(args[2], args[3], args[4], self.color)
- else
- if def(args[1]) then
- self.color = args[1]
- else
- self.color = defaultColor
- end
- self.point1 = point1orx
- self.point2 = point2or1y
- self.point1:changeColor(self.color)
- self.point2:changeColor(self.color)
- end
- self.proj2d = Line2D(Point2D(0, 0), Point2D(0, 0), self.color)
- end
- function Line3D:changeColor(newcolor)
- self.point1:changeColor(newcolor)
- self.point2:changeColor(newcolor)
- self.proj2d:changeColor(newcolor)
- self.color = newcolor
- end
- function Line3D:projection()
- self.point1:projection()
- self.point2:projection()
- self.proj2d = Line2D(self.point1.proj2d, self.point2.proj2d, self.color)
- end
- function Line3D:move(x,y,z)
- self.point1:move(x,y,z)
- self.point2:move(x,y,z)
- end
- function Line3D:disp(gc)
- if debug then gc:drawString("disp Line3D",0,0,"top") end
- self:projection()
- self.proj2d:disp(gc)
- end
- --objet
- --triangle 3D
- Triangle = class()
- function Triangle:init(point1, point2, point3, ...)
- local args = {...}
- if def(args[1]) then
- self.color = args[1]
- else
- self.color = defaultColor
- end
- self.point1 = point1
- self.point2 = point2
- self.point3 = point3
- self.point1:changeColor(self.color)
- self.point2:changeColor(self.color)
- self.point3:changeColor(self.color)
- self.proj2d1 = Point2D(0,0,self.color)
- self.proj2d2 = Point2D(0,0,self.color)
- self.proj2d3 = Point2D(0,0,self.color)
- end
- function Triangle:changeColor(newcolor)
- self.point1:changeColor(newcolor)
- self.point2:changeColor(newcolor)
- self.point3:changeColor(newcolor)
- self.proj2d1:changeColor(newcolor)
- self.proj2d2:changeColor(newcolor)
- self.proj2d3:changeColor(newcolor)
- self.color = newcolor
- end
- function Triangle:projection()
- self.point1:projection()
- self.point2:projection()
- self.point3:projection()
- self.proj2d1 = self.point1.proj2d
- self.proj2d2 = self.point2.proj2d
- self.proj2d3 = self.point3.proj2d
- end
- function Triangle:move(x,y,z)
- self.point1:move(x,y,z)
- self.point2:move(x,y,z)
- self.point3:move(x,y,z)
- end
- local function torad(a) return (a * 180 / math.pi) end
- function Triangle:rotationX(mat) -- pour la rotation dans le plan (y,z)
- local cosAngle,sinAngle = math.cos(torad(mat[3])),math.sin(torad(mat[3]))
- local newy = self.point3.y * cosAngle - self.point3.z * sinAngle
- local newz = self.point3.z * cosAngle + self.point3.y * sinAngle
- self.point3.y = self.point3.y + newy
- self.point3.z = self.point3.z + newz
- local cosAngle,sinAngle = math.cos(torad(mat[2])),math.sin(torad(mat[2]))
- local newy = self.point2.y * cosAngle - self.point2.z * sinAngle
- local newz = self.point2.z * cosAngle + self.point2.y * sinAngle
- self.point2.y = self.point2.y + newy
- self.point2.z = self.point2.z + newz
- local cosAngle,sinAngle = math.cos(torad(mat[1])),math.sin(torad(mat[1]))
- local newy = self.point1.y * cosAngle - self.point1.z * sinAngle
- local newz = self.point1.z * cosAngle + self.point1.y * sinAngle
- self.point1.y = self.point1.y + newy
- self.point1.z = self.point1.z + newz
- end
- function Triangle:rotationY(mat) -- pour la rotation dans le plan (x,z)
- local cosAngle,sinAngle = math.cos(torad(mat[3])),math.sin(torad(mat[3]))
- local newx = self.point3.x * cosAngle - self.point3.z * sinAngle
- local newz = self.point3.z * cosAngle + self.point3.x * sinAngle
- self.point3.x = self.point3.x + newx
- self.point3.z = self.point3.z + newz
- local cosAngle,sinAngle = math.cos(torad(mat[2])),math.sin(torad(mat[2]))
- local newx = self.point2.x * cosAngle - self.point2.z * sinAngle
- local newz = self.point2.z * cosAngle + self.point2.x * sinAngle
- self.point2.x = self.point2.x + newx
- self.point2.z = self.point2.z + newz
- local cosAngle,sinAngle = math.cos(torad(mat[1])),math.sin(torad(mat[1]))
- local newx = self.point1.x * cosAngle - self.point1.z * sinAngle
- local newz = self.point1.z * cosAngle + self.point1.x * sinAngle
- self.point1.x = self.point1.x + newx
- self.point1.z = self.point1.z + newz
- end
- function Triangle:rotationZ(mat) -- pour la rotation dans le plan (x,y)
- local cosAngle,sinAngle = math.cos(torad(mat[3])),math.sin(torad(mat[3]))
- local newx = self.point3.x * cosAngle - self.point3.y * sinAngle
- local newy = self.point3.y * cosAngle + self.point3.x * sinAngle
- self.point3.x = self.point3.x + newx
- self.point3.y = self.point3.y + newy
- local cosAngle,sinAngle = math.cos(torad(mat[2])),math.sin(torad(mat[2]))
- local newx = self.point2.x * cosAngle - self.point2.y * sinAngle
- local newy = self.point2.y * cosAngle + self.point2.x * sinAngle
- self.point2.x = self.point2.y + newx
- self.point2.y = self.point2.y + newy
- local cosAngle,sinAngle = math.cos(torad(mat[1])),math.sin(torad(mat[1]))
- local newx = self.point1.x * cosAngle - self.point1.y * sinAngle
- local newy = self.point1.y * cosAngle + self.point1.x * sinAngle
- self.point1.x = self.point1.x + newx
- self.point1.y = self.point1.y + newy
- end
- function Triangle:fillBottomFlatTriangle(gc,v1,v2,v3,color)
- local invslope1 = (v2.x - v1.x) / (v2.y - v1.y)
- local invslope2 = (v3.x - v1.x) / (v3.y - v1.y)
- local curx1 = v1.x
- local curx2 = v1.x
- local scanlineY,line
- for scanlineY = v1.y, v2.y do
- line = Line2D(curx1,scanlineY,curx2,scanlineY,color)
- line:disp(gc)
- curx1 = curx1 + invslope1
- curx2 = curx2 + invslope2
- end
- end
- function Triangle:fillTopFlatTriangle(gc,v1,v2,v3,color)
- local invslope1 = (v3.x - v1.x) / (v3.y - v1.y)
- local invslope2 = (v3.x - v2.x) / (v3.y - v2.y)
- local curx1 = v3.x
- local curx2 = v3.x
- local scanlineY,line
- for scanlineY = v3.y, (v1.y + 1), -1 do
- line = Line2D(curx1,scanlineY,curx2,scanlineY,color)
- line:disp(gc)
- curx1 = curx1 - invslope1
- curx2 = curx2 - invslope2
- end
- end
- function Triangle:fillTriangle(gc,color)
- self.point1:projection()
- self.point2:projection()
- self.point3:projection()
- local v1,v2,v3 = self.proj2d1,self.proj2d2,self.proj2d3
- local i = {v1,v2,v3}
- local f = function(a1,a2) return (a1.y >= a2.y) end
- i = table.sort(i, f)
- v1,v2,v3 = i[1],i[2],i[3]
- v1:changeColor(color)
- v2:changeColor(color)
- v3:changeColor(color)
- if v2.y == v3.y then
- self:fillBottomFlatTriangle(gc,v1,v2,v3,color)
- elseif v1.y == v2.y then
- self:fillTopFlatTriangle(gc,v1,v2,v3,color)
- else
- local v4 = Point2D(math.floor(v1.x + (v2.y - v1.y) / (v3.y - v1.y) * (v3.x - v1.x)),v2.y,color)
- self:fillBottomFlatTriangle(gc,v1,v2,v4,color)
- self:fillTopFlatTriangle(gc,v2,v4,v3,color)
- end
- end
- function Triangle:disp(gc)
- if debug then gc:drawString("disp Triangle",0,0,"top") end
- local line1, line2, line3
- line1 = Line3D(self.point1,self.point2,self.color)
- line2 = Line3D(self.point2,self.point3,self.color)
- line3 = Line3D(self.point1,self.point3,self.color)
- line1:disp(gc)
- line2:disp(gc)
- line3:disp(gc)
- end
- --main
- local k = Triangle(Point3D(-1,-1,-1),Point3D(-1,1,-1),Point3D(1,-1,-1),{255,0,0})
- local k1 = Triangle(Point3D(-1,1,-1),Point3D(1,1,-1),Point3D(1,-1,-1),{0,0,255})
- function on.paint(gc)
- if debug then gc:drawString("test",0,0,"top") end
- k:fillTriangle(gc, {255,0,0})
- --k1:fillTriangle(gc, k1.color)
- k:disp(gc)
- k1:disp(gc)
- end
- function on.charIn(ch)
- if ch == '+' then
- k:move(0,0,-1)
- k1:move(0,0,-1)
- elseif ch == '-' then
- k:move(0,0,1)
- k1:move(0,0,1)
- elseif ch == '6' then
- k:rotationY(5)
- k1:rotationY(5)
- elseif ch == '4' then
- k:rotationY(-5)
- k1:rotationY(-5)
- end
- screen:invalidate()
- end
- function on.arrowLeft()
- k:move(-1,0,0)
- screen:invalidate()
- end
- function on.arrowRight()
- k:move(1,0,0)
- screen:invalidate()
- end
- function on.arrowUp()
- k:move(0,1,0)
- screen:invalidate()
- end
- function on.arrowDown()
- k:move(0,-1,0)
- screen:invalidate()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement