mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-04 02:02:38 +01:00
Вот-вот
This commit is contained in:
parent
b858487c6f
commit
83a1bb14ef
BIN
Applications/.DS_Store
vendored
BIN
Applications/.DS_Store
vendored
Binary file not shown.
@ -11,6 +11,7 @@ package.loaded["OpenComputersGL/Renderer"] = nil
|
||||
package.loaded["WildCatEngine/Main"] = nil
|
||||
package.loaded["WildCatEngine/PostProcessing"] = nil
|
||||
|
||||
local computer = require("computer")
|
||||
local buffer = require("doubleBuffering")
|
||||
local event = require("event")
|
||||
local GUI = require("GUI")
|
||||
|
||||
@ -1,243 +0,0 @@
|
||||
|
||||
-------------------------------------------------------- Libraries --------------------------------------------------------
|
||||
|
||||
local vector = require("vector")
|
||||
local matrix = require("matrix")
|
||||
local buffer = require("doubleBuffering")
|
||||
local materials = require("OpenComputersGL/Materials")
|
||||
local renderer = require("OpenComputersGL/Renderer")
|
||||
local OCGL = {}
|
||||
|
||||
-------------------------------------------------------- Constants --------------------------------------------------------
|
||||
|
||||
OCGL.axis = {
|
||||
x = 1,
|
||||
y = 2,
|
||||
z = 3,
|
||||
}
|
||||
|
||||
OCGL.vertices = {}
|
||||
OCGL.triangles = {}
|
||||
OCGL.lines = {}
|
||||
|
||||
-------------------------------------------------------- Vertex field methods --------------------------------------------------------
|
||||
|
||||
function OCGL.newRotationMatrix(axis, angle)
|
||||
local sin, cos = math.sin(angle), math.cos(angle)
|
||||
if axis == OCGL.axis.x then
|
||||
return {
|
||||
{ 1, 0, 0 },
|
||||
{ 0, cos, -sin },
|
||||
{ 0, sin, cos }
|
||||
}
|
||||
elseif axis == OCGL.axis.y then
|
||||
return {
|
||||
{ cos, 0, sin },
|
||||
{ 0, 1, 0 },
|
||||
{ -sin, 0, cos }
|
||||
}
|
||||
elseif axis == OCGL.axis.z then
|
||||
return {
|
||||
{ cos, -sin, 0 },
|
||||
{ sin, cos, 0 },
|
||||
{ 0, 0, 1 }
|
||||
}
|
||||
else
|
||||
error("Axis enum " .. tostring(axis) .. " doesn't exists")
|
||||
end
|
||||
end
|
||||
|
||||
function OCGL.translate(vector3Translation)
|
||||
for vertexIndex = 1, #OCGL.vertices do
|
||||
OCGL.vertices[vertexIndex][1] = OCGL.vertices[vertexIndex][1] + vector3Translation[1]
|
||||
OCGL.vertices[vertexIndex][2] = OCGL.vertices[vertexIndex][2] + vector3Translation[2]
|
||||
OCGL.vertices[vertexIndex][3] = OCGL.vertices[vertexIndex][3] + vector3Translation[3]
|
||||
end
|
||||
end
|
||||
|
||||
function OCGL.rotate(rotationMatrix)
|
||||
OCGL.vertices = matrix.multiply(OCGL.vertices, rotationMatrix)
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Render queue methods --------------------------------------------------------
|
||||
|
||||
function OCGL.newIndexedTriangle(indexOfVertex1, indexOfVertex2, indexOfVertex3, material)
|
||||
return { indexOfVertex1, indexOfVertex2, indexOfVertex3, material }
|
||||
end
|
||||
|
||||
function OCGL.newIndexedLine(indexOfVertex1, indexOfVertex2, color)
|
||||
return { indexOfVertex1, indexOfVertex2, color }
|
||||
end
|
||||
|
||||
function OCGL.pushTriangleToRenderQueue(vector3Vertex1, vector3Vertex2, vector3Vertex3, material, meshPointer, meshTriangleIndexPointer)
|
||||
table.insert(OCGL.vertices, vector3Vertex1)
|
||||
table.insert(OCGL.vertices, vector3Vertex2)
|
||||
table.insert(OCGL.vertices, vector3Vertex3)
|
||||
table.insert(OCGL.triangles, OCGL.newIndexedTriangle(OCGL.nextVertexIndex, OCGL.nextVertexIndex + 1, OCGL.nextVertexIndex + 2, material, meshPointer, meshTriangleIndexPointer))
|
||||
OCGL.nextVertexIndex = OCGL.nextVertexIndex + 3
|
||||
end
|
||||
|
||||
function OCGL.pushLineToRenderQueue(vector3Vertex1, vector3Vertex2, color)
|
||||
table.insert(OCGL.vertices, vector3Vertex1)
|
||||
table.insert(OCGL.vertices, vector3Vertex2)
|
||||
table.insert(OCGL.lines, OCGL.newIndexedLine(OCGL.nextVertexIndex, OCGL.nextVertexIndex + 1, color))
|
||||
OCGL.nextVertexIndex = OCGL.nextVertexIndex + 3
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Rendering methods --------------------------------------------------------
|
||||
|
||||
OCGL.setProjectionSurface = renderer.setProjectionSurface
|
||||
|
||||
function OCGL.clearBuffer(backgroundColor)
|
||||
OCGL.nextVertexIndex, OCGL.vertices, OCGL.triangles, OCGL.lines = 1, {}, {}, {}
|
||||
renderer.clearDepthBuffer()
|
||||
buffer.clear(backgroundColor)
|
||||
end
|
||||
|
||||
function OCGL.createPerspectiveProjection()
|
||||
local zNearDivZ
|
||||
for vertexIndex = 1, #OCGL.vertices do
|
||||
zNearDivZ = renderer.projectionSurface.z / OCGL.vertices[vertexIndex][3]
|
||||
OCGL.vertices[vertexIndex][1] = zNearDivZ * OCGL.vertices[vertexIndex][1]
|
||||
OCGL.vertices[vertexIndex][2] = zNearDivZ * OCGL.vertices[vertexIndex][2]
|
||||
-- OCGL.vertices[vertexIndex][3] = zNearDivZ * OCGL.vertices[vertexIndex][3]
|
||||
-- OCGL.vertices[vertexIndex][3] = zNearDivZFar * OCGL.vertices[vertexIndex][3] * 10
|
||||
-- ecs.error(OCGL.vertices[vertexIndex][1], OCGL.vertices[vertexIndex][2], OCGL.vertices[vertexIndex][3])
|
||||
end
|
||||
end
|
||||
|
||||
function OCGL.render(renderMode)
|
||||
local halfWidth, halfHeight = buffer.screen.width / 2, buffer.screen.height
|
||||
local vector3Vertex1, vector3Vertex2, vector3Vertex3, material
|
||||
|
||||
for lineIndex = 1, #OCGL.lines do
|
||||
vector3Vertex1, vector3Vertex2, material = OCGL.vertices[OCGL.lines[lineIndex][1]], OCGL.vertices[OCGL.lines[lineIndex][2]], OCGL.lines[lineIndex][3]
|
||||
|
||||
if renderMode == renderer.renderModes.vertices then
|
||||
renderer.renderDot(vector3Vertex1, material)
|
||||
renderer.renderDot(vector3Vertex2, material)
|
||||
else
|
||||
renderer.renderLine(
|
||||
math.floor(vector3Vertex1[1]),
|
||||
math.floor(vector3Vertex1[2]),
|
||||
vector3Vertex1[3],
|
||||
math.floor(vector3Vertex2[1]),
|
||||
math.floor(vector3Vertex2[2]),
|
||||
vector3Vertex2[3],
|
||||
material
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
for triangleIndex = 1, #OCGL.triangles do
|
||||
vector3Vertex1, vector3Vertex2, vector3Vertex3, material = OCGL.vertices[OCGL.triangles[triangleIndex][1]], OCGL.vertices[OCGL.triangles[triangleIndex][2]], OCGL.vertices[OCGL.triangles[triangleIndex][3]], OCGL.triangles[triangleIndex][4]
|
||||
|
||||
vector3Vertex1[1], vector3Vertex1[2] = vector3Vertex1[1] + halfWidth, vector3Vertex1[2] + halfHeight
|
||||
vector3Vertex2[1], vector3Vertex2[2] = vector3Vertex2[1] + halfWidth, vector3Vertex2[2] + halfHeight
|
||||
vector3Vertex3[1], vector3Vertex3[2] = vector3Vertex3[1] + halfWidth, vector3Vertex3[2] + halfHeight
|
||||
|
||||
if renderMode == renderer.renderModes.material then
|
||||
if material.type == materials.types.solid then
|
||||
renderer.renderFilledTriangle(
|
||||
{
|
||||
vector.newVector3(vector3Vertex1[1], math.floor(vector3Vertex1[2]), vector3Vertex1[3]),
|
||||
vector.newVector3(vector3Vertex2[1], math.floor(vector3Vertex2[2]), vector3Vertex2[3]),
|
||||
vector.newVector3(vector3Vertex3[1], math.floor(vector3Vertex3[2]), vector3Vertex3[3]),
|
||||
},
|
||||
material.color
|
||||
)
|
||||
else
|
||||
error("Material type " .. tostring(material.type) .. " doesn't supported for rendering triangles")
|
||||
end
|
||||
elseif renderMode == renderer.renderModes.wireframe then
|
||||
renderer.renderLine(math.floor(vector3Vertex1[1]), math.floor(vector3Vertex1[2]), vector3Vertex1[3], math.floor(vector3Vertex2[1]), math.floor(vector3Vertex2[2]), vector3Vertex2[3], material.color or renderer.colors.wireframe)
|
||||
renderer.renderLine(math.floor(vector3Vertex2[1]), math.floor(vector3Vertex2[2]), vector3Vertex2[3], math.floor(vector3Vertex3[1]), math.floor(vector3Vertex3[2]), vector3Vertex3[3], material.color or renderer.colors.wireframe)
|
||||
renderer.renderLine(math.floor(vector3Vertex1[1]), math.floor(vector3Vertex1[2]), vector3Vertex1[3], math.floor(vector3Vertex3[1]), math.floor(vector3Vertex3[2]), vector3Vertex3[3], material.color or renderer.colors.wireframe)
|
||||
elseif renderMode == renderer.renderModes.vertices then
|
||||
renderer.renderDot(vector3Vertex1, material.color or renderer.colors.wireframe)
|
||||
renderer.renderDot(vector3Vertex2, material.color or renderer.colors.wireframe)
|
||||
renderer.renderDot(vector3Vertex3, material.color or renderer.colors.wireframe)
|
||||
else
|
||||
error("Rendermode enum " .. tostring(renderMode) .. " doesn't supported for rendering triangles")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Raycasting methods --------------------------------------------------------
|
||||
|
||||
local function vectorMultiply(a, b)
|
||||
return vector.newVector3(a[2] * b[3] - a[3] * b[2], a[3] * b[1] - a[1] * b[3], a[1] * b[2] - a[2] * b[1])
|
||||
end
|
||||
|
||||
local function getVectorDistance(a)
|
||||
return math.sqrt(a[1] ^ 2 + a[2] ^ 2 + a[3] ^ 2)
|
||||
end
|
||||
|
||||
-- В случае попадания лучика этот метод вернет сам треугольник, а также дистанцию до его плоскости
|
||||
function OCGL.triangleRaycast(vector3RayStart, vector3RayEnd)
|
||||
local minimalDistance, closestTriangleIndex
|
||||
for triangleIndex = 1, #OCGL.triangles do
|
||||
-- Это вершины треугольника
|
||||
local A, B, C = OCGL.vertices[OCGL.triangles[triangleIndex][1]], OCGL.vertices[OCGL.triangles[triangleIndex][3]], OCGL.vertices[OCGL.triangles[triangleIndex][3]]
|
||||
-- ecs.error(A[1], A[2], A[3], vector3RayStart[1], vector3RayStart[2], vector3RayStart[3])
|
||||
-- Это хз че
|
||||
local ABC = vectorMultiply(vector.newVector3(C[1] - A[1], C[2] - A[2], C[3] - A[3]), vector.newVector3(B[1] - A[1], B[2] - A[2], B[3] - A[3]))
|
||||
-- Рассчитываем удаленность виртуальной плоскости треугольника от старта нашего луча
|
||||
local D = -ABC[1] * A[1] - ABC[2] * A[2] - ABC[3] * A[3]
|
||||
local firstPart = D + ABC[1] * vector3RayStart[1] + ABC[2] * vector3RayStart[2] + ABC[3] * vector3RayStart[3]
|
||||
local secondPart = ABC[1] * vector3RayStart[1] - ABC[1] * vector3RayEnd[1] + ABC[2] * vector3RayStart[2] - ABC[2] * vector3RayEnd[2] + ABC[3] * vector3RayStart[3] - ABC[3] * vector3RayEnd[3]
|
||||
|
||||
-- ecs.error(firstPart, secondPart)
|
||||
|
||||
-- if firstPart ~= 0 or secondPart ~= 0 then ecs.error(firstPart, secondPart) end
|
||||
-- Если наш лучик не параллелен той ебучей плоскости треугольника
|
||||
if secondPart ~= 0 then
|
||||
local distance = firstPart / secondPart
|
||||
-- И если этот объект находится ближе к старту луча, нежели предыдущий
|
||||
if (distance >= 0 and distance <= 1) and (not minimalDistance or distance < minimalDistance) then
|
||||
|
||||
-- То считаем точку попадания луча в данную плоскость (но ни хуя не факт, что он попадет в треугольник!)
|
||||
local S = vector.newVector3(
|
||||
vector3RayStart[1] + (vector3RayEnd[1] - vector3RayStart[1]) * distance,
|
||||
vector3RayStart[2] + (vector3RayEnd[2] - vector3RayStart[2]) * distance,
|
||||
vector3RayStart[3] + (vector3RayEnd[3] - vector3RayStart[3]) * distance
|
||||
)
|
||||
|
||||
-- Далее считаем сумму площадей параллелограммов, образованных тремя треугольниками, образовавшихся при попадании точки в треугольник
|
||||
-- Нууу тип кароч смари: точка ебанула в центр, и треугольник распидорасило на три мелких. Ну, и три мелких могут образовать параллелограммы свои
|
||||
-- И, кароч, если сумма трех площадей этих мелких уебков будет сильно отличаться от площади жирного треугольника, то луч не попал
|
||||
-- Ну, а площадь считается через sqrt(x^2+y^2+z^2) для каждого йоба-вектора
|
||||
|
||||
---- *A *B
|
||||
|
||||
|
||||
-- * Shotxyz
|
||||
|
||||
|
||||
--- *C
|
||||
|
||||
local SA = vector.newVector3(A[1] - S[1], A[2] - S[2], A[3] - S[3])
|
||||
local SB = vector.newVector3(B[1] - S[1], B[2] - S[2], B[3] - S[3])
|
||||
local SC = vector.newVector3(C[1] - S[1], C[2] - S[2], C[3] - S[3])
|
||||
|
||||
local vectorDistanceSum = getVectorDistance(vectorMultiply(SA, SB)) + getVectorDistance(vectorMultiply(SB, SC)) + getVectorDistance(vectorMultiply(SC, SA))
|
||||
local ABCDistance = getVectorDistance(ABC)
|
||||
|
||||
-- Вот тут мы чекаем погрешность расчетов. Если все заебок, то кидаем этот треугольник в "проверенные""
|
||||
if math.abs(vectorDistanceSum - ABCDistance) < 1 then
|
||||
closestTriangleIndex = triangleIndex
|
||||
minimalDistance = distance
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ecs.error(closestTriangleIndex)
|
||||
if OCGL.triangles[closestTriangleIndex] then
|
||||
return OCGL.triangles[closestTriangleIndex][5], OCGL.triangles[closestTriangleIndex][6], minimalDistance
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Constants --------------------------------------------------------
|
||||
|
||||
return OCGL
|
||||
@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
local materials = {}
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
materials.types = {
|
||||
textured = 1,
|
||||
solid = 2,
|
||||
}
|
||||
|
||||
function materials.newSolidMaterial(color)
|
||||
return {
|
||||
type = materials.types.solid,
|
||||
color = color
|
||||
}
|
||||
end
|
||||
|
||||
function materials.newTexturedMaterial(texture)
|
||||
return {
|
||||
type = materials.types.textured,
|
||||
texture = texture
|
||||
}
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return materials
|
||||
|
||||
@ -1,355 +0,0 @@
|
||||
|
||||
-------------------------------------------------------- Libraries --------------------------------------------------------
|
||||
|
||||
local renderer = {
|
||||
depthBuffer = {},
|
||||
projectionSurface = {},
|
||||
}
|
||||
|
||||
-------------------------------------------------------- Additional methods --------------------------------------------------------
|
||||
|
||||
function renderer.clearDepthBuffer()
|
||||
for y = 1, renderer.projectionSurface.height do
|
||||
renderer.depthBuffer[y] = {}
|
||||
for x = 1, renderer.projectionSurface.width do
|
||||
renderer.depthBuffer[y][x] = math.huge
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.setProjectionSurface(x, y, z, x2, y2, z2)
|
||||
renderer.projectionSurface = { x = x, y = y, z = z, x2 = x2, y2 = y2, z2 = z2 }
|
||||
renderer.projectionSurface.width = x2 - x + 1
|
||||
renderer.projectionSurface.height = y2 - y + 1
|
||||
renderer.projectionSurface.depth = z2 - z + 1
|
||||
renderer.depthBuffer = {}
|
||||
renderer.clearDepthBuffer()
|
||||
end
|
||||
|
||||
function renderer.getDepthBufferIndexByCoordinates(x, y)
|
||||
return (y - 1) * renderer.projectionSurface.width + x
|
||||
end
|
||||
|
||||
function renderer.setPixelUsingDepthBuffer(x, y, pixelDepthValue, pixelColor)
|
||||
if x >= renderer.projectionSurface.x and y >= renderer.projectionSurface.y and x <= renderer.projectionSurface.x2 and y <= renderer.projectionSurface.y2 then
|
||||
if pixelDepthValue < renderer.depthBuffer[y][x] then
|
||||
renderer.depthBuffer[y][x] = pixelDepthValue
|
||||
buffer.semiPixelRawSet(buffer.getBufferIndexByCoordinates(x, math.ceil(y / 2)), pixelColor, y % 2 == 0)
|
||||
-- buffer.set(x, y, pixelColor, 0x0, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.isVertexInViewRange(vector3Vertex)
|
||||
return
|
||||
vector3Vertex[1] >= renderer.projectionSurface.x and
|
||||
vector3Vertex[1] <= renderer.projectionSurface.y and
|
||||
vector3Vertex[2] >= renderer.projectionSurface.x2 and
|
||||
vector3Vertex[2] <= renderer.projectionSurface.y2
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Line rendering --------------------------------------------------------
|
||||
|
||||
function renderer.renderLine(x1, y1, z1, x2, y2, z2, color)
|
||||
local incycleValueFrom, incycleValueTo, outcycleValueFrom, outcycleValueTo, isReversed, incycleValueDelta, outcycleValueDelta = x1, x2, y1, y2, false, math.abs(x2 - x1), math.abs(y2 - y1)
|
||||
if incycleValueDelta < outcycleValueDelta then
|
||||
incycleValueFrom, incycleValueTo, outcycleValueFrom, outcycleValueTo, isReversed, incycleValueDelta, outcycleValueDelta = y1, y2, x1, x2, true, outcycleValueDelta, incycleValueDelta
|
||||
end
|
||||
|
||||
if outcycleValueFrom > outcycleValueTo then
|
||||
outcycleValueFrom, outcycleValueTo = outcycleValueTo, outcycleValueFrom
|
||||
incycleValueFrom, incycleValueTo = incycleValueTo, incycleValueFrom
|
||||
z1, z2 = z2, z1
|
||||
end
|
||||
|
||||
local outcycleValue, outcycleValueCounter, outcycleValueTriggerIncrement = outcycleValueFrom, 1, incycleValueDelta / outcycleValueDelta
|
||||
local outcycleValueTrigger = outcycleValueTriggerIncrement
|
||||
local z, zStep = z1, (z2 - z1) / incycleValueDelta
|
||||
|
||||
for incycleValue = incycleValueFrom, incycleValueTo, incycleValueFrom < incycleValueTo and 1 or -1 do
|
||||
if isReversed then
|
||||
renderer.setPixelUsingDepthBuffer(outcycleValue, incycleValue, z, color)
|
||||
else
|
||||
renderer.setPixelUsingDepthBuffer(incycleValue, outcycleValue, z, color)
|
||||
end
|
||||
|
||||
outcycleValueCounter, z = outcycleValueCounter + 1, z + zStep
|
||||
if outcycleValueCounter > outcycleValueTrigger then
|
||||
outcycleValue, outcycleValueTrigger = outcycleValue + 1, outcycleValueTrigger + outcycleValueTriggerIncrement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderDot(vector3Vertex, color)
|
||||
renderer.setPixelUsingDepthBuffer(math.floor(vector3Vertex[1]), math.floor(vector3Vertex[2]), vector3Vertex[3], color)
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Triangles render --------------------------------------------------------
|
||||
|
||||
local function fillPart(x1, x2, z1, z2, y, color)
|
||||
if x1 > x2 then
|
||||
x1, x2 = x2, x1
|
||||
z1, z2 = z2, z1
|
||||
end
|
||||
local z, zStep = z1, (z2 - z1) / (x2 - x1)
|
||||
for i = x1, x2 do
|
||||
-- buffer.semiPixelSet(i, y, color)
|
||||
renderer.setPixelUsingDepthBuffer(i, y, z, color)
|
||||
z = z + zStep
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderFilledTriangle(points, color)
|
||||
local topID, centerID, bottomID = 1, 2, 3
|
||||
for i = 1, 3 do
|
||||
if points[i][2] < points[topID][2] then topID = i end
|
||||
if points[i][2] > points[bottomID][2] then bottomID = i end
|
||||
end
|
||||
for i = 1, 3 do
|
||||
if i ~= topID and i ~= bottomID then centerID = i end
|
||||
end
|
||||
|
||||
-- Рассчет дельт
|
||||
local yFromTopToCenterDelta = points[centerID][2] - points[topID][2]
|
||||
local yFromTopToBottomDelta = points[bottomID][2] - points[topID][2]
|
||||
local yFromCenterToBottomDelta = points[bottomID][2] - points[centerID][2]
|
||||
|
||||
-- Если треугольник не имеет высоты, то на кой хуй нам его вообще рисовать?
|
||||
if yFromTopToBottomDelta == 0 then return end
|
||||
|
||||
local xFromTopToBottom, xFromTopToBottomIncrement = points[topID][1], (points[bottomID][1] - points[topID][1]) / (yFromTopToBottomDelta)
|
||||
local xFromTopToBottomModifyer = xFromTopToBottomIncrement >= 0 and 1 or -1
|
||||
xFromTopToBottomIncrement = math.abs(xFromTopToBottomIncrement)
|
||||
local xFromTopToBottomTrigger = xFromTopToBottomIncrement
|
||||
local xFromTopToBottomCounter = 0
|
||||
|
||||
local zFromTopToBottom, zFromTopToBottomStep = points[topID][3], (points[bottomID][3] - points[topID][3]) / (yFromTopToBottomDelta)
|
||||
|
||||
|
||||
-- Начало отрисовки верхнего йоба-куска
|
||||
if yFromTopToCenterDelta ~= 0 then
|
||||
local xFromTopToCenter, xFromTopToCenterIncrement = points[topID][1], (points[centerID][1] - points[topID][1]) / (yFromTopToCenterDelta)
|
||||
local xFromTopToCenterModifyer = xFromTopToCenterIncrement >= 0 and 1 or -1
|
||||
xFromTopToCenterIncrement = math.abs(xFromTopToCenterIncrement)
|
||||
local xFromTopToCenterTrigger = xFromTopToCenterIncrement
|
||||
local xFromTopToCenterCounter = 0
|
||||
|
||||
local zFromTopToCenter, zFromTopToCenterStep = points[topID][3], (points[centerID][3] - points[topID][3]) / (yFromTopToCenterDelta)
|
||||
|
||||
for y = points[topID][2], points[centerID][2] - 1 do
|
||||
fillPart(xFromTopToCenter, xFromTopToBottom, zFromTopToCenter, zFromTopToBottom, y, color)
|
||||
|
||||
while xFromTopToCenterCounter < xFromTopToCenterTrigger do
|
||||
xFromTopToCenter = xFromTopToCenter + xFromTopToCenterModifyer
|
||||
xFromTopToCenterCounter = xFromTopToCenterCounter + 1
|
||||
end
|
||||
xFromTopToCenterTrigger = xFromTopToCenterTrigger + xFromTopToCenterIncrement
|
||||
|
||||
while xFromTopToBottomCounter < xFromTopToBottomTrigger do
|
||||
xFromTopToBottom = xFromTopToBottom + xFromTopToBottomModifyer
|
||||
xFromTopToBottomCounter = xFromTopToBottomCounter + 1
|
||||
end
|
||||
xFromTopToBottomTrigger = xFromTopToBottomTrigger + xFromTopToBottomIncrement
|
||||
|
||||
zFromTopToCenter = zFromTopToCenter + zFromTopToCenterStep
|
||||
zFromTopToBottom = zFromTopToBottom + zFromTopToBottomStep
|
||||
end
|
||||
end
|
||||
|
||||
-- Начало отрисовки нижнего йоба-куска
|
||||
if yFromCenterToBottomDelta ~= 0 then
|
||||
local xFromCenterToBottom, xFromCenterToBottomIncrement = points[centerID][1], (points[bottomID][1] - points[centerID][1]) / (yFromCenterToBottomDelta)
|
||||
local xFromCenterToBottomModifyer = xFromCenterToBottomIncrement >= 0 and 1 or -1
|
||||
xFromCenterToBottomIncrement = math.abs(xFromCenterToBottomIncrement)
|
||||
local xFromCenterToBottomTrigger = xFromCenterToBottomIncrement
|
||||
local xFromCenterToBottomCounter = 0
|
||||
|
||||
local zFromCenterToBottom, zFromCenterToBottomStep = points[centerID][3], (points[bottomID][3] - points[centerID][3]) / (yFromCenterToBottomDelta)
|
||||
|
||||
for y = points[centerID][2], points[bottomID][2] do
|
||||
fillPart(xFromCenterToBottom, xFromTopToBottom, zFromCenterToBottom, zFromTopToBottom, y, color)
|
||||
|
||||
while xFromCenterToBottomCounter < xFromCenterToBottomTrigger do
|
||||
xFromCenterToBottom = xFromCenterToBottom + xFromCenterToBottomModifyer
|
||||
xFromCenterToBottomCounter = xFromCenterToBottomCounter + 1
|
||||
end
|
||||
xFromCenterToBottomTrigger = xFromCenterToBottomTrigger + xFromCenterToBottomIncrement
|
||||
|
||||
while xFromTopToBottomCounter < xFromTopToBottomTrigger do
|
||||
xFromTopToBottom = xFromTopToBottom + xFromTopToBottomModifyer
|
||||
xFromTopToBottomCounter = xFromTopToBottomCounter + 1
|
||||
end
|
||||
xFromTopToBottomTrigger = xFromTopToBottomTrigger + xFromTopToBottomIncrement
|
||||
|
||||
zFromCenterToBottom = zFromCenterToBottom + zFromCenterToBottomStep
|
||||
zFromTopToBottom = zFromTopToBottom + zFromTopToBottomStep
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderTexturedTriangle(vertices, texture)
|
||||
|
||||
end
|
||||
|
||||
function renderer.renderTriangleObject(vector3Vertex1, vector3Vertex2, vector3Vertex3, renderMode, material)
|
||||
if renderMode == OCGL.renderModes.material then
|
||||
if material.type == OCGL.materialTypes.solid then
|
||||
renderer.renderFilledTriangle(
|
||||
{
|
||||
OCGL.newVector3(math.floor(vector3Vertex1[1]), math.floor(vector3Vertex1[2]), vector3Vertex1[3]),
|
||||
OCGL.newVector3(math.floor(vector3Vertex2[1]), math.floor(vector3Vertex2[2]), vector3Vertex2[3]),
|
||||
OCGL.newVector3(math.floor(vector3Vertex3[1]), math.floor(vector3Vertex3[2]), vector3Vertex3[3])
|
||||
},
|
||||
material.color
|
||||
)
|
||||
else
|
||||
error("Material type " .. tostring(material.type) .. " doesn't supported for rendering triangles")
|
||||
end
|
||||
elseif renderMode == OCGL.renderModes.wireframe then
|
||||
renderer.renderLine(math.floor(vector3Vertex1[1]), math.floor(vector3Vertex1[2]), vector3Vertex1[3], math.floor(vector3Vertex2[1]), math.floor(vector3Vertex2[2]), vector3Vertex2[3], OCGL.colors.wireframe)
|
||||
renderer.renderLine(math.floor(vector3Vertex2[1]), math.floor(vector3Vertex2[2]), vector3Vertex2[3], math.floor(vector3Vertex3[1]), math.floor(vector3Vertex3[2]), vector3Vertex3[3], OCGL.colors.wireframe)
|
||||
renderer.renderLine(math.floor(vector3Vertex1[1]), math.floor(vector3Vertex1[2]), vector3Vertex1[3], math.floor(vector3Vertex3[1]), math.floor(vector3Vertex3[2]), vector3Vertex3[3], OCGL.colors.wireframe)
|
||||
elseif renderMode == OCGL.renderModes.vertices then
|
||||
renderer.renderDot(vector3Vertex1, OCGL.colors.wireframe)
|
||||
renderer.renderDot(vector3Vertex2, OCGL.colors.wireframe)
|
||||
renderer.renderDot(vector3Vertex3, OCGL.colors.wireframe)
|
||||
else
|
||||
error("Rendermode enum " .. tostring(renderMode) .. " doesn't supported for rendering triangles")
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Mesh render --------------------------------------------------------
|
||||
|
||||
function renderer.renderMesh(mesh, renderMode)
|
||||
for triangleIndex = 1, #mesh.triangles do
|
||||
-- if
|
||||
-- renderer.isVertexInViewRange(mesh.verticesMatrix[mesh.triangles[triangleIndex][1]]) or
|
||||
-- renderer.isVertexInViewRange(mesh.verticesMatrix[mesh.triangles[triangleIndex][2]]) or
|
||||
-- renderer.isVertexInViewRange(mesh.verticesMatrix[mesh.triangles[triangleIndex][3]])
|
||||
-- then
|
||||
renderer.renderTriangleObject(
|
||||
mesh.verticesMatrix[mesh.triangles[triangleIndex][1]],
|
||||
mesh.verticesMatrix[mesh.triangles[triangleIndex][2]],
|
||||
mesh.verticesMatrix[mesh.triangles[triangleIndex][3]],
|
||||
renderMode,
|
||||
mesh.triangles[triangleIndex].material or mesh.material
|
||||
)
|
||||
-- end
|
||||
end
|
||||
|
||||
--Рендерим локальные оси
|
||||
-- if mesh.showPivotPoint then
|
||||
-- local scale = 30
|
||||
-- renderer.renderLine(
|
||||
-- mesh.pivotPoint.position,
|
||||
-- OCGL.newVector3(mesh.pivotPoint.position[1] + mesh.pivotPoint.axis[1][1] * scale, mesh.pivotPoint.position[2] + mesh.pivotPoint.axis[1][2] * scale, mesh.pivotPoint.position[3] + mesh.pivotPoint.axis[1][3] * scale),
|
||||
-- OCGL.colors.axis.x
|
||||
-- )
|
||||
-- renderer.renderLine(
|
||||
-- mesh.pivotPoint.position,
|
||||
-- OCGL.newVector3(mesh.pivotPoint.position[1] + mesh.pivotPoint.axis[2][1] * scale, mesh.pivotPoint.position[2] + mesh.pivotPoint.axis[2][2] * scale, mesh.pivotPoint.position[3] + mesh.pivotPoint.axis[2][3] * scale),
|
||||
-- OCGL.colors.axis.y
|
||||
-- )
|
||||
-- renderer.renderLine(
|
||||
-- mesh.pivotPoint.position,
|
||||
-- OCGL.newVector3(mesh.pivotPoint.position[1] + mesh.pivotPoint.axis[3][1] * scale, mesh.pivotPoint.position[2] + mesh.pivotPoint.axis[3][2] * scale, mesh.pivotPoint.position[3] + mesh.pivotPoint.axis[3][3] * scale),
|
||||
-- OCGL.colors.axis.z
|
||||
-- )
|
||||
-- end
|
||||
|
||||
return mesh
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Line object render --------------------------------------------------------
|
||||
|
||||
function renderer.renderLineObject(line, renderMode)
|
||||
if renderMode == OCGL.renderModes.vertices then
|
||||
renderer.renderDot(line.verticesMatrix[1], line.color)
|
||||
renderer.renderDot(line.verticesMatrix[2], line.color)
|
||||
else
|
||||
renderer.renderLine(
|
||||
math.floor(line.verticesMatrix[1][1]),
|
||||
math.floor(line.verticesMatrix[1][2]),
|
||||
line.verticesMatrix[1][3],
|
||||
math.floor(line.verticesMatrix[2][1]),
|
||||
math.floor(line.verticesMatrix[2][2]),
|
||||
line.verticesMatrix[2][3],
|
||||
line.color
|
||||
)
|
||||
-- else
|
||||
-- error("Rendermode enum " .. tostring(renderMode) .. " doesn't supported for rendering lines")
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------- FPS counter overlay render --------------------------------------------------------
|
||||
|
||||
local function drawSegments(x, y, segments, color)
|
||||
for i = 1, #segments do
|
||||
if segments[i] == 1 then
|
||||
buffer.semiPixelSquare(x, y, 3, 1, color)
|
||||
elseif segments[i] == 2 then
|
||||
buffer.semiPixelSquare(x + 2, y, 1, 3, color)
|
||||
elseif segments[i] == 3 then
|
||||
buffer.semiPixelSquare(x + 2, y + 2, 1, 3, color)
|
||||
elseif segments[i] == 4 then
|
||||
buffer.semiPixelSquare(x, y + 4, 3, 1, color)
|
||||
elseif segments[i] == 5 then
|
||||
buffer.semiPixelSquare(x, y + 2, 1, 3, color)
|
||||
elseif segments[i] == 6 then
|
||||
buffer.semiPixelSquare(x, y, 1, 3, color)
|
||||
elseif segments[i] == 7 then
|
||||
buffer.semiPixelSquare(x, y + 2, 3, 1, color)
|
||||
else
|
||||
error("Че за говно ты сюда напихал? Переделывай!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 1
|
||||
-- 6 2
|
||||
-- 7
|
||||
-- 5 3
|
||||
-- 4
|
||||
|
||||
function renderer.renderFPSCounter(x, y, renderMethod, color)
|
||||
local numbers = {
|
||||
["0"] = { 1, 2, 3, 4, 5, 6 },
|
||||
["1"] = { 2, 3 },
|
||||
["2"] = { 1, 2, 4, 5, 7 },
|
||||
["3"] = { 1, 2, 3, 4, 7 },
|
||||
["4"] = { 2, 3, 6, 7 },
|
||||
["5"] = { 1, 3, 4, 6, 7 },
|
||||
["6"] = { 1, 3, 4, 5, 6, 7 },
|
||||
["7"] = { 1, 2, 3 },
|
||||
["8"] = { 1, 2, 3, 4, 5, 6, 7 },
|
||||
["9"] = { 1, 2, 3, 4, 6, 7 },
|
||||
}
|
||||
|
||||
-- clock sec - 1 frame
|
||||
-- 1 sec - x frames
|
||||
|
||||
local oldClock = os.clock()
|
||||
renderMethod()
|
||||
-- local fps = tostring(math.ceil(1 / (os.clock() - oldClock) / 10))
|
||||
|
||||
buffer.text(1, 1, 0xFFFFFF, "FPS: " .. os.clock() - oldClock)
|
||||
|
||||
-- for i = 1, #fps do
|
||||
-- drawSegments(x, y, numbers[fps:sub(i, i)], color)
|
||||
-- x = x + 4
|
||||
-- end
|
||||
|
||||
return x - 3
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return renderer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,242 +0,0 @@
|
||||
|
||||
-------------------------------------------------------- Libraries --------------------------------------------------------
|
||||
|
||||
local vector = require("vector")
|
||||
local materials = require("OpenComputersGL/Materials")
|
||||
local buffer = require("doubleBuffering")
|
||||
|
||||
local renderer = {
|
||||
depthBuffer = {},
|
||||
projectionSurface = {},
|
||||
}
|
||||
|
||||
-------------------------------------------------------- Constants --------------------------------------------------------
|
||||
|
||||
renderer.colors = {
|
||||
axis = {
|
||||
x = 0xFF0000,
|
||||
y = 0x00FF00,
|
||||
z = 0x0000FF,
|
||||
},
|
||||
pivotPoint = 0xFFFFFF,
|
||||
wireframe = 0x00FFFF,
|
||||
}
|
||||
|
||||
renderer.renderModes = {
|
||||
material = 1,
|
||||
wireframe = 2,
|
||||
vertices = 3,
|
||||
}
|
||||
|
||||
-------------------------------------------------------- Renderer --------------------------------------------------------
|
||||
|
||||
function renderer.clearDepthBuffer()
|
||||
for y = 1, renderer.projectionSurface.height do
|
||||
renderer.depthBuffer[y] = {}
|
||||
for x = 1, renderer.projectionSurface.width do
|
||||
renderer.depthBuffer[y][x] = math.huge
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.setProjectionSurface(x, y, z, x2, y2, z2)
|
||||
renderer.projectionSurface = { x = x, y = y, z = z, x2 = x2, y2 = y2, z2 = z2 }
|
||||
renderer.projectionSurface.width = x2 - x + 1
|
||||
renderer.projectionSurface.height = y2 - y + 1
|
||||
renderer.projectionSurface.depth = z2 - z + 1
|
||||
renderer.depthBuffer = {}
|
||||
end
|
||||
|
||||
function renderer.setPixelUsingDepthBuffer(x, y, pixelDepthValue, pixelColor)
|
||||
if
|
||||
x >= renderer.projectionSurface.x and
|
||||
x <= renderer.projectionSurface.x2 and
|
||||
y >= renderer.projectionSurface.y and
|
||||
y <= renderer.projectionSurface.y2 and
|
||||
pixelDepthValue >= 1 and
|
||||
pixelDepthValue <= renderer.projectionSurface.z2
|
||||
then
|
||||
if pixelDepthValue < renderer.depthBuffer[y][x] then
|
||||
renderer.depthBuffer[y][x] = pixelDepthValue
|
||||
buffer.semiPixelRawSet(buffer.getBufferIndexByCoordinates(x, math.ceil(y / 2)), pixelColor, y % 2 == 0)
|
||||
-- buffer.set(x, y, pixelColor, 0x0, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.isVertexInViewRange(vector3Vertex)
|
||||
return
|
||||
vector3Vertex[1] >= renderer.projectionSurface.x and
|
||||
vector3Vertex[1] <= renderer.projectionSurface.y and
|
||||
vector3Vertex[2] >= renderer.projectionSurface.x2 and
|
||||
vector3Vertex[2] <= renderer.projectionSurface.y2
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Line rendering --------------------------------------------------------
|
||||
|
||||
function renderer.renderLine(x1, y1, z1, x2, y2, z2, color)
|
||||
local incycleValueFrom, incycleValueTo, outcycleValueFrom, outcycleValueTo, isReversed, incycleValueDelta, outcycleValueDelta = x1, x2, y1, y2, false, math.abs(x2 - x1), math.abs(y2 - y1)
|
||||
if incycleValueDelta < outcycleValueDelta then
|
||||
incycleValueFrom, incycleValueTo, outcycleValueFrom, outcycleValueTo, isReversed, incycleValueDelta, outcycleValueDelta = y1, y2, x1, x2, true, outcycleValueDelta, incycleValueDelta
|
||||
end
|
||||
|
||||
if outcycleValueFrom > outcycleValueTo then
|
||||
outcycleValueFrom, outcycleValueTo = outcycleValueTo, outcycleValueFrom
|
||||
incycleValueFrom, incycleValueTo = incycleValueTo, incycleValueFrom
|
||||
z1, z2 = z2, z1
|
||||
end
|
||||
|
||||
local outcycleValue, outcycleValueCounter, outcycleValueTriggerIncrement = outcycleValueFrom, 1, incycleValueDelta / outcycleValueDelta
|
||||
local outcycleValueTrigger = outcycleValueTriggerIncrement
|
||||
local z, zStep = z1, (z2 - z1) / incycleValueDelta
|
||||
|
||||
for incycleValue = incycleValueFrom, incycleValueTo, incycleValueFrom < incycleValueTo and 1 or -1 do
|
||||
if isReversed then
|
||||
renderer.setPixelUsingDepthBuffer(outcycleValue, incycleValue, z, color)
|
||||
else
|
||||
renderer.setPixelUsingDepthBuffer(incycleValue, outcycleValue, z, color)
|
||||
end
|
||||
|
||||
outcycleValueCounter, z = outcycleValueCounter + 1, z + zStep
|
||||
if outcycleValueCounter > outcycleValueTrigger then
|
||||
outcycleValue, outcycleValueTrigger = outcycleValue + 1, outcycleValueTrigger + outcycleValueTriggerIncrement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderDot(vector3Vertex, color)
|
||||
renderer.setPixelUsingDepthBuffer(math.floor(vector3Vertex[1]), math.floor(vector3Vertex[2]), vector3Vertex[3], color)
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Triangles render --------------------------------------------------------
|
||||
|
||||
local function fillPart(x1Screen, x2Screen, z1Screen, z2Screen, y, color)
|
||||
if x2Screen < x1Screen then x1Screen, x2Screen, z1Screen, z2Screen = x2Screen, x1Screen, z2Screen, z1Screen end
|
||||
|
||||
local z, zStep = z1Screen, (z2Screen - z1Screen) / (x2Screen - x1Screen)
|
||||
for x = math.floor(x1Screen), math.floor(x2Screen) do
|
||||
renderer.setPixelUsingDepthBuffer(x, y, z, color)
|
||||
-- buffer.semiPixelSet(x, y, color)
|
||||
z = z + zStep
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderFilledTriangle(points, color)
|
||||
local topID, centerID, bottomID = 1, 1, 1
|
||||
for i = 1, 3 do
|
||||
if points[i][2] < points[topID][2] then topID = i end
|
||||
if points[i][2] > points[bottomID][2] then bottomID = i end
|
||||
end
|
||||
for i = 1, 3 do if i ~= topID and i ~= bottomID then centerID = i end end
|
||||
|
||||
local x1ScreenStep = (points[centerID][1] - points[topID][1]) / (points[centerID][2] - points[topID][2])
|
||||
local x2ScreenStep = (points[bottomID][1] - points[topID][1]) / (points[bottomID][2] - points[topID][2])
|
||||
local x1Screen, x2Screen = points[topID][1], points[topID][1]
|
||||
|
||||
local z1ScreenStep = (points[centerID][3] - points[topID][3]) / (points[centerID][2] - points[topID][2])
|
||||
local z2ScreenStep = (points[bottomID][3] - points[topID][3]) / (points[bottomID][2] - points[topID][2])
|
||||
local z1Screen, z2Screen = points[topID][3], points[topID][3]
|
||||
|
||||
-- Рисуем первый кусок треугольника от верхней точки до центральной
|
||||
for y = points[topID][2], points[centerID][2] - 1 do
|
||||
fillPart(x1Screen, x2Screen, z1Screen, z2Screen, y, color)
|
||||
x1Screen, x2Screen, z1Screen, z2Screen = x1Screen + x1ScreenStep, x2Screen + x2ScreenStep, z1Screen + z1ScreenStep, z2Screen + z2ScreenStep
|
||||
end
|
||||
|
||||
-- Далее считаем, как будет изменяться X от центрельной точки до нижней
|
||||
x1Screen, x1ScreenStep = points[centerID][1], (points[bottomID][1] - points[centerID][1]) / (points[bottomID][2] - points[centerID][2])
|
||||
z1Screen, z1ScreenStep = points[centerID][3], (points[bottomID][3] - points[centerID][3]) / (points[bottomID][2] - points[centerID][2])
|
||||
-- И рисуем нижний кусок треугольника от центральной точки до нижней
|
||||
for y = points[centerID][2], points[bottomID][2] do
|
||||
fillPart(x1Screen, x2Screen, z1Screen, z2Screen, y, color)
|
||||
x1Screen, x2Screen, z1Screen, z2Screen = x1Screen + x1ScreenStep, x2Screen + x2ScreenStep, z1Screen + z1ScreenStep, z2Screen + z2ScreenStep
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderTexturedTriangle(vertices, texture)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Mesh Object Rendering --------------------------------------------------------
|
||||
|
||||
function renderer.renderMesh(mesh, renderMode)
|
||||
for triangleIndex = 1, #mesh.triangles do
|
||||
-- if
|
||||
-- renderer.isVertexInViewRange(mesh.verticesMatrix[mesh.triangles[triangleIndex][1]]) or
|
||||
-- renderer.isVertexInViewRange(mesh.verticesMatrix[mesh.triangles[triangleIndex][2]]) or
|
||||
-- renderer.isVertexInViewRange(mesh.verticesMatrix[mesh.triangles[triangleIndex][3]])
|
||||
-- then
|
||||
renderer.renderTriangleObject(
|
||||
mesh.verticesMatrix[mesh.triangles[triangleIndex][1]],
|
||||
mesh.verticesMatrix[mesh.triangles[triangleIndex][2]],
|
||||
mesh.verticesMatrix[mesh.triangles[triangleIndex][3]],
|
||||
renderMode,
|
||||
mesh.triangles[triangleIndex].material or mesh.material
|
||||
)
|
||||
-- end
|
||||
end
|
||||
|
||||
return mesh
|
||||
end
|
||||
|
||||
-------------------------------------------------------- FPS counter overlay render --------------------------------------------------------
|
||||
|
||||
local function drawSegments(x, y, segments, color)
|
||||
for i = 1, #segments do
|
||||
if segments[i] == 1 then
|
||||
buffer.semiPixelSquare(x, y, 3, 1, color)
|
||||
elseif segments[i] == 2 then
|
||||
buffer.semiPixelSquare(x + 2, y, 1, 3, color)
|
||||
elseif segments[i] == 3 then
|
||||
buffer.semiPixelSquare(x + 2, y + 2, 1, 3, color)
|
||||
elseif segments[i] == 4 then
|
||||
buffer.semiPixelSquare(x, y + 4, 3, 1, color)
|
||||
elseif segments[i] == 5 then
|
||||
buffer.semiPixelSquare(x, y + 2, 1, 3, color)
|
||||
elseif segments[i] == 6 then
|
||||
buffer.semiPixelSquare(x, y, 1, 3, color)
|
||||
elseif segments[i] == 7 then
|
||||
buffer.semiPixelSquare(x, y + 2, 3, 1, color)
|
||||
else
|
||||
error("Че за говно ты сюда напихал? Переделывай!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function renderer.renderFPSCounter(x, y, renderMethod, color)
|
||||
local numbers = {
|
||||
["0"] = { 1, 2, 3, 4, 5, 6 },
|
||||
["1"] = { 2, 3 },
|
||||
["2"] = { 1, 2, 4, 5, 7 },
|
||||
["3"] = { 1, 2, 3, 4, 7 },
|
||||
["4"] = { 2, 3, 6, 7 },
|
||||
["5"] = { 1, 3, 4, 6, 7 },
|
||||
["6"] = { 1, 3, 4, 5, 6, 7 },
|
||||
["7"] = { 1, 2, 3 },
|
||||
["8"] = { 1, 2, 3, 4, 5, 6, 7 },
|
||||
["9"] = { 1, 2, 3, 4, 6, 7 },
|
||||
}
|
||||
|
||||
-- clock sec - 1 frame
|
||||
-- 1 sec - x frames
|
||||
|
||||
local oldClock = os.clock()
|
||||
renderMethod()
|
||||
local fps = tostring(math.ceil(1 / (os.clock() - oldClock) / 10))
|
||||
|
||||
-- buffer.text(1, 1, 0xFFFFFF, "FPS: " .. os.clock() - oldClock)
|
||||
|
||||
for i = 1, #fps do
|
||||
drawSegments(x, y, numbers[fps:sub(i, i)], color)
|
||||
x = x + 4
|
||||
end
|
||||
|
||||
return x - 3
|
||||
end
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return renderer
|
||||
|
||||
@ -1,380 +0,0 @@
|
||||
|
||||
-------------------------------------------------------- Libraries --------------------------------------------------------
|
||||
|
||||
local vector = require("vector")
|
||||
local matrix = require("matrix")
|
||||
local OCGL = require("OpenComputersGL/Main")
|
||||
local renderer = require("OpenComputersGL/Renderer")
|
||||
local materials = require("OpenComputersGL/Materials")
|
||||
local postProcessing = require("WildCatEngine/PostProcessing")
|
||||
local wildCatEngine = {}
|
||||
|
||||
-------------------------------------------------------- Universal object methods --------------------------------------------------------
|
||||
|
||||
function wildCatEngine.newPivotPoint(vector3Position)
|
||||
return {
|
||||
position = vector3Position,
|
||||
axis = {
|
||||
vector.newVector3(1, 0, 0),
|
||||
vector.newVector3(0, 1, 0),
|
||||
vector.newVector3(0, 0, 1),
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Mesh object --------------------------------------------------------
|
||||
|
||||
local function pushMeshToRenderQueue(mesh)
|
||||
local vector3Vertex1, vector3Vertex2, vector3Vertex3
|
||||
for triangleIndex = 1, #mesh.triangles do
|
||||
vector3Vertex1, vector3Vertex2, vector3Vertex3 = mesh.vertices[mesh.triangles[triangleIndex][1]], mesh.vertices[mesh.triangles[triangleIndex][2]], mesh.vertices[mesh.triangles[triangleIndex][3]]
|
||||
OCGL.pushTriangleToRenderQueue(
|
||||
vector.newVector3(vector3Vertex1[1], vector3Vertex1[2], vector3Vertex1[3]),
|
||||
vector.newVector3(vector3Vertex2[1], vector3Vertex2[2], vector3Vertex2[3]),
|
||||
vector.newVector3(vector3Vertex3[1], vector3Vertex3[2], vector3Vertex3[3]),
|
||||
mesh.triangles[triangleIndex][4] or mesh.material,
|
||||
mesh,
|
||||
triangleIndex
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function wildCatEngine.newMesh(vector3Position, vertices, triangles, material)
|
||||
local mesh = {}
|
||||
|
||||
mesh.pivotPoint = wildCatEngine.newPivotPoint(vector3Position)
|
||||
mesh.vertices = vertices
|
||||
for vertexIndex = 1, #mesh.vertices do
|
||||
mesh.vertices[vertexIndex][1], mesh.vertices[vertexIndex][2], mesh.vertices[vertexIndex][3] = mesh.vertices[vertexIndex][1] + vector3Position[1], mesh.vertices[vertexIndex][2] + vector3Position[2], mesh.vertices[vertexIndex][3] + vector3Position[3]
|
||||
end
|
||||
mesh.triangles = triangles
|
||||
mesh.material = material
|
||||
mesh.pushToRenderQueue = pushMeshToRenderQueue
|
||||
|
||||
return mesh
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Line object --------------------------------------------------------
|
||||
|
||||
local function pushLineToRenderQueue(line)
|
||||
OCGL.pushLineToRenderQueue(
|
||||
vector.newVector3(line.vertices[1][1], line.vertices[1][2], line.vertices[1][3]),
|
||||
vector.newVector3(line.vertices[2][1], line.vertices[2][2], line.vertices[2][3]),
|
||||
line.color
|
||||
)
|
||||
end
|
||||
|
||||
function wildCatEngine.newLine(vector3Position, vector3Vertex1, vector3Vertex2, color)
|
||||
local line = {}
|
||||
|
||||
line.pivotPoint = wildCatEngine.newPivotPoint(vector3Position)
|
||||
line.vertices = { vector3Vertex1, vector3Vertex2 }
|
||||
line.color = color
|
||||
line.pushToRenderQueue = pushLineToRenderQueue
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Plane object --------------------------------------------------------
|
||||
|
||||
function wildCatEngine.newPlane(vector3Position, width, height, material)
|
||||
local halfWidth, halfHeight = width / 2, height / 2
|
||||
return wildCatEngine.newMesh(
|
||||
vector3Position,
|
||||
{
|
||||
vector.newVector3(-halfWidth, 0, -halfHeight),
|
||||
vector.newVector3(-halfWidth, 0, halfHeight),
|
||||
vector.newVector3(halfWidth, 0, halfHeight),
|
||||
vector.newVector3(halfWidth, 0, -halfHeight),
|
||||
},
|
||||
{
|
||||
OCGL.newIndexedTriangle(1, 2, 3),
|
||||
OCGL.newIndexedTriangle(1, 4, 3)
|
||||
},
|
||||
material
|
||||
)
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Cube object --------------------------------------------------------
|
||||
|
||||
--[[
|
||||
| /
|
||||
| /
|
||||
y z
|
||||
x -----
|
||||
|
||||
FRONT LEFT BACK RIGHT TOP BOTTOM
|
||||
2######3 3######6 6######7 7######2 7######6 8######5
|
||||
######## ######## ######## ######## ######## ########
|
||||
1######4 4######5 5######8 8######1 2######3 1######4
|
||||
]]
|
||||
|
||||
function wildCatEngine.newCube(vector3Position, size, material)
|
||||
local halfSize = size / 2
|
||||
return wildCatEngine.newMesh(
|
||||
vector3Position,
|
||||
{
|
||||
-- (1-2-3-4)
|
||||
vector.newVector3(-halfSize, -halfSize, -halfSize),
|
||||
vector.newVector3(-halfSize, halfSize, -halfSize),
|
||||
vector.newVector3(halfSize, halfSize, -halfSize),
|
||||
vector.newVector3(halfSize, -halfSize, -halfSize),
|
||||
-- (5-6-7-8)
|
||||
vector.newVector3(halfSize, -halfSize, halfSize),
|
||||
vector.newVector3(halfSize, halfSize, halfSize),
|
||||
vector.newVector3(-halfSize, halfSize, halfSize),
|
||||
vector.newVector3(-halfSize, -halfSize, halfSize),
|
||||
},
|
||||
{
|
||||
-- Front
|
||||
OCGL.newIndexedTriangle(1, 2, 3),
|
||||
OCGL.newIndexedTriangle(1, 4, 3),
|
||||
-- Left
|
||||
OCGL.newIndexedTriangle(4, 3, 6),
|
||||
OCGL.newIndexedTriangle(4, 5, 6),
|
||||
-- Back
|
||||
OCGL.newIndexedTriangle(5, 6, 7),
|
||||
OCGL.newIndexedTriangle(5, 8, 7),
|
||||
-- Right
|
||||
OCGL.newIndexedTriangle(8, 7, 2),
|
||||
OCGL.newIndexedTriangle(8, 1, 2),
|
||||
-- Top
|
||||
OCGL.newIndexedTriangle(2, 7, 6),
|
||||
OCGL.newIndexedTriangle(2, 3, 6),
|
||||
-- Bottom
|
||||
OCGL.newIndexedTriangle(1, 8, 5),
|
||||
OCGL.newIndexedTriangle(1, 4, 5),
|
||||
},
|
||||
material
|
||||
)
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Grid lines --------------------------------------------------------
|
||||
|
||||
function wildCatEngine.newGridLines(vector3Position, axisRange, gridRange, gridRangeStep)
|
||||
local objects = {}
|
||||
-- Grid
|
||||
for x = -gridRange, gridRange, gridRangeStep do
|
||||
table.insert(objects, 1, wildCatEngine.newLine(
|
||||
vector.newVector3(vector3Position[1] + x, vector3Position[2], vector3Position[3]),
|
||||
vector.newVector3(0, 0, -gridRange),
|
||||
vector.newVector3(0, 0, gridRange),
|
||||
0x444444
|
||||
))
|
||||
end
|
||||
for z = -gridRange, gridRange, gridRangeStep do
|
||||
table.insert(objects, 1, wildCatEngine.newLine(
|
||||
vector.newVector3(vector3Position[1], vector3Position[2], vector3Position[3] + z),
|
||||
vector.newVector3(-gridRange, 0, 0),
|
||||
vector.newVector3(gridRange, 0, 0),
|
||||
0x444444
|
||||
))
|
||||
end
|
||||
|
||||
-- Axis
|
||||
table.insert(objects, wildCatEngine.newLine(
|
||||
vector3Position,
|
||||
vector.newVector3(-axisRange, -1, 0),
|
||||
vector.newVector3(axisRange, -1, 0),
|
||||
renderer.colors.axis.x
|
||||
))
|
||||
table.insert(objects, wildCatEngine.newLine(
|
||||
vector3Position,
|
||||
vector.newVector3(0, -axisRange, 0),
|
||||
vector.newVector3(0, axisRange, 0),
|
||||
renderer.colors.axis.y
|
||||
))
|
||||
table.insert(objects, wildCatEngine.newLine(
|
||||
vector3Position,
|
||||
vector.newVector3(0, -1, -axisRange),
|
||||
vector.newVector3(0, -1, axisRange),
|
||||
renderer.colors.axis.z
|
||||
))
|
||||
|
||||
return objects
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Camera object --------------------------------------------------------
|
||||
|
||||
local function cameraSetRotation(camera, axisXRotation, axisYRotation, axisZRotation)
|
||||
camera.rotation[1], camera.rotation[2], camera.rotation[3] = axisXRotation, axisYRotation, axisZRotation
|
||||
camera.rotationMatrix = matrix.multiply(
|
||||
matrix.multiply(
|
||||
OCGL.newRotationMatrix(OCGL.axis.x, -camera.rotation[1]),
|
||||
OCGL.newRotationMatrix(OCGL.axis.y, -camera.rotation[2])
|
||||
),
|
||||
OCGL.newRotationMatrix(OCGL.axis.z, -camera.rotation[3])
|
||||
)
|
||||
-- local lookVectorMatrix = matrix.multiply({ camera.lookVector }, camera.rotationMatrix)
|
||||
-- camera.lookVector[1], camera.lookVector[2], camera.lookVector[3] = lookVectorMatrix[1][1], lookVectorMatrix[1][2], lookVectorMatrix[1][3]
|
||||
end
|
||||
|
||||
local function cameraRotate(camera, axisXAdditionalRotation, axisYAdditionalRotation, axisZAdditionalRotation)
|
||||
cameraSetRotation(camera, camera.rotation[1] + axisXAdditionalRotation, camera.rotation[2] + axisYAdditionalRotation, camera.rotation[3] + axisZAdditionalRotation)
|
||||
end
|
||||
|
||||
local function cameraSetPosition(camera, x, y, z)
|
||||
camera.position[1], camera.position[2], camera.position[3] = x, y, z
|
||||
end
|
||||
|
||||
local function cameraTranslate(camera, xTranslation, yTranslation, zTranslation)
|
||||
camera.position[1], camera.position[2], camera.position[3] = camera.position[1] + xTranslation, camera.position[2] + yTranslation, camera.position[3] + zTranslation
|
||||
end
|
||||
|
||||
function wildCatEngine.newCamera(vector3Position, vector3Rotation)
|
||||
local camera = {}
|
||||
|
||||
camera.position = vector3Position
|
||||
camera.rotation = vector3Rotation
|
||||
camera.projectionSurface = {x = 1, y = 1, z = 100, x2 = buffer.screen.width, y2 = buffer.screen.height * 2, z2 = 1000}
|
||||
-- camera.lookVector = vector.newVector3(0, 0, 1)
|
||||
|
||||
camera.setPosition = cameraSetRotation
|
||||
camera.translate = cameraTranslate
|
||||
camera.rotate = cameraRotate
|
||||
camera.setRotation = cameraSetRotation
|
||||
|
||||
-- Создаем матрицу вращения камеры
|
||||
camera:rotate(0, 0, 0)
|
||||
|
||||
return camera
|
||||
end
|
||||
|
||||
-------------------------------------------------------- Scene object --------------------------------------------------------
|
||||
|
||||
local function sceneAddObject(scene, object)
|
||||
table.insert(scene.objects, object)
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
local function sceneAddObjects(scene, objects)
|
||||
for objectIndex = 1, #objects do
|
||||
table.insert(scene.objects, objects[objectIndex])
|
||||
end
|
||||
|
||||
return objects
|
||||
end
|
||||
|
||||
local function sceneRender(scene, backgroundColor, renderMode)
|
||||
OCGL.setProjectionSurface(scene.camera.projectionSurface.x, scene.camera.projectionSurface.y, scene.camera.projectionSurface.z, scene.camera.projectionSurface.x2, scene.camera.projectionSurface.y2, scene.camera.projectionSurface.z2)
|
||||
OCGL.clearBuffer(backgroundColor)
|
||||
|
||||
for objectIndex = 1, #scene.objects do
|
||||
scene.objects[objectIndex]:pushToRenderQueue()
|
||||
end
|
||||
|
||||
OCGL.translate(vector.newVector3(-scene.camera.position[1], -scene.camera.position[2], -scene.camera.position[3]))
|
||||
OCGL.rotate(scene.camera.rotationMatrix)
|
||||
OCGL.translate(vector.newVector3(0, 0, scene.camera.projectionSurface.z))
|
||||
-- OCGL.translate(vector.newVector3(scene.camera.position[1], scene.camera.position[2], scene.camera.position[3]))
|
||||
-- OCGL.translate(vector.newVector3(-scene.camera.position[1], -scene.camera.position[2], -scene.camera.position[3]))
|
||||
|
||||
if scene.camera.projectionEnabled then OCGL.createPerspectiveProjection() end
|
||||
OCGL.render(renderMode)
|
||||
|
||||
return scene
|
||||
end
|
||||
|
||||
function wildCatEngine.newScene(...)
|
||||
local scene = {}
|
||||
|
||||
scene.objects = {}
|
||||
scene.addObject = sceneAddObject
|
||||
scene.addObjects = sceneAddObjects
|
||||
scene.render = sceneRender
|
||||
|
||||
scene.camera = wildCatEngine.newCamera(vector.newVector3(0, 0, 0), vector.newVector3(0, 0, 0))
|
||||
scene.raycast = wildCatEngine.sceneRaycast
|
||||
|
||||
return scene
|
||||
end
|
||||
|
||||
-- -------------------------------------------------------- Raycasting methods --------------------------------------------------------
|
||||
|
||||
-- local function vectorMultiply(a, b)
|
||||
-- return vector.newVector3(a[2] * b[3] - a[3] * b[2], a[3] * b[1] - a[1] * b[3], a[1] * b[2] - a[2] * b[1])
|
||||
-- end
|
||||
|
||||
-- local function getVectorDistance(a)
|
||||
-- return math.sqrt(a[1] ^ 2 + a[2] ^ 2 + a[3] ^ 2)
|
||||
-- end
|
||||
|
||||
-- -- В случае попадания лучика этот метод вернет сам треугольник, а также дистанцию до его плоскости
|
||||
-- function wildCatEngine.triangleRaycast(vector3RayStart, vector3RayEnd)
|
||||
-- local minimalDistance, closestTriangleIndex
|
||||
-- for triangleIndex = 1, #OCGL.triangles do
|
||||
-- -- Это вершины треугольника
|
||||
-- local A, B, C = OCGL.vertices[OCGL.triangles[triangleIndex][1]], OCGL.vertices[OCGL.triangles[triangleIndex][3]], OCGL.vertices[OCGL.triangles[triangleIndex][3]]
|
||||
-- -- Это хз че
|
||||
-- local ABC = vectorMultiply(vector.newVector3(C[1] - A[1], C[2] - A[2], C[3] - A[3]), vector.newVector3(B[1] - A[1], B[2] - A[2], B[3] - A[3]))
|
||||
-- -- Рассчитываем удаленность виртуальной плоскости треугольника от старта нашего луча
|
||||
-- local D = -ABC[1] * A[1] - ABC[2] * A[2] - ABC[3] * A[3]
|
||||
-- local firstPart = D + ABC[1] * vector3RayStart[1] + ABC[2] * vector3RayStart[2] + ABC[3] * vector3RayStart[3]
|
||||
-- local secondPart = ABC[1] * vector3RayStart[1] - ABC[1] * vector3RayEnd[1] + ABC[2] * vector3RayStart[2] - ABC[2] * vector3RayEnd[2] + ABC[3] * vector3RayStart[3] - ABC[3] * vector3RayEnd[3]
|
||||
|
||||
-- -- Если наш лучик не параллелен той ебучей плоскости треугольника
|
||||
-- if secondPart ~= 0 then
|
||||
-- local distance = firstPart / secondPart
|
||||
-- -- И если этот объект находится ближе к старту луча, нежели предыдущий
|
||||
-- if (distance >= 0 and distance <= 1) and (not minimalDistance or distance < minimalDistance) then
|
||||
|
||||
-- -- То считаем точку попадания луча в данную плоскость (но ни хуя не факт, что он попадет в треугольник!)
|
||||
-- local S = vector.newVector3(
|
||||
-- vector3RayStart[1] + (vector3RayEnd[1] - vector3RayStart[1]) * distance,
|
||||
-- vector3RayStart[2] + (vector3RayEnd[2] - vector3RayStart[2]) * distance,
|
||||
-- vector3RayStart[3] + (vector3RayEnd[3] - vector3RayStart[3]) * distance
|
||||
-- )
|
||||
|
||||
-- -- Далее считаем сумму площадей параллелограммов, образованных тремя треугольниками, образовавшихся при попадании точки в треугольник
|
||||
-- -- Нууу тип кароч смари: точка ебанула в центр, и треугольник распидорасило на три мелких. Ну, и три мелких могут образовать параллелограммы свои
|
||||
-- -- И, кароч, если сумма трех площадей этих мелких уебков будет сильно отличаться от площади жирного треугольника, то луч не попал
|
||||
-- -- Ну, а площадь считается через sqrt(x^2+y^2+z^2) для каждого йоба-вектора
|
||||
|
||||
-- ---- *A *B
|
||||
|
||||
|
||||
-- -- * Shotxyz
|
||||
|
||||
|
||||
-- --- *C
|
||||
|
||||
-- local SA = vector.newVector3(A[1] - S[1], A[2] - S[2], A[3] - S[3])
|
||||
-- local SB = vector.newVector3(B[1] - S[1], B[2] - S[2], B[3] - S[3])
|
||||
-- local SC = vector.newVector3(C[1] - S[1], C[2] - S[2], C[3] - S[3])
|
||||
|
||||
-- local vectorDistanceSum = getVectorDistance(vectorMultiply(SA, SB)) + getVectorDistance(vectorMultiply(SB, SC)) + getVectorDistance(vectorMultiply(SC, SA))
|
||||
-- local ABCDistance = getVectorDistance(ABC)
|
||||
|
||||
-- -- Вот тут мы чекаем погрешность расчетов. Если все заебок, то кидаем этот треугольник в "проверенные""
|
||||
-- if math.abs(vectorDistanceSum - ABCDistance) < 1 then
|
||||
-- closestTriangleIndex = triangleIndex
|
||||
-- minimalDistance = distance
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- -- ecs.error(closestTriangleIndex)
|
||||
-- return closestTriangleIndex, minimalDistance
|
||||
-- end
|
||||
|
||||
-- -- function wildCatEngine.sceneRaycast(scene, vector3RayStart, vector3RayEnd)
|
||||
-- -- local closestObjectIndex, closestTriangleIndex, minimalDistance
|
||||
|
||||
-- -- for objectIndex = 1, #scene.objects do
|
||||
-- -- if scene.objects[objectIndex].triangles then
|
||||
-- -- local triangleIndex, distance = wildCatEngine.meshRaycast(scene.objects[objectIndex], vector3RayStart, vector3RayEnd)
|
||||
-- -- if triangleIndex and (not minimalDistance or distance < minimalDistance ) then
|
||||
-- -- closestObjectIndex, closestTriangleIndex, minimalDistance = objectIndex, triangleIndex, distance
|
||||
-- -- end
|
||||
-- -- end
|
||||
-- -- end
|
||||
|
||||
-- -- return closestObjectIndex, closestTriangleIndex, minimalDistance
|
||||
-- -- end
|
||||
|
||||
-------------------------------------------------------- Zalupa --------------------------------------------------------
|
||||
|
||||
return wildCatEngine
|
||||
@ -1,12 +0,0 @@
|
||||
|
||||
-------------------------------------------------------- Libraries --------------------------------------------------------
|
||||
|
||||
local buffer = require("doubleBuffering")
|
||||
local postProcessing = {}
|
||||
|
||||
-------------------------------------------------------- Plane object --------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------- Zalupa --------------------------------------------------------
|
||||
|
||||
return postProcessing
|
||||
@ -1,222 +0,0 @@
|
||||
|
||||
local matrixLibrary = {}
|
||||
|
||||
---------------------------------------------------- Matrix tables creation ----------------------------------------------------------------
|
||||
|
||||
function matrixLibrary.newIdentityMatrix(size)
|
||||
local matrix = {}
|
||||
|
||||
for y = 1, size do
|
||||
matrix[y] = {}
|
||||
for x = 1, size do
|
||||
matrix[y][x] = (x == y) and 1 or 0
|
||||
end
|
||||
end
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function matrixLibrary.newCofactorMatrix(matrix)
|
||||
local cofactorMatrix = {}
|
||||
for y = 1, #matrix do
|
||||
cofactorMatrix[y] = {}
|
||||
for x = 1, #matrix[y] do
|
||||
cofactorMatrix[y][x] = matrixLibrary.getCofactor(matrix, y, x)
|
||||
end
|
||||
end
|
||||
|
||||
return cofactorMatrix
|
||||
end
|
||||
|
||||
function matrixLibrary.newAdjugateMatrix(matrix)
|
||||
return matrixLibrary.transpose(matrixLibrary.newCofactorMatrix(matrix))
|
||||
end
|
||||
|
||||
function matrixLibrary.newFilledMatrix(width, height, value)
|
||||
local matrix = {}
|
||||
|
||||
for y = 1, height do
|
||||
matrix[y] = {}
|
||||
for x = 1, width do
|
||||
matrix[y][x] = value
|
||||
end
|
||||
end
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function matrixLibrary.copy(matrix)
|
||||
local newMatrix = {}
|
||||
|
||||
for y = 1, #matrix do
|
||||
newMatrix[y] = {}
|
||||
for x = 1, #matrix[y] do
|
||||
newMatrix[y][x] = matrix[y][x]
|
||||
end
|
||||
end
|
||||
|
||||
return newMatrix
|
||||
end
|
||||
|
||||
function matrixLibrary.print(matrix)
|
||||
print("Matrix size: " .. #matrix .. "x" .. #matrix[1])
|
||||
for y = 1, #matrix do
|
||||
for x = 1, #matrix[y] do
|
||||
io.write(tostring((not matrix[y]) and "nil" or matrix[y][x]))
|
||||
io.write(' ')
|
||||
end
|
||||
print("")
|
||||
end
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
---------------------------------------------------- Matrix arithmetic operations ----------------------------------------------------------------
|
||||
|
||||
function matrixLibrary.multiply(matrix, data)
|
||||
local dataType = type(data)
|
||||
if dataType == "table" then
|
||||
if (#matrix[1] ~= #data) then error("Couldn't multiply matrixes AxB: A[columns] ~= B[rows]") end
|
||||
|
||||
local result = {}
|
||||
for i = 1, #matrix do
|
||||
result[i] = {}
|
||||
for j = 1, #data[1] do
|
||||
local resultElement = 0
|
||||
for k = 1, #matrix[1] do
|
||||
resultElement = resultElement + (matrix[i][k] * data[k][j])
|
||||
end
|
||||
result[i][j] = resultElement
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
elseif dataType == "number" then
|
||||
for y = 1, #matrix do
|
||||
for x = 1, #matrix[y] do
|
||||
matrix[y][x] = matrix[y][x] * data
|
||||
end
|
||||
end
|
||||
|
||||
return matrix
|
||||
else
|
||||
error("Unsupported operation data type: " .. tostring(dataType))
|
||||
end
|
||||
end
|
||||
|
||||
function matrixLibrary.divide(matrix, data)
|
||||
local dataType = type(data)
|
||||
if dataType == "table" then
|
||||
error("Matrix by matrix division doesn't supported yet")
|
||||
elseif dataType == "number" then
|
||||
for y = 1, #matrix do
|
||||
for x = 1, #matrix[y] do
|
||||
matrix[y][x] = matrix[y][x] / data
|
||||
end
|
||||
end
|
||||
|
||||
return matrix
|
||||
else
|
||||
error("Unsupported operation data type: " .. tostring(dataType))
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------- Matrix resizing methods ----------------------------------------------------------------
|
||||
|
||||
function matrixLibrary.addRow(matrix, row)
|
||||
if (#matrix[1] ~= #row) then error("Insertion row size doesn't match matrix row size: " .. #row .. " vs " .. #matrix[1]) end
|
||||
|
||||
table.insert(matrix, row)
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function matrixLibrary.addColumn(matrix, column)
|
||||
if (#matrix ~= #column ) then error("Insertion column size doesn't match matrix column size: " .. #column .. " vs " .. #matrix) end
|
||||
|
||||
for y = 1, #column do
|
||||
table.insert(matrix[y], column[y])
|
||||
end
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function matrixLibrary.removeRow(matrix, row)
|
||||
if row > #matrix then error("Can't remove row that is bigger then matrix height") end
|
||||
|
||||
table.remove(matrix, row)
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
function matrixLibrary.removeColumn(matrix, column)
|
||||
if column > #matrix[1] then error("Can't remove column that is bigger then matrix width") end
|
||||
|
||||
for y = 1, #matrix do
|
||||
table.remove(matrix[y], column)
|
||||
end
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
---------------------------------------------------- Matrix advanced manipulation methods ----------------------------------------------------------------
|
||||
|
||||
function matrixLibrary.transpose(matrix)
|
||||
local transposedMatrix = {}
|
||||
for x = 1, #matrix[1] do
|
||||
transposedMatrix[x] = {}
|
||||
for y = 1, #matrix do
|
||||
transposedMatrix[x][y] = matrix[y][x]
|
||||
end
|
||||
end
|
||||
return transposedMatrix
|
||||
end
|
||||
|
||||
function matrixLibrary.getMinor(matrix, row, column)
|
||||
return matrixLibrary.getDeterminant(matrixLibrary.removeColumn(matrixLibrary.removeRow(matrixLibrary.copy(matrix), row), column))
|
||||
end
|
||||
|
||||
function matrixLibrary.getCofactor(matrix, row, column)
|
||||
return (-1) ^ (row + column) * matrixLibrary.getMinor(matrix, row, column)
|
||||
end
|
||||
|
||||
function matrixLibrary.getDeterminant(matrix)
|
||||
local matrixSize = #matrix
|
||||
if matrixSize ~= #matrix[1] then error("Can't find determinant for matrix, row count != column count: " .. #matrix .. "x" .. #matrix[1]) end
|
||||
|
||||
if matrixSize == 1 then
|
||||
return matrix[1][1]
|
||||
elseif matrixSize == 2 then
|
||||
return matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1]
|
||||
else
|
||||
local determinant = 0
|
||||
for j = 1, matrixSize do
|
||||
determinant = determinant + matrixLibrary.getCofactor(matrix, 1, j) * matrix[1][j]
|
||||
end
|
||||
|
||||
return determinant
|
||||
end
|
||||
end
|
||||
|
||||
function matrixLibrary.invert(matrix)
|
||||
local determinant = matrixLibrary.getDeterminant(matrix)
|
||||
if determinant == 0 then error("Can't invert matrix with determinant equals 0") end
|
||||
|
||||
return matrixLibrary.divide(matrixLibrary.newAdjugateMatrix(matrix), determinant)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- local m = {
|
||||
-- {2, 5, 4},
|
||||
-- {-5, 5, 6},
|
||||
-- {1, 3, 7},
|
||||
-- }
|
||||
-- matrixLibrary.print(m)
|
||||
-- m = matrixLibrary.invert(m)
|
||||
-- matrixLibrary.print(m)
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return matrixLibrary
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
|
||||
local vectorLibrary = {}
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
function vectorLibrary.newVector2(x, y)
|
||||
-- checkArg(1, x, "number")
|
||||
-- checkArg(2, y, "number")
|
||||
return { x, y }
|
||||
end
|
||||
|
||||
function vectorLibrary.newVector3(x, y, z)
|
||||
-- checkArg(1, x, "number")
|
||||
-- checkArg(2, y, "number")
|
||||
-- checkArg(3, z, "number")
|
||||
return { x, y, z }
|
||||
end
|
||||
|
||||
function vectorLibrary.newVector4(x, y, z, w)
|
||||
-- checkArg(1, x, "number")
|
||||
-- checkArg(2, y, "number")
|
||||
-- checkArg(3, z, "number")
|
||||
-- checkArg(4, w, "number")
|
||||
return { x, y, z, w }
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return vectorLibrary
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user