computer-graphics-0/programs/lab1/src/sprite_data.hpp

152 lines
4.9 KiB
C++

#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::Lab1 {
class _Lab1SpriteData_Provider;
struct Lab1SpriteData {
public:
struct ShapeData {
public:
double rotation_radians;
RendererApi::PointI<2>::component_t radius;
RendererApi::PointI<2>::component_t diameter;
private:
[[nodiscard]] inline RendererApi::PointI<2> _rotated(RendererApi::PointI<2>::component_t custom_radius, double base_angle_radians, double angle_degrees) const {
double angle_radians = angle_degrees * (std::numbers::pi_v<double> / 180);
return {
(RendererApi::PointI<2>::component_t) (std::cos(base_angle_radians + angle_radians) * custom_radius),
(RendererApi::PointI<2>::component_t) (std::sin(base_angle_radians + angle_radians) * custom_radius),
};
}
public:
[[nodiscard]] inline RendererApi::PointI<2> static_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const {
return this->_rotated(custom_radius, 0, angle_degrees);
}
[[nodiscard]] inline RendererApi::PointI<2> pos_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const {
return this->_rotated(custom_radius, this->rotation_radians, angle_degrees);
}
[[nodiscard]] inline RendererApi::PointI<2> neg_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const {
return this->_rotated(custom_radius, -this->rotation_radians, angle_degrees);
}
};
RendererApi::PointI<2> central_pixel_tl;
std::size_t pixel_size;
bool show_grid;
ShapeData shape_data;
RendererApi::Sprite<ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sub_sprites;
std::size_t sub_sprites_count;
using Provider = _Lab1SpriteData_Provider;
};
class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider {
Q_OBJECT
private:
QMutex sync;
QElapsedTimer time;
std::size_t pixel_size;
double radians_per_second;
bool show_grid;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sub_sprites;
std::size_t sub_sprites_count;
public:
explicit _Lab1SpriteData_Provider(double radians_per_second) :
sync{}, time{},
pixel_size{1}, radians_per_second{radians_per_second}, show_grid{false},
w{0}, h{0},
sub_sprites{nullptr}, sub_sprites_count{0} {}
Lab1SpriteData get_sprite_data() override {
this->sync.lock();
RendererApi::PointI<2>::component_t radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16) / this->pixel_size;
Lab1SpriteData 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),
.pixel_size = this->pixel_size,
.show_grid = this->show_grid,
.shape_data = {
.rotation_radians = std::fmod(this->time.elapsed() / 1000.0 * radians_per_second, std::numbers::pi * 2),
.radius = radius,
.diameter = radius * 2
},
.sub_sprites = this->sub_sprites,
.sub_sprites_count = this->sub_sprites_count,
};
this->sync.unlock();
return cached;
}
public slots:
void set_pixel_size(std::size_t s) {
this->sync.lock();
this->pixel_size = s;
this->sync.unlock();
}
void increase_pixel_size() {
this->sync.lock();
this->pixel_size++;
this->sync.unlock();
}
void decrease_pixel_size() {
this->sync.lock();
if (this->pixel_size > 1)
this->pixel_size--;
this->sync.unlock();
}
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 set_show_grid(bool f) {
this->sync.lock();
this->show_grid = f;
this->sync.unlock();
}
void invert_show_grid() {
this->sync.lock();
this->show_grid = !this->show_grid;
this->sync.unlock();
}
void set_sub_sprites(RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *s, std::size_t c) {
this->sync.lock();
this->sub_sprites = s;
this->sub_sprites_count = c;
this->sync.unlock();
}
};
}