From 4a9ed23ab985163d0087b756e371bcfd2b9ea28c Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Wed, 25 Dec 2024 12:50:35 +0300 Subject: [PATCH] Sun sprite --- CMakeLists.txt | 1 + programs/lab3/CMakeLists.txt | 9 +++ programs/lab3/src/main.cpp | 59 ++++++++++++++ programs/lab3/src/sprite_data.hpp | 81 +++++++++++++++++++ programs/lab3/src/variant1.cpp | 76 +++++++++++++++++ programs/lab3/src/variant1.hpp | 10 +++ programs/labs1_2/src/main.cpp | 4 - .../utilities/matrix.hpp | 45 +++++++++++ 8 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 programs/lab3/CMakeLists.txt create mode 100644 programs/lab3/src/main.cpp create mode 100644 programs/lab3/src/sprite_data.hpp create mode 100644 programs/lab3/src/variant1.cpp create mode 100644 programs/lab3/src/variant1.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 768ea1e..0908766 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,3 +20,4 @@ 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 diff --git a/programs/lab3/CMakeLists.txt b/programs/lab3/CMakeLists.txt new file mode 100644 index 0000000..376b345 --- /dev/null +++ b/programs/lab3/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable( + lab3 + + src/main.cpp + src/sprite_data.hpp + src/variant1.cpp + +) +target_link_libraries(lab3 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities) \ No newline at end of file diff --git a/programs/lab3/src/main.cpp b/programs/lab3/src/main.cpp new file mode 100644 index 0000000..8649011 --- /dev/null +++ b/programs/lab3/src/main.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sprite_data.hpp" +#include "variant1.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Impl { + int main(int argc, char **argv) { +#if 1 + QApplication qApplication{argc, argv}; + + SpriteData::Provider sprites_data{0.1}; + + QMainWindow w{}; + + QtUtilities::KeyboardCatcherWidget kbd{&w}; + + QtUtilities::SeparateThreadedDefaultRendererLinear renderer{}; + renderer.set_sprite_data_provider(&sprites_data); + renderer.set_sprites(sprites, sprites_count); + renderer.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0}); + + QtUtilities::RendererWidget canvas{&renderer, &kbd}; + QObject::connect(&canvas, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data, &SpriteData::Provider::set_frame_size); + w.setCentralWidget(&canvas); + w.show(); + + QApplication::exec(); + + return 0; +#else + Utilities::Matrix3d x = Utilities::Matrix3d::shift(10, 10); + Utilities::Matrix3d y = x.inversed(); + + RendererApi::PointF<2> a{0, 0}; + RendererApi::PointF<2> b = x * a; + RendererApi::PointF<2> c = y * a; + RendererApi::PointF<2> d = y * b; + + + 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/lab3/src/sprite_data.hpp b/programs/lab3/src/sprite_data.hpp new file mode 100644 index 0000000..a8416a5 --- /dev/null +++ b/programs/lab3/src/sprite_data.hpp @@ -0,0 +1,81 @@ +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace BGTU::ComputerGraphicsLabWork::Impl { + class _Lab3SpriteData_Provider; + + + struct SpriteData { + public: + RendererApi::PointI<2> central_pixel; + double radius_multiplier; + Utilities::Matrix3d planets_transform[9]; + Utilities::Matrix3d stars_transform; + double time_ms; + using Provider = _Lab3SpriteData_Provider; + + }; + + class _Lab3SpriteData_Provider : public QObject, public RendererApi::Sprite::SpriteDataProvider { + Q_OBJECT + private: + QMutex sync; + QElapsedTimer time; + RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h; + + public: + explicit _Lab3SpriteData_Provider(double radians_per_second) : + sync{}, time{}, + w{0}, h{0} {} + + SpriteData get_sprite_data() override { + this->sync.lock(); + double radius = (((this->w < this->h) ? this->w : this->h) * 5 / 16.0); + Utilities::Matrix3d center_shift = Utilities::Matrix3d::shift(this->w / 2, this->h / 2); + Utilities::Matrix3d scale = Utilities::Matrix3d::scale(radius); + double current_time = this->time.elapsed(); + SpriteData cached{ + .central_pixel = RendererApi::PointI<2>(this->w, this->h) / 2, + .radius_multiplier = radius, + .planets_transform = { + center_shift * Utilities::Matrix3d::scale(radius), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 1.5), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 1.2), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 1), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.9), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.5), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.45), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.2), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.17), + }, + .stars_transform = Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.02) * scale * center_shift, + .time_ms = current_time + + }; + 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(); + } + }; +} \ No newline at end of file diff --git a/programs/lab3/src/variant1.cpp b/programs/lab3/src/variant1.cpp new file mode 100644 index 0000000..e6dd185 --- /dev/null +++ b/programs/lab3/src/variant1.cpp @@ -0,0 +1,76 @@ +#include +#include +#include + +#include "variant1.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Impl { + namespace { + + template + class TransformedShader : public Utilities::Shader { + private: + Utilities::Matrix3d transform; + real_shader_t real_shader; + public: + TransformedShader(Utilities::Matrix3d transform, real_shader_t real_shader) : transform{transform}, real_shader{real_shader} {}; + + [[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final { + auto p = this->transform * RendererApi::PointF<2>{x, y}; + return this->real_shader.get_color(p.x, p.y); + } + }; + + template + class SunShader : public Utilities::Shader { + private: + public: + SunShader() = default; + + [[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final { + RendererApi::PointF<2>::component_t distance = std::hypot(x, y) / radius; + if (distance > 1) + return RendererApi::Color::Transparent{255, 255, 0, 0}; + if (distance > 0.8) + return Utilities::colors_gradient(RendererApi::Color::Transparent{255, 255, 0, 0}, (distance - 0.8) * 5, RendererApi::Color::Transparent{255, 255, 0, 255}); + else if (distance > 0.3) + return Utilities::colors_gradient(RendererApi::Color::Transparent{255, 255, 0, 255}, (distance - 0.3) * 10 / 5, RendererApi::Color::Transparent{255, 255, 200, 255}); + else + return RendererApi::Color::Transparent{255, 255, 200, 255}; + } + }; + + template + class SunSprite : public RendererApi::Sprite { + + private: + public: + SunSprite() = default; + + void draw(BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const BGTU::ComputerGraphicsLabWork::Impl::SpriteData *data) const final { + TransformedShader> shader{data->planets_transform[0].inversed(), SunShader{}}; + Utilities::Shapes::iterate_circle_fill( + static_cast< RendererApi::PointI<2>>(data->planets_transform[0] * RendererApi::PointF<2>{0, 0}), + data->radius_multiplier * radius, + [&](bool, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { + frame->add_voxel(x, y, z, shader.get_color(x, y)); + } + ); + + } + }; + + + SunSprite<1.0, 0.1> sun_sprite{}; + + + RendererApi::Sprite *_sprites[]{ + &sun_sprite + }; + + } + + + RendererApi::Sprite **const sprites = _sprites; + std::size_t sprites_count = 1; +} \ No newline at end of file diff --git a/programs/lab3/src/variant1.hpp b/programs/lab3/src/variant1.hpp new file mode 100644 index 0000000..7c5f38f --- /dev/null +++ b/programs/lab3/src/variant1.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/programs/labs1_2/src/main.cpp b/programs/labs1_2/src/main.cpp index f63aa9e..4bf62db 100644 --- a/programs/labs1_2/src/main.cpp +++ b/programs/labs1_2/src/main.cpp @@ -16,10 +16,6 @@ #include "zoomed_scene_sprite.hpp" namespace BGTU::ComputerGraphicsLabWork::Impl { - - volatile RendererApi::Color bg{0, 0, 0}; - RendererApi::Color::Transparent fg{255, 255, 255, 127}; - int main(int argc, char **argv) { #if 1 QApplication qApplication{argc, argv}; diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp index ac3eb58..5ee6ddd 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp @@ -94,6 +94,12 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { 0, 0, 1}; } + static Matrix3 scale(elem_t s) { + return Matrix3{s, 0, 0, + 0, s, 0, + 0, 0, 1}; + } + static Matrix3 rotate(elem_t radians) { auto s = std::sin(radians); auto c = std::cos(radians); @@ -114,6 +120,38 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { this->data[1][0] * other.x + this->data[1][1] * other.y + this->data[1][2], }; } + + elem_t det() const { + return this->data[0][0] * (this->data[1][1] * this->data[2][2] - this->data[1][2] * this->data[2][1]) - + this->data[0][1] * (this->data[1][0] * this->data[2][2] - this->data[1][2] * this->data[2][0]) + + this->data[0][2] * (this->data[1][0] * this->data[2][1] - this->data[1][1] * this->data[2][0]); + } + + Matrix3 adj() const { + return Matrix3{ + this->data[1][1] * this->data[2][2] - this->data[1][2] * this->data[2][1], + -(this->data[1][0] * this->data[2][2] - this->data[1][2] * this->data[2][0]), + this->data[1][0] * this->data[2][1] - this->data[1][1] * this->data[2][0], + -(this->data[0][1] * this->data[2][2] - this->data[0][2] * this->data[2][1]), + this->data[0][0] * this->data[2][2] - this->data[0][2] * this->data[2][0], + -(this->data[0][0] * this->data[2][1] - this->data[0][1] * this->data[2][0]), + this->data[0][1] * this->data[1][2] - this->data[0][2] * this->data[1][1], + -(this->data[0][0] * this->data[1][2] - this->data[0][2] * this->data[1][0]), + this->data[0][0] * this->data[1][1] - this->data[0][1] * this->data[1][0] + }; + } + + Matrix3 transposed() const { + return Matrix3{ + this->data[0][0], this->data[1][0], this->data[2][0], + this->data[0][2], this->data[1][1], this->data[2][1], + this->data[0][1], this->data[1][2], this->data[2][2] + }; + } + + Matrix3 inversed() const { + return this->adj().transposed() / this->det(); + } }; using Matrix3i = Matrix3; @@ -221,6 +259,13 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { 0, 0, 0, 1}; } + static Matrix4 scale(elem_t s) { + return Matrix4{s, 0, 0, 0, + 0, s, 0, 0, + 0, 0, s, 0, + 0, 0, 0, 1}; + } + static Matrix4 rotate_x(elem_t radians) { auto s = std::sin(radians);