Refactoring shitcode (stage 3)

This commit is contained in:
Andrew Golovashevich 2024-10-09 15:31:37 +03:00
parent 6d10eb315b
commit e9da9c920f
6 changed files with 107 additions and 103 deletions

View File

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

63
src/drawing_assets.cpp Normal file
View File

@ -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);
}
}
}

8
src/drawing_assets.hpp Normal file
View File

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

View File

@ -1,6 +1,7 @@
#pragma once
#include <cmath>
#include <utility>
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<typename TYPE>
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;
}
};

View File

@ -1,5 +1,6 @@
#include <tuple>
#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 &&

View File

@ -1,3 +1,4 @@
#include <utility>
#include "frame.hpp"
#include "painter.hpp"
@ -5,16 +6,16 @@ template<class ShaderClass>
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++) {