Support for different lab-works and other improvements in shapes

This commit is contained in:
Andrew Golovashevich 2024-12-22 19:47:04 +03:00
parent f5f3ccee34
commit 92f95588e0
32 changed files with 1077 additions and 539 deletions

View File

@ -38,4 +38,4 @@ qt5_use_modules(cg1 Widgets)
add_subdirectory(renderer-api) add_subdirectory(renderer-api)
add_subdirectory(utilities) add_subdirectory(utilities)
add_subdirectory(qt-utilities) add_subdirectory(qt-utilities)
add_subdirectory(programs/lab1) add_subdirectory(programs/labs1_5)

View File

@ -1,18 +0,0 @@
add_executable(
lab1
src/main.cpp
src/sprite_data.hpp
src/keyboard_catcher_widget.hpp
src/variants.hpp
src/variants/variant1.cpp
src/variants/variant2.cpp
src/variants/variant3.cpp
src/variants/variant4.cpp
src/variants/variant5.cpp
src/variants/variant6.cpp
src/variants/variant8.cpp
src/variants/variant9.cpp
)
target_link_libraries(lab1 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities)

View File

@ -1,186 +0,0 @@
#pragma once
#include <array>
#include <tuple>
#include <QObject>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp>
#include "sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
struct variant_sprites {
private :
using sprite_t = RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>>;
public:
sprite_t *const *const sprites;
std::size_t const count;
constexpr variant_sprites(sprite_t **_sprites, std::size_t _count) : sprites{_sprites}, count{_count} {
}
private:
template<class ...sprites_t>
struct _make {
};
template<>
struct _make<> {
public:
constexpr _make() {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
}
};
template<class e0>
struct _make<e0> {
public:
e0 value;
constexpr _make(e0 v) : value{std::move(v)} {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
dst[pos] = &this->value;
}
};
template<class e0, class ...en>
struct _make<e0, en...> {
public:
e0 value;
_make<en...> next;
constexpr _make(e0 v, en...nv) : value{std::move(v)}, next{nv...} {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
dst[pos] = &this->value;
this->next.export_pointers(dst, pos + 1);
}
};
public:
template<class ...sprites_t>
constexpr static variant_sprites make(sprites_t...sprites) {
static _make<sprites_t...> i{sprites...};
static sprite_t *p[sizeof...(sprites)];
i.export_pointers(p, 0);
return variant_sprites{p, sizeof...(sprites)};
}
private:
template<void (...sprites)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
Lab1SpriteData::ShapeData const *data)>
struct _make_light : public RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> {
};
template<>
struct _make_light<> {
public:
constexpr _make_light() {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
}
};
template<void (s0)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
Lab1SpriteData::ShapeData const *data),
void (...sn)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
Lab1SpriteData::ShapeData const *data)>
struct _make_light<s0, sn...> : public RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> {
public:
_make_light<sn...> next;
constexpr _make_light() : next{} {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
dst[pos] = this;
this->next.export_pointers(dst, pos + 1);
}
void draw(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, const Lab1::Lab1SpriteData::ShapeData *data) const final {
s0(frame, data);
}
void clicked() final {}
};
public:
template<void (...sprites)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
Lab1SpriteData::ShapeData const *data)>
constexpr static variant_sprites make_light() {
static _make_light<sprites...> i{};
static sprite_t *p[sizeof...(sprites)];
i.export_pointers(p, 0);
return variant_sprites{p, sizeof...(sprites)};
}
};
extern variant_sprites variant1;
extern variant_sprites variant2;
extern variant_sprites variant3;
extern variant_sprites variant4;
extern variant_sprites variant5;
extern variant_sprites variant6;
extern variant_sprites variant8;
extern variant_sprites variant9;
class VariantsManager : public QObject {
Q_OBJECT
signals:
void set_sprites(
RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sprites,
std::size_t count
);
private:
inline void _set_sprites(variant_sprites sprites) {
emit this->set_sprites(sprites.sprites, sprites.count);
}
public slots:
inline void set_variant_1() {
this->_set_sprites(variant1);
};
inline void set_variant_2() {
this->_set_sprites(variant2);
};
inline void set_variant_3() {
this->_set_sprites(variant3);
};
inline void set_variant_4() {
this->_set_sprites(variant4);
};
inline void set_variant_5() {
this->_set_sprites(variant5);
};
inline void set_variant_6() {
this->_set_sprites(variant6);
};
inline void set_variant_8() {
this->_set_sprites(variant8);
};
inline void set_variant_9() {
this->_set_sprites(variant9);
};
};
}

View File

@ -0,0 +1,18 @@
add_executable(
labs
src/main.cpp
src/variants/sprite_data.hpp
src/keyboard_catcher_widget.hpp
src/variants/variants.hpp
src/variants/lab1/variant1.cpp
src/variants/lab1/variant2.cpp
src/variants/lab1/variant3.cpp
src/variants/lab1/variant4.cpp
src/variants/lab1/variant5.cpp
src/variants/lab1/variant6.cpp
src/variants/lab1/variant8.cpp
src/variants/lab1/variant9.cpp
)
target_link_libraries(labs PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities)

View File

