Move zoom further away from Renderer

This commit is contained in:
Tamás Bálint Misius
2024-08-20 16:28:24 +02:00
parent 4ed83912af
commit d5c2d87b2e
20 changed files with 172 additions and 182 deletions

View File

@@ -8,7 +8,7 @@
#include <stdexcept>
#include <png.h>
#include "Format.h"
#include "graphics/Graphics.h"
#include "graphics/VideoBuffer.h"
ByteString format::UnixtimeToDate(time_t unixtime, ByteString dateFormat, bool local)
{

View File

@@ -72,7 +72,6 @@ int main(int argc, char *argv[])
}
ren->RenderSimulation();
ren->RenderEnd();
if (auto data = ren->DumpFrame().ToPNG())
Platform::WriteFile(*data, outputFilename);

View File

@@ -1,5 +1,5 @@
#include "Format.h"
#include "graphics/Graphics.h"
#include "graphics/VideoBuffer.h"
#include "WindowIcon.h"
#include "icon_exe.png.h"

View File

@@ -2,7 +2,7 @@
#include <cmath>
#include "graphics/Graphics.h"
#include "graphics/VideoBuffer.h"
#include "simulation/SaveRenderer.h"
#include "client/GameSave.h"

View File

@@ -1,5 +1,5 @@
#include "ImageRequest.h"
#include "graphics/Graphics.h"
#include "graphics/VideoBuffer.h"
#include "client/Client.h"
#include <iostream>

View File

@@ -457,34 +457,37 @@ void Graphics::SwapClipRect(Rect<int> &rect)
clipRect &= video.Size().OriginRect();
}
bool Graphics::GradientStop::operator <(const GradientStop &other) const
void Graphics::RenderZoom()
{
return point < other.point;
}
std::vector<RGB<uint8_t>> Graphics::Gradient(std::vector<GradientStop> stops, int resolution)
{
std::vector<RGB<uint8_t>> table(resolution, 0x000000_rgb);
if (stops.size() >= 2)
if(!zoomEnabled)
return;
{
std::sort(stops.begin(), stops.end());
auto stop = -1;
for (auto i = 0; i < resolution; ++i)
int x, y, i, j;
pixel pix;
DrawFilledRect(RectSized(zoomWindowPosition, { zoomScopeSize * ZFACTOR, zoomScopeSize * ZFACTOR }), 0x000000_rgb);
DrawRect(RectSized(zoomWindowPosition - Vec2{ 2, 2 }, Vec2{ zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3 }), 0xC0C0C0_rgb);
DrawRect(RectSized(zoomWindowPosition - Vec2{ 1, 1 }, Vec2{ zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1 }), 0x000000_rgb);
for (j=0; j<zoomScopeSize; j++)
for (i=0; i<zoomScopeSize; i++)
{
pix = video[{ i + zoomScopePosition.X, j + zoomScopePosition.Y }];
for (y=0; y<ZFACTOR-1; y++)
for (x=0; x<ZFACTOR-1; x++)
video[{ i * ZFACTOR + x + zoomWindowPosition.X, j * ZFACTOR + y + zoomWindowPosition.Y }] = pix;
}
if (zoomEnabled)
{
auto point = i / (float)resolution;
while (stop < (int)stops.size() - 1 && stops[stop + 1].point <= point)
for (j=-1; j<=zoomScopeSize; j++)
{
++stop;
XorPixel(zoomScopePosition + Vec2{ j, -1 });
XorPixel(zoomScopePosition + Vec2{ j, zoomScopeSize });
}
if (stop < 0 || stop >= (int)stops.size() - 1)
for (j=0; j<zoomScopeSize; j++)
{
continue;
XorPixel(zoomScopePosition + Vec2{ -1, j });
XorPixel(zoomScopePosition + Vec2{ zoomScopeSize, j });
}
auto &left = stops[stop];
auto &right = stops[stop + 1];
auto f = (point - left.point) / (right.point - left.point);
table[i] = left.color.Blend(right.color.WithAlpha(uint8_t(f * 0xFF)));
}
}
return table;
}

