Refactoring shitcode (stage 3)
This commit is contained in:
parent
6d10eb315b
commit
e9da9c920f
@ -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
63
src/drawing_assets.cpp
Normal 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
8
src/drawing_assets.hpp
Normal 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);
|
||||
|
109
src/frame.hpp
109
src/frame.hpp
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
struct COLOR {
|
||||
unsigned char red;
|
||||
@ -15,111 +16,37 @@ struct COLOR {
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -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 &&
|
||||
|
@ -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++) {
|
||||
|
Loading…
Reference in New Issue
Block a user