@ -4,7 +4,7 @@
#include <QWidget> #include <QWidget>
#include <QKeyEvent> #include <QKeyEvent>
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl {
class KeyboardCatcherWidget : public QWidget { class KeyboardCatcherWidget : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
@ -40,6 +40,30 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
void key_pressed_0(); void key_pressed_0();
void key_pressed_F1();
void key_pressed_F2();
void key_pressed_F3();
void key_pressed_F4();
void key_pressed_F5();
void key_pressed_F6();
void key_pressed_F7();
void key_pressed_F8();
void key_pressed_F9();
void key_pressed_F10();
void key_pressed_F11();
void key_pressed_F12();
protected: protected:
void keyPressEvent(QKeyEvent *event) override { void keyPressEvent(QKeyEvent *event) override {
switch (event->key()) { switch (event->key()) {
@ -82,6 +106,42 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
case Qt::Key_0: case Qt::Key_0:
emit this->key_pressed_0(); emit this->key_pressed_0();
return; return;
case Qt::Key_F1:
emit this->key_pressed_F1();
return;
case Qt::Key_F2:
emit this->key_pressed_F2();
return;
case Qt::Key_F3:
emit this->key_pressed_F3();
return;
case Qt::Key_F4:
emit this->key_pressed_F4();
return;
case Qt::Key_F5:
emit this->key_pressed_F5();
return;
case Qt::Key_F6:
emit this->key_pressed_F6();
return;
case Qt::Key_F7:
emit this->key_pressed_F7();
return;
case Qt::Key_F8:
emit this->key_pressed_F8();
return;
case Qt::Key_F9:
emit this->key_pressed_F9();
return;
case Qt::Key_F10:
emit this->key_pressed_F10();
return;
case Qt::Key_F11:
emit this->key_pressed_F11();
return;
case Qt::Key_F12:
emit this->key_pressed_F12();
return;
} }
} }

View File

@ -9,13 +9,13 @@
#include <bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.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/renderer_widget.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp> #include <bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp>
#include "sprite_data.hpp" #include "variants/sprite_data.hpp"
#include "keyboard_catcher_widget.hpp" #include "keyboard_catcher_widget.hpp"
#include "pixel_grid_sprite.hpp" #include "pixel_grid_sprite.hpp"
#include "variants.hpp" #include "variants/variants.hpp"
#include "zoomed_scene_sprite.hpp" #include "zoomed_scene_sprite.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl {
volatile RendererApi::Color bg{0, 0, 0}; volatile RendererApi::Color bg{0, 0, 0};
RendererApi::Color::Transparent fg{255, 255, 255, 127}; RendererApi::Color::Transparent fg{255, 255, 255, 127};
@ -24,45 +24,45 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
#if 1 #if 1
QApplication qApplication{argc, argv}; QApplication qApplication{argc, argv};
PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{16, 16, 16}}; PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{16, 16, 16}};
ZoomedSceneSprite zoomed_scene_sprite{}; ZoomedSceneSprite zoomed_scene_sprite{};
auto sprites = std::to_array<RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *const>({ auto sprites = std::to_array<RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *const>({
&pixels_grid_sprite, &pixels_grid_sprite,
&zoomed_scene_sprite &zoomed_scene_sprite
}); });
Lab1SpriteData::Provider sprites_data{0.1}; SpriteData::Provider sprites_data{0.1};
sprites_data.set_pixel_size(16); sprites_data.set_pixel_size(16);
sprites_data.set_sub_sprites(variant3.sprites, variant3.count);
VariantsManager vmngr{};
QObject::connect(&vmngr, &VariantsManager::set_sprites, &sprites_data, &Lab1SpriteData::Provider::set_sub_sprites); Variants::VariantsManager vmngr{};
QObject::connect(&vmngr, &Variants::VariantsManager::set_sprites, &sprites_data, &SpriteData::Provider::set_sub_sprites);
vmngr.set_lab_1();
QMainWindow w{}; QMainWindow w{};
KeyboardCatcherWidget kbd{&w}; KeyboardCatcherWidget kbd{&w};
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data, &Lab1SpriteData::Provider::decrease_pixel_size); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data, &SpriteData::Provider::decrease_pixel_size);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data, &Lab1SpriteData::Provider::increase_pixel_size); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data, &SpriteData::Provider::increase_pixel_size);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_G, &sprites_data, &Lab1SpriteData::Provider::invert_show_grid); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_G, &sprites_data, &SpriteData::Provider::invert_show_grid);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_1, &vmngr, &VariantsManager::set_variant_1); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_1, &vmngr, &Variants::VariantsManager::set_variant_1);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_2, &vmngr, &VariantsManager::set_variant_2); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_2, &vmngr, &Variants::VariantsManager::set_variant_2);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_3, &vmngr, &VariantsManager::set_variant_3); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_3, &vmngr, &Variants::VariantsManager::set_variant_3);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_4, &vmngr, &VariantsManager::set_variant_4); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_4, &vmngr, &Variants::VariantsManager::set_variant_4);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_5, &vmngr, &VariantsManager::set_variant_5); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_5, &vmngr, &Variants::VariantsManager::set_variant_5);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_6, &vmngr, &VariantsManager::set_variant_6); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_6, &vmngr, &Variants::VariantsManager::set_variant_6);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_8, &vmngr, &VariantsManager::set_variant_8); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_8, &vmngr, &Variants::VariantsManager::set_variant_8);
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_9, &vmngr, &VariantsManager::set_variant_9); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_9, &vmngr, &Variants::VariantsManager::set_variant_9);
QtUtilities::SeparateThreadedDefaultRendererLinear<Lab1SpriteData> renderer{}; QtUtilities::SeparateThreadedDefaultRendererLinear<SpriteData> renderer{};
renderer.set_sprite_data_provider(&sprites_data); renderer.set_sprite_data_provider(&sprites_data);
renderer.set_sprites(sprites.data(), sprites.size()); renderer.set_sprites(sprites.data(), sprites.size());
renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0});
QtUtilities::RendererWidget<Lab1SpriteData> canvas{&renderer, &kbd}; QtUtilities::RendererWidget<SpriteData> canvas{&renderer, &kbd};
QObject::connect(&canvas, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data, &Lab1SpriteData::Provider::set_frame_size); QObject::connect(&canvas, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data, &SpriteData::Provider::set_frame_size);
w.setCentralWidget(&canvas); w.setCentralWidget(&canvas);
w.show(); w.show();
@ -83,5 +83,5 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
int main(int argc, char **argv) { int main(int argc, char **argv) {
return BGTU::ComputerGraphicsLabWork::Lab1::main(argc, argv); return BGTU::ComputerGraphicsLabWork::Impl::main(argc, argv);
} }

View File

