Minor improvements

This commit is contained in:
Andrew Golovashevich 2024-12-10 02:19:59 +03:00
parent 52561c8004
commit 15c715ad21
10 changed files with 106 additions and 61 deletions

View File

@ -5,15 +5,19 @@
#include <bgtu/computer_graphics_lab_work/utilities/color.hpp> #include <bgtu/computer_graphics_lab_work/utilities/color.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp> #include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp> #include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp>
int main(int argc, char **argv) { int main(int argc, char **argv) {
QApplication qApplication{argc, argv}; QApplication qApplication{argc, argv};
QMainWindow w{}; qRegisterMetaType<BGTU::ComputerGraphicsLabWork::QtUtilities::OwnedQImage>("OwnedQImage");
QMainWindow w{};
BGTU::ComputerGraphicsLabWork::QtUtilities::SeparateThreadedDefaultRendererLinear<void> renderer{}; BGTU::ComputerGraphicsLabWork::QtUtilities::SeparateThreadedDefaultRendererLinear<void> renderer{};
renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0});
BGTU::ComputerGraphicsLabWork::QtUtilities::RendererWidget<void> canvas{&renderer, &w}; BGTU::ComputerGraphicsLabWork::QtUtilities::RendererWidget<void> canvas{&renderer, &w};
w.setCentralWidget(&canvas); w.setCentralWidget(&canvas);
w.show(); w.show();
QApplication::exec(); QApplication::exec();
} }

View File

@ -1,3 +1,9 @@
add_library(qt_utilities OBJECT include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp include/bgtu/computer_graphics_lab_work/qt_utilities/_renderer_widget.hpp) add_library(
qt_utilities
OBJECT
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
)
target_include_directories(qt_utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(qt_utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(qt_utilities PUBLIC Qt5::Core Qt5::Widgets Qt5::Gui renderer_api utilities) target_link_libraries(qt_utilities PUBLIC Qt5::Core Qt5::Widgets Qt5::Gui renderer_api utilities)

View File

@ -31,7 +31,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
private slots: private slots:
virtual void receive_image(OwnedQImage<void> img) = 0; virtual void receive_image(OwnedQImage img) = 0;
}; };
} }

View File

@ -13,13 +13,13 @@
#include "owned_qimage.hpp" #include "owned_qimage.hpp"
namespace BGTU::ComputerGraphicsLabWork::QtUtilities { namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
class SeparateThreadedRenderer; class SeparateThreadedRenderer;
class _SeparateThreadedRenderer_Signals : public QObject { class _SeparateThreadedRenderer_Signals : public QObject {
Q_OBJECT Q_OBJECT
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
friend friend
class SeparateThreadedRenderer; class SeparateThreadedRenderer;
@ -27,6 +27,6 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
explicit _SeparateThreadedRenderer_Signals(QObject *owner = nullptr) : QObject{owner} {} explicit _SeparateThreadedRenderer_Signals(QObject *owner = nullptr) : QObject{owner} {}
signals: signals:
void frame_rendered(OwnedQImage<void> img); void frame_rendered(OwnedQImage img);
}; };
} }

View File

