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,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<std::string, OPERATOR_COUNT> function_name_map = {
FUNC_FUNCTIONS
};
#undef FUNC_DEFINE
/*
* 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{
[x, y](const image_data_t* d) -> blt::vec3 {

View File

@ -18,6 +18,42 @@
#include <functions.h>
#include <random>
#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)
{
@ -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<int>(x), static_cast<int>(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);
}

View File

@ -11,11 +11,15 @@
#include "imgui.h"
#include <variant>
#include <random>
#include <queue>
#include <stack>
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, 32000> node_allocator;
@ -49,7 +53,7 @@ struct node
std::optional<image> 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<int> 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<blt::size_t> select(0, terminals.size() - 1);
sub_nodes[i] = createNode(terminals[select(engine)]);
} 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:
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<int> choice(0, 1);
std::uniform_int_distribution<int> select(0, OPERATOR_COUNT - 1);
std::random_device dev;
std::mt19937_64 engine{dev()};
std::uniform_real_distribution<float> dist(0.0f, 1.0f);
node* n = createNode(static_cast<function_t>(select(engine)));
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;
}
@ -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},