@ -5,17 +5,17 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp> #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/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shapes/rectangle.hpp> #include <bgtu/computer_graphics_lab_work/utilities/shapes/rectangle.hpp>
#include "sprite_data.hpp" #include "variants/sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl {
class PixelGridSprite : public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> { class PixelGridSprite : public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> {
private: private:
RendererApi::Color bg, fg; RendererApi::Color bg, fg;
public: public:
PixelGridSprite(RendererApi::Color bg, RendererApi::Color fg) : bg{bg}, fg{fg} {}; PixelGridSprite(RendererApi::Color bg, RendererApi::Color fg) : bg{bg}, fg{fg} {};
void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override { void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const SpriteData *data) const override {
if (!data->show_grid) if (!data->show_grid)
return; return;

View File

@ -7,9 +7,9 @@
#include <bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp> #include <bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp>
#include "../sprite_data.hpp" #include "../sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
template<double z, RendererApi::Color::Transparent c, double radius_multiplier> template<double z, RendererApi::Color::Transparent c, double radius_multiplier>
void static_centered_circle_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { void static_centered_circle_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
Utilities::Shapes::draw_circle_edge(frame, {0, 0}, data->radius * radius_multiplier, z, c); Utilities::Shapes::draw_circle_edge(frame, {0, 0}, data->radius * radius_multiplier, z, c);
} }
@ -23,11 +23,11 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
static void apply_radius(RendererApi::PointI<2> *dst, std::size_t i, RendererApi::PointI<2>::component_t radius) {} static void apply_radius(RendererApi::PointI<2> *dst, std::size_t i, RendererApi::PointI<2>::component_t radius) {}
static void as_radius_and_angle_pos(RendererApi::PointI<2> *dst, std::size_t i, Lab1SpriteData::ShapeData const *data) {} static void as_radius_and_angle_pos(RendererApi::PointI<2> *dst, std::size_t i, SpriteData::ShapeData const *data) {}
static void as_radius_and_angle_neg(RendererApi::PointI<2> *dst, std::size_t i, Lab1SpriteData::ShapeData const *data) {} static void as_radius_and_angle_neg(RendererApi::PointI<2> *dst, std::size_t i, SpriteData::ShapeData const *data) {}
static void as_radius_and_angle_static(RendererApi::PointI<2> *dst, std::size_t i, Lab1SpriteData::ShapeData const *data) {} static void as_radius_and_angle_static(RendererApi::PointI<2> *dst, std::size_t i, SpriteData::ShapeData const *data) {}
}; };
template<RendererApi::PointF<2> p0, RendererApi::PointF<2>... pn> template<RendererApi::PointF<2> p0, RendererApi::PointF<2>... pn>
@ -38,24 +38,24 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
_iter_points<pn...>::apply_radius(dst, i + 1, radius); _iter_points<pn...>::apply_radius(dst, i + 1, radius);
} }
static void as_radius_and_angle_pos(RendererApi::PointI<2> *dst, std::size_t i, Lab1SpriteData::ShapeData const *data) { static void as_radius_and_angle_pos(RendererApi::PointI<2> *dst, std::size_t i, SpriteData::ShapeData const *data) {
dst[i] = data->pos_rotated(data->radius * p0.x, p0.y); dst[i] = data->pos_rotated(data->radius * p0.x, p0.y);
_iter_points<pn...>::as_radius_and_angle_pos(dst, i + 1, data); _iter_points<pn...>::as_radius_and_angle_pos(dst, i + 1, data);
} }
static void as_radius_and_angle_neg(RendererApi::PointI<2> *dst, std::size_t i, Lab1SpriteData::ShapeData const *data) { static void as_radius_and_angle_neg(RendererApi::PointI<2> *dst, std::size_t i, SpriteData::ShapeData const *data) {
dst[i] = data->neg_rotated(data->radius * p0.x, p0.y); dst[i] = data->neg_rotated(data->radius * p0.x, p0.y);
_iter_points<pn...>::as_radius_and_angle_neg(dst, i + 1, data); _iter_points<pn...>::as_radius_and_angle_neg(dst, i + 1, data);
} }
static void as_radius_and_angle_static(RendererApi::PointI<2> *dst, std::size_t i, Lab1SpriteData::ShapeData const *data) { static void as_radius_and_angle_static(RendererApi::PointI<2> *dst, std::size_t i, SpriteData::ShapeData const *data) {
dst[i] = data->static_rotated(data->radius * p0.x, p0.y); dst[i] = data->static_rotated(data->radius * p0.x, p0.y);
_iter_points<pn...>::as_radius_and_angle_static(dst, i + 1, data); _iter_points<pn...>::as_radius_and_angle_static(dst, i + 1, data);
} }
}; };
template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m> template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m>
void static_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { void static_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
union { union {
RendererApi::PointI<2> array[sizeof...(points_m)]; RendererApi::PointI<2> array[sizeof...(points_m)];
bool nothing; bool nothing;
@ -65,7 +65,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
} }
template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m> template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m>
void pos_rotated_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { void pos_rotated_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
union { union {
RendererApi::PointI<2> array[sizeof...(points_m)]; RendererApi::PointI<2> array[sizeof...(points_m)];
bool nothing; bool nothing;
@ -75,7 +75,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
} }
template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m> template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m>
void neg_rotated_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { void neg_rotated_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
union { union {
RendererApi::PointI<2> array[sizeof...(points_m)]; RendererApi::PointI<2> array[sizeof...(points_m)];
bool nothing; bool nothing;
@ -85,7 +85,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
} }
template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m> template<double z, RendererApi::Color::Transparent c, RendererApi::PointF<2>... points_m>
void static_rotated_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { void static_rotated_polygon_edge(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
union { union {
RendererApi::PointI<2> array[sizeof...(points_m)]; RendererApi::PointI<2> array[sizeof...(points_m)];
bool nothing; bool nothing;

View File

@ -1,7 +1,7 @@
#include "../variants.hpp" #include "../variants.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
variant_sprites variant1 = variant_sprites::make_light< variant_sprites variant1 = variant_sprites::make_light<
static_centered_circle_edge<5.0, {0, 127, 255}, 1.0>, static_centered_circle_edge<5.0, {0, 127, 255}, 1.0>,
static_rotated_polygon_edge<4.0, {0, 255, 255}, {1, 0}, {1, 90}, {1, 180}, {1, 270}>, static_rotated_polygon_edge<4.0, {0, 255, 255}, {1, 0}, {1, 90}, {1, 180}, {1, 270}>,

View File

@ -1,7 +1,7 @@
#include "../variants.hpp" #include "../variants.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
variant_sprites variant2 = variant_sprites::make_light< variant_sprites variant2 = variant_sprites::make_light<
static_centered_circle_edge<5.0, {127, 127, 127}, 1.0>, static_centered_circle_edge<5.0, {127, 127, 127}, 1.0>,
static_rotated_polygon_edge<4.0, {127, 127, 127}, {1, 90}, {1, 90-120}, {1, 90+120}>, static_rotated_polygon_edge<4.0, {127, 127, 127}, {1, 90}, {1, 90-120}, {1, 90+120}>,

View File

@ -1,11 +1,11 @@
#include <bgtu/computer_graphics_lab_work/utilities/shapes/circle.hpp> #include "bgtu/computer_graphics_lab_work/utilities/shapes/circle.hpp"
#include "../variants.hpp" #include "../variants.hpp"
#include "../sprite_data.hpp" #include "../sprite_data.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
template<double z, RendererApi::Color::Transparent c, double center_distance_multiplier, double center_angle_degrees, double radius_multiplier> template<double z, RendererApi::Color::Transparent c, double center_distance_multiplier, double center_angle_degrees, double radius_multiplier>
static void _variant3_circle(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { static void _variant3_circle(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
Utilities::Shapes::draw_circle_edge(frame, data->pos_rotated(data->radius * center_distance_multiplier, center_angle_degrees), data->radius * radius_multiplier, z, c); Utilities::Shapes::draw_circle_edge(frame, data->pos_rotated(data->radius * center_distance_multiplier, center_angle_degrees), data->radius * radius_multiplier, z, c);
} }

View File

@ -1,7 +1,7 @@
#include "../variants.hpp" #include "../variants.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
variant_sprites variant4 = variant_sprites::make_light< variant_sprites variant4 = variant_sprites::make_light<
static_centered_circle_edge<2.0, {127, 127, 127}, 1.0>, static_centered_circle_edge<2.0, {127, 127, 127}, 1.0>,
pos_rotated_polygon_edge<1.0, {0, 0, 255}, pos_rotated_polygon_edge<1.0, {0, 0, 255},

View File

@ -1,7 +1,7 @@
#include "../variants.hpp" #include "../variants.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
variant_sprites variant5 = variant_sprites::make_light< variant_sprites variant5 = variant_sprites::make_light<
static_centered_circle_edge<2.0, {127, 127, 127}, 1.0>, static_centered_circle_edge<2.0, {127, 127, 127}, 1.0>,
neg_rotated_polygon_edge<1.0, {0, 0, 255}, neg_rotated_polygon_edge<1.0, {0, 0, 255},

View File

@ -1,7 +1,7 @@
#include "../variants.hpp" #include "../variants.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
variant_sprites variant6 = variant_sprites::make_light< variant_sprites variant6 = variant_sprites::make_light<
static_centered_circle_edge<4.0, {127, 127, 127}, 1.0>, static_centered_circle_edge<4.0, {127, 127, 127}, 1.0>,
//sqrt(5.0)*sqrt(5.0+2.0*sqrt(5.0))/10.0 * sqrt((5.0-sqrt(5.0))/2.0) //sqrt(5.0)*sqrt(5.0+2.0*sqrt(5.0))/10.0 * sqrt((5.0-sqrt(5.0))/2.0)

View File

@ -1,7 +1,7 @@
#include "../variants.hpp" #include "../variants.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
variant_sprites variant8 = variant_sprites::make_light< variant_sprites variant8 = variant_sprites::make_light<
static_centered_circle_edge<4.0, {127, 127, 127}, 1.0>, static_centered_circle_edge<4.0, {127, 127, 127}, 1.0>,
static_rotated_polygon_edge<3.0, {0, 0, 255}, static_rotated_polygon_edge<3.0, {0, 0, 255},

View File

@ -1,11 +1,11 @@
#include <bgtu/computer_graphics_lab_work/utilities/shapes/circle.hpp> #include "bgtu/computer_graphics_lab_work/utilities/shapes/circle.hpp"
#include "../variants.hpp" #include "../variants.hpp"
#include "../sprite_data.hpp" #include "../sprite_data.hpp"
#include "common_sprites.hpp" #include "common_sprites.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab1 {
template<double z, RendererApi::Color::Transparent c, double outer_radius, double inner_radius, double angle_degrees> template<double z, RendererApi::Color::Transparent c, double outer_radius, double inner_radius, double angle_degrees>
static void _variant8_triangle(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, Lab1SpriteData::ShapeData const *data) { static void _variant8_triangle(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, SpriteData::ShapeData const *data) {
pos_rotated_polygon_edge<z, c, {outer_radius, angle_degrees}, {inner_radius, angle_degrees + 10}, {inner_radius, angle_degrees - 10}>(frame, data); pos_rotated_polygon_edge<z, c, {outer_radius, angle_degrees}, {inner_radius, angle_degrees + 10}, {inner_radius, angle_degrees - 10}>(frame, data);
} }

View File

@ -7,18 +7,18 @@
#include <QObject> #include <QObject>
#include <QMutex> #include <QMutex>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp> #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/renderer_api/sprite.hpp"
#include <bgtu/computer_graphics_lab_work/utilities/matrix.hpp> #include "bgtu/computer_graphics_lab_work/utilities/matrix.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/utilities/zoomed_voxel_painter.hpp> #include "bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl {
class _Lab1SpriteData_Provider; class _Lab1SpriteData_Provider;
struct Lab1SpriteData { struct SpriteData {
public: public:
struct ShapeData { struct ShapeData {
public: public:
@ -63,7 +63,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
}; };
class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider { class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider {
Q_OBJECT Q_OBJECT
private: private:
QMutex sync; QMutex sync;
@ -73,7 +73,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
double radians_per_second; double radians_per_second;
bool show_grid; bool show_grid;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h; RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sub_sprites; RendererApi::Sprite<SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sub_sprites;
std::size_t sub_sprites_count; std::size_t sub_sprites_count;
public: public:
@ -83,10 +83,10 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
w{0}, h{0}, w{0}, h{0},
sub_sprites{nullptr}, sub_sprites_count{0} {} sub_sprites{nullptr}, sub_sprites_count{0} {}
Lab1SpriteData get_sprite_data() override { SpriteData get_sprite_data() override {
this->sync.lock(); this->sync.lock();
RendererApi::PointI<2>::component_t radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16) / this->pixel_size; RendererApi::PointI<2>::component_t radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16) / this->pixel_size;
Lab1SpriteData cached{ SpriteData cached{
.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), .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, .pixel_size = this->pixel_size,
.show_grid = this->show_grid, .show_grid = this->show_grid,
@ -142,7 +142,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
this->sync.unlock(); this->sync.unlock();
} }
void set_sub_sprites(RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *s, std::size_t c) { void set_sub_sprites(RendererApi::Sprite<SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *s, std::size_t c) {
this->sync.lock(); this->sync.lock();
this->sub_sprites = s; this->sub_sprites = s;
this->sub_sprites_count = c; this->sub_sprites_count = c;

View File

@ -0,0 +1,274 @@
#pragma once
#include <array>
#include <tuple>
#include <QObject>
#include "bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp"
#include "bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp"
#include "sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl::Variants {
struct variant_sprites {
private :
using sprite_t = RendererApi::Sprite<SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>>;
public:
sprite_t *const *const sprites;
std::size_t const count;
constexpr variant_sprites(sprite_t **_sprites, std::size_t _count) : sprites{_sprites}, count{_count} {
}
private:
template<class ...sprites_t>
struct _make {
};
template<>
struct _make<> {
public:
constexpr _make() {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
}
};
template<class e0>
struct _make<e0> {
public:
e0 value;
constexpr _make(e0 v) : value{std::move(v)} {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
dst[pos] = &this->value;
}
};
template<class e0, class ...en>
struct _make<e0, en...> {
public:
e0 value;
_make<en...> next;
constexpr _make(e0 v, en...nv) : value{std::move(v)}, next{nv...} {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
dst[pos] = &this->value;
this->next.export_pointers(dst, pos + 1);
}
};
public:
template<class ...sprites_t>
constexpr static variant_sprites make(sprites_t...sprites) {
static _make<sprites_t...> i{sprites...};
static sprite_t *p[sizeof...(sprites)];
i.export_pointers(p, 0);
return variant_sprites{p, sizeof...(sprites)};
}
private:
template<void (...sprites)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
SpriteData::ShapeData const *data)>
struct _make_light : public RendererApi::Sprite<SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> {
};
template<>
struct _make_light<> {
public:
constexpr _make_light() {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
}
};
template<void (s0)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
SpriteData::ShapeData const *data),
void (...sn)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
SpriteData::ShapeData const *data)>
struct _make_light<s0, sn...> : public RendererApi::Sprite<SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> {
public:
_make_light<sn...> next;
constexpr _make_light() : next{} {};
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
dst[pos] = this;
this->next.export_pointers(dst, pos + 1);
}
void draw(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame, const SpriteData::ShapeData *data) const final {
s0(frame, data);
}
void clicked() final {}
};
public:
template<void (...sprites)(Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
SpriteData::ShapeData const *data)>
constexpr static variant_sprites make_light() {
static _make_light<sprites...> i{};
static sprite_t *p[sizeof...(sprites)];
i.export_pointers(p, 0);
return variant_sprites{p, sizeof...(sprites)};
}
};
namespace Lab1 {
extern variant_sprites variant1;
extern variant_sprites variant2;
extern variant_sprites variant3;
extern variant_sprites variant4;
extern variant_sprites variant5;
extern variant_sprites variant6;
extern variant_sprites variant8;
extern variant_sprites variant9;
}
class VariantsManager : public QObject {
Q_OBJECT
signals:
void set_sprites(
RendererApi::Sprite<SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sprites,
std::size_t count
);
private:
enum class LabNo {
L1, L2, L3, L4, L5
};
LabNo _current_lab = LabNo::L1;
QMutex sync;
inline LabNo get_current_lab() {
this->sync.lock();
auto copy = this->_current_lab;
this->sync.unlock();
return copy;
}
inline void set_current_lab(LabNo no) {
this->sync.lock();
this->_current_lab = no;
this->sync.unlock();
}
inline void _set_sprites(variant_sprites sprites) {
emit this->set_sprites(sprites.sprites, sprites.count);
}
public slots:
inline void set_variant_1() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant1);
default:
(void) 0;
}
};
inline void set_variant_2() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant2);
default:
(void) 0;
}
};
inline void set_variant_3() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant3);
default:
(void) 0;
}
};
inline void set_variant_4() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant4);
default:
(void) 0;
}
};
inline void set_variant_5() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant5);
default:
(void) 0;
}
};
inline void set_variant_6() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant6);
default:
(void) 0;
}
};
inline void set_variant_8() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant8);
default:
(void) 0;
}
};
inline void set_variant_9() {
switch (this->get_current_lab()) {
case LabNo::L1:
this->_set_sprites(Lab1::variant9);
default:
(void) 0;
}
};
inline void set_lab_1() {
this->set_current_lab(LabNo::L1);
this->_set_sprites(Lab1::variant3);
};
inline void set_lab_2() {
this->set_current_lab(LabNo::L2);
this->_set_sprites(Lab1::variant3);
};
inline void set_lab_3() {
this->set_current_lab(LabNo::L3);
this->_set_sprites(Lab1::variant3);
};
inline void set_lab_4() {
this->set_current_lab(LabNo::L4);
this->_set_sprites(Lab1::variant3);
};
inline void set_lab_5() {
this->set_current_lab(LabNo::L5);
this->_set_sprites(Lab1::variant3);
};
};
}

