Template argument for painters in sprites for eliminating virtual function resolving

This commit is contained in:
Andrew Golovashevich 2024-12-11 04:10:58 +03:00
parent b171ea84c2
commit 4dfbe50bb3
14 changed files with 190 additions and 127 deletions

View File

@ -4,6 +4,7 @@
#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/utilities/voxel_painter_exporter_to_packed_array.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>
@ -18,7 +19,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{32, 32, 32}};
auto sprites = std::to_array<RendererApi::Sprite<Lab1SpriteData> *const>({
auto sprites = std::to_array<RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *const>({
&pixels_grid_sprite
});

View File

@ -8,21 +8,18 @@
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
class PixelGridSprite : public RendererApi::Sprite<Lab1SpriteData> {
class PixelGridSprite : public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> {
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);
void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override {
long long start_x = data->central_pixel_tl.x - ((data->central_pixel_tl.x + data->pixel_size - 1) / data->pixel_size * data->pixel_size);
long long start_y = data->central_pixel_tl.y - ((data->central_pixel_tl.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 y_flag = ((data->central_pixel_tl.x - start_x) / data->pixel_size + (data->central_pixel_tl.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;

View File

@ -9,6 +9,7 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/matrix.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
@ -31,7 +32,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
using Provider = _Lab1SpriteData_Provider;
};
class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite<Lab1SpriteData>::SpriteDataProvider {
class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider {
Q_OBJECT
private:
QMutex sync;
@ -39,18 +40,22 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
std::size_t pixel_size;
double radians_per_second;
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w, h;
bool show_grid;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
RendererApi::Sprite<Lab1SpriteData::ShapeData> **sub_sprites;
std::size_t sub_sprites_count;
public:
explicit _Lab1SpriteData_Provider(double radians_per_second) : sync{}, time{}, pixel_size{1}, radians_per_second{radians_per_second}, show_grid{false} {}
explicit _Lab1SpriteData_Provider(double radians_per_second) :
sync{}, time{},
pixel_size{1}, radians_per_second{radians_per_second}, show_grid{false},
w{0}, h{0},
sub_sprites{nullptr}, sub_sprites_count{0} {}
Lab1SpriteData get_sprite_data() override {
this->sync.lock();
Lab1SpriteData cached{
.central_pixel_tl = static_cast<RendererApi::PointI<2>>(RendererApi::PointF<2>(this->w, this->h) / 2.0 - RendererApi::PointF<2>(this->pixel_size, this->pixel_size) / 2.0),
.central_pixel_tl = (RendererApi::PointI<2>) (RendererApi::PointF<2>(this->w, this->h) / 2.0 - RendererApi::PointF<2>(this->pixel_size, this->pixel_size) / 2.0),
.pixel_size = this->pixel_size,
.show_grid = this->show_grid,
.shape_data = {
@ -64,6 +69,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
}
public slots:
void set_pixel_size(std::size_t s) {
this->sync.lock();
this->pixel_size = s;
@ -83,7 +89,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
this->sync.unlock();
}
void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t ww, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t hh) {
void set_frame_size(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t ww, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t hh) {
this->sync.lock();
this->w = ww;
this->h = hh;

View File

@ -8,21 +8,30 @@
#include <QThread>
#include <QMutex>
#include <QElapsedTimer>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp>
#include "owned_qimage.hpp"
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t, class renderer_context_t>
using _SeparateThreadedRenderer_RenderProcedureType = void (renderer_context_t::*)(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t, RendererApi::VoxelDrawer::Exporter *, RendererApi::Color, RendererApi::Sprite<sprite_data_t> *const *, std::size_t, sprite_data_t const *);
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t>
using _SeparateThreadedRenderer_RenderProcedureType = void (renderer_context_t::*)(
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t,
Utilities::VoxelPainterExporterToRgb32Array *,
RendererApi::Color,
RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t> *const *,
std::size_t,
sprite_data_t const *
);
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t>>
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t>>
class SeparateThreadedRenderer;
class _SeparateThreadedRenderer_Signals : public QObject {
Q_OBJECT
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t>>
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t>>
friend
class SeparateThreadedRenderer;
@ -35,11 +44,10 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
public slots:
virtual void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) = 0;
virtual void set_frame_size(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t height) = 0;
virtual void set_ms_per_frame(std::uint_fast64_t ms) = 0;
virtual void set_background(RendererApi::Color) = 0;
};
}

View File

@ -8,14 +8,14 @@
#include <QColor>
#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/voxel_drawer.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter {
class OwnedQImage : public QImage, public RendererApi::VirtualVoxelPainter::Exporter {
private:
RendererApi::SpriteMetadata const **owners;
std::uint_least8_t *pixels_buffer;
RendererApi::SpriteMetadata **owners;
unsigned char *pixels_buffer;
bool owns_buffers;
public:
@ -23,8 +23,8 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
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;) {
this->owners = new RendererApi::SpriteMetadata *[width * height];
for (RendererApi::SpriteMetadata **p = this->owners - 1; p-- >= this->owners;) {
*p = nullptr;
}
}
@ -32,17 +32,17 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
OwnedQImage() : QImage(), owners{nullptr}, pixels_buffer{nullptr} {}
OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata const **owners, QImageCleanupFunction destructor, void *destructor_closure) :
OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata **owners, QImageCleanupFunction destructor, void *destructor_closure) :
QImage(data, width, height, f, destructor, destructor_closure), pixels_buffer{data}, owners{owners}, owns_buffers{false} {}
OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata const **owners) :
OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata **owners) :
QImage(data, width, height, f), pixels_buffer{data}, owners{owners}, owns_buffers{false} {}
enum _DelegateBuffers {
DelegateBuffers
};
OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata const **owners, _DelegateBuffers) :
OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata **owners, _DelegateBuffers) :
QImage(data, width, height, f), pixels_buffer{data}, owners{owners}, owns_buffers{true} {}
#if 0
@ -72,7 +72,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
}
#endif
void setPixelOwner(unsigned x, unsigned y, RendererApi::SpriteMetadata const *o) {
void setPixelOwner(unsigned x, unsigned y, RendererApi::SpriteMetadata *o) {
assert(x < this->width());
assert(y < this->height());

View File

@ -9,24 +9,24 @@
#include <QMutex>
#include <QElapsedTimer>
#include <QWaitCondition>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp>
#include "owned_qimage.hpp"
#include "_separate_threaded_renderer.hpp"
#define has_BGTU_ComputerGraphicsLabWork_QtUtilities_SeparateThreadedRenderer
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
class SeparateThreadedRenderer : public _SeparateThreadedRenderer_Signals {
private:
struct data_t {
public:
RendererApi::Sprite<sprite_data_t> *const *sprites;
RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t> *const *sprites;
std::size_t sprites_count;
RendererApi::Sprite<sprite_data_t>::SpriteDataProvider *sprite_data_provider;
RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t>::SpriteDataProvider *sprite_data_provider;
std::uint_fast64_t ms_per_frame;
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, height;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width, height;
RendererApi::Color bg;
};
@ -72,23 +72,25 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
public slots:
void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height) final;
void set_frame_size(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t height) final;
void set_ms_per_frame(std::uint_fast64_t ms) final;
void set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count);
void set_sprites(RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t> *const *sprites, std::size_t sprites_count);
void set_sprite_data_provider(RendererApi::Sprite<sprite_data_t>::SpriteDataProvider *provider);
void set_sprite_data_provider(RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t>::SpriteDataProvider *provider);
void set_background(RendererApi::Color) final;
void shutdown_thread_blocking();
public:
~SeparateThreadedRenderer();
~SeparateThreadedRenderer() override;
};
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner):
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner):
_SeparateThreadedRenderer_Signals{owner},
sync{},
renderer_context{renderer_context},
@ -105,8 +107,8 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
this->thread->start();
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
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) {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::set_frame_size(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t height) {
this->sync.lock();
const_cast<data_t *>(&this->next_data)->width = width;
const_cast<data_t *>(&this->next_data)->height = height;
@ -114,15 +116,15 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
this->sync.unlock();
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) {
this->sync.lock();
const_cast<data_t *>(&this->next_data)->ms_per_frame = ms;
this->sync.unlock();
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count) {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::set_sprites(RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t> *const *sprites, std::size_t sprites_count) {
this->sync.lock();
const_cast<data_t *>(&this->next_data)->sprites = sprites;
const_cast<data_t *>(&this->next_data)->sprites_count = sprites_count;
@ -130,24 +132,24 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
this->sync.unlock();
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprite_data_provider(RendererApi::Sprite<sprite_data_t>::SpriteDataProvider *provider) {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::set_sprite_data_provider(RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t>::SpriteDataProvider *provider) {
this->sync.lock();
const_cast<data_t *>(&this->next_data)->sprite_data_provider = provider;
this->thread->force_redraw();
this->sync.unlock();
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_background(RendererApi::Color c) {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::set_background(RendererApi::Color c) {
this->sync.lock();
const_cast<data_t *>(&this->next_data)->bg = c;
this->thread->force_redraw();
this->sync.unlock();
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::RendererThread::run() {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::RendererThread::run() {
try {
QElapsedTimer timer;
while (!this->isInterruptionRequested()) {
@ -156,27 +158,11 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
data_t cached = *const_cast<data_t *>(&this->owner->next_data);
this->owner->sync.unlock();
struct VoxelDrawerExporterImpl : public RendererApi::VoxelDrawer::Exporter {
public:
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t const w;
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t const h;
std::uint_least8_t *const pixels_argb;;
RendererApi::SpriteMetadata const **const owners;
VoxelDrawerExporterImpl(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h) :
w{w}, h{h},
pixels_argb{new std::uint_least8_t[w * h * 4]},
owners{new RendererApi::SpriteMetadata const *[w * h]} {}
void set_pixel(long long x, long long y, BGTU::ComputerGraphicsLabWork::RendererApi::Color c, BGTU::ComputerGraphicsLabWork::RendererApi::SpriteMetadata *owner) final {
if (x < 0 || this->w <= x) return;
if (y < 0 || this->h <= y) return;
this->pixels_argb[(y * this->w + x) * 4] = c.red;
this->pixels_argb[(y * this->w + x) * 4 + 1] = c.green;
this->pixels_argb[(y * this->w + x) * 4 + 2] = c.blue;
this->owners[y * this->w + x] = owner;
}
} img{cached.width, cached.height};
Utilities::VoxelPainterExporterToRgb32Array img{
cached.width, cached.height,
new unsigned char[cached.width * cached.height * 4],
new RendererApi::SpriteMetadata *[cached.width * cached.height]
};
union {
sprite_data_t data;
@ -197,7 +183,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
cached.sprites, cached.sprites_count,
sprite_data
);
emit this->owner->frame_rendered(new OwnedQImage{img.pixels_argb, img.w, img.h, QImage::Format_RGB32, img.owners, OwnedQImage::DelegateBuffers});
emit this->owner->frame_rendered(new OwnedQImage{img.pixels_packed, img.w, img.h, QImage::Format_RGB32, img.pixel_owners, OwnedQImage::DelegateBuffers});
auto elapsed = timer.elapsed();
qCritical() << elapsed << "ms";
this->sleepms(std::max<std::int_fast64_t>(static_cast<std::int_fast64_t>(cached.ms_per_frame) - elapsed, 0));
@ -207,19 +193,28 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
}
}
template<class sprite_data_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_context_t> renderer_procedure>
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::~SeparateThreadedRenderer() {
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
void SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::shutdown_thread_blocking() {
this->thread->requestInterruption();
this->thread->wait();
}
template<class sprite_data_t, class renderer_voxel_painter_t, class renderer_context_t, _SeparateThreadedRenderer_RenderProcedureType<sprite_data_t, renderer_voxel_painter_t, renderer_context_t> renderer_procedure>
SeparateThreadedRenderer<sprite_data_t, renderer_voxel_painter_t, renderer_context_t, renderer_procedure>::~SeparateThreadedRenderer() {
this->shutdown_thread_blocking();
}
template<class sprite_data_t>
class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t>> {
class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t, Utilities::VoxelPainterExporterToRgb32Array>> {
private:
Utilities::DefaultVoxelDrawerCache context;
public:
explicit SeparateThreadedDefaultRendererLinear(QObject *owner = nullptr) : SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t>>{&this->context, owner}, context{} {};
explicit SeparateThreadedDefaultRendererLinear(QObject *owner = nullptr) :
SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t, Utilities::VoxelPainterExporterToRgb32Array>>{&this->context, owner}, context{} {};
~SeparateThreadedDefaultRendererLinear() {
this->shutdown_thread_blocking();
}
};
}

View File

@ -15,9 +15,9 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
component_compact_t green;
component_compact_t blue;
inline Color() : red{0}, green{0}, blue{0} {}
constexpr Color() : red{0}, green{0}, blue{0} {}
inline Color(component_fast_t red, component_fast_t green, component_fast_t blue) : red{red}, green{green}, blue{blue} {}
constexpr Color(component_fast_t red, component_fast_t green, component_fast_t blue) : red{red}, green{green}, blue{blue} {}
class Transparent {
public:
@ -26,13 +26,13 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
component_compact_t blue;
component_compact_t alpha;
inline Transparent() : red{component_min_value}, green{component_min_value}, blue{component_min_value}, alpha{component_max_value} {}
constexpr Transparent() : red{component_min_value}, green{component_min_value}, blue{component_min_value}, alpha{component_max_value} {}
inline Transparent(component_fast_t red, component_fast_t green, component_fast_t blue) : red{red}, green{green}, blue{blue}, alpha{component_max_value} {}
constexpr Transparent(component_fast_t red, component_fast_t green, component_fast_t blue) : red{red}, green{green}, blue{blue}, alpha{component_max_value} {}
inline Transparent(component_fast_t red, component_fast_t green, component_fast_t blue, component_fast_t alpha) : red{red}, green{green}, blue{blue}, alpha{alpha} {}
constexpr Transparent(component_fast_t red, component_fast_t green, component_fast_t blue, component_fast_t alpha) : red{red}, green{green}, blue{blue}, alpha{alpha} {}
inline Transparent(Color c) : red{c.red}, green{c.green}, blue{c.blue}, alpha{component_max_value} {}
constexpr Transparent(Color c) : red{c.red}, green{c.green}, blue{c.blue}, alpha{component_max_value} {}
};
};
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <type_traits>
namespace BGTU::ComputerGraphicsLabWork::RendererApi {
template<unsigned DIMENSIONS, class _component_t>
@ -16,28 +17,34 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
component_t x;
component_t y;
inline Point(component_t x, component_t y) : x{x}, y{y} {}
constexpr 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)};
}
Point<2, _component_t> operator+(Point<2, _component_t> const &other) const {
[[nodiscard]] constexpr Point<2, _component_t> operator+(Point<2, _component_t> const &other) const noexcept {
return Point<2, _component_t>{this->x + other.x, this->y + other.y};
}
Point<2, _component_t> operator-(Point<2, _component_t> const &other) const {
[[nodiscard]] constexpr Point<2, _component_t> operator-(Point<2, _component_t> const &other) const noexcept {
return Point<2, _component_t>{this->x - other.x, this->y - other.y};
}
Point<2, _component_t> operator*(_component_t const &other) const {
[[nodiscard]] constexpr Point<2, _component_t> operator*(_component_t const &other) const noexcept {
return Point<2, _component_t>{this->x * other, this->y * other};
}
Point<2, _component_t> operator/(_component_t const &other) const {
[[nodiscard]] constexpr Point<2, _component_t> operator/(_component_t const &other) const noexcept {
return Point<2, _component_t>{this->x / other, this->y / other};
}
template<class _self_component_t = _component_t, class sfinae = std::enable_if<std::is_same_v<_self_component_t, long long>, void>::type>
[[nodiscard]] constexpr explicit operator Point<2, double>() const noexcept {
return Point<2, double>{(double) this->x, (double) this->y};
}
template<class _self_component_t = _component_t, class sfinae = std::enable_if<std::is_same_v<_self_component_t, double>, void>::type>
[[nodiscard]] constexpr explicit operator Point<2, long long>() const noexcept {
return Point<2, long long>{(long long) this->x, (long long) this->y};
}
};
template<class _component_t>

View File

@ -1,6 +1,6 @@
#pragma once
#include "voxel_drawer.hpp"
#include "voxel_painter.hpp"
#include "projection.hpp"
namespace BGTU::ComputerGraphicsLabWork::RendererApi {
@ -9,10 +9,10 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
virtual void clicked() {};
};
template<class data_t>
template<class data_t, class voxel_painter_t = VirtualVoxelPainter>
class Sprite : public SpriteMetadata {
public:
virtual void draw(VoxelDrawer *frame, data_t const *data) const = 0;
virtual void draw(voxel_painter_t *frame, data_t const *data) const = 0;
class SpriteDataProvider {
public:

View File

@ -9,7 +9,7 @@
namespace BGTU::ComputerGraphicsLabWork::RendererApi {
class SpriteMetadata;
class VoxelDrawer {
class VirtualVoxelPainter {
public:
using visible_pixel_coordinate_fast_t = std::uint_fast16_t;
using visible_pixel_coordinate_compact_t = std::uint_least16_t;

View File

@ -48,4 +48,13 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
#endif
#endif
}
namespace PackColor {
inline void color_to_rgb32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept{
buffer[offset] = color.red;
buffer[offset + 1] = color.green;
buffer[offset + 2] = color.blue;
}
}
}

View File

@ -8,7 +8,7 @@
#include <algorithm>
#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/voxel_drawer.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include "color.hpp"
#include "matrix.hpp"
@ -106,36 +106,43 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
ZElement *voxels;
};
class VoxelDrawerImpl : public RendererApi::VoxelDrawer {
public:
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _height;
class VoxelPainterImpl : public RendererApi::VirtualVoxelPainter {
friend
class DefaultVoxelDrawerCache;
private:
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t _width;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t _height;
pixel_trace_metadata *pixels_metadata;
ZElementAllocationBuffer *pixel_trace_elements_allocator;
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);
VoxelPainterImpl(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t height, pixel_trace_metadata *pixels_metadata, ZElementAllocationBuffer *pixel_trace_elements_allocator);
[[nodiscard]] inline RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width() const final {
public:
[[nodiscard]] inline RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width() const final {
return this->_width;
}
[[nodiscard]] inline RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height() const final {
[[nodiscard]] inline RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t height() const final {
return this->_height;
}
private:
inline pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
return &(this->pixels_metadata[y * this->_width + x]);
}
public:
void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c) final;
void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c, RendererApi::SpriteMetadata *owner) final;
};
private:
struct {
pixel_trace_metadata *buffer;
std::size_t size;
@ -149,13 +156,13 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
static ZElement *sort_zelements_desc(DefaultVoxelDrawerCache::ZElement *start) noexcept;
public:
template<class sprite_data_t>
template<class sprite_data_t, class voxel_exporter_t = RendererApi::VirtualVoxelPainter::Exporter>
void render(
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h,
RendererApi::VoxelDrawer::Exporter *frame,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t h,
voxel_exporter_t *frame,
RendererApi::Color bg,
RendererApi::Sprite<sprite_data_t> *const *sprites,
RendererApi::Sprite<sprite_data_t, VoxelPainterImpl> *const *sprites,
std::size_t sprites_count,
sprite_data_t const *sprite_data
);
@ -182,13 +189,13 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
}
template<class sprite_data_t>
template<class sprite_data_t, class voxel_exporter_t>
void DefaultVoxelDrawerCache::render(
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h,
RendererApi::VoxelDrawer::Exporter *frame,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t h,
voxel_exporter_t *frame,
RendererApi::Color bg,
RendererApi::Sprite<sprite_data_t> *const *sprites,
RendererApi::Sprite<sprite_data_t, VoxelPainterImpl> *const *sprites,
std::size_t sprites_count,
sprite_data_t const *sprite_data
) {
@ -201,7 +208,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
}
this->pixel_trace_elements_allocator.reset_allocations();
VoxelDrawerImpl painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator};
VoxelPainterImpl painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator};
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
new(&this->pixel_metadata_cache.buffer[i]) pixel_trace_metadata{};

View File

@ -0,0 +1,33 @@
#pragma once
#include <cstdlib>
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
#include "color.hpp"
namespace BGTU::ComputerGraphicsLabWork::Utilities {
template<std::size_t bytes_per_pixel, void (pack_color)(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept>
class VoxelPainterExporterToPackedArray : public RendererApi::VirtualVoxelPainter::Exporter {
public:
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t h;
unsigned char *pixels_packed;
RendererApi::SpriteMetadata **pixel_owners;
constexpr VoxelPainterExporterToPackedArray(
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t h,
unsigned char *pixels_packed,
RendererApi::SpriteMetadata **pixel_owners
) noexcept: w{w}, h{h}, pixels_packed{pixels_packed}, pixel_owners{pixel_owners} {}
constexpr void set_pixel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, RendererApi::Color c, RendererApi::SpriteMetadata *owner) noexcept final {
assert(x < this->w);
assert(y < this->h);
std::size_t offset = y * this->w + x;
this->pixel_owners[offset] = owner;
pack_color(this->pixels_packed, offset * bytes_per_pixel, c);
};
};
using VoxelPainterExporterToRgb32Array = VoxelPainterExporterToPackedArray<4, PackColor::color_to_rgb32>;
}

View File

@ -123,9 +123,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
}
DefaultVoxelDrawerCache::VoxelDrawerImpl::VoxelDrawerImpl(
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width,
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height,
DefaultVoxelDrawerCache::VoxelPainterImpl::VoxelPainterImpl(
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t width,
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t height,
DefaultVoxelDrawerCache::pixel_trace_metadata *pixels_metadata,
DefaultVoxelDrawerCache::ZElementAllocationBuffer *pixel_trace_elements_allocator
) : _width{width},
@ -135,10 +135,10 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
current_artist{nullptr} {}
void DefaultVoxelDrawerCache::VoxelDrawerImpl::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
void DefaultVoxelDrawerCache::VoxelPainterImpl::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
return this->add_voxel(x, y, z, c, this->current_artist);
}
void DefaultVoxelDrawerCache::VoxelDrawerImpl::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c, RendererApi::SpriteMetadata *owner) {
void DefaultVoxelDrawerCache::VoxelPainterImpl::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c, RendererApi::SpriteMetadata *owner) {
if (x < 0 || this->_width <= x) return;
if (y < 0 || this->_height <= y) return;
if (z < 0) return;