forked from BGTU/computer-graphics-0
127 lines
3.8 KiB
C++
127 lines
3.8 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;
|
|
bool is_projection_enabled;
|
|
double x_radius;
|
|
double y_radius;
|
|
|
|
explicit SpriteData(Utilities::Matrix4d transform, bool is_projection_enabled, double x_radius, double y_radius) :
|
|
transform{transform}, is_projection_enabled{is_projection_enabled}, x_radius{x_radius}, y_radius{y_radius} {}
|
|
|
|
[[nodiscard]] inline RendererApi::PointI<2> project_point(RendererApi::PointF<3> p) const {
|
|
if (this->is_projection_enabled)
|
|
return {static_cast<RendererApi::PointI<2>::component_t>((p.x - this->x_radius) / (p.z * (1 / this->x_radius) + 1) + this->x_radius), static_cast<RendererApi::PointI<2>::component_t>((p.y - this->y_radius) / (p.z * (1 / this->y_radius) + 1) + this->y_radius)};
|
|
else
|
|
return RendererApi::PointI<2>{static_cast<RendererApi::PointI<2>::component_t>(p.x), static_cast<RendererApi::PointI<2>::component_t>(p.y)};
|
|
};
|
|
};
|
|
|
|
|
|
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 scale;
|
|
|
|
double x_angle_step;
|
|
double y_angle_step;
|
|
double scale_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}, scale{1}, x_angle_step{x_angle_step}, y_angle_step{y_angle_step}, scale_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);
|
|
SpriteData cached{
|
|
Utilities::Matrix4d::shift(0, 0, this->scale) * 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(radius),
|
|
this->is_projection_enabled, this->w * 7 / 16.0, this->h * 7 / 16.0,
|
|
};
|
|
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();
|
|
}
|
|
|
|
void switch_projection() {
|
|
this->sync.lock();
|
|
this->is_projection_enabled = !this->is_projection_enabled;
|
|
this->sync.unlock();
|
|
}
|
|
};
|
|
} |