@ -11,36 +11,41 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
namespace BGTU::ComputerGraphicsLabWork::QtUtilities { namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t> class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter {
class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter<sprite_data_t> {
private: private:
RendererApi::Sprite<sprite_data_t> const **owners; RendererApi::SpriteMetadata const **owners;
public: public:
OwnedQImage(unsigned width, unsigned height) : QImage(width, height, QImage::Format_ARGB32), owners{new RendererApi::Sprite<sprite_data_t> const *[width * height]} { OwnedQImage(unsigned width, unsigned height) :
for (RendererApi::Sprite<sprite_data_t> const **p = this->owners - 1; p-- >= this->owners;) { QImage(width, height, QImage::Format_ARGB32) {
*p = nullptr; if (width == 0 || height == 0) {
this->owners = nullptr;
} else {
this->owners = new RendererApi::SpriteMetadata const *[width * height];
for (RendererApi::SpriteMetadata const **p = this->owners - 1; p-- >= this->owners;) {
*p = nullptr;
}
} }
} }
OwnedQImage() : QImage(), owners{nullptr} {} OwnedQImage() : QImage(), owners{nullptr} {}
void setPixelOwner(unsigned x, unsigned y, RendererApi::Sprite<sprite_data_t> const *o) { void setPixelOwner(unsigned x, unsigned y, RendererApi::SpriteMetadata const *o) {
assert(x < this->width()); assert(x < this->width());
assert(y < this->height()); assert(y < this->height());
this->owners[y * this->width() + x] = o; this->owners[y * this->width() + x] = o;
} }
RendererApi::Sprite<sprite_data_t> const *getPixelOwner(unsigned x, unsigned y) const { RendererApi::SpriteMetadata const *getPixelOwner(unsigned x, unsigned y) const {
assert(x < this->width()); assert(x < this->width());
assert(y < this->height()); assert(y < this->height());
return this->owners[y * this->width() + x]; return this->owners[y * this->width() + x];
} }
void set_pixel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, RendererApi::Color c, RendererApi::Sprite<sprite_data_t> const *owner) final { void set_pixel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, RendererApi::Color c, RendererApi::SpriteMetadata const *owner) final {
this->setPixelColor(x, y, QColor{c.red, c.green, c.blue}); this->setPixelColor(x, y, QColor{c.red, c.green, c.blue});
this->setPixelOwner(x, y, owner); this->setPixelOwner(x, y, owner);
} }

View File

@ -21,13 +21,13 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
class RendererWidget : public _RendererWidget_Slots { class RendererWidget : public _RendererWidget_Slots {
private: private:
QMutex sync; QMutex sync;
OwnedQImage<void> next_image; OwnedQImage next_image;
OwnedQImage<void> current_image; OwnedQImage current_image;
_SeparateThreadedRenderer_Signals *renderer; _SeparateThreadedRenderer_Signals *renderer;
private slots: private slots:
void receive_image(OwnedQImage<void> img) { void receive_image(OwnedQImage img) {
this->sync.lock(); this->sync.lock();
std::swap(this->next_image, img); std::swap(this->next_image, img);
this->sync.unlock(); this->sync.unlock();
@ -48,8 +48,9 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
QPainter painter; QPainter painter;
painter.begin(this); painter.begin(this);
painter.setPen(Qt::NoPen);
painter.setBrush(QApplication::style()->standardPalette().brush(QPalette::Background)); painter.setBrush(QApplication::style()->standardPalette().brush(QPalette::Background));
painter.drawRect(this->rect()); painter.drawRect(this->rect().x(), this->rect().y(), this->rect().width()-1, this->rect().height()-1);
painter.drawImage(this->current_image.rect(), this->current_image); painter.drawImage(this->current_image.rect(), this->current_image);
painter.end(); painter.end();
} }

View File

@ -8,13 +8,14 @@
#include <QThread> #include <QThread>
#include <QMutex> #include <QMutex>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QWaitCondition>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include "owned_qimage.hpp" #include "owned_qimage.hpp"
#include "_separate_threaded_renderer.hpp" #include "_separate_threaded_renderer.hpp"
namespace BGTU::ComputerGraphicsLabWork::QtUtilities { namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
class SeparateThreadedRenderer : public _SeparateThreadedRenderer_Signals { class SeparateThreadedRenderer : public _SeparateThreadedRenderer_Signals {
private: private:
struct data { struct data {
@ -32,12 +33,27 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
private: private:
SeparateThreadedRenderer *owner; SeparateThreadedRenderer *owner;
QWaitCondition intr;
public: public:
explicit inline RendererThread(SeparateThreadedRenderer *owner) : QThread{owner}, owner{owner} {};
explicit inline RendererThread(SeparateThreadedRenderer *owner) : QThread{owner}, owner{owner}, intr{} {
};
void requestInterruption() {
QThread::requestInterruption();
this->intr.wakeAll();
}
protected: protected:
void run() final; void run() final;
private:
void sleepms(std::uint_fast64_t ms) {
QMutex m{};
m.lock();
this->intr.wait(&m, ms);
m.unlock();
}
}; };
@ -62,10 +78,13 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
void set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data); void set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data);
void set_background(RendererApi::Color); void set_background(RendererApi::Color);
public:
~SeparateThreadedRenderer();
}; };
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner): SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner):
_SeparateThreadedRenderer_Signals{owner}, _SeparateThreadedRenderer_Signals{owner},
sync{}, sync{},
@ -81,66 +100,67 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
.height = 0, .height = 0,
.projection = nullptr .projection = nullptr
} { } {
this->thread->start();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) {
this->sync.lock(); this->sync.lock();
this->next_data.width = width; const_cast<data *>(&this->next_data)->width = width;
this->next_data.height = height; const_cast<data *>(&this->next_data)->height = height;
this->sync.unlock(); this->sync.unlock();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) {
this->sync.lock(); this->sync.lock();
this->next_data.ms_per_frame = ms; const_cast<data *>(&this->next_data)->ms_per_frame = ms;
this->sync.unlock(); this->sync.unlock();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count) { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count) {
this->sync.lock(); this->sync.lock();
this->next_data.sprites = sprites; const_cast<data *>(&this->next_data)->sprites = sprites;
this->next_data.sprites_count = sprites_count; const_cast<data *>(&this->next_data)->sprites_count = sprites_count;
this->sync.unlock(); this->sync.unlock();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprite_data(sprite_data_t const *data) { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprite_data(sprite_data_t const *sprite_data) {
this->sync.lock(); this->sync.lock();
this->next_data.sprite_data = data; const_cast<data *>(&this->next_data)->sprite_data = sprite_data;
this->sync.unlock(); this->sync.unlock();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *data) { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites_and_data(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count, sprite_data_t const *sprite_data) {
this->sync.lock(); this->sync.lock();
this->next_data.sprites = sprites; const_cast<data *>(&this->next_data)->sprites = sprites;
this->next_data.sprites_count = sprites_count; const_cast<data *>(&this->next_data)->sprites_count = sprites_count;
this->next_data.sprite_data = data; const_cast<data *>(&this->next_data)->sprite_data = sprite_data;
this->sync.unlock(); this->sync.unlock();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_background(RendererApi::Color c) { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_background(RendererApi::Color c) {
this->sync.lock(); this->sync.lock();
this->next_data.bg = c; const_cast<data *>(&this->next_data)->bg = c;
this->sync.unlock(); this->sync.unlock();
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::RendererThread::run() { void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::RendererThread::run() {
try { try {
QElapsedTimer timer; QElapsedTimer timer;
while (true) { while (!this->isInterruptionRequested()) {
timer.start(); timer.start();
this->owner->sync.lock(); this->owner->sync.lock();
data cached = *const_cast<data *>(&this->owner->next_data); data cached = *const_cast<data *>(&this->owner->next_data);
this->owner->sync.unlock(); this->owner->sync.unlock();
OwnedQImage<sprite_data_t> img{cached.width, cached.height}; OwnedQImage img{cached.width, cached.height};
(this->owner->renderer_context->*renderer_procedure)( (this->owner->renderer_context->*renderer_procedure)(
cached.width, cached.height, cached.width, cached.height,
&img, &img,
@ -149,12 +169,18 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
cached.sprites, cached.sprites_count, cached.sprites, cached.sprites_count,
cached.sprite_data cached.sprite_data
); );
emit this->owner->frame_rendered(std::move(*reinterpret_cast<OwnedQImage<void> *>(&img))); emit this->owner->frame_rendered(img);
QThread::msleep(std::max<std::uint_fast64_t>(cached.ms_per_frame - static_cast<std::uint_fast64_t>(timer.elapsed()), 0)); this->sleepms(std::max<std::uint_fast64_t>(cached.ms_per_frame - static_cast<std::uint_fast64_t>(timer.elapsed()), 0));
} }
} catch (std::exception const &e) { } catch (std::exception const &e) {
qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n"; qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n";
} }
} }
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::~SeparateThreadedRenderer() {
this->thread->requestInterruption();
this->thread->wait();
}
} }

View File

@ -4,11 +4,14 @@
#include "projection.hpp" #include "projection.hpp"
namespace BGTU::ComputerGraphicsLabWork::RendererApi { namespace BGTU::ComputerGraphicsLabWork::RendererApi {
template<class data_t> class SpriteMetadata {
class Sprite {
public: public:
virtual void draw(VoxelDrawer *frame, Projection const *projection, data_t const *data) const = 0;
virtual void clicked() {}; virtual void clicked() {};
}; };
template<class data_t>
class Sprite : public SpriteMetadata {
public:
virtual void draw(VoxelDrawer *frame, Projection const *projection, data_t const *data) const = 0;
};
} }

View File

@ -7,8 +7,7 @@
#include "point.hpp" #include "point.hpp"
namespace BGTU::ComputerGraphicsLabWork::RendererApi { namespace BGTU::ComputerGraphicsLabWork::RendererApi {
template<class> class SpriteMetadata;
class Sprite;
class VoxelDrawer { class VoxelDrawer {
public: public:
@ -31,10 +30,9 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
return this->add_voxel(p.x, p.y, z, c); return this->add_voxel(p.x, p.y, z, c);
} }
template<class sprite_data_t>
class Exporter { class Exporter {
public: public:
virtual void set_pixel(PointI<2>::component_t x, PointI<2>::component_t y, Color c, Sprite<sprite_data_t> const* owner) = 0; virtual void set_pixel(PointI<2>::component_t x, PointI<2>::component_t y, Color c, SpriteMetadata const* owner) = 0;
}; };
}; };
} }

View File

@ -24,9 +24,9 @@ namespace BGTU::ComputerGraphicsLabWork {
ZElement *next; ZElement *next;
double const z; double const z;
RendererApi::Color::Transparent const color; RendererApi::Color::Transparent const color;
RendererApi::Sprite<void> *const owner; RendererApi::SpriteMetadata *const owner;
ZElement(ZElement *next, double z, RendererApi::Color::Transparent color, RendererApi::Sprite<void> *owner) : next{next}, z{z}, color{color}, owner{owner} {} ZElement(ZElement *next, double z, RendererApi::Color::Transparent color, RendererApi::SpriteMetadata *owner) : next{next}, z{z}, color{color}, owner{owner} {}
void link_after(ZElement *new_next) { void link_after(ZElement *new_next) {
new_next->next = this->next; new_next->next = this->next;
@ -112,7 +112,7 @@ namespace BGTU::ComputerGraphicsLabWork {
pixel_trace_metadata *pixels_metadata; pixel_trace_metadata *pixels_metadata;
ZElementAllocationBuffer *pixel_trace_elements_allocator; ZElementAllocationBuffer *pixel_trace_elements_allocator;
RendererApi::Sprite<sprite_data_t> *current_artist; RendererApi::SpriteMetadata *current_artist;
VoxelDrawerImpl(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height, pixel_trace_metadata *pixels_metadata, ZElementAllocationBuffer *pixel_trace_elements_allocator); VoxelDrawerImpl(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height, pixel_trace_metadata *pixels_metadata, ZElementAllocationBuffer *pixel_trace_elements_allocator);
@ -146,7 +146,7 @@ namespace BGTU::ComputerGraphicsLabWork {
void render( void render(
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h,
RendererApi::VoxelDrawer::Exporter<sprite_data_t> *frame, RendererApi::VoxelDrawer::Exporter *frame,
RendererApi::Color bg, RendererApi::Color bg,
RendererApi::Projection const *projection, RendererApi::Projection const *projection,
RendererApi::Sprite<sprite_data_t> *const *sprites, RendererApi::Sprite<sprite_data_t> *const *sprites,
@ -170,7 +170,6 @@ namespace BGTU::ComputerGraphicsLabWork {
current_artist{nullptr} {} current_artist{nullptr} {}
template<class... args_t> template<class... args_t>
DefaultVoxelDrawerCache::ZElement *DefaultVoxelDrawerCache::ZElementAllocationBuffer::alloc_elem(args_t... args) { DefaultVoxelDrawerCache::ZElement *DefaultVoxelDrawerCache::ZElementAllocationBuffer::alloc_elem(args_t... args) {
auto cell = this->next_unallocated; auto cell = this->next_unallocated;
@ -211,13 +210,16 @@ namespace BGTU::ComputerGraphicsLabWork {
void DefaultVoxelDrawerCache::render( void DefaultVoxelDrawerCache::render(
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h,
RendererApi::VoxelDrawer::Exporter<sprite_data_t> *frame, RendererApi::VoxelDrawer::Exporter *frame,
RendererApi::Color bg, RendererApi::Color bg,
RendererApi::Projection const *projection, RendererApi::Projection const *projection,
RendererApi::Sprite<sprite_data_t> *const *sprites, RendererApi::Sprite<sprite_data_t> *const *sprites,
std::size_t sprites_count, std::size_t sprites_count,
sprite_data_t const *sprite_data sprite_data_t const *sprite_data
) { ) {
if (w == 0 || h == 0)
return;
if (this->pixel_metadata_cache.buffer == nullptr || this->pixel_metadata_cache.size < w * h) { if (this->pixel_metadata_cache.buffer == nullptr || this->pixel_metadata_cache.size < w * h) {
this->pixel_metadata_cache.buffer = static_cast<pixel_trace_metadata *>(std::realloc(this->pixel_metadata_cache.buffer, w * h * sizeof(pixel_trace_metadata))); this->pixel_metadata_cache.buffer = static_cast<pixel_trace_metadata *>(std::realloc(this->pixel_metadata_cache.buffer, w * h * sizeof(pixel_trace_metadata)));
this->pixel_metadata_cache.size = w * h; this->pixel_metadata_cache.size = w * h;
@ -254,7 +256,7 @@ namespace BGTU::ComputerGraphicsLabWork {
} }
namespace QtUtilities { namespace QtUtilities {
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)> template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Projection const *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *)>
class SeparateThreadedRenderer; class SeparateThreadedRenderer;