View File

@@ -1,56 +1,5 @@
#pragma once
#include <array>
#include <memory>
#include <vector>
#include "common/Plane.h"
#include "common/String.h"
#include "Icons.h"
#include "Pixel.h"
#include "RasterDrawMethods.h"
#include "SimulationConfig.h"
class VideoBuffer: public RasterDrawMethods<VideoBuffer>
{
PlaneAdapter<std::vector<pixel>> video;
Rect<int> GetClipRect() const
{
return video.Size().OriginRect();
}
friend struct RasterDrawMethods<VideoBuffer>;
public:
VideoBuffer(pixel const *data, Vec2<int> size);
VideoBuffer(pixel const *data, Vec2<int> size, size_t rowStride);
VideoBuffer(Vec2<int> size);
Vec2<int> Size() const
{
return video.Size();
}
pixel *Data()
{
return video.data();
}
pixel const *Data() const
{
return video.data();
}
void Crop(Rect<int>);
void Resize(float factor, bool resample = false);
void Resize(Vec2<int> size, bool resample = false);
// Automatically choose a size to fit within the given box, keeping aspect ratio
void ResizeToFit(Vec2<int> bound, bool resample = false);
static std::unique_ptr<VideoBuffer> FromPNG(std::vector<char> const &);
std::unique_ptr<std::vector<char>> ToPNG() const;
std::vector<char> ToPPM() const;
};
#include "VideoBuffer.h"
class Graphics: public RasterDrawMethods<Graphics>
{
@@ -75,15 +24,6 @@ public:
return video.data();
}
struct GradientStop
{
RGB<uint8_t> color;
float point;
bool operator <(const GradientStop &other) const;
};
static std::vector<RGB<uint8_t>> Gradient(std::vector<GradientStop> stops, int resolution);
VideoBuffer DumpFrame();
void draw_icon(int x, int y, Icon icon, unsigned char alpha = 255, bool invert = false);
@@ -98,4 +38,11 @@ public:
{
return clipRect;
}
ui::Point zoomWindowPosition = { 0, 0 };
ui::Point zoomScopePosition = { 0, 0 };
int zoomScopeSize = 32;
bool zoomEnabled = false;
int ZFACTOR = 8;
void RenderZoom();
};

View File

@@ -2,7 +2,7 @@
#include <cstring>
#include "common/RasterGeometry.h"
#include "FontReader.h"
#include "Graphics.h"
#include "VideoBuffer.h"
#include "RasterDrawMethods.h"
#define clipRect() (static_cast<Derived const &>(*this).GetClipRect())

View File

@@ -1,5 +1,5 @@
#pragma once
#include "Graphics.h"
#include "VideoBuffer.h"
#include "gui/game/RenderPreset.h"
#include "gui/interface/Point.h"
#include "common/tpt-rand.h"
@@ -80,18 +80,9 @@ public:
//Mouse position for debug information
ui::Point mousePos;
//Zoom window
ui::Point zoomWindowPosition;
ui::Point zoomScopePosition;
int zoomScopeSize;
bool zoomEnabled;
int ZFACTOR;
//Renderers
void RenderSimulation();
void RenderEnd();
void RenderZoom();
void DrawBlob(Vec2<int> pos, RGB<uint8_t> colour);
void DrawWalls();
void DrawSigns();
@@ -135,6 +126,15 @@ public:
Renderer();
struct GradientStop
{
RGB<uint8_t> color;
float point;
bool operator <(const GradientStop &other) const;
};
static std::vector<RGB<uint8_t>> Gradient(std::vector<GradientStop> stops, int resolution);
#define RENDERER_TABLE(name) \
static std::vector<RGB<uint8_t>> name; \
static inline RGB<uint8_t> name ## At(int index) \

View File

