Вот-вот

This commit is contained in:
Igor Timofeev 2017-01-04 23:07:29 +03:00
parent b858487c6f
commit 83a1bb14ef
11 changed files with 1 additions and 1513 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
Applications/.DS_Store vendored

Binary file not shown.

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,12 +0,0 @@
-------------------------------------------------------- Libraries --------------------------------------------------------
local buffer = require("doubleBuffering")
local postProcessing = {}
-------------------------------------------------------- Plane object --------------------------------------------------------
-------------------------------------------------------- Zalupa --------------------------------------------------------
return postProcessing

View File

@ -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

View File

@ -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