Some useful widgets for lab1 and pixels grid sprite with necessary data

This commit is contained in:
Andrew Golovashevich 2024-12-10 14:43:16 +03:00
parent be82c26b01
commit 056a3efc73
11 changed files with 237 additions and 56 deletions

View File

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

View File

@ -0,0 +1,34 @@
#pragma once
#include <Qt>
#include <QWidget>
#include <QKeyEvent>
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;
}
}
};
}

View File

@ -1,49 +1,54 @@
#include <QApplication>
#include <QMainWindow>
#include <QTimer>
#include <array>
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp>
#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<RendererApi::Sprite<Lab1SpriteData> *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<Lab1SpriteData> 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<Lab1SpriteData> 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<BGTU::ComputerGraphicsLabWork::QtUtilities::OwnedQImage>("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<int> 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<int> canvas{&renderer, &w};
w.setCentralWidget(&canvas);
w.show();
QApplication::exec();
return BGTU::ComputerGraphicsLabWork::Lab1::main(argc, argv);
}

View File

@ -0,0 +1,41 @@
#pragma once
#include <limits>
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include "sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
class PixelGridSprite : public RendererApi::Sprite<Lab1SpriteData> {
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<long long>(centerd.x), static_cast<long long>(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<double>::max(), c);
}
}
}
}
}
};
}

View File

@ -0,0 +1,83 @@
#pragma once
#include <cstdlib>
#include <QMutex>
#include <QElapsedTimer>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/matrix.hpp>
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<Lab1SpriteData>::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();
}
};
}

View File

@ -19,7 +19,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t>
class RendererWidget;
class _RendererWidget_Slots : public QWidget {
class _RendererWidget_SignalSlots : public QWidget {
template<class>
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);
};
}

View File

@ -20,7 +20,7 @@
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t>
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());
}
};
}

View File

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

View File

@ -17,6 +17,11 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
component_t y;
inline Point(component_t x, component_t y) : x{x}, y{y} {}
template<class new_component_t, new_component_t (converter)(_component_t const &) = [](auto p) { return new_component_t(p); }>
explicit operator Point<2, new_component_t>() const {
return Point<2, new_component_t>{converter(this->x), converter(this->y)};
}
};
template<class _component_t>
@ -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<class new_component_t>
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<unsigned DIMENSIONS>

View File

@ -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<class operator_t>
Matrix4<elem_t> _zipmap_matrix(Matrix4<elem_t> const *other, operator_t op) const {
Matrix4 < elem_t > dst;
Matrix4<elem_t> 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<elem_t> 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<elem_t>{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<class elem_t>
const Matrix3<elem_t> Matrix3<elem_t>::I{1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};
const Matrix3<elem_t> Matrix3<elem_t>::I{1, 0, 0,
0, 1, 0,
0, 0, 1};
template<class elem_t>
const Matrix3<elem_t> Matrix3<elem_t>::_tmp{};

View File

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