Lab 4 implementation

This commit is contained in:
Andrew Golovashevich 2025-03-03 02:43:48 +03:00
parent 63431f0863
commit 0b816497e9
9 changed files with 418 additions and 26 deletions

View File

@ -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)
add_subdirectory(programs/lab3)
add_subdirectory(programs/lab4)

View File

@ -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)

114
programs/lab4/src/main.cpp Normal file
View File

@ -0,0 +1,114 @@
#include <cmath>
#include <array>
#include <iostream>
#include <numbers>
#include <QApplication>
#include <QMainWindow>
#include <QTimer>
#include <QGridLayout>
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/matrix.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/keyboard_catcher_widget.hpp>
#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<double> / 2, 0, 1.01};
sprites_data_side.inc_x_angle();
SpriteData::Provider sprites_data_up{0, std::numbers::pi_v<double> / 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<SpriteData> 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<SpriteData> 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<SpriteData> 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<SpriteData> 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<SpriteData> 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<SpriteData> 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<SpriteData> 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<SpriteData> 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);
}

View File

@ -0,0 +1,105 @@
#pragma once
#include <cstdlib>
#include <cmath>
#include <numbers>
#include <QObject>
#include <QMutex>
#include <QElapsedTimer>
#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/utilities/matrix.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp>
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<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::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();
}
};
}

View File

@ -0,0 +1,100 @@
#include <utility>
#include <numbers>
#include <cmath>
#include <bgtu/computer_graphics_lab_work/utilities/shader.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp>
#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<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> {
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<double> 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<double> / 5 * angle) * len, std::sin(std::numbers::pi_v<double> / 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<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *_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<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> **const sprites = _sprites;
std::size_t sprites_count = 20;
}

View File

@ -0,0 +1,10 @@
#pragma once
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include "sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl {
extern RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> ** const sprites;
extern std::size_t sprites_count;
}

View File

@ -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;
}
}

View File

@ -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<class new_component_t>
@ -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<class _self_component_t = _component_t, class sfinae = std::enable_if<std::is_same_v<_self_component_t, long long>, 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<class _self_component_t = _component_t, class sfinae = std::enable_if<std::is_same_v<_self_component_t, double>, 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<unsigned DIMENSIONS>

View File

@ -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 = [&]<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)
if constexpr (std::is_same_v<variable_t, RendererApi::Color::Transparent> || std::is_same_v<variable_t, RendererApi::Color>) {
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 {
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));
return static_cast<variable_t>((this->v0) * k0 + (this->v1) * k1 + (this->v2) * k2);
}
}