From 056a3efc7361cc9fa23ba262e5eaba2c805ff32c Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Tue, 10 Dec 2024 14:43:16 +0300 Subject: [PATCH] Some useful widgets for lab1 and pixels grid sprite with necessary data --- programs/lab1/CMakeLists.txt | 2 +- programs/lab1/src/keyboard_catcher_widget.hpp | 34 ++++++++ programs/lab1/src/main.cpp | 81 +++++++++--------- programs/lab1/src/pixel_grid_sprite.hpp | 41 +++++++++ programs/lab1/src/sprite_data.hpp | 83 +++++++++++++++++++ .../qt_utilities/_renderer_widget.hpp | 9 +- .../qt_utilities/renderer_widget.hpp | 7 +- .../separate_threaded_renderer.hpp | 2 +- .../renderer_api/point.hpp | 11 +++ .../utilities/matrix.hpp | 21 +++-- utilities/src/memory_pages_management.cpp | 2 +- 11 files changed, 237 insertions(+), 56 deletions(-) create mode 100644 programs/lab1/src/keyboard_catcher_widget.hpp create mode 100644 programs/lab1/src/pixel_grid_sprite.hpp create mode 100644 programs/lab1/src/sprite_data.hpp diff --git a/programs/lab1/CMakeLists.txt b/programs/lab1/CMakeLists.txt index 0c557dd..d9a9612 100644 --- a/programs/lab1/CMakeLists.txt +++ b/programs/lab1/CMakeLists.txt @@ -1,2 +1,2 @@ -add_executable(lab1 src/main.cpp) +add_executable(lab1 src/main.cpp src/sprite_data.hpp src/keyboard_catcher_widget.hpp) target_link_libraries(lab1 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities) diff --git a/programs/lab1/src/keyboard_catcher_widget.hpp b/programs/lab1/src/keyboard_catcher_widget.hpp new file mode 100644 index 0000000..53d7201 --- /dev/null +++ b/programs/lab1/src/keyboard_catcher_widget.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +namespace BGTU::ComputerGraphicsLabWork::Lab1 { + class KeyboardCatcherWidget : public QWidget { + Q_OBJECT + public: + inline KeyboardCatcherWidget(QWidget *parent = nullptr) : QWidget{parent} { + this->grabKeyboard(); + } + + signals: + + void key_pressed_PageUp(); + + void key_pressed_PageDown(); + + protected: + void keyPressEvent(QKeyEvent *event) override { + switch (event->key()) { + case Qt::Key_PageUp: + emit this->key_pressed_PageUp(); + return; + case Qt::Key_PageDown: + emit this->key_pressed_PageDown(); + return; + } + + } + }; +} \ No newline at end of file diff --git a/programs/lab1/src/main.cpp b/programs/lab1/src/main.cpp index 9016d43..2827030 100644 --- a/programs/lab1/src/main.cpp +++ b/programs/lab1/src/main.cpp @@ -1,49 +1,54 @@ #include #include #include +#include #include #include #include #include #include +#include "sprite_data.hpp" +#include "keyboard_catcher_widget.hpp" +#include "pixel_grid_sprite.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Lab1 { + int main(int argc, char **argv) { + QApplication qApplication{argc, argv}; + + + PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{32, 32, 32}}; + + auto sprites = std::to_array *const>({ + &pixels_grid_sprite + }); + + + Lab1SpriteData::Provider sprites_data{1}; + sprites_data.set_pixel_size(16); + + QMainWindow w{}; + + KeyboardCatcherWidget kbd{&w}; + QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data, &Lab1SpriteData::Provider::decrease_pixel_size); + QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data, &Lab1SpriteData::Provider::increase_pixel_size); + + QtUtilities::SeparateThreadedDefaultRendererLinear renderer{}; + renderer.set_sprite_data_provider(&sprites_data); + renderer.set_sprites(sprites.data(), sprites.size()); + renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); + + QtUtilities::RendererWidget canvas{&renderer, &kbd}; + QObject::connect(&canvas, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data, &Lab1SpriteData::Provider::set_frame_size); + w.setCentralWidget(&canvas); + w.show(); + + QApplication::exec(); + + return 0; + } +} + int main(int argc, char **argv) { - - QApplication qApplication{argc, argv}; -// qRegisterMetaType("OwnedQImage"); - - QTimer fps_timeout; - unsigned frames = 0; - fps_timeout.callOnTimeout([&] { - qCritical() << (frames * 4) << "\n"; - qDebug() << (frames * 4) << "\n"; - frames = 0; - }); - fps_timeout.setInterval(250); - fps_timeout.start(); - QMainWindow w{}; - class o : public QObject { - public: - unsigned *frames; - - explicit o(unsigned *f) : QObject{}, frames{f} {} - - public slots: - - void hit() { - (*this->frames)++; - } - }; - - - o oo{&frames}; - - BGTU::ComputerGraphicsLabWork::QtUtilities::SeparateThreadedDefaultRendererLinear renderer{}; - QObject::connect(&renderer, &BGTU::ComputerGraphicsLabWork::QtUtilities::_SeparateThreadedRenderer_Signals::frame_rendered, &oo, &o::hit); - renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); - BGTU::ComputerGraphicsLabWork::QtUtilities::RendererWidget canvas{&renderer, &w}; - w.setCentralWidget(&canvas); - w.show(); - - QApplication::exec(); + return BGTU::ComputerGraphicsLabWork::Lab1::main(argc, argv); } \ No newline at end of file diff --git a/programs/lab1/src/pixel_grid_sprite.hpp b/programs/lab1/src/pixel_grid_sprite.hpp new file mode 100644 index 0000000..e00c9e5 --- /dev/null +++ b/programs/lab1/src/pixel_grid_sprite.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include +#include "sprite_data.hpp" + + +namespace BGTU::ComputerGraphicsLabWork::Lab1 { + class PixelGridSprite : public RendererApi::Sprite { + private: + RendererApi::Color bg, fg; + public: + PixelGridSprite(RendererApi::Color bg, RendererApi::Color fg) : bg{bg}, fg{fg} {}; + + void draw(BGTU::ComputerGraphicsLabWork::RendererApi::VoxelDrawer *frame, const BGTU::ComputerGraphicsLabWork::Lab1::Lab1SpriteData *data) const override { + auto centerd = (data->transform * RendererApi::PointF<2>{0, 0}); + auto center = RendererApi::PointI<2>{static_cast(centerd.x), static_cast(centerd.y)}; + + long long start_x = center.x - ((center.x + data->pixel_size - 1) / data->pixel_size * data->pixel_size); + long long start_y = center.y - ((center.y + data->pixel_size - 1) / data->pixel_size * data->pixel_size); + long long w = frame->width(); + long long h = frame->height(); + bool y_flag = ((center.x - start_x) / data->pixel_size + (center.y - start_y) / data->pixel_size) % 2 != 0; + bool x_flag; + for (long long y = start_y; y < h; y += data->pixel_size, y_flag = !y_flag) { + x_flag = y_flag; + for (long long x = start_x; x < w; x += data->pixel_size, x_flag = !x_flag) { + auto c = x_flag ? this->bg : this->fg; + + for (long long yy = y + data->pixel_size - 1; yy-- > y;) { + for (long long xx = x + data->pixel_size - 1; xx-- > x;) { + frame->add_voxel(xx, yy, std::numeric_limits::max(), c); + } + } + } + } + } + }; +} \ No newline at end of file diff --git a/programs/lab1/src/sprite_data.hpp b/programs/lab1/src/sprite_data.hpp new file mode 100644 index 0000000..0a4124d --- /dev/null +++ b/programs/lab1/src/sprite_data.hpp @@ -0,0 +1,83 @@ +#pragma once + + +#include +#include +#include +#include +#include + + +namespace BGTU::ComputerGraphicsLabWork::Lab1 { + class _Lab1SpriteData_Provider; + + + struct Lab1SpriteData { + public: + Utilities::Matrix3d transform; + std::size_t pixel_size; + bool show_grid; + + using Provider = _Lab1SpriteData_Provider; + }; + + class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite::SpriteDataProvider { + Q_OBJECT + private: + QMutex sync; + QElapsedTimer time; + + std::size_t pixel_size; + double radians_per_second; + RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w, h; + bool show_grid; + public: + explicit _Lab1SpriteData_Provider(double radians_per_second) : sync{}, time{}, pixel_size{1}, radians_per_second{radians_per_second}, show_grid{false} {} + + Lab1SpriteData get_sprite_data() override { + this->sync.lock(); + Lab1SpriteData cached{ + .transform = Utilities::Matrix3d::shift(this->pixel_size / -2.0, this->pixel_size / 2.0) * + Utilities::Matrix3d::shift(this->w / 2.0, this->h / 2.0) * + Utilities::Matrix3d::rotate(this->time.elapsed() / 1000.0 * this->radians_per_second), + .pixel_size = this->pixel_size, + .show_grid = this->show_grid + }; + this->sync.unlock(); + return cached; + } + + public slots: + void set_pixel_size(std::size_t s) { + this->sync.lock(); + this->pixel_size = s; + this->sync.unlock(); + } + + void increase_pixel_size() { + this->sync.lock(); + this->pixel_size++; + this->sync.unlock(); + } + + void decrease_pixel_size() { + this->sync.lock(); + if (this->pixel_size > 1) + this->pixel_size--; + this->sync.unlock(); + } + + void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t ww, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t hh) { + this->sync.lock(); + this->w = ww; + this->h = hh; + this->sync.unlock(); + } + + void set_show_grid(bool f) { + this->sync.lock(); + this->show_grid = f; + this->sync.unlock(); + } + }; +} \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp index 1a57cb1..1fa7ee8 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp @@ -19,7 +19,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { template class RendererWidget; - class _RendererWidget_Slots : public QWidget { + class _RendererWidget_SignalSlots : public QWidget { template friend class RendererWidget; @@ -27,11 +27,14 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { Q_OBJECT private: - inline _RendererWidget_Slots(QWidget *owner) : QWidget{owner} {} + inline explicit _RendererWidget_SignalSlots(QWidget *owner) : QWidget{owner} {} private slots: - virtual void receive_image(OwnedQImage *img) = 0; + virtual void receive_image(BGTU::ComputerGraphicsLabWork::QtUtilities::OwnedQImage *img) = 0; + signals: + + void resized(unsigned w, unsigned y); }; } \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp index 9712560..86957a0 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp @@ -20,7 +20,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { template - class RendererWidget : public _RendererWidget_Slots { + class RendererWidget : public _RendererWidget_SignalSlots { private: QMutex sync; OwnedQImage *next_image; @@ -40,8 +40,8 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { public: - explicit RendererWidget(_SeparateThreadedRenderer_Signals *renderer, QWidget *owner = nullptr) : _RendererWidget_Slots{owner}, sync{}, next_image{}, current_image{}, renderer{renderer} { - connect(this->renderer, &_SeparateThreadedRenderer_Signals::frame_rendered, this, &_RendererWidget_Slots::receive_image); + explicit RendererWidget(_SeparateThreadedRenderer_Signals *renderer, QWidget *owner = nullptr) : _RendererWidget_SignalSlots{owner}, sync{}, next_image{}, current_image{}, renderer{renderer} { + connect(this->renderer, &_SeparateThreadedRenderer_Signals::frame_rendered, this, &_RendererWidget_SignalSlots::receive_image); } protected: @@ -67,6 +67,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { void resizeEvent(QResizeEvent *event) override { this->renderer->set_frame_size(event->size().width(), event->size().height()); + emit this->resized(event->size().width(), event->size().height()); } }; } \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp index 050d822..6a58830 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp @@ -181,7 +181,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { union { sprite_data_t data; bool nothing; - } sprite_data_storage; + } sprite_data_storage{.nothing = false}; sprite_data_t const *sprite_data; if (cached.sprite_data_provider != nullptr) { sprite_data_storage.data = cached.sprite_data_provider->get_sprite_data(); diff --git a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp index ba5d136..851f032 100644 --- a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp +++ b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp @@ -17,6 +17,11 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { component_t y; inline Point(component_t x, component_t y) : x{x}, y{y} {} + + template + explicit operator Point<2, new_component_t>() const { + return Point<2, new_component_t>{converter(this->x), converter(this->y)}; + } }; template @@ -29,6 +34,12 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { component_t z; inline Point(component_t x, component_t y, component_t z) : x{x}, y{y}, z{z} {} + + + template + explicit operator Point<3, new_component_t>() const { + return Point<3, new_component_t>{new_component_t{this->x}, new_component_t{this->y}, new_component_t{this->z}}; + } }; template diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp index 7ae510b..ac3eb58 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp @@ -10,7 +10,11 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { class Matrix3 { private: elem_t data[3][3]; + + inline Matrix3() = default; + public: + inline Matrix3( elem_t e00, elem_t e01, elem_t e02, elem_t e10, elem_t e11, elem_t e12, @@ -148,7 +152,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { template Matrix4 _zipmap_matrix(Matrix4 const *other, operator_t op) const { - Matrix4 < elem_t > dst; + Matrix4 dst; auto _map_row = [&](std::size_t row_index) { dst.data[row_index][0] = op(row_index, 0, this->data[row_index][0], other->data[row_index][0]); dst.data[row_index][1] = op(row_index, 1, this->data[row_index][1], other->data[row_index][1]); @@ -211,10 +215,10 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { } static Matrix4 scale(elem_t x, elem_t y, elem_t z) { - return Matrix4 < elem_t > {x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1}; + return Matrix4{x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1}; } @@ -262,10 +266,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { }; template - const Matrix3 Matrix3::I{1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1}; + const Matrix3 Matrix3::I{1, 0, 0, + 0, 1, 0, + 0, 0, 1}; template const Matrix3 Matrix3::_tmp{}; diff --git a/utilities/src/memory_pages_management.cpp b/utilities/src/memory_pages_management.cpp index 3143ddd..69e6c57 100644 --- a/utilities/src/memory_pages_management.cpp +++ b/utilities/src/memory_pages_management.cpp @@ -16,7 +16,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { std::size_t size = max(si.dwPageSize, si.dwAllocationGranularity); void *raw = VirtualAlloc(nullptr, max(si.dwPageSize, si.dwAllocationGranularity), MEM_COMMIT, PAGE_READWRITE); - if (raw != nullptr) throw std::bad_alloc{}; + if (raw == nullptr) throw std::bad_alloc{}; return this->last_page = new(raw)Page(this->last_page, Page::calc_capacity(size)); }