diff --git a/Applications.txt b/Applications.txt index 5f1d7e71..fb06946b 100644 --- a/Applications.txt +++ b/Applications.txt @@ -300,13 +300,13 @@ name="lib/GUI.lua", url="IgorTimofeev/OpenComputers/master/lib/GUI.lua", type="Library", - version=1.43, + version=1.44, }, { name="lib/windows.lua", url="IgorTimofeev/OpenComputers/master/lib/windows.lua", type="Library", - version=1.18, + version=1.19, }, { name="lib/rayEngine.lua", @@ -396,7 +396,7 @@ name="lib/vector.lua", url="IgorTimofeev/OpenComputers/master/lib/vector.lua", type="Library", - version=1.0, + version=1.01, }, { name="lib/matrix.lua", @@ -408,31 +408,31 @@ name="lib/OpenComputersGL/Main.lua", url="IgorTimofeev/OpenComputers/master/lib/OpenComputersGL/Main.lua", type="Library", - version=1.0, + version=1.01, }, { name="lib/OpenComputersGL/Materials.lua", url="IgorTimofeev/OpenComputers/master/lib/OpenComputersGL/Materials.lua", type="Library", - version=1.0, + version=1.01, }, { name="lib/OpenComputersGL/Renderer.lua", url="IgorTimofeev/OpenComputers/master/lib/OpenComputersGL/Renderer.lua", type="Library", - version=1.0, + version=1.01, }, { name="lib/PolyCatEngine/Main.lua", url="IgorTimofeev/OpenComputers/master/lib/PolyCatEngine/Main.lua", type="Library", - version=1.03, + version=1.04, }, { name="lib/PolyCatEngine/PostProcessing.lua", url="IgorTimofeev/OpenComputers/master/lib/PolyCatEngine/PostProcessing.lua", type="Library", - version=1.01, + version=1.02, }, ----------------------------------------------------- Скрипты и дополнения к ним -------------------------------------------------------------------------- @@ -535,7 +535,7 @@ type="Application", icon="IgorTimofeev/OpenComputers/master/Applications/OCGLTest/Icon.pic", createShortcut="desktop", - version=1.05, + version=1.06, }, { name="MineOS/Applications/GeoScan2", diff --git a/Applications/OCGLTest/OCGLTest.lua b/Applications/OCGLTest/OCGLTest.lua index 3a87a63d..cd362faa 100644 --- a/Applications/OCGLTest/OCGLTest.lua +++ b/Applications/OCGLTest/OCGLTest.lua @@ -3,14 +3,15 @@ -- package.loaded["GUI"] = nil -- package.loaded["doubleBuffering"] = nil --- package.loaded["vector"] = nil --- package.loaded["matrix"] = nil +package.loaded["vector"] = nil +package.loaded["matrix"] = nil package.loaded["OpenComputersGL/Main"] = nil package.loaded["OpenComputersGL/Materials"] = nil package.loaded["OpenComputersGL/Renderer"] = nil package.loaded["PolyCatEngine/Main"] = nil package.loaded["PolyCatEngine/PostProcessing"] = nil +local colorlib = require("colorlib") local ecs = require("ECSAPI") local computer = require("computer") local buffer = require("doubleBuffering") @@ -28,46 +29,161 @@ local polyCatEngine = require("PolyCatEngine/Main") local autoRotate, showGrid = false, true local rotationAngle = math.rad(5) local translationOffset = 1 - --------------------------------------------------------- Object group -------------------------------------------------------- +local materialChange, materialHue = false, 0 local scene = polyCatEngine.newScene(0x222222) + +---------------------------------------------- GRAPHEN SAMPLES YOPTA ---------------------------------------------- + scene.camera:translate(0, 0, -20) +local light = scene:addObject(polyCatEngine.newLight(vector.newVector3(0, 10, 0), 1000)) -scene:addObject(polyCatEngine.newPolyCatMesh(vector.newVector3(0, 0, 0), 7)) -scene:addObject(polyCatEngine.newFloatingText(vector.newVector3(0, -12, 0), 0xEEEEEE, "Хуй пизда целка блядина")) +---------------------------------------------- Lighting test ---------------------------------------------- +-- scene:addObject(polyCatEngine.newCube(vector.newVector3(0, 0, 0), 5, materials.newSolidMaterial(0xFF4444))) +-- scene:addObject( +-- polyCatEngine.newMesh( +-- vector.newVector3(0, 0, 0), +-- { +-- vector.newVector3(0, 0, 10), +-- vector.newVector3(10, 0, 10), +-- vector.newVector3(5, 0, 0), +-- }, +-- { +-- OCGL.newIndexedTriangle(1, 2, 3) +-- }, +-- materials.newSolidMaterial(0xFF4444) +-- ) +-- ) --- scene:addObjects(polyCatEngine.newGridLines( --- vector.newVector3(0, 0, 0), --- 50, --- 40, --- 8 --- )) --- scene:addObject(polyCatEngine.newPlane( --- vector.newVector3(0, 0, 0), --- 60, --- 60, --- materials.newSolidMaterial(0xEEEEEE) --- )) +---------------------------------------------- Cubes ---------------------------------------------- local spaceBetween = 2 local cubeSize = 5 -local xCube, zCube = 0 - cubeSize - spaceBetween, 12 - cubeSize - spaceBetween -for j = 1, 3 do - for i = 1, 3 do +local xCubes, yCubes = 3, 3 +local xCubeStart = -math.floor(xCubes / 2) * (cubeSize + spaceBetween) +local xCube, zCube = xCubeStart, -math.floor(yCubes / 2) * (cubeSize + spaceBetween) +local hueCube, hueCubeStep = 0, 359 / (xCubes * yCubes) +for j = 1, yCubes do + for i = 1, xCubes do if not (i == 2 and j == 2) then scene:addObject(polyCatEngine.newCube( vector.newVector3(xCube, 0, zCube), cubeSize, - materials.newSolidMaterial(tonumber("0x" .. string.rep(tostring(math.random(0x0, 0xF)), 6))) + materials.newSolidMaterial(colorlib.HSBtoHEX(hueCube, 100, 100)) )) + hueCube = hueCube + hueCubeStep end xCube = xCube + cubeSize + spaceBetween end - zCube, xCube = zCube + cubeSize + spaceBetween, -cubeSize - spaceBetween + zCube, xCube = zCube + cubeSize + spaceBetween, xCubeStart end +---------------------------------------------- Cat ---------------------------------------------- + +-- scene:addObject(polyCatEngine.newPolyCatMesh(vector.newVector3(0, 5, 0), 5)) +-- scene:addObject(polyCatEngine.newFloatingText(vector.newVector3(0, -12, 0), 0xEEEEEE, "Тест плавающего текста")) + +---------------------------------------------- Texture ---------------------------------------------- + +-- scene.camera:translate(0, 20, 0) +-- scene.camera:rotate(math.rad(90), 0, 0) +-- local texturedPlane = scene:addObject(polyCatEngine.newTexturedPlane(vector.newVector3(0, 0, 0), 20, 20, materials.newDebugTexture(16, 16, 40))) + +---------------------------------------------- Fractal ---------------------------------------------- + +-- local function createField(vector3Position, xCellCount, yCellCount, cellSize) +-- local totalWidth, totalHeight = xCellCount * cellSize, yCellCount * cellSize +-- local halfWidth, halfHeight = totalWidth / 2, totalHeight / 2 +-- xCellCount, yCellCount = xCellCount + 1, yCellCount + 1 +-- local vertices, triangles = {}, {} + +-- local vertexIndex = 1 +-- for yCell = 1, yCellCount do +-- for xCell = 1, xCellCount do +-- table.insert(vertices, vector.newVector3(xCell * cellSize - cellSize - halfWidth, yCell * cellSize - cellSize - halfHeight, 0)) + +-- if xCell < xCellCount and yCell < yCellCount then +-- table.insert(triangles, +-- OCGL.newIndexedTriangle( +-- vertexIndex, +-- vertexIndex + 1, +-- vertexIndex + xCellCount +-- ) +-- ) +-- table.insert(triangles, +-- OCGL.newIndexedTriangle( +-- vertexIndex + 1, +-- vertexIndex + xCellCount + 1, +-- vertexIndex + xCellCount +-- ) +-- ) +-- end + +-- vertexIndex = vertexIndex + 1 +-- end +-- end + +-- local mesh = polyCatEngine.newMesh(vector3Position, vertices, triangles,materials.newSolidMaterial(0xFF8888)) + +-- local function getRandomSignedInt(from, to) +-- return (math.random(0, 1) == 1 and 1 or -1) * (math.random(from, to)) +-- end + +-- local function getRandomDirection() +-- return getRandomSignedInt(5, 100) / 100 +-- end + +-- mesh.randomizeTrianglesColor = function(mesh, hueChangeSpeed, brightnessChangeSpeed, minimumBrightness) +-- mesh.hue = mesh.hue and mesh.hue + hueChangeSpeed or math.random(0, 360) +-- if mesh.hue > 359 then mesh.hue = 0 end + +-- for triangleIndex = 1, #mesh.triangles do +-- mesh.triangles[triangleIndex].brightness = mesh.triangles[triangleIndex].brightness and mesh.triangles[triangleIndex].brightness + getRandomSignedInt(1, brightnessChangeSpeed) or math.random(minimumBrightness, 100) +-- if mesh.triangles[triangleIndex].brightness > 100 then +-- mesh.triangles[triangleIndex].brightness = 100 +-- elseif mesh.triangles[triangleIndex].brightness < minimumBrightness then +-- mesh.triangles[triangleIndex].brightness = minimumBrightness +-- end +-- mesh.triangles[triangleIndex][4] = materials.newSolidMaterial(colorlib.HSBtoHEX(mesh.hue, 100, mesh.triangles[triangleIndex].brightness)) +-- end +-- end + +-- mesh.randomizeVerticesPosition = function(mesh, speed) +-- local vertexIndex = 1 +-- for yCell = 1, yCellCount do +-- for xCell = 1, xCellCount do +-- if xCell > 1 and xCell < xCellCount and yCell > 1 and yCell < yCellCount then +-- mesh.vertices[vertexIndex].offset = mesh.vertices[vertexIndex].offset or {0, 0} +-- mesh.vertices[vertexIndex].direction = mesh.vertices[vertexIndex].direction or {getRandomDirection(), getRandomDirection()} + +-- local newOffset = { +-- mesh.vertices[vertexIndex].direction[1] * (speed * cellSize), +-- mesh.vertices[vertexIndex].direction[1] * (speed * cellSize) +-- } + +-- for i = 1, 2 do +-- if math.abs(mesh.vertices[vertexIndex].offset[i] + newOffset[i]) < cellSize / 2 then +-- mesh.vertices[vertexIndex].offset[i] = mesh.vertices[vertexIndex].offset[i] + newOffset[i] +-- mesh.vertices[vertexIndex][i] = mesh.vertices[vertexIndex][i] + newOffset[i] +-- else +-- mesh.vertices[vertexIndex].direction[i] = getRandomDirection() +-- end +-- end +-- end +-- vertexIndex = vertexIndex + 1 +-- end +-- end +-- end + +-- return mesh +-- end + +-- local plane = createField(vector.newVector3(0, 0, 0), 8, 4, 4) +-- scene:addObject(plane) + +-------------------------------------------------------- Main methods -------------------------------------------------------- + local function move(x, y, z) local moveVector = vector.newVector3(x, y, z) OCGL.rotateVector(moveVector, OCGL.axis.x, scene.camera.rotation[1]) @@ -87,9 +203,10 @@ local controls = { -- +- [13 ] = function() end, [12 ] = function() end, - -- G, X + -- G, Z, X [34 ] = function() scene.showGrid = not scene.showGrid end, - [45 ] = function() scene.renderMode = scene.renderMode + 1; if scene.renderMode > 3 then scene.renderMode = 1 end end, + [44 ] = function() scene.auxiliaryMode = scene.auxiliaryMode + 1; if scene.auxiliaryMode > 3 then scene.auxiliaryMode = 1 end end, + [45 ] = function() scene.renderMode = scene.renderMode + 1; if scene.renderMode > 4 then scene.renderMode = 1 end end, -- WASD [17 ] = function() move(0, 0, translationOffset) end, [31 ] = function() move(0, 0, -translationOffset) end, @@ -102,12 +219,21 @@ local controls = { [14 ] = function() os.exit() end, [19 ] = function() autoRotate = not autoRotate end, [28 ] = function() scene.camera.projectionEnabled = not scene.camera.projectionEnabled end, + -- M + [50 ] = function() materialChange = not materialChange end, + -- NUM 4 6 8 5 1 3 + [75 ] = function() light.position[1] = light.position[1] - translationOffset end, + [77 ] = function() light.position[1] = light.position[1] + translationOffset end, + [72 ] = function() light.position[2] = light.position[2] + translationOffset end, + [80 ] = function() light.position[2] = light.position[2] - translationOffset end, + [79 ] = function() light.position[3] = light.position[3] - translationOffset end, + [81 ] = function() light.position[3] = light.position[3] + translationOffset end, } -------------------------------------------------------- Main shit -------------------------------------------------------- buffer.start() -polyCatEngine.intro(vector.newVector3(0, 0, 0), 20) +-- polyCatEngine.intro(vector.newVector3(0, 0, 0), 20) local function drawInvertedText(x, y, text) local index = buffer.getBufferIndexByCoordinates(x, y) @@ -125,12 +251,18 @@ local function drawCross(x, y) end local function renderMethod() + if materialChange then + plane:randomizeTrianglesColor(5, 5, 50) + plane:randomizeVerticesPosition(0.05) + end + scene:render() drawCross(math.floor(buffer.screen.width / 2), math.floor(buffer.screen.height / 2)) local y = 6 local total = computer.totalMemory() - buffer.text(2, y, 0xFFFFFF, "RenderMode: " .. scene.renderMode); y = y + 2 + buffer.text(2, y, 0xFFFFFF, "RenderMode: " .. scene.renderMode); y = y + 1 + buffer.text(2, y, 0xFFFFFF, "AuxiliaryMode: " .. scene.auxiliaryMode); y = y + 2 buffer.text(2, y, 0xFFFFFF, "CameraFOV: " .. string.format("%.2f", math.deg(scene.camera.FOV))); y = y + 1 buffer.text(2, y, 0xFFFFFF, "СameraPosition: " .. string.format("%.2f", scene.camera.position[1]) .. " x " .. string.format("%.2f", scene.camera.position[2]) .. " x " .. string.format("%.2f", scene.camera.position[3])); y = y + 1 buffer.text(2, y, 0xFFFFFF, "СameraRotation: " .. string.format("%.2f", math.deg(scene.camera.rotation[1])) .. " x " .. string.format("%.2f", math.deg(scene.camera.rotation[2])) .. " x " .. string.format("%.2f", math.deg(scene.camera.rotation[3]))); y = y + 1 @@ -170,7 +302,9 @@ while true do if e[5] == 1 then scene.objects[objectIndex].triangles[triangleIndex][4] = nil else - scene.objects[objectIndex].material = materials.newSolidMaterial(math.random(0x0, 0xFFFFFF)) + -- scene.objects[objectIndex].material = materials.newSolidMaterial(math.random(0x0, 0xFFFFFF)) + -- scene.objects[objectIndex].material = materials.newTexturedMaterial(materials.newDebugTexture(16, 16, math.random(0, 360))) + scene.objects[objectIndex].triangles[triangleIndex][4] = materials.newSolidMaterial(math.random(0x0, 0xFFFFFF)) end end end diff --git a/lib/GUI.lua b/lib/GUI.lua index 7b583909..432b4827 100755 --- a/lib/GUI.lua +++ b/lib/GUI.lua @@ -388,8 +388,10 @@ local function drawContainerContent(container) end -- Delete every container's children object -local function deleteContainersContent(container) - for objectIndex = 1, #container.children do container.children[objectIndex] = nil end +local function deleteContainersContent(container, from, to) + for objectIndex = from or 1, to or #container.children do + container.children[objectIndex] = nil + end end -- Universal container to store any other objects like buttons, labels, etc @@ -1756,7 +1758,7 @@ local function drawChart(object) for y = object.y + object.height - 3, object.y + 1, -chartHeight * object.yAxisValueInterval do local stringValue = getAxisValue(value, object.yAxisPostfix) yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue)) - table.insert(yAxisValues, {y = math.round(y), value = stringValue}) + table.insert(yAxisValues, {y = math.ceil(y), value = stringValue}) value = value + dy * object.yAxisValueInterval end table.insert(yAxisValues, {y = object.y, value = getAxisValue(yMax, object.yAxisPostfix)}) @@ -1788,21 +1790,15 @@ local function drawChart(object) if absdx >= absdy then local step, y = dy / absdx, y1 for x = x1, x2, (x1 < x2 and 1 or -1) do - if object.drawAsFilled then - buffer.semiPixelSquare(math.floor(x), math.floor(y), 1, math.floor(object.y + chartHeight) * 2 - y - 1, object.colors.chart) - else - buffer.semiPixelSet(math.floor(x), math.floor(y), object.colors.chart) - end + local yFloor = math.floor(y) + buffer.semiPixelSquare(math.floor(x), yFloor, 1, math.floor(object.y + chartHeight) * 2 - yFloor - 1, object.colors.chart) y = y + step end else local step, x = dx / absdy, x1 for y = y1, y2, (y1 < y2 and 1 or -1) do - if object.drawAsFilled then - buffer.semiPixelSquare(math.floor(x), math.floor(y), 1, math.floor(object.y + chartHeight) * 2 - y - 1, object.colors.chart) - else - buffer.semiPixelSet(math.floor(x), math.floor(y), object.colors.chart) - end + local yFloor = math.floor(y) + buffer.semiPixelSquare(math.floor(x), yFloor, 1, math.floor(object.y + chartHeight) * 2 - yFloor - 1, object.colors.chart) x = x + step end end @@ -1814,13 +1810,17 @@ local function drawChart(object) local y = math.floor(object.y + object.height - 3 - (valuesCopy[i][2] - yMin) / dy * (chartHeight - 1)) * 2 local xNext = math.floor(chartX + (valuesCopy[i + 1][1] - xMin) / dx * (chartWidth - 1)) local yNext = math.floor(object.y + object.height - 3 - (valuesCopy[i + 1][2] - yMin) / dy * (chartHeight - 1)) * 2 - fillVerticalPart(x, y, xNext, yNext) + if object.fillChartArea then + fillVerticalPart(x, y, xNext, yNext) + else + buffer.semiPixelLine(x, y, xNext, yNext, object.colors.chart) + end end return object end -function GUI.chart(x, y, width, height, axisColor, axisValueColor, axisHelpersColor, chartColor, xAxisValueInterval, yAxisValueInterval, xAxisPostfix, yAxisPostfix, drawAsFilled, values) +function GUI.chart(x, y, width, height, axisColor, axisValueColor, axisHelpersColor, chartColor, xAxisValueInterval, yAxisValueInterval, xAxisPostfix, yAxisPostfix, fillChartArea, values) local object = GUI.object(x, y, width, height) object.colors = {axis = axisColor, chart = chartColor, axisValue = axisValueColor, helpers = axisHelpersColor} @@ -1830,7 +1830,7 @@ function GUI.chart(x, y, width, height, axisColor, axisValueColor, axisHelpersCo object.yAxisPostfix = yAxisPostfix object.xAxisValueInterval = xAxisValueInterval object.yAxisValueInterval = yAxisValueInterval - object.drawAsFilled = drawAsFilled + object.fillChartArea = fillChartArea return object end @@ -1839,7 +1839,16 @@ end -- buffer.start() -- local x, y, width, height = 2, 2, 150, 40 --- local chart = GUI.chart(x, y, width, height, 0xFFFFFF, 0xBBBBBB, 0x777777, 0xFF4444, 0.1, 0.15, "%", " RF/t", false, {}) +-- local chart = GUI.chart(x, y, width, height, 0xFFFFFF, 0xBBBBBB, 0x777777, 0xFF4444, 0.1, 0.15, "%", " RF/t", true, {}) + +-- -- buffer.clear(0x262626) +-- -- buffer.square(x, y, width, height, 0x1D1D1D) +-- -- for i = 1, 50 do +-- -- table.insert(chart.values, {i, math.random(1, 100)}) +-- -- end +-- -- chart:draw() +-- -- buffer.draw() + -- local counter = 1 -- while true do -- buffer.clear(0x262626) diff --git a/lib/OpenComputersGL/Main.lua b/lib/OpenComputersGL/Main.lua index e2b1766c..a39430a1 100644 --- a/lib/OpenComputersGL/Main.lua +++ b/lib/OpenComputersGL/Main.lua @@ -1,6 +1,7 @@ -------------------------------------------------------- Libraries -------------------------------------------------------- +local colorlib = require("colorlib") local vector = require("vector") local matrix = require("matrix") local buffer = require("doubleBuffering") @@ -16,10 +17,39 @@ OCGL.axis = { z = 3, } +OCGL.colors = { + axis = { + x = 0xFF0000, + y = 0x00FF00, + z = 0x0000FF, + }, + pivotPoint = 0xFFFFFF, + wireframe = 0x000000, + vertices = 0xFFDB40, + lights = 0x44FF44 +} + +OCGL.renderModes = { + disabled = 1, + constantShading = 2, + flatShading = 3, + textured = 4 +} + +OCGL.auxiliaryModes = { + disabled = 1, + wireframe = 2, + vertices = 3, +} + +OCGL.renderMode = 3 +OCGL.auxiliaryMode = 1 + OCGL.vertices = {} OCGL.triangles = {} OCGL.lines = {} OCGL.floatingTexts = {} +OCGL.lights = {} -------------------------------------------------------- Vertex field methods -------------------------------------------------------- @@ -50,6 +80,10 @@ end -------------------------------------------------------- Render queue methods -------------------------------------------------------- +function OCGL.newIndexedLight(indexOfVertex1, emissionDistance) + return { indexOfVertex1, emissionDistance } +end + function OCGL.newIndexedTriangle(indexOfVertex1, indexOfVertex2, indexOfVertex3, material) return { indexOfVertex1, indexOfVertex2, indexOfVertex3, material } end @@ -62,11 +96,17 @@ function OCGL.newIndexedFloatingText(indexOfVertex, color, text) return {indexOfVertex, text, color} end -function OCGL.pushTriangleToRenderQueue(vector3Vertex1, vector3Vertex2, vector3Vertex3, material, meshPointer, meshTriangleIndexPointer) +function OCGL.pushLightToRenderQueue(vector3Vertex, emissionDistance) + table.insert(OCGL.vertices, vector3Vertex) + table.insert(OCGL.lights, OCGL.newIndexedLight(OCGL.nextVertexIndex, emissionDistance)) + OCGL.nextVertexIndex = OCGL.nextVertexIndex + 1 +end + +function OCGL.pushTriangleToRenderQueue(vector3Vertex1, vector3Vertex2, vector3Vertex3, material) 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)) + table.insert(OCGL.triangles, OCGL.newIndexedTriangle(OCGL.nextVertexIndex, OCGL.nextVertexIndex + 1, OCGL.nextVertexIndex + 2, material)) OCGL.nextVertexIndex = OCGL.nextVertexIndex + 3 end @@ -85,94 +125,162 @@ end -------------------------------------------------------- Rendering methods -------------------------------------------------------- -OCGL.setViewport = renderer.setViewport - function OCGL.clearBuffer(backgroundColor) - OCGL.nextVertexIndex, OCGL.vertices, OCGL.triangles, OCGL.lines, OCGL.floatingTexts = 1, {}, {}, {}, {} + OCGL.nextVertexIndex, OCGL.vertices, OCGL.triangles, OCGL.lines, OCGL.floatingTexts, OCGL.lights = 1, {}, {}, {}, {}, {} renderer.clearDepthBuffer() buffer.clear(backgroundColor) end function OCGL.createPerspectiveProjection() - local zNearDivZ + local zProjectionDivZ for vertexIndex = 1, #OCGL.vertices do - zNearDivZ = math.abs(renderer.viewport.projectionSurface / 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] + zProjectionDivZ = math.abs(renderer.viewport.projectionSurface / OCGL.vertices[vertexIndex][3]) + OCGL.vertices[vertexIndex][1] = zProjectionDivZ * OCGL.vertices[vertexIndex][1] + OCGL.vertices[vertexIndex][2] = zProjectionDivZ * OCGL.vertices[vertexIndex][2] end end -function OCGL.render(renderMode) - local vector3Vertex1, vector3Vertex2, vector3Vertex3, material = {}, {}, {} +function OCGL.getTriangleLightIntensity(vertex1, vertex2, vertex3, indexedLight) + local lightVector = { + OCGL.vertices[indexedLight[1]][1] - vertex1[1], + OCGL.vertices[indexedLight[1]][2] - vertex1[2], + OCGL.vertices[indexedLight[1]][3] - vertex1[3] + } + local lightDistance = vector.length(lightVector) + + if lightDistance <= indexedLight[2] then + local normalVector = { + vertex1[2] * (vertex2[3] - vertex3[3]) + vertex2[2] * (vertex3[3] - vertex1[3]) + vertex3[2] * (vertex1[3] - vertex2[3]), + vertex1[3] * (vertex2[1] - vertex3[1]) + vertex2[3] * (vertex3[1] - vertex1[1]) + vertex3[3] * (vertex1[1] - vertex2[1]), + vertex1[1] * (vertex2[2] - vertex3[2]) + vertex2[1] * (vertex3[2] - vertex1[2]) + vertex3[1] * (vertex1[2] - vertex2[2]) + } + -- buffer.text(2, buffer.screen.height - 2, 0x0, "normalVector: " .. normalVector[1] .. " x " .. normalVector[2] .. " x " .. normalVector[3]) - -- 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] + local cameraScalar = vector.scalarMultiply({0, 0, 100}, normalVector) + local lightScalar = vector.scalarMultiply(lightVector, normalVector ) - -- 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 + -- buffer.text(2, buffer.screen.height - 1, 0xFFFFFF, "Scalars: " .. cameraScalar .. " x " .. lightScalar) + if cameraScalar < 0 and lightScalar >= 0 or cameraScalar >= 0 and lightScalar < 0 then + local absAngle = math.abs(math.acos(lightScalar / (lightDistance * vector.length(normalVector)))) + if absAngle > 1.5707963267949 then + absAngle = 3.1415926535898 - absAngle + end + -- buffer.text(2, buffer.screen.height, 0xFFFFFF, "Angle: " .. math.deg(angle) .. ", newAngle: " .. math.deg(absAngle) .. ", intensity: " .. absAngle / 1.5707963267949) + return (1 - lightDistance / indexedLight[2]) * (1 - absAngle / 1.5707963267949) + else + return 0 + end + else + -- buffer.text(2, buffer.screen.height, 0x0, "Out of light range: " .. lightDistance .. " vs " .. indexedLight[2]) + return 0 + end +end + +function OCGL.calculateLights() + for triangleIndex = 1, #OCGL.triangles do + OCGL.triangles[triangleIndex][5] = OCGL.getTriangleLightIntensity( + OCGL.vertices[OCGL.triangles[triangleIndex][1]], + OCGL.vertices[OCGL.triangles[triangleIndex][2]], + OCGL.vertices[OCGL.triangles[triangleIndex][3]], + OCGL.lights[1] + ) + end +end + +function OCGL.render() + local vertex1, vertex2, vertex3, material, auxiliaryColor = {}, {}, {} + + for triangleIndex = 1, #OCGL.triangles do + vertex1[1], vertex1[2], vertex1[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][1]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][1]][2], OCGL.vertices[OCGL.triangles[triangleIndex][1]][3] + vertex2[1], vertex2[2], vertex2[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][2]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][2]][2], OCGL.vertices[OCGL.triangles[triangleIndex][2]][3] + vertex3[1], vertex3[2], vertex3[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][3]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][3]][2], OCGL.vertices[OCGL.triangles[triangleIndex][3]][3] + material = OCGL.triangles[triangleIndex][4] + + if + -- renderer.isVertexInViewRange(vertex1[1], vertex1[2], vertex1[3]) or + -- renderer.isVertexInViewRange(vertex2[1], vertex2[2], vertex2[3]) or + -- renderer.isVertexInViewRange(vertex3[1], vertex3[2], vertex3[3]) + true + then + if material.type == materials.types.solid then + if OCGL.renderMode == OCGL.renderModes.constantShading then + renderer.renderFilledTriangle({ vertex1, vertex2, vertex3 }, material.color) + elseif OCGL.renderMode == OCGL.renderModes.flatShading then + local finalColor = 0x0 + if #OCGL.lights > 0 then + finalColor = colorlib.alphaBlend(material.color, 0x0, OCGL.triangles[triangleIndex][5] * 255) + OCGL.triangles[triangleIndex][5] = nil + end + renderer.renderFilledTriangle({ vertex1, vertex2, vertex3 }, finalColor) + end + elseif material.type == materials.types.textured then + vertex1[4], vertex1[5] = OCGL.vertices[OCGL.triangles[triangleIndex][1]][4], OCGL.vertices[OCGL.triangles[triangleIndex][1]][5] + vertex2[4], vertex2[5] = OCGL.vertices[OCGL.triangles[triangleIndex][2]][4], OCGL.vertices[OCGL.triangles[triangleIndex][2]][5] + vertex3[4], vertex3[5] = OCGL.vertices[OCGL.triangles[triangleIndex][3]][4], OCGL.vertices[OCGL.triangles[triangleIndex][3]][5] + + renderer.renderTexturedTriangle({ vertex1, vertex2, vertex3 }, material.texture) + else + error("Material type " .. tostring(material.type) .. " doesn't supported for rendering triangles") + end + + if OCGL.auxiliaryMode ~= OCGL.auxiliaryModes.disabled then + vertex1[1], vertex1[2], vertex1[3] = math.floor(renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][1]][1]), math.floor(renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][1]][2]), math.floor(OCGL.vertices[OCGL.triangles[triangleIndex][1]][3]) + vertex2[1], vertex2[2], vertex2[3] = math.floor(renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][2]][1]), math.floor(renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][2]][2]), math.floor(OCGL.vertices[OCGL.triangles[triangleIndex][2]][3]) + vertex3[1], vertex3[2], vertex3[3] = math.floor(renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][3]][1]), math.floor(renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][3]][2]), math.floor(OCGL.vertices[OCGL.triangles[triangleIndex][3]][3]) + + if OCGL.auxiliaryMode == OCGL.auxiliaryModes.wireframe then + renderer.renderLine(vertex1[1], vertex1[2], vertex1[3], vertex2[1], vertex2[2], vertex2[3], OCGL.colors.wireframe) + renderer.renderLine(vertex2[1], vertex2[2], vertex2[3], vertex3[1], vertex3[2], vertex3[3], OCGL.colors.wireframe) + renderer.renderLine(vertex1[1], vertex1[2], vertex1[3], vertex3[1], vertex3[2], vertex3[3], OCGL.colors.wireframe) + elseif OCGL.auxiliaryMode == OCGL.auxiliaryModes.vertices then + renderer.renderDot(vertex1[1], vertex1[2], vertex1[3], OCGL.colors.vertices) + renderer.renderDot(vertex2[1], vertex2[2], vertex2[3], OCGL.colors.vertices) + renderer.renderDot(vertex3[1], vertex3[2], vertex3[3], OCGL.colors.vertices) + end + end + end + end + + if OCGL.auxiliaryMode ~= OCGL.auxiliaryModes.disabled then + for lightIndex = 1, #OCGL.lights do + renderer.renderDot( + math.floor(renderer.viewport.xCenter + OCGL.vertices[OCGL.lights[lightIndex][1]][1]), + math.floor(renderer.viewport.yCenter - OCGL.vertices[OCGL.lights[lightIndex][1]][2]), + math.floor(OCGL.vertices[OCGL.lights[lightIndex][1]][3]), + OCGL.colors.lights + ) + end + end for floatingTextIndex = 1, #OCGL.floatingTexts do - vector3Vertex1 = OCGL.vertices[OCGL.floatingTexts[floatingTextIndex][1]] + vertex1 = OCGL.vertices[OCGL.floatingTexts[floatingTextIndex][1]] renderer.renderFloatingText( - renderer.viewport.xCenter + vector3Vertex1[1], - renderer.viewport.yCenter - vector3Vertex1[2], - vector3Vertex1[3], + renderer.viewport.xCenter + vertex1[1], + renderer.viewport.yCenter - vertex1[2], + vertex1[3], OCGL.floatingTexts[floatingTextIndex][2], OCGL.floatingTexts[floatingTextIndex][3] ) end - for triangleIndex = 1, #OCGL.triangles do - material = OCGL.triangles[triangleIndex][4] - vector3Vertex1[1], vector3Vertex1[2], vector3Vertex1[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][1]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][1]][2], OCGL.vertices[OCGL.triangles[triangleIndex][1]][3] - vector3Vertex2[1], vector3Vertex2[2], vector3Vertex2[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][2]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][2]][2], OCGL.vertices[OCGL.triangles[triangleIndex][2]][3] - vector3Vertex3[1], vector3Vertex3[2], vector3Vertex3[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][3]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][3]][2], OCGL.vertices[OCGL.triangles[triangleIndex][3]][3] - - if - renderer.isVertexInViewRange(vector3Vertex1[1], vector3Vertex1[2], vector3Vertex1[3]) or - renderer.isVertexInViewRange(vector3Vertex2[1], vector3Vertex2[2], vector3Vertex2[3]) or - renderer.isVertexInViewRange(vector3Vertex3[1], vector3Vertex3[2], vector3Vertex3[3]) - then - if renderMode == renderer.renderModes.material then - if material.type == materials.types.solid then - renderer.renderFilledTriangle( - { - vector3Vertex1, - vector3Vertex2, - vector3Vertex3 - }, - 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 + -- for lineIndex = 1, #OCGL.lines do + -- vertex1, vertex2, material = OCGL.vertices[OCGL.lines[lineIndex][1]], OCGL.vertices[OCGL.lines[lineIndex][2]], OCGL.lines[lineIndex][3] + + -- if OCGL.renderMode == renderer.renderModes.vertices then + -- renderer.renderDot(vertex1, material) + -- renderer.renderDot(vertex2, material) + -- else + -- renderer.renderLine( + -- math.floor(vertex1[1]), + -- math.floor(vertex1[2]), + -- vertex1[3], + -- math.floor(vertex2[1]), + -- math.floor(vertex2[2]), + -- vertex2[3], + -- material + -- ) + -- end + -- end end -------------------------------------------------------- Raycasting methods -------------------------------------------------------- diff --git a/lib/OpenComputersGL/Materials.lua b/lib/OpenComputersGL/Materials.lua index f03068ce..6b90a003 100644 --- a/lib/OpenComputersGL/Materials.lua +++ b/lib/OpenComputersGL/Materials.lua @@ -9,6 +9,29 @@ materials.types = { solid = 2, } +function materials.newDebugTexture(width, height, h) + local colorlib = require("colorlib") + local texture = {width = width, height = height} + + local bStep = 100 / height + local sStep = 100 / width + + local s, b = 0, 0 + local blackSquare = false + for y = 1, height do + texture[y] = {} + for x = 1, width do + texture[y][x] = blackSquare == true and 0x0 or colorlib.HSBtoHEX(h, s, b) + blackSquare = not blackSquare + b = b + bStep + end + b = 0 + s = s + sStep + blackSquare = not blackSquare + end + return texture +end + function materials.newSolidMaterial(color) return { type = materials.types.solid, diff --git a/lib/OpenComputersGL/Renderer.lua b/lib/OpenComputersGL/Renderer.lua index 10b07685..fabcb348 100644 --- a/lib/OpenComputersGL/Renderer.lua +++ b/lib/OpenComputersGL/Renderer.lua @@ -1,6 +1,7 @@ -------------------------------------------------------- Libraries -------------------------------------------------------- +local computer = require("computer") local vector = require("vector") local unicode = require("unicode") local materials = require("OpenComputersGL/Materials") @@ -11,24 +12,6 @@ local renderer = { viewport = {}, } --------------------------------------------------------- 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() @@ -109,25 +92,15 @@ function renderer.renderLine(x1, y1, z1, x2, y2, z2, color) end end -function renderer.renderDot(vector3Vertex, color) - renderer.setPixelUsingDepthBuffer(math.floor(vector3Vertex[1]), math.floor(vector3Vertex[2]), vector3Vertex[3], color) +function renderer.renderDot(x, y, z, color) + renderer.setPixelUsingDepthBuffer(x, y, z, 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 function getTriangleDrawingShit(points) local topID, centerID, bottomID = 1, 1, 1 + for i = 1, 3 do points[i][2] = math.floor(points[i][2]) if points[i][2] < points[topID][2] then topID = i end @@ -135,14 +108,45 @@ function renderer.renderFilledTriangle(points, color) 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 yCenterMinusYTop = points[centerID][2] - points[topID][2] + local yBottomMinusYTop = 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 x1ScreenStep = (points[centerID][1] - points[topID][1]) / yCenterMinusYTop + local x2ScreenStep = (points[bottomID][1] - points[topID][1]) / yBottomMinusYTop + local z1Screen, z2Screen = points[topID][3], points[topID][3] + local z1ScreenStep = (points[centerID][3] - points[topID][3]) / yCenterMinusYTop + local z2ScreenStep = (points[bottomID][3] - points[topID][3]) / yBottomMinusYTop + return topID, centerID, bottomID, x1Screen, x2Screen, x1ScreenStep, x2ScreenStep, z1Screen, z2Screen, z1ScreenStep, z2ScreenStep +end + + +local function getTriangleSecondPartScreenCoordinates(points, centerID, bottomID) + -- return x1Screen, x1ScreenStep, z1Screen, z1ScreenStep + local yBottomMinusYCenter = points[bottomID][2] - points[centerID][2] + return + points[centerID][1], + (points[bottomID][1] - points[centerID][1]) / yBottomMinusYCenter, + points[centerID][3], + (points[bottomID][3] - points[centerID][3]) / yBottomMinusYCenter +end + +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) + z = z + zStep + end +end + +function renderer.renderFilledTriangle(points, color) + local topID, centerID, bottomID, x1Screen, x2Screen, x1ScreenStep, x2ScreenStep, z1Screen, z2Screen, z1ScreenStep, z2ScreenStep = getTriangleDrawingShit(points) -- Рисуем первый кусок треугольника от верхней точки до центральной for y = points[topID][2], points[centerID][2] - 1 do fillPart(x1Screen, x2Screen, z1Screen, z2Screen, y, color) @@ -150,8 +154,7 @@ function renderer.renderFilledTriangle(points, color) 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]) + x1Screen, x1ScreenStep, z1Screen, z1ScreenStep = getTriangleSecondPartScreenCoordinates(points, centerID, bottomID) -- И рисуем нижний кусок треугольника от центральной точки до нижней for y = points[centerID][2], points[bottomID][2] do fillPart(x1Screen, x2Screen, z1Screen, z2Screen, y, color) @@ -159,8 +162,70 @@ function renderer.renderFilledTriangle(points, color) end end -function renderer.renderTexturedTriangle(vertices, texture) +local function fillTexturedPart(firstZ, secondZ, x1Screen, x2Screen, z1Screen, z2Screen, u1Texture, u2Texture, v1Texture, v2Texture, y, texture) + if x2Screen < x1Screen then + x1Screen, x2Screen, z1Screen, z2Screen = x2Screen, x1Screen, z2Screen, z1Screen + u1Texture, u2Texture = u2Texture, u1Texture + v1Texture, v2Texture = v2Texture, v1Texture + end + local z, zStep = z1Screen, (z2Screen - z1Screen) / (x2Screen - x1Screen) + + -- secondZ - (v2Texture - v1Texture) + -- z - x + + u2Texture = u1Texture + (u2Texture - u1Texture) * (secondZ / z) + v2Texture = v1Texture + (v2Texture - v1Texture) * (secondZ / z) + + local u, uStep = u1Texture, (u2Texture - u1Texture) / (x2Screen - x1Screen) + local v, vStep = v1Texture, (v2Texture - v1Texture) / (x2Screen - x1Screen) + + -- buffer.text(1, 1, 0xFF00FF, "GOVNO: " .. math.abs(renderer.viewport.projectionSurface / z)) + + local color, uVal, vVal + for x = math.floor(x1Screen), math.floor(x2Screen) do + uVal, vVal = math.floor(u + 0.5), math.floor(v + 0.5) + if texture[vVal] and texture[vVal][uVal] then + color = texture[vVal][uVal] + else + color = 0x00FF00 + end + renderer.setPixelUsingDepthBuffer(x, y, z, color) + -- buffer.semiPixelSet(x, y, color) + z, u, v = z + zStep, u + uStep, v + vStep + end +end + +function renderer.renderTexturedTriangle(points, texture) + local topID, centerID, bottomID, x1Screen, x2Screen, x1ScreenStep, x2ScreenStep, z1Screen, z2Screen, z1ScreenStep, z2ScreenStep = getTriangleDrawingShit(points) + + local u1Texture, u2Texture = points[topID][4], points[topID][4] + local u1TextureStep = (points[centerID][4] - points[topID][4]) / (points[centerID][2] - points[topID][2]) + local u2TextureStep = (points[bottomID][4] - points[topID][4]) / (points[bottomID][2] - points[topID][2]) + + local v1Texture, v2Texture = points[topID][5], points[topID][5] + local v1TextureStep = (points[centerID][5] - points[topID][5]) / (points[centerID][2] - points[topID][2]) + local v2TextureStep = (points[bottomID][5] - points[topID][5]) / (points[bottomID][2] - points[topID][2]) + + for y = points[topID][2], points[centerID][2] - 1 do + fillTexturedPart(points[topID][3], points[bottomID][3], x1Screen, x2Screen, z1Screen, z2Screen, u1Texture, u2Texture, v1Texture, v2Texture, y, texture) + x1Screen, x2Screen, z1Screen, z2Screen = x1Screen + x1ScreenStep, x2Screen + x2ScreenStep, z1Screen + z1ScreenStep, z2Screen + z2ScreenStep + u1Texture, u2Texture, v1Texture, v2Texture = u1Texture + u1TextureStep, u2Texture + u2TextureStep, v1Texture + v1TextureStep, v2Texture + v2TextureStep + end + + x1Screen, x1ScreenStep, z1Screen, z1ScreenStep = getTriangleSecondPartScreenCoordinates(points, centerID, bottomID) + u1Texture, u1TextureStep = points[centerID][4], (points[bottomID][4] - points[centerID][4]) / (points[bottomID][2] - points[centerID][2]) + v1Texture, v1TextureStep = points[centerID][5], (points[bottomID][5] - points[centerID][5]) / (points[bottomID][2] - points[centerID][2]) + + for y = points[centerID][2], points[bottomID][2] do + fillTexturedPart(points[topID][3], points[bottomID][3], x1Screen, x2Screen, z1Screen, z2Screen, u1Texture, u2Texture, v1Texture, v2Texture, y, texture) + x1Screen, x2Screen, z1Screen, z2Screen = x1Screen + x1ScreenStep, x2Screen + x2ScreenStep, z1Screen + z1ScreenStep, z2Screen + z2ScreenStep + u1Texture, u2Texture, v1Texture, v2Texture = u1Texture + u1TextureStep, u2Texture + u2TextureStep, v1Texture + v1TextureStep, v2Texture + v2TextureStep + end + + -- for i = 1, 3 do + -- buffer.text(math.floor(points[i][1]), math.floor(points[i][2]), 0xFFFFFF, "ID " .. i .. ": u = " .. points[i][4] .. ", v = " .. points[topID][5]) + -- end end -------------------------------------------------------- Floating text rendering -------------------------------------------------------- @@ -238,7 +303,7 @@ function renderer.renderFPSCounter(x, y, renderMethod, color) renderMethod() local fps = tostring(math.ceil(1 / (os.clock() - oldClock) / 10)) - -- buffer.text(1, 1, 0xFFFFFF, "FPS: " .. os.clock() - oldClock) + -- buffer.text(1, 1, 0xFFFFFF, "FPS: " .. fps) for i = 1, #fps do drawSegments(x, y, numbers[fps:sub(i, i)], color) @@ -248,7 +313,24 @@ function renderer.renderFPSCounter(x, y, renderMethod, color) return x - 3 end +------------------------------------------------------------------------------------------------------------------------ +-- buffer.start() +-- buffer.clear(0xFFFFFF) + +-- local texture = materials.newDebugTexture(16, 16, 0xFF00FF, 0x000000) +-- renderer.renderTexturedTriangle({ +-- {2, 2, 1, 1, 1}, +-- {2, 52, 1, 1, 16}, +-- {52, 52, 1, 16, 16}, +-- }, texture) +-- renderer.renderTexturedTriangle({ +-- {2, 2, 1, 1, 1}, +-- {52, 2, 1, 16, 1}, +-- {52, 52, 1, 16, 16}, +-- }, texture) + +-- buffer.draw(true) ------------------------------------------------------------------------------------------------------------------------ diff --git a/lib/PolyCatEngine/Main.lua b/lib/PolyCatEngine/Main.lua index 41df502a..9b3b7ee6 100644 --- a/lib/PolyCatEngine/Main.lua +++ b/lib/PolyCatEngine/Main.lua @@ -23,6 +23,23 @@ function polyCatEngine.newPivotPoint(vector3Position) } end +-------------------------------------------------------- Light object -------------------------------------------------------- + +local function pushLightToRenderQueue(light) + OCGL.pushLightToRenderQueue( + vector.newVector3(light.position[1], light.position[2], light.position[3]), + light.emissionDistance + ) +end + +function polyCatEngine.newLight(vector3Position, emissionDistance) + return { + position = vector3Position, + emissionDistance = emissionDistance, + pushToRenderQueue = pushLightToRenderQueue + } +end + -------------------------------------------------------- Mesh object -------------------------------------------------------- local function pushMeshToRenderQueue(mesh) @@ -30,12 +47,10 @@ local function pushMeshToRenderQueue(mesh) 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 + vector.newVector5(vector3Vertex1[1], vector3Vertex1[2], vector3Vertex1[3], vector3Vertex1[4], vector3Vertex1[5]), + vector.newVector5(vector3Vertex2[1], vector3Vertex2[2], vector3Vertex2[3], vector3Vertex2[4], vector3Vertex2[5]), + vector.newVector5(vector3Vertex3[1], vector3Vertex3[2], vector3Vertex3[3], vector3Vertex3[4], vector3Vertex3[5]), + mesh.triangles[triangleIndex][4] or mesh.material ) end end @@ -67,14 +82,11 @@ local function pushLineToRenderQueue(line) end function polyCatEngine.newLine(vector3Position, vector3Vertex1, vector3Vertex2, color) - local line = {} - - -- line.pivotPoint = polyCatEngine.newPivotPoint(vector3Position) - line.vertices = { vector3Vertex1, vector3Vertex2 } - line.color = color - line.pushToRenderQueue = pushLineToRenderQueue - - return line + return { + vertices = { vector3Vertex1, vector3Vertex2 }, + color = color, + pushToRenderQueue = pushLineToRenderQueue + } end -------------------------------------------------------- Floating text object -------------------------------------------------------- @@ -88,33 +100,31 @@ local function pushFloatingTextToRenderQueue(floatingText) end function polyCatEngine.newFloatingText(vector3Position, color, text) - local floatingText = {} - - floatingText.position = vector3Position - floatingText.color = color - floatingText.text = text - floatingText.pushToRenderQueue = pushFloatingTextToRenderQueue - - return floatingText + return { + position = vector3Position, + color = color, + text = text, + pushToRenderQueue = pushFloatingTextToRenderQueue + } end -------------------------------------------------------- Plane object -------------------------------------------------------- -function polyCatEngine.newPlane(vector3Position, width, height, material) - local halfWidth, halfHeight = width / 2, height / 2 +function polyCatEngine.newTexturedPlane(vector3Position, width, height, texture) + width, height = width / 2, height / 2 return polyCatEngine.newMesh( vector3Position, { - vector.newVector3(-halfWidth, 0, -halfHeight), - vector.newVector3(-halfWidth, 0, halfHeight), - vector.newVector3(halfWidth, 0, halfHeight), - vector.newVector3(halfWidth, 0, -halfHeight), + vector.newVector5(-width, 0, -height, 1, texture.height), + vector.newVector5(-width, 0, height, 1, 1), + vector.newVector5(width, 0, height, texture.width, 1), + vector.newVector5(width, 0, -height, texture.width, texture.height), }, { OCGL.newIndexedTriangle(1, 2, 3), OCGL.newIndexedTriangle(1, 4, 3) }, - material + materials.newTexturedMaterial(texture) ) end @@ -172,51 +182,6 @@ function polyCatEngine.newCube(vector3Position, size, material) ) end --------------------------------------------------------- Grid lines -------------------------------------------------------- - -function polyCatEngine.newGridLines(vector3Position, axisRange, gridRange, gridRangeStep) - local objects = {} - -- Grid - for x = -gridRange, gridRange, gridRangeStep do - table.insert(objects, 1, polyCatEngine.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, polyCatEngine.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, polyCatEngine.newLine( - vector3Position, - vector.newVector3(-axisRange, -1, 0), - vector.newVector3(axisRange, -1, 0), - renderer.colors.axis.x - )) - table.insert(objects, polyCatEngine.newLine( - vector3Position, - vector.newVector3(0, -axisRange, 0), - vector.newVector3(0, axisRange, 0), - renderer.colors.axis.y - )) - table.insert(objects, polyCatEngine.newLine( - vector3Position, - vector.newVector3(0, -1, -axisRange), - vector.newVector3(0, -1, axisRange), - renderer.colors.axis.z - )) - - return objects -end - -------------------------------------------------------- Camera object -------------------------------------------------------- @@ -292,20 +257,16 @@ end 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 - + for objectIndex = 1, #objects do table.insert(scene.objects, objects[objectIndex]) end return objects end local function sceneRender(scene) - OCGL.setViewport( 1, 1, buffer.screen.width, buffer.screen.height * 2, scene.camera.nearClippingSurface, scene.camera.farClippingSurface, scene.camera.projectionSurface) + renderer.setViewport( 1, 1, buffer.screen.width, buffer.screen.height * 2, scene.camera.nearClippingSurface, scene.camera.farClippingSurface, scene.camera.projectionSurface) OCGL.clearBuffer(scene.backgroundColor) for objectIndex = 1, #scene.objects do @@ -317,8 +278,17 @@ local function sceneRender(scene) OCGL.rotate(OCGL.axis.x, -scene.camera.rotation[1]) -- OCGL.rotate(OCGL.axis.z, -scene.camera.rotation[3]) - if scene.camera.projectionEnabled then OCGL.createPerspectiveProjection() end - OCGL.render(scene.renderMode) + if scene.renderMode == OCGL.renderModes.flatShading then + OCGL.calculateLights() + end + + if scene.camera.projectionEnabled then + OCGL.createPerspectiveProjection() + end + + OCGL.renderMode = scene.renderMode + OCGL.auxiliaryMode = scene.auxiliaryMode + OCGL.render() return scene end @@ -326,7 +296,9 @@ end function polyCatEngine.newScene(backgroundColor) local scene = {} - scene.renderMode = renderer.renderModes.material + scene.renderMode = OCGL.renderModes.constantShading + scene.auxiliaryMode = OCGL.auxiliaryModes.disabled + scene.backgroundColor = backgroundColor scene.objects = {} diff --git a/lib/vector.lua b/lib/vector.lua index c863fcbe..f7854170 100644 --- a/lib/vector.lua +++ b/lib/vector.lua @@ -4,26 +4,45 @@ 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 +function vectorLibrary.newVector5(x, y, z, u, v) + return { x, y, z, u, v } +end + +function vectorLibrary.scalarMultiply(vectorA, vectorB) + local result = 0 + for dismension = 1, #vectorA do + result = result + vectorA[dismension] * vectorB[dismension] + end + + return result +end + +function vectorLibrary.length(vector) + local result = 0 + for dismension = 1, #vector do + result = result + vector[dismension] ^ 2 + end + + return math.sqrt(result) +end + +function vectorLibrary.normalize(vector) + local invertedLength = 1 / vectorLibrary.length(vector) + vector[1], vector[2], vector[3] = vector[1] * invertedLength, vector[2] * invertedLength, vector[3] * invertedLength + return vector +end + ------------------------------------------------------------------------------------------------------------------------ return vectorLibrary diff --git a/lib/windows.lua b/lib/windows.lua index 4181e4b0..d439315b 100755 --- a/lib/windows.lua +++ b/lib/windows.lua @@ -9,7 +9,7 @@ local GUI = require("GUI") local unicode = require("unicode") local event = require("event") ------------------------------------------ Main variables ----------------------------------------- +----------------------------------------- Constants ----------------------------------------- local windows = {} @@ -40,75 +40,64 @@ end local function buttonHandler(window, object, objectIndex, eventData) if object.switchMode then object.pressed = not object.pressed - window:draw() - buffer.draw() + window:draw(); buffer.draw() executeObjectMethod(object.onTouch, eventData) else object.pressed = true - window:draw() - buffer.draw() + window:draw(); buffer.draw() os.sleep(0.2) object.pressed = false - window:draw() - buffer.draw() + window:draw(); buffer.draw() executeObjectMethod(object.onTouch, eventData) end end local function tabBarTabHandler(window, object, objectIndex, eventData) object.parent.parent.selectedTab = objectIndex - window:draw() - buffer.draw() - executeObjectMethod(object.parent.parent.onTabSwitched, eventData) + window:draw(); buffer.draw() + executeObjectMethod(object.parent.parent.onTabSwitched, object.parent.parent.selectedTab, eventData) end local function inputTextBoxHandler(window, object, objectIndex, eventData) object:input() - window:draw() - buffer.draw() - executeObjectMethod(object.onInputFinished, object.text) + window:draw(); buffer.draw() + executeObjectMethod(object.onInputFinished, object.text, eventData) end local function textBoxScrollHandler(window, object, objectIndex, eventData) if eventData[5] == 1 then object:scrollUp() - window:draw() - buffer.draw() + window:draw(); buffer.draw() else object:scrollDown() - window:draw() - buffer.draw() + window:draw(); buffer.draw() end end local function horizontalSliderHandler(window, object, objectIndex, eventData) local clickPosition = eventData[3] - object.x + 1 object.value = object.minimumValue + (clickPosition * (object.maximumValue - object.minimumValue) / object.width) - window:draw() - buffer.draw() - executeObjectMethod(object.onValueChanged, object.value) + window:draw(); buffer.draw() + executeObjectMethod(object.onValueChanged, object.value, eventData) end local function switchHandler(window, object, objectIndex, eventData) object.state = not object.state - window:draw() - buffer.draw() - executeObjectMethod(object.onStateChanged, object.state) + window:draw(); buffer.draw() + executeObjectMethod(object.onStateChanged, object.state, eventData) end local function comboBoxHandler(window, object, objectIndex, eventData) object:selectItem() - executeObjectMethod(object.onItemSelected, object.items[object.currentItem]) + executeObjectMethod(object.onItemSelected, object.items[object.currentItem], eventData) end local function menuItemHandler(window, object, objectIndex, eventData) object.pressed = true - window:draw() - buffer.draw() + window:draw(); buffer.draw() executeObjectMethod(object.onTouch, eventData) object.pressed = false - window:draw() - buffer.draw() + window:draw(); buffer.draw() end local function scrollBarHandler(window, object, objectIndex, eventData) @@ -136,9 +125,8 @@ local function scrollBarHandler(window, object, objectIndex, eventData) end end end - window:draw() - buffer.draw() object.value = newValue + window:draw(); buffer.draw() executeObjectMethod(object.onTouch, eventData) end @@ -157,7 +145,7 @@ local function treeViewHandler(window, object, objectIndex, eventData) else object.currentFile = object.fileList[fileIndex].path object:draw(); buffer.draw() - executeObjectMethod(object.onFileSelected, object.currentFile) + executeObjectMethod(object.onFileSelected, object.currentFile, eventData) end end elseif eventData[1] == "scroll" then @@ -176,10 +164,12 @@ local function treeViewHandler(window, object, objectIndex, eventData) end local function colorSelectorHandler(window, object, objectIndex, eventData) - object.pressed = true; object:draw(); buffer.draw() + object.pressed = true + object:draw(); buffer.draw() object.color = require("palette").show("auto", "auto", object.color) or object.color - object.pressed = false; object:draw(); buffer.draw() - executeObjectMethod(object.onTouch) + object.pressed = false + object:draw(); buffer.draw() + executeObjectMethod(object.onTouch, eventData) end function windows.handleEventData(window, eventData) @@ -339,10 +329,6 @@ end ----------------------------------------- Playground ----------------------------------------- --- buffer.start() --- buffer.clear(0xFF8888) --- buffer.draw(true) - -- local myWindow = windows.empty(2, 2, 60, 30, 60, 30) -- myWindow:addColorSelector(2, 2, 30, 3, 0xFF00FF, "Text") -- myWindow:draw()