From 8f04baeb65d6eb06caaecce1ce7dacc1240c424e Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Thu, 25 Jan 2024 14:44:47 -0500 Subject: [PATCH] functional but slow --- .../Testing/Temporary/LastTest.log | 4 +- include/functions.h | 41 ++++---- include/image.h | 2 +- src/functions.cpp | 98 +++++++++++++++---- src/main.cpp | 89 +++++++++++++++-- 5 files changed, 185 insertions(+), 49 deletions(-) diff --git a/cmake-build-release/Testing/Temporary/LastTest.log b/cmake-build-release/Testing/Temporary/LastTest.log index 22cafb0..e5da0f2 100644 --- a/cmake-build-release/Testing/Temporary/LastTest.log +++ b/cmake-build-release/Testing/Temporary/LastTest.log @@ -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 diff --git a/include/functions.h b/include/functions.h index 27a3ef8..38e4234 100644 --- a/include/functions.h +++ b/include/functions.h @@ -125,26 +125,26 @@ void f_if(ARGS); // NAME MIN MAX FUNC ALLOWED FUNC LIST #define FUNC_FUNCTIONS \ - FUNC_DEFINE(Y, 0, 0, f_x, FUNC_ALLOW_NONE) \ - FUNC_DEFINE(X, 0, 0, f_y, FUNC_ALLOW_NONE) \ + FUNC_DEFINE(X, 0, 0, f_x, 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(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(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(SCALAR, 0, 0, f_scalar, FUNC_ALLOW_NONE) \ - FUNC_DEFINE(COLOR, 0, 0, f_color, FUNC_ALLOW_NONE) \ - FUNC_DEFINE(LOG, 1, 1, f_log, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(SQRT, 1, 1, f_sqrt, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(SIN, 1, 1, f_sin, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(COS, 1, 1, f_cos, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(ATAN, 1, 1, f_atan, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(ADD, 2, 2, f_add, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(SUB, 2, 2, f_sub, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(MUL, 2, 2, f_mul, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(DIV, 2, 2, f_div, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(OR, 2, 2, f_or, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(AND, 2, 2, f_and, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(XOR, 2, 2, f_xor, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ - FUNC_DEFINE(IF, 3, 3, f_if, FUNC_ALLOW_BOOL, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(COLOR, 0, 0, f_color, FUNC_ALLOW_NONE) \ + FUNC_DEFINE(LOG, 1, 1, f_log, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(SQRT, 1, 1, f_sqrt, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(SIN, 1, 1, f_sin, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(COS, 1, 1, f_cos, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(ATAN, 1, 1, f_atan, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(ADD, 2, 2, f_add, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(SUB, 2, 2, f_sub, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(MUL, 2, 2, f_mul, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(DIV, 2, 2, f_div, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(OR, 2, 2, f_or, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(AND, 2, 2, f_and, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(XOR, 2, 2, f_xor, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ + FUNC_DEFINE(IF, 3, 3, f_if, FUNC_ALLOW_BOOL, FUNC_ALLOW_ANY, FUNC_ALLOW_ANY) \ #undef FUNC_ALLOW_ANY #undef FUNC_ALLOW_NONE @@ -215,6 +215,11 @@ DEF_FUNC_LIST(FUNC_ALLOW_TERMINALS, function_t::SCALAR, function_t::X, function_ FUNC_FUNCTIONS }; #undef FUNC_DEFINE +#define FUNC_DEFINE(NAME, MIN_ARGS, MAX_ARGS, FUNC, ...) #NAME, +[[maybe_unused]] static inline std::array function_name_map = { + FUNC_FUNCTIONS +}; +#undef FUNC_DEFINE /* * Helper functions diff --git a/include/image.h b/include/image.h index bbeb334..bbafaf2 100644 --- a/include/image.h +++ b/include/image.h @@ -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{ [x, y](const image_data_t* d) -> blt::vec3 { diff --git a/src/functions.cpp b/src/functions.cpp index 8ad2032..b2ac0bd 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -18,6 +18,42 @@ #include #include #include +#include + +#define FUNCTION_COORD() \ + int xi = static_cast(x); \ + int yi = static_cast(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(i1.x()); \ + auto bitsGI1 = blt::mem::type_cast(i1.y()); \ + auto bitsBI1 = blt::mem::type_cast(i1.z()); \ + \ + auto bitsRI2 = blt::mem::type_cast(i2.x()); \ + auto bitsGI2 = blt::mem::type_cast(i2.y()); \ + auto bitsBI2 = blt::mem::type_cast(i2.z()); \ + \ + auto r = blt::mem::type_cast(bitsRI1 op bitsRI2); \ + auto g = blt::mem::type_cast(bitsGI1 op bitsGI2); \ + auto b = blt::mem::type_cast(bitsBI1 op bitsBI2); \ + \ + img.set(blt::vec3{r, g, b}, xi, yi); inline float protect_div(float x, float y, float d = 0) { @@ -85,14 +121,14 @@ void f_cnoise(image& img, float x, float y, blt::size_t argc, const image** argv scaleRY *= argv[5]->get().x(); auto valR = stb_perlin_noise3(protect_div(x, scaleRX, z), - protect_div(y, scaleRY, z), - z, 0, 0, 0); + protect_div(y, scaleRY, z), + z, 0, 0, 0); auto valG = stb_perlin_noise3(protect_div(x, scaleGX, z), - protect_div(y, scaleGY, z), - z, 0, 0, 0); + protect_div(y, scaleGY, z), + z, 0, 0, 0); auto valB = stb_perlin_noise3(protect_div(x, scaleBX, z), - protect_div(y, scaleBY, z), - z, 0, 0, 0); + protect_div(y, scaleBY, z), + z, 0, 0, 0); img.set({valR, valG, valB}, static_cast(x), static_cast(y)); } @@ -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) { - + 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) { - + 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) { - +#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) { - +#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) { - +#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) { - +#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) { - +#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) { - +#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) { - +#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) { - + BITWISE_FUNCTION(|); } 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) { - + BITWISE_FUNCTION(^); } 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); } diff --git a/src/main.cpp b/src/main.cpp index 1a2fafb..e1f2ee5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,11 +11,15 @@ #include "imgui.h" #include #include +#include +#include blt::gfx::matrix_state_manager global_matrices; blt::gfx::resource_manager resources; blt::gfx::batch_renderer_2d renderer_2d(resources); +constexpr blt::i32 MAX_DEPTH = 25; + struct node; blt::area_allocator node_allocator; @@ -49,7 +53,7 @@ struct node std::optional img; - void grow() + void grow(bool use_terminals) { auto min_children = function_arg_min_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 choice(0, 1); argc = dist(engine); + if (argc == 0) + return; const auto& allowed_args_args = function_arg_allowed_map[to_underlying(type)]; for (size_t i = 0; i < argc; i++) { // 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()}; argc = function_arg_max_map[to_underlying(type)]; + if (argc == 0) + return; + const auto& allowed_args_args = function_arg_allowed_map[to_underlying(type)]; for (size_t i = 0; i < argc; i++) populate_node(i, engine, allowed_args_args[i], use_terminals); @@ -84,6 +93,13 @@ struct node if (use_terminal) { 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 select(0, terminals.size() - 1); sub_nodes[i] = createNode(terminals[select(engine)]); } else @@ -101,7 +117,26 @@ 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: explicit node(function_t type): type(type) { @@ -119,13 +154,31 @@ struct node 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 choice(0, 1); + std::uniform_int_distribution select(0, OPERATOR_COUNT - 1); - std::random_device dev; - std::mt19937_64 engine{dev()}; - std::uniform_real_distribution dist(0.0f, 1.0f); + node* n = createNode(static_cast(select(engine))); - n->full(true); + std::queue> 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; } @@ -169,6 +222,17 @@ struct node evaluate(); } + void printTree() + { + print_tree(); + std::cout << std::endl; + } + + bool hasImage() + { + return img.has_value(); + } + image& getImage() { return img.value(); @@ -226,13 +290,20 @@ void update(std::int32_t w, std::int32_t h) BLT_INFO("Uploading"); //delete texture; - texture->upload((void*) root->getImage().getData().data(), GL_RGB, 0, 0, 0, -1, -1, GL_FLOAT); + if (root->hasImage()) + 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(file); //texture = new blt::gfx::texture_gl2D(file); resources.set("img", texture); } + if (ImGui::Button("Display")) + { + if (root) + root->printTree(); + } + auto lw = 512.0f; auto lh = 512.0f; //renderer_2d.drawRectangle(blt::vec4{0.5, 0.0, 1.0, 1.0},