View File

@ -5,16 +5,16 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp> #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/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp> #include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include "sprite_data.hpp" #include "variants/sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Lab1 { namespace BGTU::ComputerGraphicsLabWork::Impl {
class ZoomedSceneSprite : public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> { class ZoomedSceneSprite : public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> {
private: private:
public: public:
ZoomedSceneSprite() = default; ZoomedSceneSprite() = default;
void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override { void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const SpriteData *data) const override {
Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> zoomed_painter{frame, data->central_pixel_tl, data->pixel_size}; Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> zoomed_painter{frame, data->central_pixel_tl, data->pixel_size};
for (std::size_t i = 0; i < data->sub_sprites_count; i++) { for (std::size_t i = 0; i < data->sub_sprites_count; i++) {

View File

@ -50,6 +50,10 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
constexpr bool operator!=(Color::Transparent const &other) const noexcept { constexpr bool operator!=(Color::Transparent const &other) const noexcept {
return !(*this == other); return !(*this == other);
} }
[[nodiscard]] constexpr Color without_alpha() const noexcept {
return Color{this->red, this->green, this->blue};
};
}; };
}; };
} }

View File

@ -9,14 +9,18 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
virtual void clicked() {}; virtual void clicked() {};
}; };
template<class data_t, class voxel_painter_t = VirtualVoxelPainter> template<class _data_t, class _voxel_painter_t = VirtualVoxelPainter>
class Sprite : public SpriteMetadata { class Sprite : public SpriteMetadata {
public: public:
virtual void draw(voxel_painter_t *frame, data_t const *data) const = 0; using data_t = _data_t;
using voxel_painter_t = _voxel_painter_t;
virtual void draw(_voxel_painter_t *frame, _data_t const *data) const = 0;
class SpriteDataProvider { class SpriteDataProvider {
public: public:
virtual data_t get_sprite_data() = 0; virtual _data_t get_sprite_data() = 0;
}; };
}; };
} }

View File

@ -1,7 +1,6 @@
add_library( add_library(
utilities utilities
OBJECT OBJECT
src/shader.cpp
src/memory_pages_management.cpp src/memory_pages_management.cpp
src/default_renderer_linear_implementation.cpp src/default_renderer_linear_implementation.cpp
src/default_renderer_linear_shapes_intrinsics.cpp src/default_renderer_linear_shapes_intrinsics.cpp

View File

@ -8,7 +8,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
constexpr RendererApi::Color _apply_transparent_color_pure(RendererApi::Color bg, RendererApi::Color::Transparent fg) { constexpr RendererApi::Color _apply_transparent_color_pure(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
#if 1 #if 1
if (fg.alpha == 255) if (fg.alpha == 255)
return {fg.red, fg.green, fg.blue}; return fg.without_alpha();
else if (fg.alpha == 0)
return bg;
// pmovzxbd // pmovzxbd
const std::uint_fast32_t bg_i32[4]{bg.red, bg.green, bg.blue}; const std::uint_fast32_t bg_i32[4]{bg.red, bg.green, bg.blue};
@ -31,7 +33,11 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
// divps // divps
const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f}; const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f};
return {(RendererApi::Color::component_compact_t) sum_fixed_f[0], (RendererApi::Color::component_compact_t) sum_fixed_f[1], (RendererApi::Color::component_compact_t) sum_fixed_f[2]}; return {
(RendererApi::Color::component_compact_t) sum_fixed_f[0],
(RendererApi::Color::component_compact_t) sum_fixed_f[1],
(RendererApi::Color::component_compact_t) sum_fixed_f[2]
};
#else #else
return RendererApi::Color{ return RendererApi::Color{
@ -172,6 +178,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
buffer[offset + 1] = color.green; buffer[offset + 1] = color.green;
buffer[offset + 2] = color.blue; buffer[offset + 2] = color.blue;
} }
inline void color_to_bgr32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept { inline void color_to_bgr32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept {
buffer[offset] = color.blue; buffer[offset] = color.blue;
buffer[offset + 1] = color.green; buffer[offset + 1] = color.green;

View File

@ -165,6 +165,25 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
) { ) {
this->fill_rectangle(left, top, right, bottom, z, fill, this->current_artist); this->fill_rectangle(left, top, right, bottom, z, fill, this->current_artist);
} }
void draw_h_line(
RendererApi::PointI<2>::component_t y,
RendererApi::PointI<2>::component_t left,
RendererApi::PointI<2>::component_t right,
double z,
RendererApi::Color::Transparent color,
RendererApi::SpriteMetadata *owner
);
inline void draw_h_line(
RendererApi::PointI<2>::component_t y,
RendererApi::PointI<2>::component_t left,
RendererApi::PointI<2>::component_t right,
double z,
RendererApi::Color::Transparent color
) {
this->draw_h_line(y, left, right, z, color, this->current_artist);
}
}; };
private: private:

View File

