GP_Image_Test/include/image.h

198 lines
6.8 KiB
C
Raw Normal View History

2024-01-16 14:53:31 -05:00
/*
* <Short Description>
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GP_IMAGE_TEST_IMAGE_H
#define GP_IMAGE_TEST_IMAGE_H
#include <blt/std/types.h>
#include <array>
#include <optional>
#include "blt/std/assert.h"
2024-01-24 23:42:15 -05:00
#include "blt/std/utility.h"
#include "blt/std/allocator.h"
#include "blt/math/vectors.h"
#include <variant>
2024-01-29 21:33:22 -05:00
#include <config.h>
2024-01-16 14:53:31 -05:00
2024-01-24 23:42:15 -05:00
using image_data_t = std::array<blt::vec3, width * height>;
2024-03-23 19:41:03 -04:00
inline blt::bump_allocator<image_data_t> img_allocator(8192);
2024-01-16 14:53:31 -05:00
class image
{
private:
2024-01-27 12:28:37 -05:00
mutable std::variant<image_data_t*, blt::vec3, float> data;
2024-01-16 14:53:31 -05:00
public:
2024-01-24 23:42:15 -05:00
image()
{
data = img_allocator.allocate(1);
img_allocator.construct(std::get<image_data_t*>(data));
}
2024-01-16 14:53:31 -05:00
2024-01-24 23:42:15 -05:00
image(const image& copy)
2024-01-19 15:27:32 -05:00
{
2024-01-24 23:42:15 -05:00
std::visit(blt::lambda_visitor{
[&](const image_data_t* d) {
data = img_allocator.allocate(1);
img_allocator.construct(std::get<image_data_t*>(data));
for (size_t i = 0; i < d->size(); i++)
std::get<image_data_t*>(data)[i] = d[i];
},
[&](const blt::vec3& v) {
this->data = v;
},
[&](float f) {
this->data = f;
}
}, copy.data);
2024-01-19 15:27:32 -05:00
}
2024-01-24 23:42:15 -05:00
image(image&& move)
2024-01-16 14:53:31 -05:00
{
2024-01-24 23:42:15 -05:00
data = std::move(move.data);
move.data = nullptr;
2024-01-16 14:53:31 -05:00
}
2024-01-24 23:42:15 -05:00
image& operator=(const image& copy)
2024-01-16 14:53:31 -05:00
{
2024-01-24 23:42:15 -05:00
if (&copy == this)
return *this;
std::visit(blt::lambda_visitor{
[&](const image_data_t* d) {
if (std::holds_alternative<image_data_t*>(data))
img_allocator.deallocate(std::get<image_data_t*>(data), 1);
data = img_allocator.allocate(1);
img_allocator.construct(std::get<image_data_t*>(data));
for (size_t i = 0; i < d->size(); i++)
std::get<image_data_t*>(data)[i] = d[i];
},
[&](const blt::vec3& v) {
this->data = v;
},
[&](float f) {
this->data = f;
}
}, copy.data);
return *this;
};
image& operator=(image&& move)
{
std::swap(move.data, data);
return *this;
}
image(const blt::vec3& v): data(v)
{}
image(float f): data(f)
{}
image_data_t& getData()
2024-01-27 12:28:37 -05:00
{
if (std::holds_alternative<image_data_t*>(data))
return *std::get<image_data_t*>(data);
else
{
blt::vec3 color = std::visit(blt::lambda_visitor{
[](const image_data_t*) -> blt::vec3 {
BLT_ASSERT("There has been an error in the matrix. You should not have gotten here!");
return {};
},
[](const blt::vec3& v) -> blt::vec3 {
return v;
},
[](float f) -> blt::vec3 {
return blt::vec3{f, f, f};
}
}, data);
data = img_allocator.allocate(1);
img_allocator.construct(std::get<image_data_t*>(data));
for (auto& v : *std::get<image_data_t*>(data))
v = color;
return *std::get<image_data_t*>(data);
}
}
[[nodiscard]] const image_data_t& getData() const
2024-01-24 23:42:15 -05:00
{
if (std::holds_alternative<image_data_t*>(data))
return *std::get<image_data_t*>(data);
else
{
blt::vec3 color = std::visit(blt::lambda_visitor{
[](const image_data_t*) -> blt::vec3 {
BLT_ASSERT("There has been an error in the matrix. You should not have gotten here!");
2024-01-25 11:08:23 -05:00
return {};
2024-01-24 23:42:15 -05:00
},
[](const blt::vec3& v) -> blt::vec3 {
return v;
},
[](float f) -> blt::vec3 {
return blt::vec3{f, f, f};
}
}, data);
data = img_allocator.allocate(1);
img_allocator.construct(std::get<image_data_t*>(data));
for (auto& v : *std::get<image_data_t*>(data))
v = color;
return *std::get<image_data_t*>(data);
}
}
2024-01-25 14:44:47 -05:00
[[nodiscard]] blt::vec3 get(blt::i32 x = 0, blt::i32 y = 0) const
2024-01-24 23:42:15 -05:00
{
return std::visit(blt::lambda_visitor{
[x, y](const image_data_t* d) -> blt::vec3 {
if (x < 0 || y < 0 || x >= width || y >= height)
return blt::vec3{0,0,0};
return (*d)[y * height + x];
},
[](const blt::vec3& v) -> blt::vec3 {
return v;
},
[](float f) -> blt::vec3 {
return blt::vec3{f, f, f};
}
}, data);
}
void set(const blt::vec3& c, blt::i32 x, blt::i32 y)
{
if (!std::holds_alternative<image_data_t*>(data))
{
data = img_allocator.allocate(1);
img_allocator.construct(std::get<image_data_t*>(data));
}
(*std::get<image_data_t*>(data))[y * height + x] = c;
}
~image()
{
if (std::holds_alternative<image_data_t*>(data))
img_allocator.deallocate(std::get<image_data_t*>(data), 1);
2024-01-16 14:53:31 -05:00
}
};
#endif //GP_IMAGE_TEST_IMAGE_H