diff --git a/CMakeLists.txt b/CMakeLists.txt index 0908766..1bb7050 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_AUTOMOC ON) enable_language(ASM_NASM) -option(__AVX2__ "Tells compiler to use AVX2 extension if possible" OFF) +option(__AVX2__ "Tells compiler to use AVX2 extension if possible" ON) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if (__AVX2__) @@ -20,4 +20,5 @@ add_subdirectory(renderer-api) add_subdirectory(utilities) add_subdirectory(qt-utilities) add_subdirectory(programs/labs1_2) -add_subdirectory(programs/lab3) \ No newline at end of file +add_subdirectory(programs/lab3) +add_subdirectory(programs/lab4) \ No newline at end of file diff --git a/programs/lab4/CMakeLists.txt b/programs/lab4/CMakeLists.txt new file mode 100644 index 0000000..2630eea --- /dev/null +++ b/programs/lab4/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable( + lab4 + + src/main.cpp + src/sprite_data.hpp + src/variant4.cpp + +) +target_link_libraries(lab4 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities) \ No newline at end of file diff --git a/programs/lab4/src/main.cpp b/programs/lab4/src/main.cpp new file mode 100644 index 0000000..d7a8132 --- /dev/null +++ b/programs/lab4/src/main.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sprite_data.hpp" +#include "variant4.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Impl { + int main(int argc, char **argv) { +#if 1 + QApplication qApplication{argc, argv}; + + SpriteData::Provider sprites_data_front{0.0, 0.0, 1.01}; + SpriteData::Provider sprites_data_side{std::numbers::pi_v / 2, 0, 1.01}; + sprites_data_side.inc_x_angle(); + SpriteData::Provider sprites_data_up{0, std::numbers::pi_v / 2, 1.01}; + sprites_data_up.inc_y_angle(); + SpriteData::Provider sprites_data_custom{0.1, 0.1, 1.01}; + + QMainWindow w{}; + + + QtUtilities::KeyboardCatcherWidget kbd{&w}; + + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Left, &sprites_data_custom, &SpriteData::Provider::dec_y_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Right, &sprites_data_custom, &SpriteData::Provider::inc_y_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Down, &sprites_data_custom, &SpriteData::Provider::dec_x_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Up, &sprites_data_custom, &SpriteData::Provider::inc_x_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_A, &sprites_data_custom, &SpriteData::Provider::dec_y_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_D, &sprites_data_custom, &SpriteData::Provider::inc_y_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_S, &sprites_data_custom, &SpriteData::Provider::dec_x_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_W, &sprites_data_custom, &SpriteData::Provider::inc_x_angle); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data_front, &SpriteData::Provider::dec_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data_front, &SpriteData::Provider::inc_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data_side, &SpriteData::Provider::dec_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data_side, &SpriteData::Provider::inc_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data_up, &SpriteData::Provider::dec_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data_up, &SpriteData::Provider::inc_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data_custom, &SpriteData::Provider::dec_scale); + QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data_custom, &SpriteData::Provider::inc_scale); + + + + QtUtilities::SeparateThreadedDefaultRendererLinear renderer_front{}; + renderer_front.set_sprite_data_provider(&sprites_data_front); + renderer_front.set_sprites(sprites, sprites_count); + renderer_front.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); + QtUtilities::SeparateThreadedDefaultRendererLinear renderer_side{}; + renderer_side.set_sprite_data_provider(&sprites_data_side); + renderer_side.set_sprites(sprites, sprites_count); + renderer_side.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); + QtUtilities::SeparateThreadedDefaultRendererLinear renderer_up{}; + renderer_up.set_sprite_data_provider(&sprites_data_up); + renderer_up.set_sprites(sprites, sprites_count); + renderer_up.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); + QtUtilities::SeparateThreadedDefaultRendererLinear renderer_custom{}; + renderer_custom.set_sprite_data_provider(&sprites_data_custom); + renderer_custom.set_sprites(sprites, sprites_count); + renderer_custom.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); + + + QGridLayout layout{&kbd}; + kbd.setLayout(&layout); + + QtUtilities::RendererWidget canvas_front{&renderer_front, &kbd}; + layout.addWidget(&canvas_front, 0, 0); + QObject::connect(&canvas_front, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data_front, &SpriteData::Provider::set_frame_size); + QtUtilities::RendererWidget canvas_side{&renderer_side, &kbd}; + layout.addWidget(&canvas_side, 0, 1); + QObject::connect(&canvas_side, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data_side, &SpriteData::Provider::set_frame_size); + QtUtilities::RendererWidget canvas_up{&renderer_up, &kbd}; + layout.addWidget(&canvas_up, 1, 0); + QObject::connect(&canvas_up, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data_up, &SpriteData::Provider::set_frame_size); + QtUtilities::RendererWidget canvas_custom{&renderer_custom, &kbd}; + layout.addWidget(&canvas_custom, 1, 1); + QObject::connect(&canvas_custom, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data_custom, &SpriteData::Provider::set_frame_size); + + + w.setCentralWidget(&kbd); + w.show(); + + QApplication::exec(); + + return 0; +#else + Utilities::Matrix3d x = Utilities::Matrix3d::shift(0, 9); + Utilities::Matrix3d y = Utilities::Matrix3d::rotate(3.14); + + RendererApi::PointF<2> a{0, 1}; + RendererApi::PointF<2> b = x * a; + RendererApi::PointF<2> c = x * y * a; + RendererApi::PointF<2> d = y * x * a; + + + return 0; +#endif + } +} + + +int main(int argc, char **argv) { + return BGTU::ComputerGraphicsLabWork::Impl::main(argc, argv); +} \ No newline at end of file diff --git a/programs/lab4/src/sprite_data.hpp b/programs/lab4/src/sprite_data.hpp new file mode 100644 index 0000000..4dc68e4 --- /dev/null +++ b/programs/lab4/src/sprite_data.hpp @@ -0,0 +1,105 @@ +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace BGTU::ComputerGraphicsLabWork::Impl { + class _Lab3SpriteData_Provider; + + + struct SpriteData { + public: + Utilities::Matrix4d transform; + using Provider = _Lab3SpriteData_Provider; + + }; + + class _Lab3SpriteData_Provider : public QObject, public RendererApi::Sprite::SpriteDataProvider { + Q_OBJECT + private: + QMutex sync; + double x_angle; + double y_angle; + double scale; + + double x_angle_step; + double y_angle_step; + double scale_step; + + RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h; + + public: + explicit _Lab3SpriteData_Provider( + double x_angle_step, + double y_angle_step, + double scale_step + ) : x_angle{0}, y_angle{0}, scale{1}, x_angle_step{x_angle_step}, y_angle_step{y_angle_step}, scale_step{scale_step}, + w{0}, h{0} {} + + SpriteData get_sprite_data() override { + this->sync.lock(); + double radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16.0); + SpriteData cached{ + .transform = Utilities::Matrix4d::shift(this->w / 2, this->h / 2, radius * 2) * Utilities::Matrix4d::rotate_x(this->x_angle) * Utilities::Matrix4d::rotate_y(this->y_angle) * Utilities::Matrix4d::scale(this->scale) * Utilities::Matrix4d::scale(radius) + }; + this->sync.unlock(); + return cached; + } + + public slots: + + void set_frame_size(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t ww, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t hh) { + this->sync.lock(); + this->w = ww; + this->h = hh; + this->sync.unlock(); + } + + void inc_x_angle() { + this->sync.lock(); + this->x_angle += this->x_angle_step; + this->sync.unlock(); + } + + void dec_x_angle() { + this->sync.lock(); + this->x_angle -= this->x_angle_step; + this->sync.unlock(); + } + + void inc_y_angle() { + this->sync.lock(); + this->y_angle += this->y_angle_step; + this->sync.unlock(); + } + + void dec_y_angle() { + this->sync.lock(); + this->y_angle -= this->y_angle_step; + this->sync.unlock(); + } + + void inc_scale() { + this->sync.lock(); + this->scale *= this->scale_step; + this->sync.unlock(); + } + + void dec_scale() { + this->sync.lock(); + this->scale /= this->scale_step; + this->sync.unlock(); + } + }; +} \ No newline at end of file diff --git a/programs/lab4/src/variant4.cpp b/programs/lab4/src/variant4.cpp new file mode 100644 index 0000000..c8ca4a7 --- /dev/null +++ b/programs/lab4/src/variant4.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include + +#include "sprite_data.hpp" +#include "variant4.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Impl { + namespace { + constexpr RendererApi::Color::Transparent edge_color{0, 255, 255, 200}; + + class Triangle : public RendererApi::Sprite { + private: + const RendererApi::PointF<3> a, b, c; + public: + constexpr Triangle(RendererApi::PointF<3> a, RendererApi::PointF<3> b, RendererApi::PointF<3> c) : a{a}, b{b}, c{c} {} + + private: + void draw(BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const BGTU::ComputerGraphicsLabWork::Impl::SpriteData *data) const final { + RendererApi::PointF<3> ta = data->transform * this->a; + RendererApi::PointF<3> tb = data->transform * this->b; + RendererApi::PointF<3> tc = data->transform * this->c; + + Utilities::Shapes::triangle_barycentric_interpolator z_interpolator{ + {ta.x, ta.y}, + {tb.x, tb.y}, + {tc.x, tc.y}, + ta.z, tb.z, tc.z + }; + + Utilities::Shapes::iterate_triangle_fill( + ta.x, ta.y, + tb.x, tb.y, + tc.x, tc.y, + [&](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { + if (is_edge) + frame->add_voxel(x, y, z_interpolator.interpolate_point(x, y), edge_color); + } + ); + } + }; + + constexpr RendererApi::PointF<3> angle5(double angle, double len) { + return {std::cos(std::numbers::pi_v / 5 * angle) * len, std::sin(std::numbers::pi_v / 5 * angle) * len, 0}; + } + + + Triangle triangles[] = { + {{0.0, 0.0, 1.0}, angle5(0, 2), angle5(1, 1)}, + {{0.0, 0.0, -1.0}, angle5(0, 2), angle5(1, 1)}, + {{0.0, 0.0, 1.0}, angle5(2, 2), angle5(1, 1)}, + {{0.0, 0.0, -1.0}, angle5(2, 2), angle5(1, 1)}, + {{0.0, 0.0, 1.0}, angle5(2, 2), angle5(3, 1)}, + {{0.0, 0.0, -1.0}, angle5(2, 2), angle5(3, 1)}, + {{0.0, 0.0, 1.0}, angle5(4, 2), angle5(3, 1)}, + {{0.0, 0.0, -1.0}, angle5(4, 2), angle5(3, 1)}, + {{0.0, 0.0, 1.0}, angle5(4, 2), angle5(5, 1)}, + {{0.0, 0.0, -1.0}, angle5(4, 2), angle5(5, 1)}, + {{0.0, 0.0, 1.0}, angle5(6, 2), angle5(5, 1)}, + {{0.0, 0.0, -1.0}, angle5(6, 2), angle5(5, 1)}, + {{0.0, 0.0, 1.0}, angle5(6, 2), angle5(7, 1)}, + {{0.0, 0.0, -1.0}, angle5(6, 2), angle5(7, 1)}, + {{0.0, 0.0, 1.0}, angle5(8, 2), angle5(7, 1)}, + {{0.0, 0.0, -1.0}, angle5(8, 2), angle5(7, 1)}, + {{0.0, 0.0, 1.0}, angle5(8, 2), angle5(9, 1)}, + {{0.0, 0.0, -1.0}, angle5(8, 2), angle5(9, 1)}, + {{0.0, 0.0, 1.0}, angle5(0, 2), angle5(9, 1)}, + {{0.0, 0.0, -1.0}, angle5(0, 2), angle5(9, 1)}, + }; + + RendererApi::Sprite *_sprites[]{ + &triangles[0], + &triangles[1], + &triangles[2], + &triangles[3], + &triangles[4], + &triangles[5], + &triangles[6], + &triangles[7], + &triangles[8], + &triangles[9], + &triangles[10], + &triangles[11], + &triangles[12], + &triangles[13], + &triangles[14], + &triangles[15], + &triangles[16], + &triangles[17], + &triangles[18], + &triangles[19], + }; + } + + + RendererApi::Sprite **const sprites = _sprites; + std::size_t sprites_count = 20; +} diff --git a/programs/lab4/src/variant4.hpp b/programs/lab4/src/variant4.hpp new file mode 100644 index 0000000..7c5f38f --- /dev/null +++ b/programs/lab4/src/variant4.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include +#include "sprite_data.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Impl { + extern RendererApi::Sprite ** const sprites; + extern std::size_t sprites_count; +} \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/keyboard_catcher_widget.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/keyboard_catcher_widget.hpp index b9330cc..7246993 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/keyboard_catcher_widget.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/keyboard_catcher_widget.hpp @@ -68,6 +68,22 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { void key_pressed_F12(); + void key_pressed_Up(); + + void key_pressed_Down(); + + void key_pressed_Left(); + + void key_pressed_Right(); + + void key_pressed_W(); + + void key_pressed_A(); + + void key_pressed_S(); + + void key_pressed_D(); + protected: void keyPressEvent(QKeyEvent *event) override { switch (event->key()) { @@ -146,6 +162,30 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { case Qt::Key_F12: emit this->key_pressed_F12(); return; + case Qt::Key_Up: + emit this->key_pressed_Up(); + return; + case Qt::Key_Down: + emit this->key_pressed_Down(); + return; + case Qt::Key_Left: + emit this->key_pressed_Left(); + return; + case Qt::Key_Right: + emit this->key_pressed_Right(); + return; + case Qt::Key_W: + emit this->key_pressed_W(); + return; + case Qt::Key_A: + emit this->key_pressed_A(); + return; + case Qt::Key_D: + emit this->key_pressed_D(); + return; + case Qt::Key_S: + emit this->key_pressed_S(); + return; } } diff --git a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp index d3c6f86..ca93ecc 100644 --- a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp +++ b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp @@ -63,7 +63,7 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { component_t y; component_t z; - inline Point(component_t x, component_t y, component_t z) : x{x}, y{y}, z{z} {} + constexpr Point(component_t x, component_t y, component_t z) : x{x}, y{y}, z{z} {} template @@ -72,21 +72,31 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { } - Point<3, _component_t> operator+(Point<2, _component_t> const &other) const { + constexpr Point<3, _component_t> operator+(Point<2, _component_t> const &other) const { return Point<3, _component_t>{this->x + other.x, this->y + other.y, this->z + other.z}; } - Point<3, _component_t> operator-(Point<2, _component_t> const &other) const { + constexpr Point<3, _component_t> operator-(Point<2, _component_t> const &other) const { return Point<3, _component_t>{this->x - other.x, this->y - other.y, this->z - other.z}; } - Point<3, _component_t> operator*(_component_t const &other) const { + constexpr Point<3, _component_t> operator*(_component_t const &other) const { return Point<3, _component_t>{this->x * other, this->y * other, this->z * other}; } - Point<3, _component_t> operator/(_component_t const &other) const { + constexpr Point<3, _component_t> operator/(_component_t const &other) const { return Point<3, _component_t>{this->x / other, this->y / other, this->z / other}; } + + template, void>::type> + [[nodiscard]] constexpr explicit operator Point<3, double>() const noexcept { + return Point<3, double>{(double) this->x, (double) this->y, (double) this->z}; + } + + template, void>::type> + [[nodiscard]] constexpr explicit operator Point<3, long long>() const noexcept { + return Point<3, long long>{(long long) this->x, (long long) this->y, (long long) this->z}; + } }; template diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp index 4e9d402..3f98307 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp @@ -287,27 +287,30 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { 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 = [&](intermediate_t (variable_t::*offset)) -> intermediate_t { - return static_cast((this->v0.*offset) * k0 + (this->v1.*offset) * k1 + (this->v2.*offset) * k2); - }; - if constexpr (std::is_same_v) { - 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) { - return RendererApi::Color{ - f(&RendererApi::Color::red), - f(&RendererApi::Color::green), - f(&RendererApi::Color::blue) + + if constexpr (std::is_same_v || std::is_same_v) { + auto f = [&](intermediate_t (variable_t::*offset)) -> intermediate_t { + return static_cast((this->v0.*offset) * k0 + (this->v1.*offset) * k1 + (this->v2.*offset) * k2); }; + if constexpr (std::is_same_v) { + 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 { + return RendererApi::Color{ + f(&RendererApi::Color::red), + f(&RendererApi::Color::green), + f(&RendererApi::Color::blue) + }; + } } else { - return static_cast(f(&variable_t::variable_t)); + return static_cast((this->v0) * k0 + (this->v1) * k1 + (this->v2) * k2); } }