Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local RGB = unpack
- local cos = math.cos
- local sin = math.sin
- local tan = math.tan
- local tCos, tSin, tTan = {}, {}, {}
- local torad = function(a)
- return (a * math.pi / 180)
- end
- local init = function()
- for k = -180, 180 do
- table.insert(tCos, cos(torad(k)))
- table.insert(tSin, sin(torad(k)))
- table.insert(tTan, tan(torad(k)))
- end
- end
- if (#tCos) == 0 then
- init()
- end
- local defaultColor = { 0, 0, 0 }
- local screen = platform.window
- function def(var)
- return (var ~= nil)
- end
- function undef(var)
- return (var == nil)
- end
- --moteur 2D
- --point 2D
- Point2D = class()
- function Point2D:init(x, y, color)
- self.x = x
- self.y = y
- if def(color) then
- self.color = color
- 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))
- 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)
- gc:drawLine(self.point1.x, self.point1.y, self.point2.x, self.point2.y)
- end
- --moteur 3D
- --point 3D
- local fov = 70
- Point3D = class()
- function Point3D:init(x, y, z, color)
- self.x = x
- self.y = y
- self.z = z
- if def(color) then
- self.color = color
- 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 f = (screen:width() / 2) / tTan[math.floor(fov / 2) + 181]
- 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:transform(matrix)
- local newPoint3D = Point3D(0, 0, 0, self.color)
- newPoint3D.x = matrix[1][1] * self.x + matrix[1][2] * self.y + matrix[1][3] * self.z
- newPoint3D.y = matrix[2][1] * self.x + matrix[2][2] * self.y + matrix[2][3] * self.z
- newPoint3D.z = matrix[3][1] * self.x + matrix[3][2] * self.y + matrix[3][3] * self.z
- return newPoint3D
- 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:rotate(xangle, yangle, zangle)
- local newPoint
- local xangle, yangle, zangle = xangle + 181, yangle + 181, zangle + 181
- local xmatrix = {
- { 1, 0, 0 },
- { 0, tCos[xangle], -tSin[xangle] },
- { 0, tSin[xangle], tCos[xangle] }
- }
- local ymatrix = {
- { tCos[yangle], 0, tSin[yangle] },
- { 0, 1, 0 },
- { -tSin[yangle], 0, tCos[yangle] }
- }
- local zmatrix = {
- { tCos[zangle], -tSin[zangle], 0 },
- { tSin[zangle], tCos[zangle], 0 },
- { 0, 0, 1 }
- }
- newPoint = self:transform(xmatrix)
- newPoint = newPoint:transform(ymatrix)
- newPoint = newPoint:transform(zmatrix)
- self.x = newPoint.x
- self.y = newPoint.y
- self.z = newPoint.z
- end
- function Point3D:disp(gc)
- if self:isInScreen() then
- 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:rotate(xangle, yangle, zangle)
- self.point1:rotate(xangle, yangle, zangle)
- self.point2:rotate(xangle, yangle, zangle)
- end
- function Line3D:move(x, y, z)
- self.point1:move(x, y, z)
- self.point2:move(x, y, z)
- end
- function Line3D:disp(gc)
- self:projection()
- self.proj2d:disp(gc)
- end
- --objet
- --triangle 3D
- Triangle = class()
- function Triangle:init(point1, point2, point3, fill, fillcolor, ...)
- 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)
- if def(fill) then
- self.tofill = fill
- else
- self.tofill = false
- end
- if def(fillcolor) then
- self.tofillcolor = fillcolor
- else
- self.tofillcolor = defaultColor
- end
- 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
- function Triangle:rotate(xangle, yangle, zangle)
- self.point1:rotate(xangle, yangle, zangle)
- self.point2:rotate(xangle, yangle, zangle)
- self.point3:rotate(xangle, yangle, zangle)
- end
- --partie problematique
- function Triangle:fillBottomFlatTriangle(v1, v2, v3, color)
- local invslope1 = (v2.x - v1.x) / (v2.y - v1.y)
- local invslope2 = (v3.x - v1.x) / (v3.y - v1.y)
- if undef(color) then
- color = defaultColor
- end
- local curx1 = v1.x
- local curx2 = v1.x
- for scanlineY = v1.y, v2.y do
- local line = Line2D(curx1, scanlineY, curx2, scanlineY)
- line:disp(gc)
- curx1 = curx1 + invslope1
- curx2 = curx2 + invslope2
- end
- end
- function Triangle:fillTopFlatTriangle(v1, v2, v3, color)
- local invslope1 = (v3.x - v1.x) / (v3.y - v1.y)
- local invslope2 = (v3.x - v2.x) / (v3.y - v2.y)
- if undef(color) then
- color = defaultColor
- end
- local curx1 = v3.x
- local curx2 = v3.x
- for scanlineY = v3.y, (v1.y + 1), -1 do
- local line = Line2D(curx1, scanlineY, curx2, scanlineY, color)
- line:disp(gc)
- curx1 = curx1 - invslope1
- curx2 = curx2 - invslope2
- end
- end
- function Triangle:fillTriangle(color)
- local v1, v2, v3 = self.point1:projection(), self.point2:projection(), self.point3:projection()
- if v2.y < v3.y then
- v2, v3 = v3, v2
- end
- if v1.y < v2.y then
- v1, v2 = v2, v1
- end
- if v2.y < v3.y then
- v2, v3 = v3, v2
- end
- if v2.y == v3.y then
- self:fillBottomFlatTriangle(v1, v2, v3, color)
- elseif v1.y == v2.y then
- self:fillTopFlatTriangle(v1, v2, v3, color)
- else
- local v4 = Point2D((v1.x + ((v2.y - v1.y) / (v3.y - v1.y)) * (v3.x - v1.x)), v2.y, color)
- self:fillBottomFlatTriangle(v1, v2, v4, color)
- self:fillTopFlatTriangle(v2, v4, v3, color)
- end
- end
- function Triangle:disp(gc)
- 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)
- if self.tofill then
- self:fillTriangle(self.tofillcolor)
- end
- end
- Object3D = class()
- function Object3D:init(name, listObject, color)
- self.name = name
- self.listObject = listObject
- self.color = color
- self.position = Point3D(0, 0, 0)
- self.rotation = Point3D(0, 0, 0)
- end
- function Object3D:rotate(xangle, yangle, zangle)
- for k = 1, #self.listObject do
- local obj = self.listObject[k]
- obj:rotate(xangle, yangle, zangle)
- end
- end
- function Object3D:move(xmove, ymove, zmove)
- for k = 1, #self.listObject do
- local obj = self.listObject[k]
- if undef(obj.axex) then
- obj:move(xmove, ymove, zmove)
- end
- end
- end
- function Object3D:disp(gc)
- for k = 1, #self.listObject do
- local obj = self.listObject[k]
- if def(obj.name) then
- gc:drawString(obj.name, screen:height(), 0, "bottom")
- end
- obj:disp(gc)
- end
- end
- --axes
- Axes = class()
- function Axes:init(posx, posy, posz)
- print("Axes init")
- self.axex = Line3D(Point3D(0, 0, 0), posx, posx.color)
- self.axey = Line3D(Point3D(0, 0, 0), posy, posy.color)
- self.axez = Line3D(Point3D(0, 0, 0), posz, posz.color)
- end
- function Axes:rotate(xangle, yangle, zangle)
- print("Axes rotate")
- self.axex:rotate(xangle, yangle, zangle)
- self.axey:rotate(xangle, yangle, zangle)
- self.axez:rotate(xangle, yangle, zangle)
- end
- function Axes:disp(gc)
- print("Axes disp")
- self.axex:disp(gc)
- self.axey:disp(gc)
- self.axez:disp(gc)
- local pointx, pointy, pointz = self.axex.point2, self.axey.point2, self.axez.point2
- pointx:projection()
- pointy:projection()
- pointz:projection()
- gc:setColorRGB(RGB(self.axex.color))
- gc:drawString("x", pointx.proj2d.x, pointx.proj2d.y)
- gc:setColorRGB(RGB(self.axey.color))
- gc:drawString("y", pointy.proj2d.x, pointy.proj2d.y)
- gc:setColorRGB(RGB(self.axez.color))
- gc:drawString("z", pointz.proj2d.x, pointz.proj2d.y)
- end
- --main
- --devant
- 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 })
- --gauche
- 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 })
- --derriere
- 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 })
- --droite
- 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 })
- --haut
- 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 })
- --bas
- 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 })
- --axes
- 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 }))
- --cube
- local cube = Object3D("cube", { face1, face2, face3, face4, face5, face6, axes })
- local incx = -5
- local incy = -5
- function on.paint(gc)
- cube:disp(gc)
- end
- function on.charIn(ch)
- if ch == '+' and fov > 0 then
- fov = fov - 5
- elseif ch == '-' and fov < 180 then
- fov = fov + 5
- elseif ch == '8' then
- incx = -5
- elseif ch == '2' then
- incx = 5
- elseif ch == '6' then
- incy = -5
- elseif ch == '4' then
- incy = 5
- elseif ch == 'p' then
- timer.stop()
- elseif ch == 's' then
- timer.start(0.01)
- end
- screen:invalidate()
- end
- function on.timer()
- cube:rotate(incx, incy, 0)
- screen:invalidate()
- end
- function on.arrowLeft()
- cube:move(-1, 0, 0)
- screen:invalidate()
- end
- function on.arrowRight()
- cube:move(1, 0, 0)
- screen:invalidate()
- end
- function on.arrowUp()
- cube:move(0, 1, 0)
- screen:invalidate()
- end
- function on.arrowDown()
- cube:move(0, -1, 0)
- screen:invalidate()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement