diff --git a/programs/labs1_5/src/main.cpp b/programs/labs1_5/src/main.cpp index 6b76317..7286879 100644 --- a/programs/labs1_5/src/main.cpp +++ b/programs/labs1_5/src/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "variants/sprite_data.hpp" #include "keyboard_catcher_widget.hpp" #include "pixel_grid_sprite.hpp" @@ -77,15 +78,29 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { return 0; #else +//Utilities::Shapes::iterate_line(-3,-3, 3, 0, [](long long x, long long y) { +// std::cout << x << "\t\t" << y << std::endl; +//}); +//return 0; - for (int y = 3; y >= -3; y--) { - for (int x = -3; x <= 3; x++) { -// if (x != 0) { - std::cout /*<< '(' << y << ',' << x << '|' << (double)y / (double)x << '|'*/ << std::atan2((double) y , (double) x) / std::numbers::pi_v * 360 << "\t "; -// } - } - std::cout << std::endl; - } + Utilities::Shapes::iterate_triangle_fill_h_lines( + -1, -3, + 3, 0, + -2, 3, + [](long long x, long long y) { + std::cout << x << "\t" << y << std::endl; + }, + [](long long y, long long x1, long long x2) { std::cout << x1 << ">" << x2 << '\t' << y << std::endl; } + ); + +// for (int y = 3; y >= -3; y--) { +// for (int x = -3; x <= 3; x++) { +//// if (x != 0) { +// std::cout /*<< '(' << y << ',' << x << '|' << (double)y / (double)x << '|'*/ << std::atan2((double) y , (double) x) / std::numbers::pi_v * 360 << "\t "; +//// } +// } +// std::cout << std::endl; +// } // auto c = Utilities::apply_transparent_color(*(RendererApi::Color *) &bg, fg); // std::cout << c.red << c.green << c.blue << std::endl; diff --git a/programs/labs1_5/src/variants/lab2/variant3.cpp b/programs/labs1_5/src/variants/lab2/variant3.cpp index a58c6e3..f979234 100644 --- a/programs/labs1_5/src/variants/lab2/variant3.cpp +++ b/programs/labs1_5/src/variants/lab2/variant3.cpp @@ -2,12 +2,30 @@ #include #include #include +#include #include #include "../variants.hpp" #include "../sprite_data.hpp" namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab2 { namespace { + class HsvSectorShader : public Utilities::Shader { + private: + RendererApi::PointF<2>::component_t cx, cy; + double angle_offset_radians; + public: + HsvSectorShader(RendererApi::PointF<2>::component_t cx, RendererApi::PointF<2>::component_t cy, double angle_offset_radians) : cx{cx}, cy{cy}, angle_offset_radians{angle_offset_radians} {} + + HsvSectorShader(RendererApi::PointF<2> c, double angle_offset_radians) : cx{c.x}, cy{c.y}, angle_offset_radians{angle_offset_radians} {} + + HsvSectorShader(RendererApi::PointI<2> c, double angle_offset_radians) : cx{(double) c.x}, cy{(double) c.y}, angle_offset_radians{angle_offset_radians} {} + + [[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final { + double angle = std::atan2(static_cast(y - this->cy), static_cast(x - this->cx)) + this->angle_offset_radians; + return Utilities::hsv_to_rgb_360_1_1(std::fmod(std::fmod(angle / std::numbers::pi_v * 180, 360.0) + 360, 360.0), 1.0, 1.0); + } + }; + template class Circle : public RendererApi::Sprite> { private: @@ -40,23 +58,6 @@ namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab2 { } }; - class HsvSectorShader : public Utilities::Shader { - private: - RendererApi::PointF<2>::component_t cx, cy; - double angle_offset_radians; - public: - HsvSectorShader(RendererApi::PointF<2>::component_t cx, RendererApi::PointF<2>::component_t cy, double angle_offset_radians) : cx{cx}, cy{cy}, angle_offset_radians{angle_offset_radians} {} - - HsvSectorShader(RendererApi::PointF<2> c, double angle_offset_radians) : cx{c.x}, cy{c.y}, angle_offset_radians{angle_offset_radians} {} - - HsvSectorShader(RendererApi::PointI<2> c, double angle_offset_radians) : cx{(double) c.x}, cy{(double) c.y}, angle_offset_radians{angle_offset_radians} {} - - [[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final { - double angle = std::atan2(static_cast(y - this->cy), static_cast(x - this->cx)) + this->angle_offset_radians; - return Utilities::hsv_to_rgb_360_1_1(std::fmod(std::fmod(angle / std::numbers::pi_v * 180, 360.0) + 360, 360.0), 1.0, 1.0); - } - }; - enum class ShaderType : unsigned { SOLID_RED, SOLID_GREEN, @@ -216,9 +217,111 @@ namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab2 { this->sync.unlock(); } }; + + template + class Triangle : public RendererApi::Sprite> { + private: + enum class ShaderType : unsigned { + SOLID_RED, + SOLID_GREEN, + SOLID_BLUE, + SECTOR_STATIC, + SECTOR_ROTATED_POS, + SECTOR_ROTATED_NEG, + BARYCENTRIC, + BARYCENTRIC_SEMI_TRANSPARENT, + }; + + static inline ShaderType const next_shader_type[] = { + ShaderType::SOLID_GREEN, + ShaderType::SOLID_BLUE, + ShaderType::SECTOR_STATIC, + ShaderType::SECTOR_ROTATED_POS, + ShaderType::SECTOR_ROTATED_NEG, + ShaderType::BARYCENTRIC, + ShaderType::BARYCENTRIC_SEMI_TRANSPARENT, + ShaderType::SOLID_RED, + }; + + QMutex sync; + ShaderType current_shader; + + template + void _select_shader(SpriteData::ShapeData const *data, receiver_t receiver) const { + const_cast(&(this->sync))->lock(); + ShaderType t = this->current_shader; + const_cast(&(this->sync))->unlock(); + switch (t) { + case ShaderType::SOLID_RED: { + auto s = Utilities::MonoShader::static_; + receiver(s); + return; + } + case ShaderType::SOLID_GREEN: { + auto s = Utilities::MonoShader::static_; + receiver(s); + return; + } + case ShaderType::SOLID_BLUE: { + auto s = Utilities::MonoShader::static_; + receiver(s); + return; + } + case ShaderType::SECTOR_STATIC: { + HsvSectorShader s{0, 0, 0}; + receiver(s); + return; + } + case ShaderType::SECTOR_ROTATED_POS: { + HsvSectorShader s{0, 0, data->rotation_radians}; + receiver(s); + return; + } + case ShaderType::SECTOR_ROTATED_NEG: { + HsvSectorShader s{0, 0, -data->rotation_radians}; + receiver(s); + return; + } + case ShaderType::BARYCENTRIC: + case ShaderType::BARYCENTRIC_SEMI_TRANSPARENT:; + } + }; + public: + Triangle() : sync{}, current_shader{ShaderType::SOLID_RED} {} + + + Triangle(Triangle &&other) noexcept: sync{}, current_shader{other.current_shader} {} + + void draw(Utilities::ZoomedVoxelPainter *frame, SpriteData::ShapeData const *data) const final { + this->_select_shader( + data, + [&](shader_t const &shader) { + Utilities::Shapes::iterate_triangle_fill( + data->pos_rotated(data->radius * radius_multiplier, -120.0), + data->pos_rotated(data->radius * radius_multiplier, 0.0), + data->pos_rotated(data->radius * radius_multiplier, 120.0), + [&](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { + if (is_edge) { + frame->add_voxel(x, y, z, edge_color); + } else { + frame->add_voxel(x, y, z, shader.get_color(x, y)); + } + } + ); + } + ); + } + + void clicked() final { + this->sync.lock(); + this->current_shader = next_shader_type[(unsigned) this->current_shader]; + this->sync.unlock(); + } + }; } variant_sprites variant3 = variant_sprites::make( Circle<4.0, {255, 255, 255}, 0.0, 0.0, 1.0>{}, + Triangle<3.0, {255, 255, 255}, 1.0>{}, Circle<2.0, {255, 255, 255}, 0.6666666666666, 0.0, 0.16666666666666666>{}, Circle<2.0, {255, 255, 255}, 0.6666666666666, 120.0, 0.16666666666666666>{}, Circle<2.0, {255, 255, 255}, 0.6666666666666, -120.0, 0.16666666666666666>{}, diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shader.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shader.hpp index 33d64ba..0fa0b6b 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shader.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shader.hpp @@ -87,7 +87,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { return dynamic_cast(other) == nullptr; } - constexpr Shader::Empty const Shader::empty{}; + constexpr inline Shader::Empty const Shader::empty{}; class MonoShader : public Shader { private: diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/line.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/line.hpp index dd10915..87ca218 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/line.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/line.hpp @@ -8,8 +8,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { class brezenham_line_iterable { private: RendererApi::PointI<2>::component_t start_arg, start_ret, end_arg; - RendererApi::PointI<2>::component_t delta_ret, delta_arg; + RendererApi::PointI<2>::component_t delta_ret; RendererApi::PointI<2>::component_t delta_error, error_threshold; + bool is_reverse; bool swap_flag; public: constexpr brezenham_line_iterable( @@ -37,7 +38,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { this->delta_ret = (x2 > x1) ? 1 : -1; this->swap_flag = true; } - this->delta_arg = (this->end_arg > this->start_arg) ? 1 : -1; + this->is_reverse = this->end_arg < this->start_arg; } constexpr brezenham_line_iterable( @@ -48,29 +49,54 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { class iterator { private: RendererApi::PointI<2>::component_t arg, ret, end_arg; - RendererApi::PointI<2>::component_t delta_ret, delta_arg; + RendererApi::PointI<2>::component_t delta_ret; RendererApi::PointI<2>::component_t error, delta_error, error_threshold; bool swap_flag; + RendererApi::PointI<2> point; + bool is_ended; + bool is_reverse; constexpr iterator( RendererApi::PointI<2>::component_t arg, RendererApi::PointI<2>::component_t ret, RendererApi::PointI<2>::component_t end_arg, - RendererApi::PointI<2>::component_t delta_ret, RendererApi::PointI<2>::component_t delta_arg, + RendererApi::PointI<2>::component_t delta_ret, RendererApi::PointI<2>::component_t delta_error, RendererApi::PointI<2>::component_t error_threshold, - bool swap_flag - ) noexcept: arg{arg}, ret{ret}, end_arg{end_arg}, delta_ret{delta_ret}, delta_arg{delta_arg}, error{0}, delta_error{delta_error}, swap_flag{swap_flag}, error_threshold{error_threshold} {} + bool swap_flag, + bool is_reverse + ) noexcept: + arg{arg}, ret{ret}, end_arg{end_arg}, + delta_ret{delta_ret}, + error{0}, delta_error{delta_error}, error_threshold{error_threshold}, + swap_flag{swap_flag}, point{swap_flag ? ret : arg, swap_flag ? arg : ret}, + is_ended{false}, + is_reverse{is_reverse} {} friend class brezenham_line_iterable; public: constexpr iterator &operator++() noexcept { - if (*this == nullptr) + if (this->is_ended) return *this; - this->arg += this->delta_arg; - this->error += this->delta_error; - if (this->error >= this->error_threshold) { - this->ret += this->delta_ret; - this->error -= this->error_threshold; + if (this->is_reverse) { + this->arg--; + this->error += this->delta_error; + if (this->error >= this->error_threshold) { + this->ret += this->delta_ret; + this->error -= this->error_threshold; + } + this->is_ended = this->arg < this->end_arg; + } else { + this->arg++; + this->error += this->delta_error; + if (this->error >= this->error_threshold) { + this->ret += this->delta_ret; + this->error -= this->error_threshold; + } + this->is_ended = this->arg > this->end_arg; } + if (this->swap_flag) + this->point = {this->ret, this->arg}; + else + this->point = {this->arg, this->ret}; return *this; } @@ -81,27 +107,29 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { } constexpr RendererApi::PointI<2> operator*() const noexcept { - if (this->swap_flag) - return {this->ret, this->arg}; - else - return {this->arg, this->ret}; + return this->point; + } + + constexpr RendererApi::PointI<2> const *operator->() const noexcept { + return &this->point; } constexpr bool operator==(std::nullptr_t) const noexcept { - return (this->arg > this->end_arg) ^ (this->delta_arg < 0); + return this->is_ended; } constexpr bool operator!=(std::nullptr_t) const noexcept { - return !(*this == nullptr); + return !this->is_ended; } }; [[nodiscard]] constexpr iterator begin() const noexcept { return iterator{ this->start_arg, this->start_ret, this->end_arg, - this->delta_ret, this->delta_arg, + this->delta_ret, this->delta_error, this->error_threshold, - this->swap_flag + this->swap_flag, + this->is_reverse }; } @@ -133,7 +161,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { ) { if (y2 < y1) std::swap(y1, y2); - for (RendererApi::PointI<2>::component_t y = y1; x <= y2; y++) { + for (RendererApi::PointI<2>::component_t y = y1; y <= y2; y++) { receiver(x, y); } } diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp index 7c9e6cc..41ae27d 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp @@ -27,14 +27,14 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { auto it = brezenham_line_iterable{points[i - 1], points[i]}.begin(); // it++; for (; it != nullptr; it++) { - receiver((*it).x, (*it).y); + receiver(it->x, it->y); } } if (points[0] != points[points_count - 1]) { auto it = brezenham_line_iterable{points[points_count - 1], points[0]}.begin(); // it++; for (; it != nullptr; it++) { - receiver((*it).x, (*it).y); + receiver(it->x, it->y); } } } 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 d41d4e2..2f396b5 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 @@ -6,170 +6,213 @@ #include #include #include "line.hpp" +#include "../shader.hpp" namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { - - template - void iterate_triangle_fill( + template + void iterate_triangle_fill_h_lines( 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 - 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}}; - } + edge_point_receiver_t edge_point_receiver, + fill_line_receiver_t fill_line_receiver + ) { + 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); }; - 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} {} + 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 && y0 != y2) + _swap(&x0, &y0, &x1, &y1); + if (y1 == y2 && x2 < x1) + _swap(&x1, &y1, &x2, &y2); - brezenham_line_iterable::iterator &_left() { - if (this->upper_left == nullptr) - return this->lower_left; - else - return this->upper_left; - } + auto _impl = [&]( + brezenham_line_iterable::iterator upper_cathetus, + brezenham_line_iterable::iterator lower_cathetus, + brezenham_line_iterable::iterator hypotenuse + ) { + RendererApi::PointI<2>::component_t x, ex, y; - public: - inline iterator &operator++() { - if (this->cx < this->ex) { - this->cx++; - return *this; + x = upper_cathetus->x; + y = upper_cathetus->y; + edge_point_receiver(x, y); + + UPPER_CATHETUS: + upper_cathetus++; + if (upper_cathetus == nullptr) { + goto LOWER_CATHETUS; } - if (this->upper_left != nullptr) { - RendererApi::PointI<2>::component_t sx = (*(this->upper_left)).x; + if (upper_cathetus->y < y) { while (true) { - this->upper_left++; - if (this->upper_left == nullptr) - goto LOWER; - if ((*(this->upper_left)).y < this->cy) - { - this->cy--; - return *this; + if constexpr (is_r2l) { + if (hypotenuse->x < x) { + edge_point_receiver(hypotenuse->x, hypotenuse->y); + ex = hypotenuse->x; + goto HYPOTENUSE_UPPER; + } + } else { + if (hypotenuse->x > x) { + edge_point_receiver(hypotenuse->x, hypotenuse->y); + ex = hypotenuse->x; + goto HYPOTENUSE_UPPER; + } + } - (*++(this->upper_left)).y >= this->cy - if ((*(this->upper_left)).x < sx) - return *this; + hypotenuse++; + if (hypotenuse->y < y) { + edge_point_receiver(upper_cathetus->x, upper_cathetus->y); + x = upper_cathetus->x; + y = upper_cathetus->y; + goto UPPER_CATHETUS; + } } + } + + edge_point_receiver(upper_cathetus->x, upper_cathetus->y); + if constexpr (is_r2l) { + x = ((x < upper_cathetus->x) ? x : (upper_cathetus->x)); } else { - LOWER: - RendererApi::PointI<2>::component_t sx = (*(this->upper_left)).x; + x = ((x > upper_cathetus->x) ? x : (upper_cathetus->x)); } - while ((*++(this->right)).y >= this->cy) { - if ((*(this->right)).x > this->ex) - return *this; + goto UPPER_CATHETUS; + + HYPOTENUSE_UPPER: + hypotenuse++; + if (hypotenuse->y < y) { + if constexpr (is_r2l) { + fill_line_receiver(y, ex + 1, x); + } else { + fill_line_receiver(y, x + 1, ex); + } + y--; + x = upper_cathetus->x; + edge_point_receiver(upper_cathetus->x, y); + goto UPPER_CATHETUS; } - this->cy--; + if constexpr (is_r2l) { + ex = ((ex > hypotenuse->x) ? ex : (hypotenuse->x)); + if (hypotenuse->x < x) + edge_point_receiver(hypotenuse->x, hypotenuse->y); + } else { + ex = ((ex < hypotenuse->x) ? ex : (hypotenuse->x)); + if (hypotenuse->x > x) + edge_point_receiver(hypotenuse->x, hypotenuse->y); + } + goto HYPOTENUSE_UPPER; + LOWER_CATHETUS: + lower_cathetus++; + if (lower_cathetus == nullptr) { + ex = x; + goto HYPOTENUSE_LOWER; + } + if (lower_cathetus->y < y) { + while (true) { + if constexpr (is_r2l) { + if (hypotenuse->x < x) { + edge_point_receiver(hypotenuse->x, hypotenuse->y); + ex = hypotenuse->x; + goto HYPOTENUSE_LOWER; + } + } else { + if (hypotenuse->x > x) { + edge_point_receiver(hypotenuse->x, hypotenuse->y); + ex = hypotenuse->x; + goto HYPOTENUSE_LOWER; + } + } + hypotenuse++; + if (hypotenuse->y < y) { + edge_point_receiver(lower_cathetus->x, lower_cathetus->y); + x = lower_cathetus->x; + y = lower_cathetus->y; + goto LOWER_CATHETUS; + } + } + } + + edge_point_receiver(lower_cathetus->x, lower_cathetus->y); + if constexpr (is_r2l) { + x = ((x < lower_cathetus->x) ? x : (lower_cathetus->x)); + } else { + x = ((x > lower_cathetus->x) ? x : (lower_cathetus->x)); + } + goto LOWER_CATHETUS; + + HYPOTENUSE_LOWER: + hypotenuse++; + if (hypotenuse == nullptr) { + return; + } + if (hypotenuse->y < y) { + if constexpr (is_r2l) { + fill_line_receiver(y, ex + 1, x); + } else { + fill_line_receiver(y, x + 1, ex); + } + y--; + x = lower_cathetus->x; + edge_point_receiver(lower_cathetus->x, y); + goto LOWER_CATHETUS; + } + if constexpr (is_r2l) { + ex = ((ex > hypotenuse->x) ? ex : (hypotenuse->x)); + if (hypotenuse->x < x) + edge_point_receiver(hypotenuse->x, hypotenuse->y); + } else { + ex = ((ex < hypotenuse->x) ? ex : (hypotenuse->x)); + if (hypotenuse->x > x) + edge_point_receiver(hypotenuse->x, hypotenuse->y); + } + goto HYPOTENUSE_LOWER; + }; + + auto dir = (x0 - x1) * (y2 - y1) - (x2 - x1) * (y0 - y1); + if (dir > 0) { + _impl.template operator()( + brezenham_line_iterable{x0, y0, x1, y1}.begin(), + brezenham_line_iterable{x1, y1, x2, y2}.begin(), + brezenham_line_iterable{x0, y0, x2, y2}.begin() + ); + } else if (dir < 0) { + _impl.template operator()( + brezenham_line_iterable{x0, y0, x1, y1}.begin(), + brezenham_line_iterable{x1, y1, x2, y2}.begin(), + brezenham_line_iterable{x0, y0, x2, y2}.begin() + ); + } else { + iterate_line(x0, y0, x2, y2, edge_point_receiver); } + } - 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 + void iterate_triangle_fill_h_lines( + RendererApi::PointI<2> p0, + RendererApi::PointI<2> p1, + RendererApi::PointI<2> p2, + edge_point_receiver_t edge_point_receiver, + fill_line_receiver_t fill_line_receiver + ) { + iterate_triangle_fill_h_lines( + p0.x, p0.y, + p1.x, p1.y, + p2.x, p2.y, + edge_point_receiver, + fill_line_receiver + ); + } template void iterate_triangle_fill( @@ -178,40 +221,16 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { 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::component_t>::min(); - RendererApi::PointI<2>::component_t ex = std::numeric_limits::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; + iterate_triangle_fill_h_lines( + x0, y0, + x1, y1, + x2, y2, + [&](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 x, RendererApi::PointI<2>::component_t ex) { + for (; x < ex; x++) + receiver(false, x, y); } - - 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 @@ -255,7 +274,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { 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); + return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } @@ -302,7 +321,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { } }; - +#if 0 class triangle_barycentric_shader : public Shader { private: triangle_barycentric_interpolator interpolator; @@ -317,4 +336,5 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { return this->interpolator.interpolate_point(x, y); } }; +#endif } \ No newline at end of file