@ -2,29 +2,138 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include "matrix.hpp" #include "matrix.hpp"
namespace BGTU::ComputerGraphicsLabWork::Utilities { namespace BGTU::ComputerGraphicsLabWork::Utilities {
class Shader { class Shader {
public: public:
[[nodiscard]] virtual RendererApi::Color::Transparent get_color(double x, double y) const = 0; [[nodiscard]] virtual RendererApi::Color::Transparent get_color(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const = 0;
static Shader const *empty_shader; [[nodiscard]] inline RendererApi::Color::Transparent get_color(RendererApi::PointI<2> p) const {
return this->get_color(p.x, p.y);
};
class Empty;
static Shader::Empty const empty;
}; };
class Shader::Empty : public Shader {
public:
constexpr Empty() noexcept = default;
[[nodiscard]] constexpr RendererApi::Color::Transparent get_color(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const noexcept final {
return RendererApi::Color::Transparent{0, 0, 0, 0};
};
operator Shader::Empty const *() const noexcept { // NOLINT(*-explicit-constructor)
return this;
}
Shader::Empty const *operator->() const noexcept {
return this;
}
};
constexpr bool operator==(Shader::Empty const &, Shader::Empty const &) noexcept {
return true;
}
constexpr bool operator==(Shader::Empty const &, Shader::Empty const *) noexcept {
return true;
}
constexpr bool operator==(Shader::Empty const &, Shader const *other) noexcept {
return dynamic_cast<Shader::Empty const *>(other) != nullptr;
}
constexpr bool operator!=(Shader::Empty const &, Shader::Empty const &) noexcept {
return false;
}
constexpr bool operator!=(Shader::Empty const &, Shader::Empty const *) noexcept {
return false;
}
constexpr bool operator!=(Shader::Empty const &, Shader const *other) noexcept {
return dynamic_cast<Shader::Empty const *>(other) == nullptr;
}
constexpr bool operator==(Shader::Empty const *, Shader::Empty const &) noexcept {
return true;
}
constexpr bool operator==(Shader const *other, Shader::Empty const &) noexcept {
return dynamic_cast<Shader::Empty const *>(other) != nullptr;
}
constexpr bool operator!=(Shader::Empty const *, Shader::Empty const &) noexcept {
return false;
}
constexpr bool operator!=(Shader const *other, Shader::Empty const &) noexcept {
return dynamic_cast<Shader::Empty const *>(other) == nullptr;
}
constexpr Shader::Empty const Shader::empty{};
class MonoShader : public Shader { class MonoShader : public Shader {
private: private:
RendererApi::Color::Transparent c; RendererApi::Color::Transparent c;
public: public:
inline explicit MonoShader(RendererApi::Color::Transparent c) : c{c} {} constexpr explicit MonoShader(RendererApi::Color::Transparent c) noexcept: c{c} {}
[[nodiscard]] inline RendererApi::Color::Transparent get_color(double x, double y) const override { [[nodiscard]] constexpr RendererApi::Color::Transparent get_color(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const noexcept final {
return this->c; return this->c;
}; };
template<RendererApi::Color::Transparent _color>
class Static : public Shader {
public:
constexpr Static() noexcept = default;
static constexpr RendererApi::Color::Transparent const COLOR = _color;
[[nodiscard]] constexpr RendererApi::Color::Transparent get_color(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const noexcept final {
return _color;
};
private:
static MonoShader::Static<_color> const INSTANCE;
public:
operator MonoShader::Static<_color> const *() const noexcept { // NOLINT(*-explicit-constructor)
return &INSTANCE;
}
MonoShader::Static<_color> const *operator->() const noexcept {
return &INSTANCE;
}
template<RendererApi::Color::Transparent other_color>
constexpr bool operator==(MonoShader::Static<other_color>) const noexcept {
return _color == other_color;
}
};
template<RendererApi::Color::Transparent color>
static MonoShader::Static<color> const static_;
}; };
template<RendererApi::Color::Transparent color>
constexpr MonoShader::Static<color> const MonoShader::Static<color>::INSTANCE{};
template<RendererApi::Color::Transparent color>
constexpr MonoShader::Static<color> const MonoShader::static_{};
class TransformedShader : public Shader { class TransformedShader : public Shader {
private: private:
Shader const *shader; Shader const *shader;
@ -33,7 +142,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
public: public:
inline TransformedShader(Shader const *s, Matrix4d t) : shader{s}, transform{t} {} inline TransformedShader(Shader const *s, Matrix4d t) : shader{s}, transform{t} {}
[[nodiscard]] inline RendererApi::Color::Transparent get_color(double x, double y) const override { [[nodiscard]] inline RendererApi::Color::Transparent get_color(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const override {
RendererApi::PointF<3> in{x, y, 0}; RendererApi::PointF<3> in{x, y, 0};
RendererApi::PointF<3> out = this->transform * in; RendererApi::PointF<3> out = this->transform * in;
return this->shader->get_color(out.x, out.y); return this->shader->get_color(out.x, out.y);

View File

@ -6,30 +6,109 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
template<class edger_receiver_t, class fill_receiver_t>
void iterate_circle_fill_h_lines(
RendererApi::PointI<2>::component_t cx, RendererApi::PointI<2>::component_t cy,
RendererApi::PointI<2>::component_t r,
edger_receiver_t edge_point_receiver,
fill_receiver_t fill_line_receiver
) {
RendererApi::PointI<2>::component_t x = 0, y = r;
RendererApi::PointI<2>::component_t last_y = r + 1;
RendererApi::PointI<2>::component_t _r2 = r * r;
while (x < y) {
RendererApi::PointI<2>::component_t _x2 = x * x;
RendererApi::PointI<2>::component_t _y_1 = y - 1;
RendererApi::PointI<2>::component_t D1 = _x2 + y * y - _r2;
RendererApi::PointI<2>::component_t D2 = _x2 + _y_1 * _y_1 - _r2;
if (D1 > -D2)
y--;
if (y < last_y) {
edge_point_receiver(cx - x, cy + y);
fill_line_receiver(cy + y, cx - x + 1, cx + x);
edge_point_receiver(cx + x, cy + y);
edge_point_receiver(cx - y, cy + x);
fill_line_receiver(cy + x, cx - y + 1, cx + y);
edge_point_receiver(cx + y, cy + x);
if (x > 0) {
edge_point_receiver(cx - y, cy - x);
fill_line_receiver(cy - x, cx - y + 1, cx + y);
edge_point_receiver(cx + y, cy - x);
}
edge_point_receiver(cx - x, cy - y);
fill_line_receiver(cy - y, cx - x + 1, cx + x);
edge_point_receiver(cx + x, cy - y);
last_y = y;
} else {
edge_point_receiver(cx - x, cy + y);
edge_point_receiver(cx + x, cy + y);
edge_point_receiver(cx - y, cy + x);
edge_point_receiver(cx + y, cy + x);
if (x > 0) {
edge_point_receiver(cx - y, cy - x);
edge_point_receiver(cx + y, cy - x);
}
edge_point_receiver(cx - x, cy - y);
edge_point_receiver(cx + x, cy - y);
}
x++;
}
}
template<class edger_receiver_t, class fill_receiver_t>
void iterate_circle_fill_h_lines(
RendererApi::PointI<2> c,
RendererApi::PointI<2>::component_t r,
edger_receiver_t edge_point_receiver,
fill_receiver_t fill_line_receiver
) {
iterate_circle_fill_h_lines(c.x, c.y, r, edge_point_receiver, fill_line_receiver);
}
template<class receiver_t>
void iterate_circle_fill(
RendererApi::PointI<2>::component_t cx, RendererApi::PointI<2>::component_t cy,
RendererApi::PointI<2>::component_t r,
receiver_t receiver
) {
iterate_circle_fill_h_lines(
cx, cy, r,
[&](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { receiver(true, x, y); },
[&](RendererApi::PointI<2>::component_t y, RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t x2) {
for (RendererApi::PointI<2>::component_t x = x1; x < x2; x++) receiver(x, y);
}
);
}
template<class receiver_t>
void iterate_circle_fill(
RendererApi::PointI<2> c,
RendererApi::PointI<2>::component_t r,
receiver_t receiver
) {
iterate_circle_fill_lines<receiver_t>(c.x, c.y, r, receiver);
}
template<class receiver_t> template<class receiver_t>
void iterate_circle_edge( void iterate_circle_edge(
RendererApi::PointI<2>::component_t cx, RendererApi::PointI<2>::component_t cy, RendererApi::PointI<2>::component_t cx, RendererApi::PointI<2>::component_t cy,
RendererApi::PointI<2>::component_t r, RendererApi::PointI<2>::component_t r,
receiver_t receiver receiver_t receiver
) { ) {
RendererApi::PointI<2>::component_t x = 0, y = r; iterate_circle_fill_h_lines(
while (x < y) { cx, cy, r,
RendererApi::PointI<2>::component_t D1 = x * x + y * y - r * r; receiver,
RendererApi::PointI<2>::component_t D2 = x * x + (y - 1) * (y - 1) - r * r; [](RendererApi::PointI<2>::component_t y, RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t x2) {}
);
if (D1 > -D2)
y--;
receiver(cx + x, cy + y);
receiver(cx + x, cy - y);
receiver(cx + y, cy + x);
receiver(cx + y, cy - x);
receiver(cx - x, cy + y);
receiver(cx - x, cy - y);
receiver(cx - y, cy + x);
receiver(cx - y, cy - x);
x++;
}
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstdlib> #include <cstdlib>
#include <utility>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
@ -108,4 +109,66 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
return nullptr; return nullptr;
} }
}; };
template<class receiver_t>
void iterate_h_line(
RendererApi::PointI<2>::component_t y,
RendererApi::PointI<2>::component_t x1,
RendererApi::PointI<2>::component_t x2,
receiver_t receiver
) {
if (x2 < x1)
std::swap(x1, x2);
for (RendererApi::PointI<2>::component_t x = x1; x <= x2; x++) {
receiver(x, y);
}
}
template<class receiver_t>
void iterate_v_line(
RendererApi::PointI<2>::component_t x,
RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t y2,
receiver_t receiver
) {
if (y2 < y1)
std::swap(y1, y2);
for (RendererApi::PointI<2>::component_t y = y1; x <= y2; y++) {
receiver(x, y);
}
}
template<class receiver_t>
void iterate_brezenham(
RendererApi::PointI<2>::component_t x1,
RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2,
RendererApi::PointI<2>::component_t y2,
receiver_t receiver
) {
// todo transpose
for (auto p: brezenham_line_iterable{x1, y1, x2, y2}) {
receiver(p.x, p.y);
}
}
template<class receiver_t>
void iterate_line(
RendererApi::PointI<2>::component_t x1,
RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2,
RendererApi::PointI<2>::component_t y2,
receiver_t receiver
) {
if (x1 == x2) {
iterate_v_line(x1, y1, y2, receiver);
return;
}
if (y1 == y2) {
iterate_h_line(y1, x1, x2, receiver);
return;
}
iterate_brezenham(x1, y1, x2, y2, receiver);
}
} }

View File

@ -66,4 +66,5 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
[=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline, owner); } [=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline, owner); }
); );
} }
} }

View File

