From e9da9c920f54f8df39f911b48737da3b15cf0838 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Wed, 9 Oct 2024 15:31:37 +0300 Subject: [PATCH] Refactoring shitcode (stage 3) --- CMakeLists.txt | 5 +- src/drawing_assets.cpp | 63 +++++++++++++++++++++++ src/drawing_assets.hpp | 8 +++ src/frame.hpp | 111 +++++++---------------------------------- src/painter.cpp | 6 ++- src/shaders.cpp | 17 ++++--- 6 files changed, 107 insertions(+), 103 deletions(-) create mode 100644 src/drawing_assets.cpp create mode 100644 src/drawing_assets.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1912f82..55e2e15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,11 @@ add_executable( WIN32 src/frame.hpp - src/main.cpp + src/drawing_assets.hpp + src/drawing_assets.cpp src/painter.cpp src/painter.hpp + src/main.cpp + src/shaders.cpp ) \ No newline at end of file diff --git a/src/drawing_assets.cpp b/src/drawing_assets.cpp new file mode 100644 index 0000000..313217a --- /dev/null +++ b/src/drawing_assets.cpp @@ -0,0 +1,63 @@ +#include "frame.hpp" +#include "drawing_assets.hpp" + +void draw_circle(Frame *frame, int cx, int cy, int radius, COLOR outline) { + int x = 0, y = radius; + while (x < y) { + int D1 = x * x + y * y - radius * radius; + int D2 = x * x + (y - 1) * (y - 1) - radius * radius; + + if (D1 > -D2) + y--; + + frame->set_pixel(cx + x, cy + y, outline); + frame->set_pixel(cx + x, cy - y, outline); + frame->set_pixel(cx + y, cy + x, outline); + frame->set_pixel(cx + y, cy - x, outline); + frame->set_pixel(cx - x, cy + y, outline); + frame->set_pixel(cx - x, cy - y, outline); + frame->set_pixel(cx - y, cy + x, outline); + frame->set_pixel(cx - y, cy - x, outline); + x++; + } +} + +void draw_line(Frame *frame, int x1, int y1, int x2, int y2, COLOR color) { + int dy = y2 - y1, dx = x2 - x1; + if (dx == 0 && dy == 0) { + frame->set_pixel(x1, y1, color); + return; + } + + if (abs(dx) > abs(dy)) { + if (x2 < x1) { + std::swap(x1, x2); + std::swap(y1, y2); + dx = -dx; + dy = -dy; + } + + int y, dx2 = dx / 2, p = 0; + if (dy < 0) dx2 = -dx2; + for (int x = x1; x <= x2; x++) { + y = (p + dx2) / dx + y1; + p += dy; + frame->set_pixel(x, y, color); + } + } else { + if (y2 < y1) { + std::swap(x1, x2); + std::swap(y1, y2); + dx = -dx; + dy = -dy; + } + + int x, dy2 = dy / 2, p = 0; + if (dx < 0) dy2 = -dy2; + for (int y = y1; y <= y2; y++) { + x = (p + dy2) / dy + x1; + p += dx; + frame->set_pixel(x, y, color); + } + } +} \ No newline at end of file diff --git a/src/drawing_assets.hpp b/src/drawing_assets.hpp new file mode 100644 index 0000000..ca4a7b2 --- /dev/null +++ b/src/drawing_assets.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "frame.hpp" + +void draw_circle(Frame *frame, int cx, int cy, int radius, COLOR outline); + +void draw_line(Frame *frame, int x1, int y1, int x2, int y2, COLOR color); + diff --git a/src/frame.hpp b/src/frame.hpp index a052481..9798763 100644 --- a/src/frame.hpp +++ b/src/frame.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include struct COLOR { unsigned char red; @@ -12,114 +13,40 @@ struct COLOR { COLOR(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {} -} ; - - -template -void swap(TYPE &a, TYPE &b) { - TYPE t = a; - a = b; - b = t; -} +}; class Frame { COLOR *pixels; - - COLOR **matrix; public: - int width, height; - Frame(int _width, int _height) : width(_width), height(_height) { + const int width, height; + + Frame(int _width, int _height) : width{_width}, height{_height} { int size = width * height; - pixels = new COLOR[size]; - - matrix = new COLOR *[height]; - - for (int i = 0; i < height; i++) { - matrix[i] = pixels + i * width; - } + this->pixels = new COLOR[size]; } +private: + [[nodiscard]] COLOR _get_pixel(int x, int y) const { + return this->pixels[y * this->width + x]; + } + [[nodiscard]] COLOR &_get_pixel(int x, int y) { + return this->pixels[y * this->width + x]; + } + +public: void set_pixel(int x, int y, COLOR color) { - matrix[y][x] = color; + this->_get_pixel(x, y) = color; } - COLOR get_pixel(int x, int y) { - return matrix[y][x]; - } - - - void draw_circle(int x0, int y0, int radius, COLOR outline) { - int x = 0, y = radius; - while (x < y) { - // Определяем, какая точка (пиксель): (x, y) или (x, y - 1) ближе к линии окружности - int D1 = x * x + y * y - radius * radius; - int D2 = x * x + (y - 1) * (y - 1) - radius * radius; - - // Если ближе точка (x, y - 1), то смещаемся к ней - if (D1 > -D2) - y--; - - // Перенос и отражение вычисленных координат на все октанты окружности - set_pixel(x0 + x, y0 + y, outline); - set_pixel(x0 + x, y0 - y, outline); - set_pixel(x0 + y, y0 + x, outline); - set_pixel(x0 + y, y0 - x, outline); - set_pixel(x0 - x, y0 + y, outline); - set_pixel(x0 - x, y0 - y, outline); - set_pixel(x0 - y, y0 + x, outline); - set_pixel(x0 - y, y0 - x, outline); - x++; - } - } - - - void draw_line(int x1, int y1, int x2, int y2, COLOR color) { - int dy = y2 - y1, dx = x2 - x1; - if (dx == 0 && dy == 0) { - matrix[y1][x1] = color; - return; - } - - if (abs(dx) > abs(dy)) { - if (x2 < x1) { - swap(x1, x2); - swap(y1, y2); - dx = -dx; - dy = -dy; - } - - int y, dx2 = dx / 2, p = 0; - if (dy < 0) dx2 = -dx2; - for (int x = x1; x <= x2; x++) { - y = (p + dx2) / dx + y1; - p += dy; - matrix[y][x] = color; - } - } else { - if (y2 < y1) { - swap(x1, x2); - swap(y1, y2); - dx = -dx; - dy = -dy; - } - - int x, dy2 = dy / 2, p = 0; - if (dx < 0) dy2 = -dy2; - for (int y = y1; y <= y2; y++) { - x = (p + dy2) / dy + x1; - p += dx; - matrix[y][x] = color; - } - } + [[nodiscard]] COLOR get_pixel(int x, int y) const { + return this->_get_pixel(x, y); } ~Frame() { - delete[]pixels; - delete[]matrix; + delete[]this->pixels; } - }; diff --git a/src/painter.cpp b/src/painter.cpp index d63e850..83e3932 100644 --- a/src/painter.cpp +++ b/src/painter.cpp @@ -1,5 +1,6 @@ #include #include "frame.hpp" +#include "drawing_assets.hpp" #include "painter.hpp" @@ -34,7 +35,8 @@ class DemoPainter : public Painter { // Рисуем стороны квадрата for (int i = 0; i < 4; i++) { int i2 = (i + 1) % 4; - frame->draw_line( // Добавляем везде 0.5f, чтобы вещественные числа правильно округлялись при преобразовании к целому типу + draw_line( + frame, int(A[i].x + 0.5f), int(A[i].y + 0.5f), int(A[i2].x + 0.5f), @@ -42,7 +44,7 @@ class DemoPainter : public Painter { } // Рисуем описанную окружность - frame->draw_circle((int) C.x, (int) C.y, int(a * sqrt(2) + 0.5f), COLOR(100, 100, 250)); + draw_circle(frame, (int) C.x, (int) C.y, int(a * sqrt(2) + 0.5f), COLOR(100, 100, 250)); // Рисуем пиксель, на который кликнул пользователь if (state->clicked_pixel.x >= 0 && state->clicked_pixel.x < W && diff --git a/src/shaders.cpp b/src/shaders.cpp index 0cf0ee7..3ce86ae 100644 --- a/src/shaders.cpp +++ b/src/shaders.cpp @@ -1,3 +1,4 @@ +#include #include "frame.hpp" #include "painter.hpp" @@ -5,16 +6,16 @@ template void Triangle(Frame *f, float x0, float y0, float x1, float y1, float x2, float y2, COLOR color, ShaderClass *shader) { // Отсортируем точки таким образом, чтобы выполнилось условие: y0 < y1 < y2 if (y1 < y0) { - swap(y1, y0); - swap(x1, x0); + std::swap(y1, y0); + std::swap(x1, x0); } if (y2 < y1) { - swap(y2, y1); - swap(x2, x1); + std::swap(y2, y1); + std::swap(x2, x1); } if (y1 < y0) { - swap(y1, y0); - swap(x1, x0); + std::swap(y1, y0); + std::swap(x1, x0); } // Определяем номера строк пикселей, в которых располагаются точки треугольника int Y0 = (int) (y0 + 0.5f); @@ -31,7 +32,7 @@ void Triangle(Frame *f, float x0, float y0, float x1, float y1, float x2, float for (float y = Y0 + 0.5f; y < Y1; y++) { int X0 = (int) ((y - y0) / (y1 - y0) * (x1 - x0) + x0 + 0.5f); int X1 = (int) ((y - y0) / (y2 - y0) * (x2 - x0) + x0 + 0.5f); - if (X0 > X1) swap(X0, X1); + if (X0 > X1) std::swap(X0, X1); if (X0 < 0) X0 = 0; if (X1 > f->width) X1 = f->width; for (int x = X0; x < X1; x++) { @@ -43,7 +44,7 @@ void Triangle(Frame *f, float x0, float y0, float x1, float y1, float x2, float for (float y = Y1 + 0.5f; y < Y2; y++) { int X0 = (int) ((y - y1) / (y2 - y1) * (x2 - x1) + x1 + 0.5f); int X1 = (int) ((y - y0) / (y2 - y0) * (x2 - x0) + x0 + 0.5f); - if (X0 > X1) swap(X0, X1); + if (X0 > X1) std::swap(X0, X1); if (X0 < 0) X0 = 0; if (X1 > f->width) X1 = f->width; for (int x = X0; x < X1; x++) {