@@ -5,11 +5,6 @@
#include "simulation/ElementClasses.h"
#include "simulation/ElementGraphics.h"
void Renderer::RenderEnd()
{
RenderZoom();
}
void Renderer::SetSample(Vec2<int> pos)
{
sampleColor = GetPixel(pos);
@@ -26,41 +21,6 @@ void Renderer::clearScreen() {
}
}
void Renderer::RenderZoom()
{
if(!zoomEnabled)
return;
{
int x, y, i, j;
pixel pix;
DrawFilledRect(RectSized(zoomWindowPosition, { zoomScopeSize * ZFACTOR, zoomScopeSize * ZFACTOR }), 0x000000_rgb);
DrawRect(RectSized(zoomWindowPosition - Vec2{ 2, 2 }, Vec2{ zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3 }), 0xC0C0C0_rgb);
DrawRect(RectSized(zoomWindowPosition - Vec2{ 1, 1 }, Vec2{ zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1 }), 0x000000_rgb);
for (j=0; j<zoomScopeSize; j++)
for (i=0; i<zoomScopeSize; i++)
{
pix = video[{ i + zoomScopePosition.X, j + zoomScopePosition.Y }];
for (y=0; y<ZFACTOR-1; y++)
for (x=0; x<ZFACTOR-1; x++)
video[{ i * ZFACTOR + x + zoomWindowPosition.X, j * ZFACTOR + y + zoomWindowPosition.Y }] = pix;
}
if (zoomEnabled)
{
for (j=-1; j<=zoomScopeSize; j++)
{
XorPixel(zoomScopePosition + Vec2{ j, -1 });
XorPixel(zoomScopePosition + Vec2{ j, zoomScopeSize });
}
for (j=0; j<zoomScopeSize; j++)
{
XorPixel(zoomScopePosition + Vec2{ -1, j });
XorPixel(zoomScopePosition + Vec2{ zoomScopeSize, j });
}
}
}
}
void Renderer::DrawBlob(Vec2<int> pos, RGB<uint8_t> colour)
{
BlendPixel(pos + Vec2{ +1, 0 }, colour.WithAlpha(112));
@@ -116,20 +76,20 @@ void Renderer::PopulateTables()
if (!tablesPopulated)
{
tablesPopulated = true;
flameTable = Graphics::Gradient({
flameTable = Gradient({
{ 0x000000_rgb, 0.00f },
{ 0x60300F_rgb, 0.50f },
{ 0xDFBF6F_rgb, 0.90f },
{ 0xAF9F0F_rgb, 1.00f },
}, 200);
plasmaTable = Graphics::Gradient({
plasmaTable = Gradient({
{ 0x000000_rgb, 0.00f },
{ 0x301040_rgb, 0.25f },
{ 0x301060_rgb, 0.50f },
{ 0xAFFFFF_rgb, 0.90f },
{ 0xAFFFFF_rgb, 1.00f },
}, 200);
heatTable = Graphics::Gradient({
heatTable = Gradient({
{ 0x2B00FF_rgb, 0.00f },
{ 0x003CFF_rgb, 0.01f },
{ 0x00C0FF_rgb, 0.05f },
@@ -141,7 +101,7 @@ void Renderer::PopulateTables()
{ 0xFF0000_rgb, 0.71f },
{ 0xFF00DC_rgb, 1.00f },
}, 1024);
clfmTable = Graphics::Gradient({
clfmTable = Gradient({
{ 0x000000_rgb, 0.00f },
{ 0x0A0917_rgb, 0.10f },
{ 0x19163C_rgb, 0.20f },
@@ -151,7 +111,7 @@ void Renderer::PopulateTables()
{ 0x57A0B4_rgb, 0.80f },
{ 0x5EC4C6_rgb, 1.00f },
}, 200);
firwTable = Graphics::Gradient({
firwTable = Gradient({
{ 0xFF00FF_rgb, 0.00f },
{ 0x0000FF_rgb, 0.20f },
{ 0x00FFFF_rgb, 0.40f },
@@ -171,11 +131,6 @@ Renderer::Renderer():
sampleColor(0xFFFFFFFF),
foundElements(0),
mousePos(0, 0),
zoomWindowPosition(0, 0),
zoomScopePosition(0, 0),
zoomScopeSize(32),
zoomEnabled(false),
ZFACTOR(8),
gridSize(0)
{
PopulateTables();
@@ -321,3 +276,35 @@ VideoBuffer Renderer::DumpFrame()
}
template struct RasterDrawMethods<Renderer>;
bool Renderer::GradientStop::operator <(const GradientStop &other) const
{
return point < other.point;
}
std::vector<RGB<uint8_t>> Renderer::Gradient(std::vector<GradientStop> stops, int resolution)
{
std::vector<RGB<uint8_t>> table(resolution, 0x000000_rgb);
if (stops.size() >= 2)
{
std::sort(stops.begin(), stops.end());
auto stop = -1;
for (auto i = 0; i < resolution; ++i)
{
auto point = i / (float)resolution;
while (stop < (int)stops.size() - 1 && stops[stop + 1].point <= point)
{
++stop;
}
if (stop < 0 || stop >= (int)stops.size() - 1)
{
continue;
}
auto &left = stops[stop];
auto &right = stops[stop + 1];
auto f = (point - left.point) / (right.point - left.point);
table[i] = left.color.Blend(right.color.WithAlpha(uint8_t(f * 0xFF)));
}
}
return table;
}

View File

@@ -0,0 +1,54 @@
#pragma once
#include <array>
#include <memory>
#include <vector>
#include "common/Plane.h"
#include "common/String.h"
#include "gui/interface/Point.h"
#include "Icons.h"
#include "Pixel.h"
#include "RasterDrawMethods.h"
#include "SimulationConfig.h"
class VideoBuffer: public RasterDrawMethods<VideoBuffer>
{
PlaneAdapter<std::vector<pixel>> video;
Rect<int> GetClipRect() const
{
return video.Size().OriginRect();
}
friend struct RasterDrawMethods<VideoBuffer>;
public:
VideoBuffer(pixel const *data, Vec2<int> size);
VideoBuffer(pixel const *data, Vec2<int> size, size_t rowStride);
VideoBuffer(Vec2<int> size);
Vec2<int> Size() const
{
return video.Size();
}
pixel *Data()
{
return video.data();
}
pixel const *Data() const
{
return video.data();
}
void Crop(Rect<int>);
void Resize(float factor, bool resample = false);
void Resize(Vec2<int> size, bool resample = false);
// Automatically choose a size to fit within the given box, keeping aspect ratio
void ResizeToFit(Vec2<int> bound, bool resample = false);
static std::unique_ptr<VideoBuffer> FromPNG(std::vector<char> const &);
std::unique_ptr<std::vector<char>> ToPNG() const;
std::vector<char> ToPPM() const;
};

View File

@@ -87,6 +87,7 @@ GameController::GameController():
gameView->AttachController(this);
gameModel->AddObserver(gameView);
gameModel->view = gameView; // mvc is a joke
gameView->SetDebugHUD(GlobalPrefs::Ref().Get("Renderer.DebugMode", false));

View File

@@ -1091,24 +1091,24 @@ void GameModel::SetLastTool(Tool * newTool)
void GameModel::SetZoomEnabled(bool enabled)
{
ren->zoomEnabled = enabled;
view->GetGraphics()->zoomEnabled = enabled;
notifyZoomChanged();
}
bool GameModel::GetZoomEnabled()
{
return ren->zoomEnabled;
return view->GetGraphics()->zoomEnabled;
}
void GameModel::SetZoomPosition(ui::Point position)
{
ren->zoomScopePosition = position;
view->GetGraphics()->zoomScopePosition = position;
notifyZoomChanged();
}
ui::Point GameModel::GetZoomPosition()
{
return ren->zoomScopePosition;
return view->GetGraphics()->zoomScopePosition;
}
bool GameModel::MouseInZoom(ui::Point position)
@@ -1141,35 +1141,35 @@ ui::Point GameModel::AdjustZoomCoords(ui::Point position)
void GameModel::SetZoomWindowPosition(ui::Point position)
{
ren->zoomWindowPosition = position;
view->GetGraphics()->zoomWindowPosition = position;
notifyZoomChanged();
}
ui::Point GameModel::GetZoomWindowPosition()
{
return ren->zoomWindowPosition;
return view->GetGraphics()->zoomWindowPosition;
}
void GameModel::SetZoomSize(int size)
{
ren->zoomScopeSize = size;
view->GetGraphics()->zoomScopeSize = size;
notifyZoomChanged();
}
int GameModel::GetZoomSize()
{
return ren->zoomScopeSize;
return view->GetGraphics()->zoomScopeSize;
}
void GameModel::SetZoomFactor(int factor)
{
ren->ZFACTOR = factor;
view->GetGraphics()->ZFACTOR = factor;
notifyZoomChanged();
}
int GameModel::GetZoomFactor()
{
return ren->ZFACTOR;
return view->GetGraphics()->ZFACTOR;
}
void GameModel::SetActiveColourPreset(size_t preset)

View File

@@ -273,4 +273,6 @@ public:
void UpdateUpTo(int upTo);
void BeforeSim();
void AfterSim();
GameView *view = nullptr;
};

View File

@@ -2245,9 +2245,9 @@ void GameView::OnDraw()
}
c->AfterSimDraw();
ren->RenderEnd();
std::copy_n(ren->Data(), ren->Size().X * ren->Size().Y, g->Data());
g->RenderZoom();
if (doScreenshot)
{

View File

@@ -1,6 +1,6 @@
#include "Slider.h"
#include "graphics/Graphics.h"
#include "graphics/Renderer.h"
namespace ui {
@@ -70,7 +70,7 @@ void Slider::SetColour(Colour col1, Colour col2)
{
this->col1 = col1;
this->col2 = col2;
bgGradient = Graphics::Gradient({
bgGradient = Renderer::Gradient({
{ col1.NoAlpha(), 0.f },
{ col2.NoAlpha(), 1.f },
}, Size.X-7);

View File

@@ -190,7 +190,6 @@ void RenderView::OnDraw()
ren->sim = sim;
ren->clearScreen();
ren->RenderSimulation();
ren->RenderEnd();
ren->sim = nullptr;
for (auto y = 0; y < YRES; ++y)
{

View File

@@ -2,6 +2,7 @@
#include "gui/game/GameController.h"
#include "gui/game/GameModel.h"
#include "graphics/Renderer.h"
#include "graphics/Graphics.h"
#include "simulation/ElementGraphics.h"
static int renderMode(lua_State *L)
@@ -148,13 +149,13 @@ static int zoomEnabled(lua_State *L)
auto *lsi = GetLSI();
if (lua_gettop(L) == 0)
{
lua_pushboolean(L, lsi->ren->zoomEnabled);
lua_pushboolean(L, lsi->g->zoomEnabled);
return 1;
}
else
{
luaL_checktype(L, -1, LUA_TBOOLEAN);
lsi->ren->zoomEnabled = lua_toboolean(L, -1);
lsi->g->zoomEnabled = lua_toboolean(L, -1);
return 0;
}
}
@@ -162,14 +163,13 @@ static int zoomEnabled(lua_State *L)
static int zoomWindow(lua_State *L)
{
auto *lsi = GetLSI();
auto *ren = lsi->ren;
if (lua_gettop(L) == 0)
{
ui::Point location = ren->zoomWindowPosition;
ui::Point location = lsi->g->zoomWindowPosition;
lua_pushnumber(L, location.X);
lua_pushnumber(L, location.Y);
lua_pushnumber(L, ren->ZFACTOR);
lua_pushnumber(L, ren->zoomScopeSize * ren->ZFACTOR);
lua_pushnumber(L, lsi->g->ZFACTOR);
lua_pushnumber(L, lsi->g->zoomScopeSize * lsi->g->ZFACTOR);
return 4;
}
int x = luaL_optint(L, 1, 0);
@@ -179,24 +179,23 @@ static int zoomWindow(lua_State *L)
return luaL_error(L, "Zoom factor must be greater than 0");
// To prevent crash when zoom window is outside screen
if (x < 0 || y < 0 || ren->zoomScopeSize * f + x > XRES || ren->zoomScopeSize * f + y > YRES)
if (x < 0 || y < 0 || lsi->g->zoomScopeSize * f + x > XRES || lsi->g->zoomScopeSize * f + y > YRES)
return luaL_error(L, "Zoom window outside of bounds");
ren->zoomWindowPosition = ui::Point(x, y);
ren->ZFACTOR = f;
lsi->g->zoomWindowPosition = ui::Point(x, y);
lsi->g->ZFACTOR = f;
return 0;
}
static int zoomScope(lua_State *L)
{
auto *lsi = GetLSI();
auto *ren = lsi->ren;
if (lua_gettop(L) == 0)
{
ui::Point location = ren->zoomScopePosition;
ui::Point location = lsi->g->zoomScopePosition;
lua_pushnumber(L, location.X);
lua_pushnumber(L, location.Y);
lua_pushnumber(L, ren->zoomScopeSize);
lua_pushnumber(L, lsi->g->zoomScopeSize);
return 3;
}
int x = luaL_optint(L, 1, 0);
@@ -206,15 +205,15 @@ static int zoomScope(lua_State *L)
return luaL_error(L, "Zoom scope size must be greater than 0");
// To prevent crash when zoom or scope window is outside screen
int windowEdgeRight = ren->ZFACTOR * s + ren->zoomWindowPosition.X;
int windowEdgeBottom = ren->ZFACTOR * s + ren->zoomWindowPosition.Y;
int windowEdgeRight = lsi->g->ZFACTOR * s + lsi->g->zoomWindowPosition.X;
int windowEdgeBottom = lsi->g->ZFACTOR * s + lsi->g->zoomWindowPosition.Y;
if (x < 0 || y < 0 || x + s > XRES || y + s > YRES)
return luaL_error(L, "Zoom scope outside of bounds");
if (windowEdgeRight > XRES || windowEdgeBottom > YRES)
return luaL_error(L, "Zoom window outside of bounds");
ren->zoomScopePosition = ui::Point(x, y);
ren->zoomScopeSize = s;
lsi->g->zoomScopePosition = ui::Point(x, y);
lsi->g->zoomScopeSize = s;
return 0;
}

View File

@@ -2,7 +2,7 @@
#include "client/GameSave.h"
#include "graphics/Graphics.h"
#include "graphics/VideoBuffer.h"
#include "graphics/Renderer.h"
#include "Simulation.h"
@@ -55,7 +55,6 @@ std::unique_ptr<VideoBuffer> SaveRenderer::Render(const GameSave *save, bool dec
}
ren->RenderSimulation();
ren->RenderEnd();
auto tempThumb = std::make_unique<VideoBuffer>(save->blockSize * CELL);
tempThumb->BlendImage(ren->Data(), 0xFF, ren->Size().OriginRect());

View File

@@ -1,6 +1,6 @@
#include "Sign.h"
#include "graphics/Graphics.h"
#include "graphics/Renderer.h"
#include "Simulation.h"
#include "SimulationData.h"
@@ -136,7 +136,7 @@ String sign::getDisplayText(const RenderableSimulation *sim, int &x0, int &y0, i
}
}
w = Graphics::TextSize(drawable_text.c_str()).X + 4;
w = Renderer::TextSize(drawable_text.c_str()).X + 4;
h = 15;
x0 = (ju == Right) ? x - w : (ju == Left) ? x : x - w/2;
y0 = (y > 18) ? y - 18 : y + 4;