Drawing square to screen (almost)
This commit is contained in:
parent
4dfbe50bb3
commit
73132bbec5
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
project(cg1)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
@ -1,2 +1,16 @@
|
||||
add_executable(lab1 src/main.cpp src/sprite_data.hpp src/keyboard_catcher_widget.hpp)
|
||||
add_executable(
|
||||
lab1
|
||||
src/main.cpp
|
||||
src/sprite_data.hpp
|
||||
src/keyboard_catcher_widget.hpp
|
||||
|
||||
src/variants/variant1.cpp
|
||||
src/variants/variant2.cpp
|
||||
src/variants/variant3.cpp
|
||||
src/variants/variant4.cpp
|
||||
src/variants/variant5.cpp
|
||||
src/variants/variant6.cpp
|
||||
src/variants/variant8.cpp
|
||||
src/variants/variant9.cpp
|
||||
)
|
||||
target_link_libraries(lab1 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities)
|
||||
|
@ -18,6 +18,8 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
|
||||
void key_pressed_PageDown();
|
||||
|
||||
void key_pressed_G();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override {
|
||||
switch (event->key()) {
|
||||
@ -27,6 +29,9 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
case Qt::Key_PageDown:
|
||||
emit this->key_pressed_PageDown();
|
||||
return;
|
||||
case Qt::Key_G:
|
||||
emit this->key_pressed_G();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QTimer>
|
||||
#include <array>
|
||||
#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>
|
||||
@ -11,27 +12,38 @@
|
||||
#include "sprite_data.hpp"
|
||||
#include "keyboard_catcher_widget.hpp"
|
||||
#include "pixel_grid_sprite.hpp"
|
||||
#include "variants.hpp"
|
||||
#include "zoomed_scene_sprite.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
|
||||
volatile RendererApi::Color bg{0, 0, 0};
|
||||
RendererApi::Color::Transparent fg{255, 255, 255, 127};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#if 1
|
||||
QApplication qApplication{argc, argv};
|
||||
|
||||
|
||||
PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{32, 32, 32}};
|
||||
PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{16, 16, 16}};
|
||||
ZoomedSceneSprite zoomed_scene_sprite{};
|
||||
|
||||
auto sprites = std::to_array<RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *const>({
|
||||
&pixels_grid_sprite
|
||||
&pixels_grid_sprite,
|
||||
&zoomed_scene_sprite
|
||||
});
|
||||
|
||||
|
||||
Lab1SpriteData::Provider sprites_data{1};
|
||||
sprites_data.set_pixel_size(16);
|
||||
sprites_data.set_sub_sprites(variant1.sprites, variant1.count);
|
||||
|
||||
QMainWindow w{};
|
||||
|
||||
KeyboardCatcherWidget kbd{&w};
|
||||
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data, &Lab1SpriteData::Provider::decrease_pixel_size);
|
||||
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data, &Lab1SpriteData::Provider::increase_pixel_size);
|
||||
QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_G, &sprites_data, &Lab1SpriteData::Provider::invert_show_grid);
|
||||
|
||||
QtUtilities::SeparateThreadedDefaultRendererLinear<Lab1SpriteData> renderer{};
|
||||
renderer.set_sprite_data_provider(&sprites_data);
|
||||
@ -46,6 +58,15 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
QApplication::exec();
|
||||
|
||||
return 0;
|
||||
#else
|
||||
|
||||
|
||||
|
||||
auto c = Utilities::apply_transparent_color(*(RendererApi::Color*)&bg, fg);
|
||||
std::cout << c.red << c.green << c.blue << std::endl;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||
#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/shapes/rectangle.hpp>
|
||||
#include "sprite_data.hpp"
|
||||
|
||||
|
||||
@ -15,6 +16,9 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
PixelGridSprite(RendererApi::Color bg, RendererApi::Color fg) : bg{bg}, fg{fg} {};
|
||||
|
||||
void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override {
|
||||
if (!data->show_grid)
|
||||
return;
|
||||
|
||||
long long start_x = data->central_pixel_tl.x - ((data->central_pixel_tl.x + data->pixel_size - 1) / data->pixel_size * data->pixel_size);
|
||||
long long start_y = data->central_pixel_tl.y - ((data->central_pixel_tl.y + data->pixel_size - 1) / data->pixel_size * data->pixel_size);
|
||||
long long w = frame->width();
|
||||
@ -26,11 +30,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
for (long long x = start_x; x < w; x += data->pixel_size, x_flag = !x_flag) {
|
||||
auto c = x_flag ? this->bg : this->fg;
|
||||
|
||||
for (long long yy = y + data->pixel_size; yy-- > y;) {
|
||||
for (long long xx = x + data->pixel_size; xx-- > x;) {
|
||||
frame->add_voxel(xx, yy, std::numeric_limits<double>::max(), c);
|
||||
}
|
||||
}
|
||||
Utilities::Shapes::fill_rectangle_wh(frame, x, y, data->pixel_size, data->pixel_size, std::numeric_limits<double>::max(), c, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,14 @@
|
||||
#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 {
|
||||
@ -19,17 +21,37 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
struct Lab1SpriteData {
|
||||
public:
|
||||
struct ShapeData {
|
||||
public:
|
||||
double rotation_radians;
|
||||
RendererApi::PointI<2>::component_t radius;
|
||||
RendererApi::PointI<2>::component_t diameter;
|
||||
|
||||
[[nodiscard]] inline RendererApi::PointI<2> pos_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const {
|
||||
double angle_radians = angle_degrees * (std::numbers::pi_v<double> / 180);
|
||||
return {
|
||||
(RendererApi::PointI<2>::component_t) (std::cos(this->rotation_radians + angle_radians) * custom_radius),
|
||||
(RendererApi::PointI<2>::component_t) (std::sin(this->rotation_radians + angle_radians) * custom_radius),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline RendererApi::PointI<2> neg_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const {
|
||||
double angle_radians = angle_degrees * (std::numbers::pi_v<double> / 180);
|
||||
return {
|
||||
(RendererApi::PointI<2>::component_t) (std::cos(-this->rotation_radians + angle_radians) * custom_radius),
|
||||
(RendererApi::PointI<2>::component_t) (std::sin(-this->rotation_radians + angle_radians) * custom_radius),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
RendererApi::PointI<2> central_pixel_tl;
|
||||
std::size_t pixel_size;
|
||||
bool show_grid;
|
||||
ShapeData shape_data;
|
||||
RendererApi::Sprite<ShapeData> **sub_sprites;
|
||||
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 {
|
||||
@ -42,7 +64,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
double radians_per_second;
|
||||
bool show_grid;
|
||||
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
|
||||
RendererApi::Sprite<Lab1SpriteData::ShapeData> **sub_sprites;
|
||||
RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> *const *sub_sprites;
|
||||
std::size_t sub_sprites_count;
|
||||
|
||||
public:
|
||||
@ -54,15 +76,18 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
|
||||
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)
|
||||
.rotation_radians = std::fmod(this->time.elapsed() / 1000.0 * radians_per_second, std::numbers::pi),
|
||||
.radius = radius,
|
||||
.diameter = radius * 2
|
||||
},
|
||||
.sub_sprites = nullptr,
|
||||
.sub_sprites_count = 0
|
||||
.sub_sprites = this->sub_sprites,
|
||||
.sub_sprites_count = this->sub_sprites_count,
|
||||
};
|
||||
this->sync.unlock();
|
||||
return cached;
|
||||
@ -101,5 +126,18 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
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();
|
||||
}
|
||||
};
|
||||
}
|
83
programs/lab1/src/variants.hpp
Normal file
83
programs/lab1/src/variants.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp>
|
||||
#include "sprite_data.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
struct variant_sprites {
|
||||
private :
|
||||
using sprite_t = RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>>;
|
||||
public:
|
||||
|
||||
|
||||
sprite_t *const *const sprites;
|
||||
std::size_t const count;
|
||||
|
||||
|
||||
constexpr variant_sprites(sprite_t *const *const _sprites, std::size_t _count) : sprites{_sprites}, count{_count}{
|
||||
|
||||
}
|
||||
private:
|
||||
template<class ...sprites_t>
|
||||
struct _make {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _make<> {
|
||||
public:
|
||||
constexpr _make() {};
|
||||
|
||||
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
|
||||
}
|
||||
};
|
||||
|
||||
template<class e0>
|
||||
struct _make<e0> {
|
||||
public:
|
||||
e0 value;
|
||||
|
||||
constexpr _make(e0 v) : value{std::move(v)} {};
|
||||
|
||||
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
|
||||
dst[pos] = &this->value;
|
||||
}
|
||||
};
|
||||
|
||||
template<class e0, class ...en>
|
||||
struct _make<e0, en...> {
|
||||
public:
|
||||
e0 value;
|
||||
_make<en...> next;
|
||||
|
||||
constexpr _make(e0 v, en...nv) : value{std::move(v)}, next{nv...} {};
|
||||
|
||||
constexpr void export_pointers(sprite_t **dst, std::size_t pos) {
|
||||
dst[pos] = &this->value;
|
||||
this->next.export_pointers(dst, pos + 1);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template<class ...sprites_t>
|
||||
constexpr static variant_sprites make(sprites_t...sprites) {
|
||||
static _make<sprites_t...> i{sprites...};
|
||||
static sprite_t *p[sizeof...(sprites)];
|
||||
|
||||
i.export_pointers(p, 0);
|
||||
return variant_sprites{p, sizeof...(sprites)};
|
||||
}
|
||||
};
|
||||
|
||||
extern variant_sprites variant1;
|
||||
extern variant_sprites variant2;
|
||||
extern variant_sprites variant3;
|
||||
extern variant_sprites variant4;
|
||||
extern variant_sprites variant5;
|
||||
extern variant_sprites variant6;
|
||||
extern variant_sprites variant8;
|
||||
extern variant_sprites variant9;
|
||||
}
|
29
programs/lab1/src/variants/variant1.cpp
Normal file
29
programs/lab1/src/variants/variant1.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include <tuple>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp>
|
||||
#include "../variants.hpp"
|
||||
#include "../sprite_data.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Lab1{
|
||||
namespace Variant1 {
|
||||
class S1 : public RendererApi::Sprite<Lab1SpriteData::ShapeData, Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>> {
|
||||
public:
|
||||
void draw(
|
||||
BGTU::ComputerGraphicsLabWork::Utilities::ZoomedVoxelPainter<BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *frame,
|
||||
const BGTU::ComputerGraphicsLabWork::Lab1::Lab1SpriteData::ShapeData *data
|
||||
) const final {
|
||||
Utilities::Shapes::draw_polygon_edge(
|
||||
frame,
|
||||
{data->neg_rotated(data->radius / 2, 0), data->neg_rotated(data->radius / 2, 90), data->neg_rotated(data->radius / 2, 180), data->neg_rotated(data->radius / 2, 270),},
|
||||
1,
|
||||
{255, 0, 0}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
variant_sprites variant1 = variant_sprites::make(Variant1::S1{});
|
||||
}
|
0
programs/lab1/src/variants/variant2.cpp
Normal file
0
programs/lab1/src/variants/variant2.cpp
Normal file
0
programs/lab1/src/variants/variant3.cpp
Normal file
0
programs/lab1/src/variants/variant3.cpp
Normal file
0
programs/lab1/src/variants/variant4.cpp
Normal file
0
programs/lab1/src/variants/variant4.cpp
Normal file
0
programs/lab1/src/variants/variant5.cpp
Normal file
0
programs/lab1/src/variants/variant5.cpp
Normal file
0
programs/lab1/src/variants/variant6.cpp
Normal file
0
programs/lab1/src/variants/variant6.cpp
Normal file
0
programs/lab1/src/variants/variant8.cpp
Normal file
0
programs/lab1/src/variants/variant8.cpp
Normal file
0
programs/lab1/src/variants/variant9.cpp
Normal file
0
programs/lab1/src/variants/variant9.cpp
Normal file
25
programs/lab1/src/zoomed_scene_sprite.hpp
Normal file
25
programs/lab1/src/zoomed_scene_sprite.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||
#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/default_renderer_linear.hpp>
|
||||
#include "sprite_data.hpp"
|
||||
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Lab1 {
|
||||
class ZoomedSceneSprite : public RendererApi::Sprite<Lab1SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> {
|
||||
private:
|
||||
public:
|
||||
ZoomedSceneSprite() = default;
|
||||
|
||||
void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override {
|
||||
Utilities::ZoomedVoxelPainter<Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> zoomed_painter{frame, data->central_pixel_tl, data->pixel_size};
|
||||
|
||||
for (std::size_t i = 0; i < data->sub_sprites_count; i++) {
|
||||
data->sub_sprites[i]->draw(&zoomed_painter, &data->shape_data);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -18,7 +18,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||
using _SeparateThreadedRenderer_RenderProcedureType = void (renderer_context_t::*)(
|
||||
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t,
|
||||
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t,
|
||||
Utilities::VoxelPainterExporterToRgb32Array *,
|
||||
Utilities::VoxelPainterExporterToBgr32Array *,
|
||||
RendererApi::Color,
|
||||
RendererApi::Sprite<sprite_data_t, renderer_voxel_painter_t> *const *,
|
||||
std::size_t,
|
||||
|
@ -158,7 +158,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||
data_t cached = *const_cast<data_t *>(&this->owner->next_data);
|
||||
this->owner->sync.unlock();
|
||||
|
||||
Utilities::VoxelPainterExporterToRgb32Array img{
|
||||
Utilities::VoxelPainterExporterToBgr32Array img{
|
||||
cached.width, cached.height,
|
||||
new unsigned char[cached.width * cached.height * 4],
|
||||
new RendererApi::SpriteMetadata *[cached.width * cached.height]
|
||||
@ -206,12 +206,12 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
|
||||
|
||||
|
||||
template<class sprite_data_t>
|
||||
class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t, Utilities::VoxelPainterExporterToRgb32Array>> {
|
||||
class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t, Utilities::VoxelPainterExporterToBgr32Array>> {
|
||||
private:
|
||||
Utilities::DefaultVoxelDrawerCache context;
|
||||
public:
|
||||
explicit SeparateThreadedDefaultRendererLinear(QObject *owner = nullptr) :
|
||||
SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t, Utilities::VoxelPainterExporterToRgb32Array>>{&this->context, owner}, context{} {};
|
||||
SeparateThreadedRenderer<sprite_data_t, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl, Utilities::DefaultVoxelDrawerCache, &Utilities::DefaultVoxelDrawerCache::render<sprite_data_t, Utilities::VoxelPainterExporterToBgr32Array>>{&this->context, owner}, context{} {};
|
||||
|
||||
~SeparateThreadedDefaultRendererLinear() {
|
||||
this->shutdown_thread_blocking();
|
||||
|
@ -35,7 +35,6 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
|
||||
return Point<2, _component_t>{this->x / other, this->y / 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<2, double>() const noexcept {
|
||||
return Point<2, double>{(double) this->x, (double) this->y};
|
||||
@ -45,6 +44,14 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi {
|
||||
[[nodiscard]] constexpr explicit operator Point<2, long long>() const noexcept {
|
||||
return Point<2, long long>{(long long) this->x, (long long) this->y};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator==(Point<2, _component_t> const &other) const noexcept {
|
||||
return this->x == other.x && this->y == other.y;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator!=(Point<2, _component_t> const &other) const noexcept {
|
||||
return this->x != other.x || this->y != other.y;
|
||||
}
|
||||
};
|
||||
|
||||
template<class _component_t>
|
||||
|
@ -1,24 +1,139 @@
|
||||
#pragma once
|
||||
|
||||
#include <climits>
|
||||
#include <emmintrin.h>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
#if defined(__AVX512F__)
|
||||
return _apply_transparent_color_avx512(bg, fg);
|
||||
#elif 0 && defined(__AVX2__)
|
||||
return _apply_transparent_color_avx2(bg, fg);
|
||||
#else
|
||||
constexpr RendererApi::Color _apply_transparent_color_pure(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
#if 1
|
||||
if (fg.alpha == 255)
|
||||
return {fg.red, fg.green, fg.blue};
|
||||
|
||||
// pmovzxbd
|
||||
const std::uint_fast32_t bg_i32[4]{bg.red, bg.green, bg.blue};
|
||||
const std::uint_fast32_t fg_i32[4]{fg.red, fg.green, fg.blue};
|
||||
|
||||
// cvtdq2pd
|
||||
const float bg_f[4]{(float) bg_i32[0], (float) bg_i32[1], (float) bg_i32[2]};
|
||||
const float fg_f[4]{(float) fg_i32[0], (float) fg_i32[1], (float) fg_i32[2]};
|
||||
|
||||
const float alpha_f = fg.alpha;
|
||||
const float neg_alpha_f = 255.f - alpha_f;
|
||||
|
||||
// mulps
|
||||
const float bg_alpha[4]{bg_f[0] * neg_alpha_f, bg_f[1] * neg_alpha_f, bg_f[1] * neg_alpha_f};
|
||||
const float fg_alpha[4]{fg_f[0] * alpha_f, fg_f[1] * alpha_f, fg_f[1] * alpha_f};
|
||||
|
||||
// addps
|
||||
const float sum_f[4]{bg_alpha[0] + fg_alpha[0], bg_alpha[1] + fg_alpha[1], bg_alpha[2] + fg_alpha[2]};
|
||||
|
||||
// divps
|
||||
const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f};
|
||||
|
||||
return {(RendererApi::Color::component_compact_t) sum_fixed_f[0], (RendererApi::Color::component_compact_t) sum_fixed_f[1], (RendererApi::Color::component_compact_t) sum_fixed_f[2]};
|
||||
|
||||
#else
|
||||
return RendererApi::Color{
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.red) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.red) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<float>(fg.red) * static_cast<float>(fg.alpha) + static_cast<float>(bg.red) * (static_cast<float>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.green) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.green) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.blue) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.blue) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
};
|
||||
#elif 1
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# if defined(__AVX512F__)
|
||||
|
||||
extern RendererApi::Color _apply_transparent_color_avx512f(RendererApi::Color bg, RendererApi::Color::Transparent fg);
|
||||
|
||||
inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
return _apply_transparent_color_avx512f(bg, fg);
|
||||
}
|
||||
|
||||
# pragma comment(linker, "/alternatename:?_apply_transparent_color_avx512f@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z=?_apply_transparent_color_pure@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z")
|
||||
|
||||
# elif defined(__AVX2__)
|
||||
|
||||
extern RendererApi::Color _apply_transparent_color_avx2(RendererApi::Color bg, RendererApi::Color::Transparent fg);
|
||||
|
||||
inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
return _apply_transparent_color_avx2(bg, fg);
|
||||
}
|
||||
|
||||
# pragma comment(linker, "/alternatename:?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z=?_apply_transparent_color_pure@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z")
|
||||
|
||||
# else
|
||||
|
||||
inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
return _apply_transparent_color_pure(bg, fg);
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z
|
||||
// ?apply_transparent_color@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z
|
||||
#if 0
|
||||
#if 0
|
||||
RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) {
|
||||
return _apply_transparent_color_avx2(bg, fg);
|
||||
|
||||
if (fg.alpha == 255)
|
||||
return {fg.red, fg.green, fg.blue};
|
||||
|
||||
// pmovzxbd
|
||||
const std::uint_fast32_t bg_i32[4]{bg.red, bg.green, bg.blue};
|
||||
const std::uint_fast32_t fg_i32[4]{fg.red, fg.green, fg.blue};
|
||||
|
||||
// cvtdq2pd
|
||||
const float bg_f[4]{(float) bg_i32[0], (float) bg_i32[1], (float) bg_i32[2]};
|
||||
const float fg_f[4]{(float) fg_i32[0], (float) fg_i32[1], (float) fg_i32[2]};
|
||||
|
||||
const float alpha_f = fg.alpha;
|
||||
const float neg_alpha_f = 255.f - alpha_f;
|
||||
|
||||
// mulps
|
||||
const float bg_alpha[4]{bg_f[0] * neg_alpha_f, bg_f[1] * neg_alpha_f, bg_f[1] * neg_alpha_f};
|
||||
const float fg_alpha[4]{fg_f[0] * alpha_f, fg_f[1] * alpha_f, fg_f[1] * alpha_f};
|
||||
|
||||
// addps
|
||||
const float sum_f[4]{bg_alpha[0] + fg_alpha[0], bg_alpha[1] + fg_alpha[1], bg_alpha[2] + fg_alpha[2]};
|
||||
|
||||
// divps
|
||||
const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f};
|
||||
|
||||
return {(RendererApi::Color::component_compact_t) sum_fixed_f[0], (RendererApi::Color::component_compact_t) sum_fixed_f[1], (RendererApi::Color::component_compact_t) sum_fixed_f[2]};
|
||||
|
||||
#else
|
||||
return RendererApi::Color{
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<float>(fg.red) * static_cast<float>(fg.alpha) + static_cast<float>(bg.red) * (static_cast<float>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.green) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.green) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.blue) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.blue) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
};
|
||||
|
||||
|
||||
/*__m128i bg_vec = _mm_cvtsi32_si128(*(std::int32_t *) &bg);
|
||||
__m128i fg_vec = _mm_cvtsi32_si128(*(std::int32_t *) &fg);
|
||||
|
||||
bg_vec = _mm_cvtepu8_epi16(bg_vec);
|
||||
fg_vec = _mm_cvtepu8_epi16(fg_vec);
|
||||
|
||||
// bg_vec = _mm_cvtepi16_ph(bg_vec);
|
||||
// fg_vec = _mm_cvtepi16_ph(fg_vec);*/
|
||||
|
||||
#if defined(__AVX512F__)
|
||||
return _apply_transparent_color_avx512(bg, fg);
|
||||
#elif defined(__AVX2__)
|
||||
return _apply_transparent_color_avx2(bg, fg);
|
||||
#else
|
||||
#if 0
|
||||
return RendererApi::Color{
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<float>(fg.red) * static_cast<float>(fg.alpha) + static_cast<float>(bg.red) * (static_cast<float>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.green) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.green) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
static_cast<RendererApi::Color::component_fast_t>(((static_cast<std::uint_fast16_t>(fg.blue) * static_cast<std::uint_fast16_t>(fg.alpha) + static_cast<std::uint_fast16_t>(bg.blue) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha))) / 255)),
|
||||
};
|
||||
#elif 0
|
||||
static auto calc = [&](RendererApi::Color::component_fast_t s, RendererApi::Color::component_fast_t o) {
|
||||
auto oo = static_cast<std::uint_fast16_t>(o) * static_cast<std::uint_fast16_t>(fg.alpha);
|
||||
auto ss = static_cast<std::uint_fast16_t>(s) * (static_cast<std::uint_fast16_t>(255) - static_cast<std::uint_fast16_t>(fg.alpha));
|
||||
@ -29,7 +144,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
calc(bg.green, fg.green),
|
||||
calc(bg.blue, fg.blue)
|
||||
};
|
||||
#else
|
||||
#elif 0
|
||||
static __m128i vec_256 = _mm_set_epi16(256, 256, 256, 0, 0, 0, 0, 0);
|
||||
__m128i vec_bg = _mm_set_epi16(bg.red, bg.green, bg.blue, 0, 0, 0, 0, 0);
|
||||
__m128i vec_fg = _mm_set_epi16(fg.red, fg.green, fg.blue, 0, 0, 0, 0, 0);
|
||||
@ -49,12 +164,18 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
namespace PackColor {
|
||||
inline void color_to_rgb32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept {
|
||||
buffer[offset] = color.red;
|
||||
buffer[offset + 1] = color.green;
|
||||
buffer[offset + 2] = color.blue;
|
||||
}
|
||||
inline void color_to_bgr32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept {
|
||||
buffer[offset] = color.blue;
|
||||
buffer[offset + 1] = color.green;
|
||||
buffer[offset + 2] = color.red;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
#include <cstdlib>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
|
||||
class brezenham_line_iterable {
|
||||
private:
|
||||
RendererApi::PointI<2>::component_t start_arg, start_ret, end_arg;
|
||||
@ -11,7 +11,12 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
RendererApi::PointI<2>::component_t delta_error, error_threshold;
|
||||
bool swap_flag;
|
||||
public:
|
||||
inline brezenham_line_iterable(RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1, RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2) {
|
||||
constexpr brezenham_line_iterable(
|
||||
RendererApi::PointI<2>::component_t x1,
|
||||
RendererApi::PointI<2>::component_t y1,
|
||||
RendererApi::PointI<2>::component_t x2,
|
||||
RendererApi::PointI<2>::component_t y2
|
||||
) noexcept {
|
||||
RendererApi::PointI<2>::component_t delta_x = (x1 > x2) ? (x1 - x2) : (x2 - x1);
|
||||
RendererApi::PointI<2>::component_t delta_y = (y1 > y2) ? (y1 - y2) : (y2 - y1);
|
||||
if (delta_x > delta_y) {
|
||||
@ -33,12 +38,10 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
}
|
||||
}
|
||||
|
||||
struct point {
|
||||
public:
|
||||
RendererApi::PointI<2>::component_t x, y;
|
||||
|
||||
inline point(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) : x{x}, y{y} {}
|
||||
};
|
||||
constexpr brezenham_line_iterable(
|
||||
RendererApi::PointI<2> start,
|
||||
RendererApi::PointI<2> end
|
||||
) noexcept: brezenham_line_iterable{start.x, start.y, end.x, end.y} {}
|
||||
|
||||
class iterator {
|
||||
private:
|
||||
@ -47,17 +50,17 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
RendererApi::PointI<2>::component_t error, delta_error, error_threshold;
|
||||
bool swap_flag;
|
||||
|
||||
inline iterator(
|
||||
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_error, RendererApi::PointI<2>::component_t error_threshold,
|
||||
bool swap_flag
|
||||
) : arg{arg}, ret{ret}, end_arg{end_arg}, delta_ret{delta_ret}, error{0}, delta_error{delta_error}, swap_flag{swap_flag}, error_threshold{error_threshold} {}
|
||||
) noexcept: arg{arg}, ret{ret}, end_arg{end_arg}, delta_ret{delta_ret}, error{0}, delta_error{delta_error}, swap_flag{swap_flag}, error_threshold{error_threshold} {}
|
||||
|
||||
friend class brezenham_line_iterable;
|
||||
|
||||
public:
|
||||
inline iterator &operator++() {
|
||||
constexpr iterator &operator++() noexcept {
|
||||
this->arg++;
|
||||
this->error += this->delta_error;
|
||||
if (this->error >= this->error_threshold) {
|
||||
@ -67,29 +70,29 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline iterator operator++(int) {
|
||||
constexpr iterator operator++(int) noexcept {
|
||||
iterator next = *this;
|
||||
++(*this);
|
||||
return next;
|
||||
}
|
||||
|
||||
inline point operator*() const {
|
||||
constexpr RendererApi::PointI<2> operator*() const noexcept {
|
||||
if (this->swap_flag)
|
||||
return point{this->ret, this->arg};
|
||||
return {this->ret, this->arg};
|
||||
else
|
||||
return point{this->arg, this->ret};
|
||||
return {this->arg, this->ret};
|
||||
}
|
||||
|
||||
inline bool operator==(std::nullptr_t) const {
|
||||
constexpr bool operator==(std::nullptr_t) const noexcept {
|
||||
return this->arg > this->end_arg;
|
||||
}
|
||||
|
||||
inline bool operator!=(std::nullptr_t) const {
|
||||
constexpr bool operator!=(std::nullptr_t) const noexcept {
|
||||
return this->arg <= this->end_arg;
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] inline iterator begin() const {
|
||||
[[nodiscard]] constexpr iterator begin() const noexcept {
|
||||
return iterator{
|
||||
this->start_arg, this->start_ret, this->end_arg,
|
||||
this->delta_ret,
|
||||
@ -98,7 +101,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::nullptr_t end() const {
|
||||
[[nodiscard]] constexpr std::nullptr_t end() const noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
#include "../color.hpp"
|
||||
#include "brezenham.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
|
||||
template<class receiver_t, std::size_t points_count>
|
||||
void iterate_polygon_edge(
|
||||
RendererApi::PointI<2> (&&points)[points_count],
|
||||
receiver_t receiver
|
||||
) {
|
||||
if constexpr (points_count == 0) {
|
||||
return;
|
||||
} else if constexpr (points_count == 1) {
|
||||
receiver(points[0].x, points[0].y);
|
||||
return;
|
||||
} else {
|
||||
receiver(points[0].x, points[0].y);
|
||||
for (std::size_t i = 1; i < points_count; i++) {
|
||||
if (points[i - 1] == points[i])
|
||||
continue;
|
||||
auto it = brezenham_line_iterable{points[i - 1], points[i]}.begin();
|
||||
it++;
|
||||
for (; it != nullptr; it++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t points_count, class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_polygon_edge(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2> (&&points)[points_count],
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline
|
||||
) {
|
||||
iterate_polygon_edge(
|
||||
std::move(points),
|
||||
[=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline); }
|
||||
);
|
||||
}
|
||||
|
||||
template<std::size_t points_count, class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_polygon_edge(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2> (&&points)[points_count],
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::SpriteMetadata *owner
|
||||
) {
|
||||
iterate_polygon_edge(
|
||||
std::move(points),
|
||||
[=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline, owner); }
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
#include "../color.hpp"
|
||||
#include "brezenham.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
|
||||
template<class receiver_t, std::size_t points_count>
|
||||
void iterate_polyline(
|
||||
RendererApi::PointI<2> (&&points)[points_count],
|
||||
receiver_t receiver
|
||||
) {
|
||||
if constexpr (points_count == 0) {
|
||||
return;
|
||||
} else if constexpr (points_count == 1) {
|
||||
receiver(points[0].x, points[0].y);
|
||||
return;
|
||||
} else {
|
||||
receiver(points[0].x, points[0].y);
|
||||
for (std::size_t i = 1; i < points_count; i++) {
|
||||
if (points[i - 1] == points[i])
|
||||
continue;
|
||||
auto it = brezenham_line_iterable{points[i - 1], points[i]}.begin();
|
||||
it++;
|
||||
for (; it != nullptr; it++) {
|
||||
receiver((*it).x, (*it).y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<std::size_t points_count, class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_polyline_edge(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2> (&&points)[points_count],
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline
|
||||
) {
|
||||
iterate_polyline(
|
||||
points,
|
||||
[=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline); }
|
||||
);
|
||||
}
|
||||
|
||||
template<std::size_t points_count, class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_polyline_edge(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2> (&&points)[points_count],
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::SpriteMetadata *owner
|
||||
) {
|
||||
iterate_polyline(
|
||||
points,
|
||||
[=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline, owner); }
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,272 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/utilities/color.hpp>
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
|
||||
class rectangle_fill_iterable {
|
||||
private:
|
||||
RendererApi::PointI<2>::component_t x_start, y_start, x_end, y_end;
|
||||
|
||||
constexpr rectangle_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
|
||||
) noexcept: x_start{x0}, y_start{y0}, x_end{x1}, y_end{y1} {}
|
||||
|
||||
public:
|
||||
static constexpr rectangle_fill_iterable from_wh(
|
||||
RendererApi::PointI<2>::component_t x,
|
||||
RendererApi::PointI<2>::component_t y,
|
||||
RendererApi::PointI<2>::component_t w,
|
||||
RendererApi::PointI<2>::component_t h
|
||||
) noexcept {
|
||||
return {x, y, x + w, y + h};
|
||||
}
|
||||
|
||||
static constexpr rectangle_fill_iterable from_edges(
|
||||
RendererApi::PointI<2>::component_t left,
|
||||
RendererApi::PointI<2>::component_t top,
|
||||
RendererApi::PointI<2>::component_t right,
|
||||
RendererApi::PointI<2>::component_t bottom
|
||||
) noexcept {
|
||||
return {left, top, right, bottom};
|
||||
}
|
||||
|
||||
class iterator {
|
||||
private:
|
||||
RendererApi::PointI<2>::component_t x_start, x_end, y_end;
|
||||
RendererApi::PointI<2>::component_t x, y;
|
||||
|
||||
constexpr iterator(
|
||||
RendererApi::PointI<2>::component_t x0,
|
||||
RendererApi::PointI<2>::component_t y0,
|
||||
RendererApi::PointI<2>::component_t x1,
|
||||
RendererApi::PointI<2>::component_t y1
|
||||
) noexcept: x_start{x0}, x_end{x1}, y_end{y1}, x{x0}, y{y0} {}
|
||||
|
||||
friend class rectangle_fill_iterable;
|
||||
|
||||
public:
|
||||
constexpr iterator &operator++() noexcept {
|
||||
if (++this->x > this->x_end) {
|
||||
if (this->y < this->y_end) {
|
||||
this->y++;
|
||||
}
|
||||
this->x = x_start;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator operator++(int) noexcept {
|
||||
iterator next = *this;
|
||||
++(*this);
|
||||
return next;
|
||||
}
|
||||
|
||||
constexpr RendererApi::PointI<2> operator*() const noexcept {
|
||||
return {this->x, this->y};
|
||||
}
|
||||
|
||||
constexpr bool operator==(std::nullptr_t) const noexcept {
|
||||
return this->y >= this->y_end;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(std::nullptr_t) const noexcept {
|
||||
return this->y < this->y_end;
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr iterator begin() const noexcept {
|
||||
return iterator{
|
||||
this->x_start, this->y_start,
|
||||
this->x_end, this->y_end
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::nullptr_t end() const noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<class receiver_t>
|
||||
void iterate_rectangle_fill_edges(
|
||||
RendererApi::PointI<2>::component_t left,
|
||||
RendererApi::PointI<2>::component_t top,
|
||||
RendererApi::PointI<2>::component_t right,
|
||||
RendererApi::PointI<2>::component_t bottom,
|
||||
receiver_t receiver
|
||||
) {
|
||||
for (RendererApi::PointI<2>::component_t x = left; x < right; x++) {
|
||||
receiver(true, x, top);
|
||||
}
|
||||
|
||||
right--;
|
||||
bottom--;
|
||||
for (RendererApi::PointI<2>::component_t y = top; y < bottom; y++) {
|
||||
RendererApi::PointI<2>::component_t x = left;
|
||||
receiver(true, x, y);
|
||||
for (x++; x < right; x++) {
|
||||
receiver(false, x, y);
|
||||
}
|
||||
receiver(true, x, y);
|
||||
}
|
||||
bottom++;
|
||||
|
||||
for (RendererApi::PointI<2>::component_t x = left; x <= right; x++) {
|
||||
receiver(true, x, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
template<class receiver_t>
|
||||
void iterate_rectangle_fill_wh(
|
||||
RendererApi::PointI<2>::component_t x,
|
||||
RendererApi::PointI<2>::component_t y,
|
||||
RendererApi::PointI<2>::component_t width,
|
||||
RendererApi::PointI<2>::component_t height,
|
||||
receiver_t receiver
|
||||
) {
|
||||
return iterate_rectangle_fill_edges<receiver_t>(x, y, x + width, y + height, receiver);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_rectangle_edges(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t left,
|
||||
RendererApi::PointI<2>::component_t top,
|
||||
RendererApi::PointI<2>::component_t right,
|
||||
RendererApi::PointI<2>::component_t bottom,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline
|
||||
) {
|
||||
iterate_rectangle_fill_edges(
|
||||
left, top, right, bottom,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_rectangle_wh(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t x,
|
||||
RendererApi::PointI<2>::component_t y,
|
||||
RendererApi::PointI<2>::component_t width,
|
||||
RendererApi::PointI<2>::component_t height,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline
|
||||
) {
|
||||
iterate_rectangle_fill_wh(
|
||||
x, y, width, height,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void fill_rectangle_edges(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t left,
|
||||
RendererApi::PointI<2>::component_t top,
|
||||
RendererApi::PointI<2>::component_t right,
|
||||
RendererApi::PointI<2>::component_t bottom,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::Color::Transparent fill
|
||||
) {
|
||||
iterate_rectangle_fill_edges(
|
||||
left, top, right, bottom,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, is_edge ? outline : fill); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void fill_rectangle_wh(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t x,
|
||||
RendererApi::PointI<2>::component_t y,
|
||||
RendererApi::PointI<2>::component_t width,
|
||||
RendererApi::PointI<2>::component_t height,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::Color::Transparent fill
|
||||
) {
|
||||
iterate_rectangle_fill_wh(
|
||||
x, y, width, height,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, is_edge ? outline : fill); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_rectangle_edges(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t left,
|
||||
RendererApi::PointI<2>::component_t top,
|
||||
RendererApi::PointI<2>::component_t right,
|
||||
RendererApi::PointI<2>::component_t bottom,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::SpriteMetadata *owner
|
||||
) {
|
||||
iterate_rectangle_fill_edges(
|
||||
left, top, right, bottom,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline, owner); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void draw_rectangle_wh(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t x,
|
||||
RendererApi::PointI<2>::component_t y,
|
||||
RendererApi::PointI<2>::component_t width,
|
||||
RendererApi::PointI<2>::component_t height,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::SpriteMetadata *owner
|
||||
) {
|
||||
iterate_rectangle_fill_wh(
|
||||
x, y, width, height,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline, owner); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void fill_rectangle_edges(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t left,
|
||||
RendererApi::PointI<2>::component_t top,
|
||||
RendererApi::PointI<2>::component_t right,
|
||||
RendererApi::PointI<2>::component_t bottom,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::Color::Transparent fill,
|
||||
RendererApi::SpriteMetadata *owner
|
||||
) {
|
||||
iterate_rectangle_fill_edges(
|
||||
left, top, right, bottom,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, (is_edge ? outline : fill), owner); }
|
||||
);
|
||||
}
|
||||
|
||||
template<class voxel_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
void fill_rectangle_wh(
|
||||
voxel_painter_t *painter,
|
||||
RendererApi::PointI<2>::component_t x,
|
||||
RendererApi::PointI<2>::component_t y,
|
||||
RendererApi::PointI<2>::component_t width,
|
||||
RendererApi::PointI<2>::component_t height,
|
||||
double z,
|
||||
RendererApi::Color::Transparent outline,
|
||||
RendererApi::Color::Transparent fill,
|
||||
RendererApi::SpriteMetadata *owner
|
||||
) {
|
||||
iterate_rectangle_fill_wh(
|
||||
x, y, width, height,
|
||||
[=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, (is_edge ? outline : fill), owner); }
|
||||
);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||
#include "brezenham.hpp"
|
||||
#include "bgtu/computer_graphics_lab_work/utilities/shapes/brezenham.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
|
||||
|
@ -29,5 +29,5 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
};
|
||||
};
|
||||
|
||||
using VoxelPainterExporterToRgb32Array = VoxelPainterExporterToPackedArray<4, PackColor::color_to_rgb32>;
|
||||
using VoxelPainterExporterToBgr32Array = VoxelPainterExporterToPackedArray<4, PackColor::color_to_bgr32>;
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/voxel_painter.hpp>
|
||||
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
|
||||
#include "shapes/rectangle.hpp"
|
||||
|
||||
namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
template<class unzoomed_painter_t = RendererApi::VirtualVoxelPainter>
|
||||
class ZoomedVoxelPainter : public RendererApi::VirtualVoxelPainter {
|
||||
private:
|
||||
unzoomed_painter_t *dst;
|
||||
RendererApi::PointI<2>::component_t cx, cy;
|
||||
std::size_t pixel_size;
|
||||
public:
|
||||
constexpr ZoomedVoxelPainter(
|
||||
unzoomed_painter_t *dst,
|
||||
RendererApi::PointI<2>::component_t cx,
|
||||
RendererApi::PointI<2>::component_t cy,
|
||||
std::size_t pixel_size
|
||||
) noexcept: dst{dst}, cx{cx}, cy{cy}, pixel_size{pixel_size} {}
|
||||
|
||||
constexpr ZoomedVoxelPainter(
|
||||
unzoomed_painter_t *dst,
|
||||
RendererApi::PointI<2> center_tl,
|
||||
std::size_t pixel_size
|
||||
) noexcept: dst{dst}, cx{center_tl.x}, cy{center_tl.y}, pixel_size{pixel_size} {}
|
||||
|
||||
void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c) final {
|
||||
Shapes::fill_rectangle_wh<unzoomed_painter_t>(
|
||||
this->dst,
|
||||
this->cx + x * this->pixel_size,
|
||||
this->cy + y * this->pixel_size,
|
||||
this->pixel_size,
|
||||
this->pixel_size,
|
||||
z,
|
||||
c, c
|
||||
);
|
||||
}
|
||||
|
||||
void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c, RendererApi::SpriteMetadata *owner) final {
|
||||
Shapes::fill_rectangle_wh<unzoomed_painter_t>(
|
||||
this->dst,
|
||||
this->cx + x * this->pixel_size,
|
||||
this->cy + y * this->pixel_size,
|
||||
this->pixel_size,
|
||||
this->pixel_size,
|
||||
z,
|
||||
c, c,
|
||||
owner
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr visible_pixel_coordinate_fast_t width() const override {
|
||||
throw std::exception{"This wrapper doesn't provides such information"};
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr visible_pixel_coordinate_fast_t height() const override {
|
||||
throw std::exception{"This wrapper doesn't provides such information"};
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
@ -14,23 +14,24 @@
|
||||
|
||||
%macro impl_body 1
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
movd xmm0, edi
|
||||
movd xmm1, esi
|
||||
shr esi, 24
|
||||
cmp r8d, 255
|
||||
je %%not_opaque
|
||||
movd xmm0, edi
|
||||
mov r8d, esi
|
||||
%elifidn __OUTPUT_FORMAT__, win64
|
||||
; movzx r9d, WORD [rdx]
|
||||
; movzx r10d, BYTE [rdx+2]
|
||||
; shl r10d, 16
|
||||
; or r9d, r10d
|
||||
movd xmm0, DWORD [rdx]
|
||||
movd xmm1, r8d
|
||||
shr r8d, 24
|
||||
cmp r8d, 255
|
||||
je %%not_opaque
|
||||
movd xmm0, DWORD [rdx]
|
||||
%else
|
||||
%error "Unsupported output format"
|
||||
%endif
|
||||
|
||||
pmovzxbd xmm0, xmm0 ; 0-extend 8bit->32bit
|
||||
pmovzxbd xmm1, xmm1 ; 0-extend 8bit->32bit
|
||||
shr r8d, 24
|
||||
pmovzxbd xmm0, xmm0 ; 0-extend 8bit->32bit SSE4.1
|
||||
pmovzxbd xmm1, xmm1 ; 0-extend 8bit->32bit SSE4.1
|
||||
%if %1 >= __AVX512F__
|
||||
vpbroadcastd xmm2, r8d ; fill vector with 32bit values
|
||||
%elif %1 >= __AVX2__
|
||||
@ -44,12 +45,19 @@
|
||||
movd xmm3, r8d
|
||||
vpbroadcastd xmm3, xmm3
|
||||
%endif
|
||||
cvtdq2ps xmm0, xmm0 ; i32 -> float SSE2
|
||||
cvtdq2ps xmm1, xmm1 ; i32 -> float SSE2
|
||||
cvtdq2ps xmm2, xmm2 ; i32 -> float SSE2
|
||||
cvtdq2ps xmm3, xmm3 ; i32 -> float SSE2
|
||||
movups xmm4, xmm3
|
||||
|
||||
psubd xmm3, xmm2 ; sub 32bit integers
|
||||
pmuludq xmm0, xmm3 ; mul unsigned 32bit integers
|
||||
pmuludq xmm1, xmm2 ; mul unsigned 32bit integers
|
||||
paddd xmm0, xmm1 ; add 32bit integers
|
||||
psrld xmm0, 8 ; 0-shift 32bit integers right
|
||||
subps xmm3, xmm2
|
||||
mulps xmm0, xmm3
|
||||
mulps xmm1, xmm2
|
||||
addps xmm0, xmm1
|
||||
divps xmm0, xmm4
|
||||
|
||||
cvttps2dq xmm0, xmm0
|
||||
|
||||
pextrd r9d, xmm0, 0 ; extracts 32 bit integer
|
||||
pextrd r10d, xmm0, 1 ; extracts 32 bit integer
|
||||
@ -60,11 +68,21 @@
|
||||
or r9d, r11d
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
mov eax, r9d
|
||||
movd eax, r9d
|
||||
%elifidn __OUTPUT_FORMAT__, win64
|
||||
mov DWORD [rcx], r9d
|
||||
%else
|
||||
%error "Unsupported output format"
|
||||
%endif
|
||||
ret
|
||||
|
||||
%%not_opaque:
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
movd eax, xmm1
|
||||
%elifidn __OUTPUT_FORMAT__, win64
|
||||
movd DWORD [rcx], xmm1
|
||||
%else
|
||||
%error "Unsupported output format"
|
||||
%endif
|
||||
ret
|
||||
%endmacro
|
||||
@ -75,7 +93,10 @@ section .text
|
||||
|
||||
; avx2
|
||||
|
||||
global ?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc
|
||||
global ?_apply_transparent_color_avx512f@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc
|
||||
?_apply_transparent_color_avx512f@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z:
|
||||
impl_body __AVX512F__
|
||||
|
||||
global ?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc
|
||||
?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z:
|
||||
impl_body __AVX2__
|
Loading…
Reference in New Issue
Block a user