@ -0,0 +1,320 @@
#pragma once
#include <cstdlib>
#include <type_traits>
#include <utility>
#include <limits>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include "line.hpp"
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
template<class receiver_t>
void iterate_triangle_fill(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2,
receiver_t receiver
);
class triangle_fill_iterable {
private:
brezenham_line_iterable upper_left;
brezenham_line_iterable lower_left;
brezenham_line_iterable right;
template<class receiver_t>
friend
void iterate_triangle_fill(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2,
receiver_t
);
inline triangle_fill_iterable(
brezenham_line_iterable upper_left,
brezenham_line_iterable lower_left,
brezenham_line_iterable right
) : upper_left{upper_left}, lower_left{lower_left}, right{right} {}
struct _pre_constructor {
private:
inline static void sort_points(RendererApi::PointI<2>::component_t *x0, RendererApi::PointI<2>::component_t *y0, RendererApi::PointI<2>::component_t *x1, RendererApi::PointI<2>::component_t *y1, RendererApi::PointI<2>::component_t *x2, RendererApi::PointI<2>::component_t *y2) {
auto _swap = [](RendererApi::PointI<2>::component_t *sx0, RendererApi::PointI<2>::component_t *sy0, RendererApi::PointI<2>::component_t *sx1, RendererApi::PointI<2>::component_t *sy1) {
RendererApi::PointI<2>::component_t tmp;
tmp = *sx0;
*sx0 = *sx1;
*sx1 = tmp;
tmp = *sy0;
*sy0 = *sy1;
*sy1 = tmp;
};
if (*y0 < *y1)
_swap(x0, y0, x1, y1);
if (*y1 < *y2)
_swap(x1, y1, x2, y2);
if (*y0 < *y1)
_swap(x0, y0, x1, y1);
if (*y0 == *y1 && *x0 < *x1)
_swap(x0, y0, x1, y1);
if (*y1 == *y2 && *x2 < *x1)
_swap(x1, y1, x2, y2);
}
public:
static inline triangle_fill_iterable create(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2
) {
_pre_constructor::sort_points(&x0, &y0, &x1, &y1, &x2, &y2);
return triangle_fill_iterable{brezenham_line_iterable{x0, y0, x1, y1}, brezenham_line_iterable{x1, y1, x2, y2}, brezenham_line_iterable{x0, y0, x2, y2}};
}
};
public:
inline triangle_fill_iterable(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2
) : triangle_fill_iterable{_pre_constructor::create(x0, y0, x1, y1, x2, y2)} {
}
#if 0
class iterator {
private:
brezenham_line_iterable::iterator upper_left;
brezenham_line_iterable::iterator lower_left;
brezenham_line_iterable::iterator right;
RendererApi::PointI<2>::component_t cx, ex, cy;
friend class triangle_fill;
inline iterator(
brezenham_line_iterable const &upper_left,
brezenham_line_iterable const &lower_left,
brezenham_line_iterable const &right
) : upper_left{upper_left.begin()}, lower_left{lower_left.begin()}, right{right.begin()}, cx{(*this->upper_left).x}, ex{(*this->right).x}, cy{(*this->upper_left).y} {}
brezenham_line_iterable::iterator &_left() {
if (this->upper_left == nullptr)
return this->lower_left;
else
return this->upper_left;
}
public:
inline iterator &operator++() {
if (this->cx < this->ex) {
this->cx++;
return *this;
}
if (this->upper_left != nullptr) {
RendererApi::PointI<2>::component_t sx = (*(this->upper_left)).x;
while (true) {
this->upper_left++;
if (this->upper_left == nullptr)
goto LOWER;
if ((*(this->upper_left)).y < this->cy)
{
this->cy--;
return *this;
(*++(this->upper_left)).y >= this->cy
if ((*(this->upper_left)).x < sx)
return *this;
}
} else {
LOWER:
RendererApi::PointI<2>::component_t sx = (*(this->upper_left)).x;
}
while ((*++(this->right)).y >= this->cy) {
if ((*(this->right)).x > this->ex)
return *this;
}
this->cy--;
}
inline iterator operator++(int) {
iterator next = *this;
++(*this);
return next;
}
inline point operator*() const {
if (this->swap_flag)
return point{this->ret, this->arg};
else
return point{this->arg, this->ret};
}
inline bool operator==(std::nullptr_t) const {
return this->arg >= this->end_arg;
}
inline bool operator!=(std::nullptr_t) const {
return this->arg < this->end_arg;
}
};
#endif
};
template<class receiver_t>
void iterate_triangle_fill(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2,
receiver_t receiver
) {
triangle_fill_iterable init{x0, y0, x1, y1, x2, y2};
auto right = init.right.begin();
RendererApi::PointI<2>::component_t cy = (*right).y;
RendererApi::PointI<2>::component_t sx = std::numeric_limits<RendererApi::PointI<2>::component_t>::min();
RendererApi::PointI<2>::component_t ex = std::numeric_limits<RendererApi::PointI<2>::component_t>::max();
auto loop = [&](brezenham_line_iterable left) {
for (auto lp: left) {
if (lp.y == cy) {
receiver(true, lp.x, lp.y);
sx = (lp.x > sx) ? (lp.x) : sx;
continue;
}
for (; (*right).y > lp.y; right++) {
if ((*right).x > sx)
receiver(true, (*right).x, (*right).y);
ex = ((*right).x < ex) ? ((*right).x) : ex;
}
for (RendererApi::PointI<2>::component_t x = sx + 1; x < ex; x++)
receiver(false, x, cy);
cy--;
receiver(true, lp.x, lp.y);
}
};
loop(init.upper_left);
loop(init.lower_left);
for (; right != nullptr; right++) {
if ((*right).x > sx)
receiver(true, (*right).x, (*right).y);
}
}
template<class receiver_t>
void iterate_triangle_fill(
RendererApi::PointI<2> p0,
RendererApi::PointI<2> p1,
RendererApi::PointI<2> p2,
receiver_t receiver
) {
iterate_triangle_fill(
p0.x, p0.y,
p1.x, p1.y,
p2.x, p2.y,
receiver
);
}
template<class variable_t>
struct triangle_barycentric_interpolator {
public:
struct pole {
RendererApi::PointI<2> coord;
variable_t value;
};
private:
long double full_square;
RendererApi::PointI<2> p0;
RendererApi::PointI<2> p1;
RendererApi::PointI<2> p2;
variable_t v0;
variable_t v1;
variable_t v2;
struct _empty {
};
std::conditional_t<std::is_same_v<variable_t, RendererApi::Color::Transparent>, bool, _empty> skip_alpha;
static long double calculate_square_2(
RendererApi::PointI<2> p0,
RendererApi::PointI<2> p1,
RendererApi::PointI<2> p2
) noexcept {
return (p2.x - p1.x) * (p2.y - p0.y) + (p2.x - p0.x) * (p1.y - p0.y);
}
public:
triangle_barycentric_interpolator(
RendererApi::PointI<2> p0, RendererApi::PointI<2> p1, RendererApi::PointI<2> p2,
variable_t v0, variable_t v1, variable_t v2
) : p0{p0}, p1{p1}, p2{p2}, v0{v0}, v1{v1}, v2{v2}, full_square{calculate_square_2(p0, p1, p2)} {
if constexpr (std::is_same_v<variable_t, RendererApi::Color::Transparent>) {
this->skip_alpha = v0.alpha == v1.alpha && v0.alpha == v2.alpha;
}
}
variable_t interpolate_point(RendererApi::PointI<2> p) const {
const double k0 = calculate_square_2(p, this->p1, this->p2) / this->full_square;
const double k1 = calculate_square_2(p, this->p2, this->p0) / this->full_square;
const double k2 = calculate_square_2(p, this->p0, this->p1) / this->full_square;
auto f = [&]<class intermediate_t>(intermediate_t (variable_t::*offset)) -> intermediate_t {
return static_cast<intermediate_t>((this->v0.*offset) * k0 + (this->v1.*offset) * k1 + (this->v2.*offset) * k2);
};
if constexpr (std::is_same_v<variable_t, RendererApi::Color::Transparent>) {
RendererApi::Color base{
f(&RendererApi::Color::Transparent::red),
f(&RendererApi::Color::Transparent::green),
f(&RendererApi::Color::Transparent::blue),
};
return RendererApi::Color::Transparent{
base.red, base.green, base.blue,
(this->skip_alpha ? this->v0.alpha : f(&RendererApi::Color::Transparent::alpha))
};
} else if constexpr (std::is_same_v<variable_t, RendererApi::Color>) {
return RendererApi::Color{
f(&RendererApi::Color::red),
f(&RendererApi::Color::green),
f(&RendererApi::Color::blue)
};
} else {
return static_cast<variable_t>(f(&variable_t::variable_t));
}
}
variable_t interpolate_point(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const {
return this->interpolate_point(RendererApi::PointI<2>{x, y});
}
};
class triangle_barycentric_shader : public Shader {
private:
triangle_barycentric_interpolator<RendererApi::Color::Transparent> interpolator;
public:
inline triangle_barycentric_shader(
RendererApi::PointI<2> p0, RendererApi::PointI<2> p1, RendererApi::PointI<2> p2,
RendererApi::Color::Transparent c0, RendererApi::Color::Transparent c1, RendererApi::Color::Transparent c2
) : interpolator{p0, p1, p2, c0, c1, c2} {}
[[nodiscard]] inline RendererApi::Color::Transparent get_color(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) const final {
return this->interpolator.interpolate_point(x, y);
}
};
}

View File

@ -1,214 +0,0 @@
#pragma once
#include <cstdlib>
#include <utility>
#include <limits>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include "bgtu/computer_graphics_lab_work/utilities/shapes/line.hpp"
namespace BGTU::ComputerGraphicsLabWork::Utilities {
template<class receiver_t>
void fill_triangle(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2,
receiver_t receiver
) noexcept(receiver(static_cast<bool>(false), static_cast<RendererApi::PointI<2>::component_t>(0), static_cast<RendererApi::PointI<2>::component_t>(0)));
class triangle_fill_iterable {
private:
brezenham_line_iterable upper_left;
brezenham_line_iterable lower_left;
brezenham_line_iterable right;
template<class receiver_t>
friend
void fill_triangle(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2,
receiver_t
) noexcept(std::declval<receiver_t>()(static_cast<bool>(false), static_cast<RendererApi::PointI<2>::component_t>(0), static_cast<RendererApi::PointI<2>::component_t>(0)));
inline triangle_fill_iterable(
brezenham_line_iterable upper_left,
brezenham_line_iterable lower_left,
brezenham_line_iterable right
) : upper_left{upper_left}, lower_left{lower_left}, right{right} {}
struct _pre_constructor {
private:
inline static void sort_points(RendererApi::PointI<2>::component_t *x0, RendererApi::PointI<2>::component_t *y0, RendererApi::PointI<2>::component_t *x1,RendererApi::PointI<2>::component_t *y1, RendererApi::PointI<2>::component_t *x2, RendererApi::PointI<2>::component_t *y2) {
auto _swap = [](RendererApi::PointI<2>::component_t *sx0, RendererApi::PointI<2>::component_t *sy0, RendererApi::PointI<2>::component_t *sx1, RendererApi::PointI<2>::component_t *sy1) {
RendererApi::PointI<2>::component_t tmp;
tmp = *sx0;
*sx0 = *sx1;
*sx1 = tmp;
tmp = *sy0;
*sy0 = *sy1;
*sy1 = tmp;
};
if (*y0 < *y1)
_swap(x0, y0, x1, y1);
if (*y1 < *y2)
_swap(x1, y1, x2, y2);
if (*y0 < *y1)
_swap(x0, y0, x1, y1);
if (*y0 == *y1 && *x0 < *x1)
_swap(x0, y0, x1, y1);
if (*y1 == *y2 && *x2 < *x1)
_swap(x1, y1, x2, y2);
}
public:
static inline triangle_fill_iterable create(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2
) {
_pre_constructor::sort_points(&x0, &y0, &x1, &y1, &x2, &y2);
return triangle_fill_iterable{brezenham_line_iterable{x0, y0, x1, y1}, brezenham_line_iterable{x1, y1, x2, y2}, brezenham_line_iterable{x0, y0, x2, y2}};
}
};
public:
inline triangle_fill_iterable(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2
) : triangle_fill_iterable{_pre_constructor::create(x0, y0, x1, y1, x2, y2)} {
}
#if 0
class iterator {
private:
brezenham_line_iterable::iterator upper_left;
brezenham_line_iterable::iterator lower_left;
brezenham_line_iterable::iterator right;
RendererApi::PointI<2>::component_t cx, ex, cy;
friend class triangle_fill;
inline iterator(
brezenham_line_iterable const &upper_left,
brezenham_line_iterable const &lower_left,
brezenham_line_iterable const &right
) : upper_left{upper_left.begin()}, lower_left{lower_left.begin()}, right{right.begin()}, cx{(*this->upper_left).x}, ex{(*this->right).x}, cy{(*this->upper_left).y} {}
brezenham_line_iterable::iterator &_left() {
if (this->upper_left == nullptr)
return this->lower_left;
else
return this->upper_left;
}
public:
inline iterator &operator++() {
if (this->cx < this->ex) {
this->cx++;
return *this;
}
if (this->upper_left != nullptr) {
RendererApi::PointI<2>::component_t sx = (*(this->upper_left)).x;
while (true) {
this->upper_left++;
if (this->upper_left == nullptr)
goto LOWER;
if ((*(this->upper_left)).y < this->cy)
{
this->cy--;
return *this;
(*++(this->upper_left)).y >= this->cy
if ((*(this->upper_left)).x < sx)
return *this;
}
} else {
LOWER:
RendererApi::PointI<2>::component_t sx = (*(this->upper_left)).x;
}
while ((*++(this->right)).y >= this->cy) {
if ((*(this->right)).x > this->ex)
return *this;
}
this->cy--;
}
inline iterator operator++(int) {
iterator next = *this;
++(*this);
return next;
}
inline point operator*() const {
if (this->swap_flag)
return point{this->ret, this->arg};
else
return point{this->arg, this->ret};
}
inline bool operator==(std::nullptr_t) const {
return this->arg >= this->end_arg;
}
inline bool operator!=(std::nullptr_t) const {
return this->arg < this->end_arg;
}
};
#endif
};
template<class receiver_t>
void fill_triangle(
RendererApi::PointI<2>::component_t x0, RendererApi::PointI<2>::component_t y0,
RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1,
RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2,
receiver_t receiver
) noexcept(receiver(static_cast<bool>(false), static_cast<RendererApi::PointI<2>::component_t>(0), static_cast<RendererApi::PointI<2>::component_t>(0))) {
triangle_fill_iterable init{x0, y0, x1, y1, x2, y2};
auto right = init.right.begin();
RendererApi::PointI<2>::component_t cy = (*right).y;
RendererApi::PointI<2>::component_t sx = std::numeric_limits<RendererApi::PointI<2>::component_t>::min();
RendererApi::PointI<2>::component_t ex = std::numeric_limits<RendererApi::PointI<2>::component_t>::max();
auto loop = [&](brezenham_line_iterable left) {
for (auto lp: left) {
if (lp.y == cy) {
receiver(true, lp.x, lp.y);
sx = (lp.x > sx) ? (lp.x) : sx;
continue;
}
for (; (*right).y > lp.y; right++) {
if ((*right).x > sx)
receiver(true, (*right).x, (*right).y);
ex = ((*right).x < ex) ? ((*right).x) : ex;
}
for (RendererApi::PointI<2>::component_t x = sx + 1; x < ex; x++)
receiver(false, x, cy);
cy--;
receiver(true, lp.x, lp.y);
}
};
loop(init.upper_left);
loop(init.lower_left);
for (; right != nullptr; right++) {
if ((*right).x > sx)
receiver(true, (*right).x, (*right).y);
}
}
}

View File

@ -25,4 +25,22 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
} }
); );
} }
void DefaultVoxelDrawerCache::VoxelPainterImpl::draw_h_line(
RendererApi::PointI<2>::component_t y,
RendererApi::PointI<2>::component_t left,
RendererApi::PointI<2>::component_t right,
double z,
RendererApi::Color::Transparent color,
RendererApi::SpriteMetadata *owner
) {
if (y < 0 || y >= this->_height) return;
if (left < 0) left = 0;
if (right >= this->_width) right = this->_width;
for (RendererApi::PointI<2>::component_t x = left; x < right; x++) {
this->_add_voxel(x, y, z, color, owner);
}
}
} }

View File

@ -1,19 +0,0 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shader.hpp>
namespace BGTU::ComputerGraphicsLabWork::Utilities {
class EmptyShader : public Shader {
public:
EmptyShader() = default;
[[nodiscard]] RendererApi::Color::Transparent get_color(double x, double y) const override {
return RendererApi::Color::Transparent{0, 0, 0, 0};
}
};
static const EmptyShader empty_shader_instance;
Shader const *Shader::empty_shader = &empty_shader_instance;
}