Utilities module for Qt, default voxel drawer and minor improvements
This commit is contained in:
parent
cdc8337219
commit
08ced011c6
@ -1,9 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.29)
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
project(cg1)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
add_executable(
|
||||
@ -26,4 +26,5 @@ add_executable(
|
||||
qt5_use_modules(cg1 Widgets)
|
||||
|
||||
add_subdirectory(renderer-api)
|
||||
add_subdirectory(utilities)
|
||||
add_subdirectory(utilities)
|
||||
add_subdirectory(qt-utilities)
|
3
qt-utilities/CMakeLists.txt
Normal file
3
qt-utilities/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_library(qt_utilities OBJECT src/separate_threaded_renderer.cpp)
|
||||
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)
|
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <Qt>
|
||||
#include <QObject>
|
||||
#include <QImage>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_drawer.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||
template<class sprite_data_t>
|
||||
class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter<sprite_data_t> {
|
||||
private:
|
||||
RendererApi::Sprite<sprite_data_t> const *owners;
|
||||
|
||||
public:
|
||||
OwnedQImage(unsigned width, unsigned height) : QImage(width, height, QImage::Format_ARGB32), owners{new RendererApi::Sprite<sprite_data_t> const *[width * height]} {
|
||||
for (RendererApi::Sprite<sprite_data_t> const *&e: this->owners) {
|
||||
e = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void setPixelOwner(unsigned x, unsigned y, RendererApi::Sprite<sprite_data_t> const *o) {
|
||||
assert(x < this->width());
|
||||
assert(y < this->height());
|
||||
|
||||
this->owners[y * this->width() + x] = o;
|
||||
}
|
||||
|
||||
RendererApi::Sprite<sprite_data_t> const *getPixelOwner(unsigned x, unsigned y) const {
|
||||
assert(x < this->width());
|
||||
assert(y < this->height());
|
||||
|
||||
return this->owners[y * this->width() + x];
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Qt>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QMutex>
|
||||
#include "owned_qimage.hpp"
|
||||
#include "separate_threaded_renderer.hpp"
|
||||
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||
template<class sprite_data_t>
|
||||
class RendererWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QMutex sync;
|
||||
OwnedQImage <sprite_data_t> *next_image;
|
||||
OwnedQImage <sprite_data_t> *current_image;
|
||||
SeparateThreadedRenderer
|
||||
};
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include <Qt>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#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/sprite.hpp>
|
||||
#include "owned_qimage.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
class SeparateThreadedRenderer : public QObject {
|
||||
private:
|
||||
struct data {
|
||||
public:
|
||||
RendererApi::Sprite<sprite_data_t> *const *sprites;
|
||||
std::size_t sprites_count;
|
||||
sprite_data_t const *sprite_data;
|
||||
std::uint_fast64_t ms_per_frame;
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, height;
|
||||
RendererApi::Projection *projection;
|
||||
};
|
||||
|
||||
class RendererThread : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
SeparateThreadedRenderer *owner;
|
||||
|
||||
public:
|
||||
explicit inline RendererThread(SeparateThreadedRenderer *owner) : QThread{owner}, owner{owner} {};
|
||||
|
||||
protected:
|
||||
void run() final;
|
||||
};
|
||||
|
||||
|
||||
volatile data next_data;
|
||||
QMutex sync;
|
||||
RendererThread *thread;
|
||||
QImage *sentinel_img;
|
||||
renderer_context_t *renderer_context;
|
||||
public:
|
||||
explicit SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner = nullptr);
|
||||
|
||||
public slots:
|
||||
|
||||
void set_frame_size(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height);
|
||||
|
||||
void set_ms_per_frame(std::uint_fast64_t ms);
|
||||
|
||||
void set_sprites(RendererApi::Sprite<sprite_data_t> *const *sprites, std::size_t sprites_count);
|
||||
|
||||
void set_sprite_data(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);
|
||||
|
||||
signals:
|
||||
|
||||
void frame_rendered(OwnedQImage<sprite_data_t> *img);
|
||||
};
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::SeparateThreadedRenderer(renderer_context_t *renderer_context, QObject *owner):
|
||||
QObject{owner},
|
||||
sync{},
|
||||
renderer_context{renderer_context},
|
||||
sentinel_img{new QImage(0, 0, QImage::Format_ARGB32)},
|
||||
thread{new RendererThread(this)},
|
||||
next_data{
|
||||
.sprites = nullptr,
|
||||
.sprites_count = 0,
|
||||
.sprite_data = nullptr,
|
||||
.ms_per_frame = 1000 / 60,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.projection = nullptr
|
||||
} {
|
||||
}
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
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->next_data.width = width;
|
||||
this->next_data.height = height;
|
||||
this->sync.unlock();
|
||||
}
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_ms_per_frame(std::uint_fast64_t ms) {
|
||||
this->sync.lock();
|
||||
this->next_data.ms_per_frame = ms;
|
||||
this->sync.unlock();
|
||||
}
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
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->next_data.sprites = sprites;
|
||||
this->next_data.sprites_count = sprites_count;
|
||||
this->sync.unlock();
|
||||
}
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::set_sprite_data(sprite_data_t const *data) {
|
||||
this->sync.lock();
|
||||
this->next_data.sprite_data = data;
|
||||
this->sync.unlock();
|
||||
}
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
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) {
|
||||
this->sync.lock();
|
||||
this->next_data.sprites = sprites;
|
||||
this->next_data.sprites_count = sprites_count;
|
||||
this->next_data.sprite_data = data;
|
||||
this->sync.unlock();
|
||||
}
|
||||
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
void SeparateThreadedRenderer<sprite_data_t, renderer_context_t, renderer_procedure>::RendererThread::run() {
|
||||
try {
|
||||
QElapsedTimer timer;
|
||||
while (true) {
|
||||
timer.start();
|
||||
this->owner->sync.lock();
|
||||
data cached = this->owner->next_data;
|
||||
this->owner->sync.unlock();
|
||||
|
||||
auto img = new OwnedQImage<sprite_data_t>(cached.width, cached.height);
|
||||
(this->owner->renderer_context->*renderer_procedure)(img, cached.sprite_data, cached.sprites, cached.sprites_count);
|
||||
emit this->owner->frame_rendered(img);
|
||||
QThread::msleep(std::max(cached.ms_per_frame - timer.elapsed(), 0));
|
||||
}
|
||||
} catch (std::exception const &e) {
|
||||
qCritical() << typeid(e).name() << ": " << e.what() << "\n" << "Renderer thread died" << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
4
qt-utilities/src/separate_threaded_renderer.cpp
Normal file
4
qt-utilities/src/separate_threaded_renderer.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include <bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
@ -7,6 +7,9 @@
|
||||
#include "point.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::RendererApi {
|
||||
template<class>
|
||||
class Sprite;
|
||||
|
||||
class VoxelDrawer {
|
||||
public:
|
||||
using visible_pixel_coordinate_fast_t = std::uint_fast16_t;
|
||||
@ -22,10 +25,15 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
|
||||
|
||||
[[nodiscard]] virtual visible_pixel_coordinate_fast_t height() const = 0;
|
||||
|
||||
virtual void update_pixel(PointI<2>::component_t x, PointI<2>::component_t y, double z, Color::Transparent c) = 0;
|
||||
virtual void add_voxel(PointI<2>::component_t x, PointI<2>::component_t y, double z, Color::Transparent c) = 0;
|
||||
|
||||
inline void update_pixel(PointI<2> p, double z, Color::Transparent c) {
|
||||
return this->update_pixel(p.x, p.y, z, c);
|
||||
inline void add_voxel(PointI<2> p, double z, Color::Transparent c) {
|
||||
return this->add_voxel(p.x, p.y, z, c);
|
||||
}
|
||||
|
||||
template<class sprite_data_t>
|
||||
class Exporter {
|
||||
virtual void set_pixel(PointI<2>::component_t x, PointI<2>::component_t y, Color c, Sprite<sprite_data_t> const* owner) = 0;
|
||||
};
|
||||
};
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
add_library(utilities OBJECT src/shader.cpp)
|
||||
add_library(utilities OBJECT src/shader.cpp src/memory_pages_managment.cpp)
|
||||
target_include_directories(utilities PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_link_libraries(utilities PUBLIC renderer_api)
|
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <climits>
|
||||
// #include <emmintrin.h>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
#if 1
|
||||
static auto calc = [&](RendererApi::Color::component_fast_t s, RendererApi::Color::component_fast_t o) {
|
||||
auto oo = static_cast<std::uint_fast16_t>(o) * static_cast<std::uint_fast16_t>(fg.alpha);
|
||||
auto ss = static_cast<std::uint_fast16_t>(s) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha));
|
||||
return static_cast<std::uint_fast8_t >((oo + ss) / 256);
|
||||
};
|
||||
return RendererApi::Color{
|
||||
calc(bg.red, fg.red),
|
||||
calc(bg.green, fg.green),
|
||||
calc(bg.blue, fg.blue)
|
||||
};
|
||||
#else
|
||||
static __m128i vec_256 = _mm_set_epi16(256, 256, 256, 0, 0, 0, 0, 0);
|
||||
__m128i vec_bg = _mm_set_epi16(bg.red, bg.green, bg.blue, 0, 0, 0, 0, 0);
|
||||
__m128i vec_fg = _mm_set_epi16(fg.red, fg.green, fg.blue, 0, 0, 0, 0, 0);
|
||||
__m128i vec_alpha = _mm_set_epi16(fg.alpha, fg.alpha, fg.alpha, 0, 0, 0, 0, 0);
|
||||
|
||||
union {
|
||||
std::uint_fast64_t packed = static_cast<std::uint_fast64_t>(_mm_cvtsi128_si64(_mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(vec_fg, vec_alpha), _mm_mullo_epi16(vec_bg, _mm_sub_epi16(vec_256, vec_alpha))), 8)));
|
||||
std::uint16_t unpacked[3];
|
||||
} raw;
|
||||
return RendererApi::Color{
|
||||
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[0]),
|
||||
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[1]),
|
||||
static_cast<RendererApi::Color::component_compact_t>(raw.unpacked[2])
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
@ -0,0 +1,300 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
#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/sprite.hpp>
|
||||
#include "color.hpp"
|
||||
#include "matrix.hpp"
|
||||
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork {
|
||||
namespace Utilities {
|
||||
class DefaultVoxelDrawerLinear : public RendererApi::VoxelDrawer {
|
||||
private:
|
||||
class ZElement {
|
||||
public:
|
||||
ZElement *next;
|
||||
double const z;
|
||||
RendererApi::Color::Transparent const color;
|
||||
RendererApi::Sprite<void> *const owner;
|
||||
|
||||
ZElement(ZElement *next, double z, RendererApi::Color::Transparent color, RendererApi::Sprite<void> *owner) : next{next}, z{z}, color{color}, owner{owner} {}
|
||||
|
||||
void link_after(ZElement *new_next) {
|
||||
new_next->next = this->next;
|
||||
this->next = new_next;
|
||||
}
|
||||
};
|
||||
|
||||
class ZElementAllocationBuffer {
|
||||
private:
|
||||
union Cell {
|
||||
ZElement allocated;
|
||||
struct Empty {
|
||||
Cell *next_empty;
|
||||
} empty;
|
||||
};
|
||||
|
||||
|
||||
class Page {
|
||||
public:
|
||||
Page *next;
|
||||
private:
|
||||
|
||||
std::size_t initialized;
|
||||
std::size_t capacity;
|
||||
|
||||
Cell buffer[0];
|
||||
|
||||
public:
|
||||
explicit Page(Page *next, std::size_t capacity) : next{next}, initialized{0}, capacity{capacity} {};
|
||||
|
||||
Cell *try_allocate();
|
||||
|
||||
static std::size_t calc_capacity(std::size_t bytes) {
|
||||
return (bytes - offsetof(Page, buffer)) / sizeof(Cell);
|
||||
};
|
||||
|
||||
void reset_allocations() {
|
||||
this->initialized = 0;
|
||||
}
|
||||
};
|
||||
|
||||
Cell *next_unallocated;
|
||||
Page *last_page;
|
||||
Page sentinel;
|
||||
|
||||
public:
|
||||
ZElementAllocationBuffer() : next_unallocated{nullptr}, sentinel{nullptr, 0}, last_page{&this->sentinel} {};
|
||||
|
||||
private:
|
||||
Page *_native_extend();
|
||||
|
||||
public:
|
||||
template<class ...args_t>
|
||||
ZElement *alloc_elem(args_t...args);
|
||||
|
||||
void free_elem(ZElement *e);
|
||||
|
||||
private:
|
||||
void _native_free_page(Page *p);
|
||||
|
||||
public:
|
||||
void release_resources();
|
||||
|
||||
void reset_allocations();
|
||||
|
||||
~ZElementAllocationBuffer();
|
||||
};
|
||||
|
||||
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _height;
|
||||
|
||||
struct pixel_trace_metadata {
|
||||
public:
|
||||
pixel_trace_metadata() : nearest_z{std::numeric_limits<double>::max()}, voxels{nullptr} {};
|
||||
|
||||
double nearest_z;
|
||||
ZElement *voxels;
|
||||
} *pixels_metadata;
|
||||
|
||||
ZElementAllocationBuffer allocator;
|
||||
RendererApi::Sprite<void> *current_artist;
|
||||
public:
|
||||
inline DefaultVoxelDrawerLinear(std::uint_fast16_t width, std::uint_fast16_t height);
|
||||
|
||||
~DefaultVoxelDrawerLinear();
|
||||
|
||||
template<class data_t>
|
||||
void set_current_artist(RendererApi::Sprite<data_t> *sprite) {
|
||||
this->current_artist = reinterpret_cast<RendererApi::Sprite<void> *>(sprite);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::uint_fast16_t height() const final {
|
||||
return this->_height;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline std::uint_fast16_t width() const final {
|
||||
return this->_width;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
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(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) final;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
template<class sdata_t>
|
||||
void export_(RendererApi::Color background, RendererApi::VoxelDrawer::Exporter<sdata_t> *receiver);
|
||||
|
||||
void release_resources();
|
||||
};
|
||||
|
||||
DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Cell *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page::try_allocate() {
|
||||
if (this->initialized < this->capacity) {
|
||||
Cell *cell = &(this->buffer[this->initialized++]);
|
||||
return cell;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<class... args_t>
|
||||
DefaultVoxelDrawerLinear::ZElement *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::alloc_elem(args_t... args) {
|
||||
auto cell = this->next_unallocated;
|
||||
if (cell != nullptr) {
|
||||
this->next_unallocated = cell->empty.next_empty;
|
||||
return &(cell->allocated);
|
||||
}
|
||||
|
||||
while ((cell = this->last_page->try_allocate()) == nullptr)
|
||||
this->_native_extend();
|
||||
|
||||
return new(&(cell->allocated)) ZElement{args...};
|
||||
}
|
||||
|
||||
|
||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::free_elem(DefaultVoxelDrawerLinear::ZElement *e) {
|
||||
Cell *cell = reinterpret_cast<Cell *>(e);
|
||||
cell->empty.next_empty = this->next_unallocated;
|
||||
this->next_unallocated = cell;
|
||||
}
|
||||
|
||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::release_resources() {
|
||||
Page *p;
|
||||
while (this->last_page != nullptr) {
|
||||
p = this->last_page;
|
||||
this->last_page = p->next;
|
||||
this->_native_free_page(p);
|
||||
}
|
||||
this->next_unallocated = nullptr;
|
||||
}
|
||||
|
||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::reset_allocations() {
|
||||
Page *p = this->last_page;
|
||||
while (p != nullptr) {
|
||||
p->reset_allocations();
|
||||
p = p->next;
|
||||
}
|
||||
this->next_unallocated = nullptr;
|
||||
}
|
||||
|
||||
DefaultVoxelDrawerLinear::ZElementAllocationBuffer::~ZElementAllocationBuffer() {
|
||||
this->release_resources();
|
||||
}
|
||||
|
||||
|
||||
DefaultVoxelDrawerLinear::DefaultVoxelDrawerLinear(std::uint_fast16_t width, std::uint_fast16_t height) :
|
||||
_width{width},
|
||||
_height{height},
|
||||
pixels_metadata{new pixel_trace_metadata[sizeof(ZElement) * width * height]{}},
|
||||
allocator{},
|
||||
current_artist{nullptr} {}
|
||||
|
||||
DefaultVoxelDrawerLinear::~DefaultVoxelDrawerLinear() {
|
||||
delete[] this->pixels_metadata;
|
||||
}
|
||||
|
||||
void DefaultVoxelDrawerLinear::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
|
||||
if (x < 0 || this->_width <= x) return;
|
||||
if (y < 0 || this->_height <= y) return;
|
||||
if (z < 0) return;
|
||||
auto p = this->at(x, y);
|
||||
if (z <= p->nearest_z) {
|
||||
p->nearest_z = z;
|
||||
#if 1
|
||||
if (c.alpha == 255) {
|
||||
ZElement *e;
|
||||
while (p->voxels != nullptr) {
|
||||
e = p->voxels;
|
||||
p->voxels = e->next;
|
||||
this->allocator.free_elem(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p->voxels = this->allocator.alloc_elem(p->voxels, z, c, this->current_artist);
|
||||
}
|
||||
|
||||
void DefaultVoxelDrawerLinear::release_resources() {
|
||||
this->allocator.release_resources();
|
||||
}
|
||||
|
||||
template<class sdata_t>
|
||||
void DefaultVoxelDrawerLinear::export_(RendererApi::Color background, RendererApi::VoxelDrawer::Exporter<sdata_t> *receiver) {
|
||||
std::vector<ZElement *> sorter;
|
||||
std::uint_fast16_t y = 0;
|
||||
std::uint_fast16_t x = 0;
|
||||
|
||||
for (std::int_fast64_t i = this->_width * this->_height - 1; i >= 0; i--) {
|
||||
for (ZElement *e = this->pixels_metadata[i].voxels; e != nullptr; e = e->next) {
|
||||
sorter.push_back(e);
|
||||
}
|
||||
std::sort(sorter.rbegin(), sorter.rend(), [](ZElement *l, ZElement *r) { return l->z < r->z; });
|
||||
RendererApi::Color p = background;
|
||||
for (auto a: sorter) {
|
||||
p = apply_transparent_color(p, a->color);
|
||||
}
|
||||
receiver->export_pixel(x, y, p, sorter[sorter.size() - 1]->owner);
|
||||
if (++x >= this->_width) {
|
||||
y++;
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace QtUtilities {
|
||||
template<class sprite_data_t, class renderer_context_t, void (renderer_context_t::*renderer_procedure)(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t)>
|
||||
class SeparateThreadedRenderer;
|
||||
|
||||
#if 0
|
||||
template<class sprite_data_t, bool _private_param>
|
||||
class _SeparateThreadedDefaultRendererLinear {
|
||||
};
|
||||
|
||||
template<class sprite_data_t>
|
||||
class _SeparateThreadedDefaultRendererLinear<sprite_data_t, false> {
|
||||
template<class, bool>
|
||||
friend
|
||||
class _SeparateThreadedDefaultRendererLinear;
|
||||
|
||||
|
||||
private:
|
||||
_SeparateThreadedDefaultRendererLinear() = delete;
|
||||
|
||||
class Context : public Utilities::DefaultVoxelDrawerLinear<sprite_data_t> {
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
class _SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, SeparateThreadedDefaultRendererLinear < sprite_data_t>, &SeparateThreadedDefaultRendererLinear<sprite_data_t>::render
|
||||
|
||||
> {
|
||||
public:
|
||||
|
||||
void render(RendererApi::VoxelDrawer::Exporter<sprite_data_t> *, sprite_data_t *, RendererApi::Sprite<sprite_data_t> *const *, std::size_t) {
|
||||
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
@ -17,11 +17,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
elem_t e20, elem_t e21, elem_t e22
|
||||
) : data{e00, e01, e02, e10, e11, e12, e20, e21, e22} {}
|
||||
|
||||
static inline const Matrix3<elem_t> I{1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1};
|
||||
static const Matrix3<elem_t> I;
|
||||
private:
|
||||
static inline const Matrix3<elem_t> _tmp{};
|
||||
static const Matrix3<elem_t> _tmp;
|
||||
|
||||
|
||||
template<class operator_t>
|
||||
@ -143,17 +141,14 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
elem_t e30, elem_t e31, elem_t e32, elem_t e33
|
||||
) : data{e00, e01, e02, e03, e10, e11, e12, e13, e20, e21, e22, e23, e30, e31, e32, e33} {}
|
||||
|
||||
static inline const Matrix4<elem_t> I{1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1};
|
||||
static const Matrix4<elem_t> I;
|
||||
|
||||
private:
|
||||
static inline const Matrix4<elem_t> _tmp{};
|
||||
static const Matrix4<elem_t> _tmp;
|
||||
|
||||
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]);
|
||||
@ -216,10 +211,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};
|
||||
}
|
||||
|
||||
|
||||
@ -266,6 +261,24 @@ 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};
|
||||
|
||||
template<class elem_t>
|
||||
const Matrix3<elem_t> Matrix3<elem_t>::_tmp{};
|
||||
|
||||
template<class elem_t>
|
||||
const Matrix4<elem_t> Matrix4<elem_t>::I{1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1};
|
||||
|
||||
template<class elem_t>
|
||||
const Matrix4<elem_t> Matrix4<elem_t>::_tmp{};
|
||||
|
||||
using Matrix4i = Matrix4<int>;
|
||||
using Matrix4l = Matrix4<long>;
|
||||
using Matrix4f = Matrix4<float>;
|
||||
|
29
utilities/src/memory_pages_managment.cpp
Normal file
29
utilities/src/memory_pages_managment.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
#include <Windows.h>
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page *DefaultVoxelDrawerLinear::ZElementAllocationBuffer::_native_extend() {
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
|
||||
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{};
|
||||
return this->last_page = new(raw)Page(this->last_page, Page::calc_capacity(size));
|
||||
}
|
||||
|
||||
|
||||
void DefaultVoxelDrawerLinear::ZElementAllocationBuffer::_native_free_page(DefaultVoxelDrawerLinear::ZElementAllocationBuffer::Page *p) {
|
||||
VirtualFree(p, 0, MEM_DECOMMIT | MEM_RELEASE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# error ""
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user