functional but slow

main
Brett 2024-01-25 14:44:47 -05:00
parent 8dce8be241
commit 8f04baeb65
5 changed files with 185 additions and 49 deletions

View File

@ -1,3 +1,3 @@
Start testing: Jan 25 10:57 EST Start testing: Jan 25 14:42 EST
---------------------------------------------------------- ----------------------------------------------------------
End testing: Jan 25 10:57 EST End testing: Jan 25 14:42 EST

View File

@ -125,8 +125,8 @@ void f_if(ARGS);
// NAME MIN MAX FUNC ALLOWED FUNC LIST // NAME MIN MAX FUNC ALLOWED FUNC LIST
#define FUNC_FUNCTIONS \ #define FUNC_FUNCTIONS \
FUNC_DEFINE(Y, 0, 0, f_x, FUNC_ALLOW_NONE) \ FUNC_DEFINE(X, 0, 0, f_x, FUNC_ALLOW_NONE) \
FUNC_DEFINE(X, 0, 0, f_y, FUNC_ALLOW_NONE) \ FUNC_DEFINE(Y, 0, 0, f_y, FUNC_ALLOW_NONE) \
FUNC_DEFINE(RANDOM, 0, 0, f_random, FUNC_ALLOW_NONE) \ FUNC_DEFINE(RANDOM, 0, 0, f_random, FUNC_ALLOW_NONE) \
FUNC_DEFINE(NOISE, 0, 2, f_noise, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR) \ FUNC_DEFINE(NOISE, 0, 2, f_noise, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR) \
FUNC_DEFINE(CNOISE, 0, 6, f_cnoise, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR) \ FUNC_DEFINE(CNOISE, 0, 6, f_cnoise, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR, FUNC_ALLOW_SCALAR) \
@ -215,6 +215,11 @@ DEF_FUNC_LIST(FUNC_ALLOW_TERMINALS, function_t::SCALAR, function_t::X, function_
FUNC_FUNCTIONS FUNC_FUNCTIONS
}; };
#undef FUNC_DEFINE #undef FUNC_DEFINE
#define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) #NAME,
[[maybe_unused]] static inline std::array<std::string, OPERATOR_COUNT> function_name_map = {
FUNC_FUNCTIONS
};
#undef FUNC_DEFINE
/* /*
* Helper functions * Helper functions

View File

@ -133,7 +133,7 @@ class image
} }
} }
blt::vec3 get(blt::i32 x = 0, blt::i32 y = 0) const [[nodiscard]] blt::vec3 get(blt::i32 x = 0, blt::i32 y = 0) const
{ {
return std::visit(blt::lambda_visitor{ return std::visit(blt::lambda_visitor{
[x, y](const image_data_t* d) -> blt::vec3 { [x, y](const image_data_t* d) -> blt::vec3 {

View File

@ -18,6 +18,42 @@
#include <functions.h> #include <functions.h>
#include <random> #include <random>
#include <blt/gfx/stb/stb_perlin.h> #include <blt/gfx/stb/stb_perlin.h>
#include <blt/std/memory_util.h>
#define FUNCTION_COORD() \
int xi = static_cast<int>(x); \
int yi = static_cast<int>(y);
#define GET_IMAGE(name, pos) auto name = argv[pos]->get(xi, yi);
#define SINGLE_FUNCTION(op) \
FUNCTION_COORD() \
GET_IMAGE(i1, 0) \
img.set(blt::vec3{op(i1.x()), op(i1.y()), op(i1.z())}, xi, yi);
#define DOUBLE_FUNCTION(op) \
FUNCTION_COORD() \
GET_IMAGE(i1, 0) \
GET_IMAGE(i2, 1) \
img.set(blt::vec3{op(i1.x(), i2.x()), op(i1.y(), i2.y()), op(i1.z(), i2.z())}, xi, yi);
#define BITWISE_FUNCTION(op) \
FUNCTION_COORD() \
GET_IMAGE(i1, 0) \
GET_IMAGE(i2, 1) \
auto bitsRI1 = blt::mem::type_cast<blt::u32>(i1.x()); \
auto bitsGI1 = blt::mem::type_cast<blt::u32>(i1.y()); \
auto bitsBI1 = blt::mem::type_cast<blt::u32>(i1.z()); \
\
auto bitsRI2 = blt::mem::type_cast<blt::u32>(i2.x()); \
auto bitsGI2 = blt::mem::type_cast<blt::u32>(i2.y()); \
auto bitsBI2 = blt::mem::type_cast<blt::u32>(i2.z()); \
\
auto r = blt::mem::type_cast<float>(bitsRI1 op bitsRI2); \
auto g = blt::mem::type_cast<float>(bitsGI1 op bitsGI2); \
auto b = blt::mem::type_cast<float>(bitsBI1 op bitsBI2); \
\
img.set(blt::vec3{r, g, b}, xi, yi);
inline float protect_div(float x, float y, float d = 0) inline float protect_div(float x, float y, float d = 0)
{ {
@ -108,65 +144,89 @@ void f_color(image& img, float x, float y, blt::size_t argc, const image** argv,
void f_log(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_log(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
SINGLE_FUNCTION(std::log);
} }
void f_sqrt(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_sqrt(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
SINGLE_FUNCTION(std::sqrt);
} }
void f_sin(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_sin(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD_SIN(x) ((std::sin(x) + 1) * 0.5f)
SINGLE_FUNCTION(F_MOD_SIN);
#undef F_MOD_SIN
} }
void f_cos(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_cos(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD_COS(x) ((std::cos(x) + 1) * 0.5f)
SINGLE_FUNCTION(F_MOD_COS);
#undef F_MOD_COS
} }
void f_atan(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_atan(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD_ATAN(x) ((std::atan(x) + 1) * 0.5f)
SINGLE_FUNCTION(F_MOD_ATAN);
#undef F_MOD_ATAN
} }
void f_add(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_add(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD(x, y) (x + y)
DOUBLE_FUNCTION(F_MOD);
#undef F_MOD
} }
void f_sub(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_sub(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD(x, y) (x - y)
DOUBLE_FUNCTION(F_MOD);
#undef F_MOD
} }
void f_mul(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_mul(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD(x, y) (x * y)
DOUBLE_FUNCTION(F_MOD);
#undef F_MOD
} }
void f_div(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_div(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
#define F_MOD(x, y) protect_div(x, y)
DOUBLE_FUNCTION(F_MOD);
#undef F_MOD
} }
void f_or(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_or(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
BITWISE_FUNCTION(|);
} }
void f_and(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_and(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
BITWISE_FUNCTION(&);
} }
void f_xor(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_xor(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
BITWISE_FUNCTION(^);
} }
void f_if(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) void f_if(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data)
{ {
FUNCTION_COORD();
GET_IMAGE(i1, 0);
GET_IMAGE(i2, 1);
GET_IMAGE(i3, 2);
constexpr float SCALE = 0.1;
if (i1.x() > SCALE || i1.x() < -SCALE)
img.set(i2, xi, yi);
else
img.set(i3, xi, yi);
} }

View File

@ -11,11 +11,15 @@
#include "imgui.h" #include "imgui.h"
#include <variant> #include <variant>
#include <random> #include <random>
#include <queue>
#include <stack>
blt::gfx::matrix_state_manager global_matrices; blt::gfx::matrix_state_manager global_matrices;
blt::gfx::resource_manager resources; blt::gfx::resource_manager resources;
blt::gfx::batch_renderer_2d renderer_2d(resources); blt::gfx::batch_renderer_2d renderer_2d(resources);
constexpr blt::i32 MAX_DEPTH = 25;
struct node; struct node;
blt::area_allocator<node, 32000> node_allocator; blt::area_allocator<node, 32000> node_allocator;
@ -49,7 +53,7 @@ struct node
std::optional<image> img; std::optional<image> img;
void grow() void grow(bool use_terminals)
{ {
auto min_children = function_arg_min_map[to_underlying(type)]; auto min_children = function_arg_min_map[to_underlying(type)];
auto max_children = function_arg_max_map[to_underlying(type)]; auto max_children = function_arg_max_map[to_underlying(type)];
@ -60,11 +64,13 @@ struct node
static std::uniform_int_distribution<int> choice(0, 1); static std::uniform_int_distribution<int> choice(0, 1);
argc = dist(engine); argc = dist(engine);
if (argc == 0)
return;
const auto& allowed_args_args = function_arg_allowed_map[to_underlying(type)]; const auto& allowed_args_args = function_arg_allowed_map[to_underlying(type)];
for (size_t i = 0; i < argc; i++) for (size_t i = 0; i < argc; i++)
{ {
// 50/50 chance to either use a terminal or use from the function list. // 50/50 chance to either use a terminal or use from the function list.
populate_node(i, engine, allowed_args_args[i], choice(engine)); populate_node(i, engine, allowed_args_args[i], choice(engine) || use_terminals);
} }
} }
@ -74,6 +80,9 @@ struct node
static thread_local std::mt19937_64 engine{dev()}; static thread_local std::mt19937_64 engine{dev()};
argc = function_arg_max_map[to_underlying(type)]; argc = function_arg_max_map[to_underlying(type)];
if (argc == 0)
return;
const auto& allowed_args_args = function_arg_allowed_map[to_underlying(type)]; const auto& allowed_args_args = function_arg_allowed_map[to_underlying(type)];
for (size_t i = 0; i < argc; i++) for (size_t i = 0; i < argc; i++)
populate_node(i, engine, allowed_args_args[i], use_terminals); populate_node(i, engine, allowed_args_args[i], use_terminals);
@ -84,6 +93,13 @@ struct node
if (use_terminal) if (use_terminal)
{ {
auto terminals = intersection(allowed_args, FUNC_ALLOW_TERMINALS_SET); auto terminals = intersection(allowed_args, FUNC_ALLOW_TERMINALS_SET);
if (terminals.empty())
{
terminals = FUNC_ALLOW_TERMINALS;
// BLT_INFO("%s:", function_name_map[to_underlying(type)].c_str());
// for (auto v : allowed_args)
// BLT_INFO(function_name_map[to_underlying(v)]);
}
std::uniform_int_distribution<blt::size_t> select(0, terminals.size() - 1); std::uniform_int_distribution<blt::size_t> select(0, terminals.size() - 1);
sub_nodes[i] = createNode(terminals[select(engine)]); sub_nodes[i] = createNode(terminals[select(engine)]);
} else } else
@ -102,6 +118,25 @@ struct node
} }
} }
void print_tree()
{
if (argc > 0)
std::cout << "(";
if (argc > 0)
std::cout << function_name_map[to_underlying(type)] << " ";
else
{
evaluate();
if (type == function_t::SCALAR)
std::cout << img->get().x() << " ";
else
std::cout << '{' << img->get().x() << ", " << img->get().y() << ", " << img->get().z() << "} ";
}
for (size_t i = 0; i < argc; i++)
sub_nodes[i]->print_tree();
if (argc > 0)
std::cout << ") ";
}
public: public:
explicit node(function_t type): type(type) explicit node(function_t type): type(type)
{ {
@ -119,13 +154,31 @@ struct node
static node* construct_random_tree() static node* construct_random_tree()
{ {
node* n = createNode(function_t::NOISE); static std::random_device dev;
static std::mt19937_64 engine{dev()};
std::uniform_int_distribution<int> choice(0, 1);
std::uniform_int_distribution<int> select(0, OPERATOR_COUNT - 1);
std::random_device dev; node* n = createNode(static_cast<function_t>(select(engine)));
std::mt19937_64 engine{dev()};
std::uniform_real_distribution<float> dist(0.0f, 1.0f);
n->full(true); std::queue<std::pair<node*, size_t>> grow_queue;
size_t current_depth = 0;
grow_queue.emplace(n, current_depth);
while (!grow_queue.empty())
{
auto front = grow_queue.front();
if (front.second != current_depth)
current_depth++;
if (choice(engine))
front.first->grow(front.second >= MAX_DEPTH);
else
front.first->full(front.second >= MAX_DEPTH);
for (size_t i = 0; i < front.first->argc; i++)
grow_queue.emplace(front.first->sub_nodes[i], current_depth + 1);
grow_queue.pop();
}
return n; return n;
} }
@ -169,6 +222,17 @@ struct node
evaluate(); evaluate();
} }
void printTree()
{
print_tree();
std::cout << std::endl;
}
bool hasImage()
{
return img.has_value();
}
image& getImage() image& getImage()
{ {
return img.value(); return img.value();
@ -226,6 +290,7 @@ void update(std::int32_t w, std::int32_t h)
BLT_INFO("Uploading"); BLT_INFO("Uploading");
//delete texture; //delete texture;
if (root->hasImage())
texture->upload((void*) root->getImage().getData().data(), GL_RGB, 0, 0, 0, -1, -1, GL_FLOAT); texture->upload((void*) root->getImage().getData().data(), GL_RGB, 0, 0, 0, -1, -1, GL_FLOAT);
//texture->upload((void*) test.data(), GL_RGBA, 0, 0, 0, width, height, GL_UNSIGNED_BYTE); //texture->upload((void*) test.data(), GL_RGBA, 0, 0, 0, width, height, GL_UNSIGNED_BYTE);
//texture->upload(file); //texture->upload(file);
@ -233,6 +298,12 @@ void update(std::int32_t w, std::int32_t h)
resources.set("img", texture); resources.set("img", texture);
} }
if (ImGui::Button("Display"))
{
if (root)
root->printTree();
}
auto lw = 512.0f; auto lw = 512.0f;
auto lh = 512.0f; auto lh = 512.0f;
//renderer_2d.drawRectangle(blt::vec4{0.5, 0.0, 1.0, 1.0}, //renderer_2d.drawRectangle(blt::vec4{0.5, 0.0, 1.0, 1.0},