diff --git a/inc/Math.hpp b/inc/Math.hpp new file mode 100644 index 0000000..e607c19 --- /dev/null +++ b/inc/Math.hpp @@ -0,0 +1,12 @@ +#include "raylib.h" +#include "raymath.h" + +Color ColorLerp(Color c1, Color c2, float amount) +{ + Color ret{0}; + ret.r = Clamp(Lerp(c1.r, c2.r, amount), 0, 255); + ret.g = Clamp(Lerp(c1.g, c2.g, amount), 0, 255); + ret.b = Clamp(Lerp(c1.b, c2.b, amount), 0, 255); + ret.a = Clamp(Lerp(c1.a, c2.a, amount), 0, 255); + return ret; +} \ No newline at end of file diff --git a/inc/Tree.hpp b/inc/Tree.hpp new file mode 100644 index 0000000..6538bed --- /dev/null +++ b/inc/Tree.hpp @@ -0,0 +1,43 @@ + +#include "raylib.h"; +#include +#include +#include + +#define MAX_DEPTH 11 + +struct branch +{ + Color color; + uint8_t numOfBranches; + float lenghthRatio; +}; + +struct draw_args +{ + Vector2 start; + float angleDeg; + float lenghth; + int dep; +}; + +class Tree +{ + +public: + Tree(int size); + ~Tree(); + void Draw(Rectangle dest); + void new_tree(); + void generate_tree(); + void draw_tree(draw_args first); + void draw_branch(draw_args arg); + Vector2 draw_line(Vector2 start, float angleDeg, float lenghth, int dep); + +private: + int size = 0; + RenderTexture2D target = {0}; + Vector2 start = {0}; + std::vector tree; + std::list draw_calls; +}; \ No newline at end of file diff --git a/main.cpp b/main.cpp index cb67369..017f915 100644 --- a/main.cpp +++ b/main.cpp @@ -1,153 +1,33 @@ -#include -#include -#include -#include #include "raylib.h" -#include "raymath.h" +#include "Tree.hpp" -#define MAX_DEPTH 11 const int screenWidth = 800; const int screenHeight = 800; -#define textureWidth screenWidth -#define textureHeight screenHeight - -const Vector2 start = {textureWidth / 2, textureHeight}; - -Color ColorLerp(Color c1, Color c2, float amount) -{ - Color ret{0}; - ret.r = Clamp(Lerp(c1.r, c2.r, amount), 0, 255); - ret.g = Clamp(Lerp(c1.g, c2.g, amount), 0, 255); - ret.b = Clamp(Lerp(c1.b, c2.b, amount), 0, 255); - ret.a = Clamp(Lerp(c1.a, c2.a, amount), 0, 255); - return ret; -} - -struct branch -{ - Color color; - uint8_t numOfBranches; - float lenghthRatio; -}; - -struct draw_args -{ - Vector2 start; - float angleDeg; - float lenghth; - int dep; -}; - -static std::vector tree(MAX_DEPTH); -static std::list draw_calls; -static RenderTexture2D target; - -Vector2 draw_line(Vector2 start, float angleDeg, float lenghth, int dep) -{ - angleDeg += 180.0f; - float angle = (angleDeg * PI) / 180.0f; - float nx = lenghth * std::sin(angle); - float ny = lenghth * std::cos(angle); - Vector2 end = {start.x + nx, start.y + ny}; - - float thick = 2.0; - float fstep = 1.0 / ((lenghth / thick) * 1.5); - - for (float i = 0; i < 1; i += fstep) - { - Vector2 point = Vector2Lerp(start, end, i); - Color color = ColorLerp(tree[dep - 1].color, tree[dep].color, i); - DrawCircleV(point, thick, color); - } - return end; -} - -void draw_branch(draw_args arg) -{ - if (arg.dep >= MAX_DEPTH) - return; - - Vector2 next = draw_line(arg.start, arg.angleDeg, arg.lenghth, arg.dep); - - float next_len = tree[arg.dep].lenghthRatio; - float sectors = tree[arg.dep].numOfBranches + 1; - float degres = 180.0f / sectors; - - for (size_t i = 0; i < tree[arg.dep].numOfBranches; i++) - { - float newAngle = arg.angleDeg - 90 + (degres * (i + 1)); - draw_calls.push_back((draw_args){next, newAngle, arg.lenghth * next_len, arg.dep + 1}); - } -} - -void draw_tree(draw_args first) -{ - draw_calls.push_back(first); - - while (!draw_calls.empty()) - { - draw_branch(draw_calls.front()); - draw_calls.pop_front(); - } -} - -void generate_tree() -{ - for (size_t i = 0; i < MAX_DEPTH; i++) - { - uint8_t r = GetRandomValue(0, 255); - uint8_t g = GetRandomValue(0, 255); - uint8_t b = GetRandomValue(0, 255); - tree[i].color = (Color){r, g, b, 255}; - - tree[i].numOfBranches = GetRandomValue(1, 3); - - tree[i].lenghthRatio = ((float)GetRandomValue(600, 700)) / 1000.0f; - } - - tree[0].color = tree[1].color; -} - -void new_tree() -{ - generate_tree(); - - BeginTextureMode(target); - ClearBackground(WHITE); - draw_tree((draw_args){start, 0, textureHeight / 4, 1}); - EndTextureMode(); -} int main(void) { InitWindow(screenWidth, screenHeight, "raylib"); SetTargetFPS(60); - - target = LoadRenderTexture(textureWidth, textureHeight); - - new_tree(); - - Rectangle source = {0, 0, (float)target.texture.width, (float)-target.texture.height}; - Rectangle dest = {0, 0, screenWidth, screenHeight}; - Vector2 position = {0, 0}; - Vector2 origin = {0.0f, 0.0f}; - - while (!WindowShouldClose()) { + Tree tre(800); + tre.new_tree(); - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) + Rectangle dest = {0, 0, screenWidth, screenHeight}; + + while (!WindowShouldClose()) { - new_tree(); + + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) + { + tre.new_tree(); + } + + BeginDrawing(); + tre.Draw(dest); + EndDrawing(); } - - BeginDrawing(); - - DrawTexturePro(target.texture, source, dest, origin, 0.0f, WHITE); - - EndDrawing(); } - CloseWindow(); return 0; } \ No newline at end of file diff --git a/src/Tree.cpp b/src/Tree.cpp new file mode 100644 index 0000000..9faab88 --- /dev/null +++ b/src/Tree.cpp @@ -0,0 +1,103 @@ +#include "Tree.hpp" +#include "raylib.h" +#include "raymath.h" +#include "Math.hpp" +#include + +Tree::Tree(int size) +{ + this->size = size; + target = LoadRenderTexture(size, size); + start.x = size / 2; + start.y = size; + + tree.assign(11, {0}); +} + +Tree::~Tree() +{ + UnloadRenderTexture(target); +} + +void Tree::Draw(Rectangle dest) +{ + Rectangle source = {0, 0, (float)target.texture.width, (float)-target.texture.height}; + Vector2 origin = {0.0f, 0.0f}; + DrawTexturePro(target.texture, source, dest, origin, 0.0f, WHITE); +} + +Vector2 Tree::draw_line(Vector2 start, float angleDeg, float lenghth, int dep) +{ + angleDeg += 180.0f; + float angle = (angleDeg * PI) / 180.0f; + float nx = lenghth * std::sin(angle); + float ny = lenghth * std::cos(angle); + Vector2 end = {start.x + nx, start.y + ny}; + + float thick = 2.0; + float fstep = 1.0 / ((lenghth / thick) * 1.5); + + for (float i = 0; i < 1; i += fstep) + { + Vector2 point = Vector2Lerp(start, end, i); + Color color = ColorLerp(tree[dep - 1].color, tree[dep].color, i); + DrawCircleV(point, thick, color); + } + return end; +} + +void Tree::draw_branch(draw_args arg) +{ + if (arg.dep >= MAX_DEPTH) + return; + + Vector2 next = draw_line(arg.start, arg.angleDeg, arg.lenghth, arg.dep); + + float next_len = tree[arg.dep].lenghthRatio; + float sectors = tree[arg.dep].numOfBranches + 1; + float degres = 180.0f / sectors; + + for (size_t i = 0; i < tree[arg.dep].numOfBranches; i++) + { + float newAngle = arg.angleDeg - 90 + (degres * (i + 1)); + draw_calls.push_back((draw_args){next, newAngle, arg.lenghth * next_len, arg.dep + 1}); + } +} + +void Tree::draw_tree(draw_args first) +{ + draw_calls.push_back(first); + + while (!draw_calls.empty()) + { + draw_branch(draw_calls.front()); + draw_calls.pop_front(); + } +} + +void Tree::generate_tree() +{ + for (size_t i = 0; i < MAX_DEPTH; i++) + { + uint8_t r = GetRandomValue(0, 255); + uint8_t g = GetRandomValue(0, 255); + uint8_t b = GetRandomValue(0, 255); + tree[i].color = (Color){r, g, b, 255}; + + tree[i].numOfBranches = GetRandomValue(1, 3); + + tree[i].lenghthRatio = ((float)GetRandomValue(600, 700)) / 1000.0f; + } + + tree[0].color = tree[1].color; +} + +void Tree::new_tree() +{ + generate_tree(); + + BeginTextureMode(target); + ClearBackground(WHITE); + draw_tree((draw_args){start, 0, size / 4, 1}); + EndTextureMode(); +} \ No newline at end of file