bresenham-0.rs/programs/lab5/src/sprite_data.hpp

122 lines
3.3 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::Impl {
class _Lab5SpriteData_Provider;
struct SpriteData {
public:
using Provider = _Lab5SpriteData_Provider;
Utilities::Matrix4d transform;
explicit SpriteData(Utilities::Matrix4d transform) :
transform{transform} {}
};
class _Lab5SpriteData_Provider : public QObject, public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider {
Q_OBJECT
private:
QMutex sync;
double x_angle;
double y_angle;
double distance;
double x_angle_step;
double y_angle_step;
double distance_step;
bool is_projection_enabled;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
public:
explicit _Lab5SpriteData_Provider(
double x_angle_step,
double y_angle_step,
double scale_step
) : x_angle{0}, y_angle{0}, distance{0}, x_angle_step{x_angle_step}, y_angle_step{y_angle_step}, distance_step{scale_step},
w{0}, h{0}, is_projection_enabled{false} {}
SpriteData get_sprite_data() override {
this->sync.lock();
double radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16.0);
auto projection = this->is_projection_enabled
? Utilities::Matrix4d::projection_central(-1.5, 1.5, -1.5, 1.5, 1, 9) * Utilities::Matrix4d::scale(5, 5, -1) * Utilities::Matrix4d::shift(0, 0, 7 + this->distance)
: Utilities::Matrix4d::projection_orto(-2, 2, -2, 2, -6, 2);
SpriteData cached{
Utilities::Matrix4d::shift(this->w / 2, this->h / 2, 0) * Utilities::Matrix4d::scale(radius) * projection * Utilities::Matrix4d::rotate_x(this->x_angle) * Utilities::Matrix4d::rotate_y(this->y_angle),
};
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_distance() {
this->sync.lock();
this->distance += this->distance_step;
this->sync.unlock();
}
void dec_distance() {
this->sync.lock();
this->distance -= this->distance_step;
if (this->distance < 0)
this->distance = 0;
this->sync.unlock();
}
void switch_projection() {
this->sync.lock();
this->is_projection_enabled = !this->is_projection_enabled;
this->sync.unlock();
}
};
}