Skip to content

Commit 6e4c82a

Browse files
committed
i dont like ffts
1 parent 2b212aa commit 6e4c82a

17 files changed

+25636
-174
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CC := gcc
22
CXX := g++
33
CFLAGS := -std=c11 -Werror -g -Iinclude -MMD
44
CXXFLAGS := -std=c++17 -Werror -g -Iinclude -MMD -fopenmp
5-
LDFLAGS := -lglfw -lX11 -lpthread -lXrandr -lXi -ldl -lfftw3 -fopenmp
5+
LDFLAGS := -lglfw -lX11 -lpthread -lXrandr -lXi -ldl -lfftw3 -fopenmp -lxcb
66
BIN_DIR := bin
77
SRC_DIR := src
88
OBJ_DIR := obj
@@ -14,7 +14,7 @@ C_SRC := $(shell find $(SRC_DIR) -name '*.c')
1414
CPP_OBJ := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(CPP_SRC))
1515
C_OBJ := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(C_SRC))
1616
OBJ := $(CPP_OBJ) $(C_OBJ)
17-
DEP := $(OBJ:.o=.d) # Add this line to handle dependencies
17+
DEP := $(OBJ:.o=.d)
1818

1919
TARGET := main
2020

include/Grid.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <Shader.hpp>
88

9+
#include <string>
10+
911
class Grid {
1012
private:
1113
unsigned int VAO, VBO, EBO;
@@ -26,12 +28,16 @@ class Grid {
2628
Grid(unsigned int width, unsigned int height);
2729
virtual ~Grid();
2830
void draw();
29-
virtual void update() {}
31+
virtual void update() = 0;
32+
virtual void drawImGui() = 0;
3033
void setWidth(unsigned int width);
3134
void setHeight(unsigned int height);
3235
unsigned int getWidth() const;
3336
unsigned int getHeight() const;
3437

38+
virtual void parse(std::string pattern) = 0;
39+
virtual std::string toString() const = 0;
40+
3541
void reset();
3642
void randomize();
3743

include/Math.hpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
const double EPSILON = 0.0000001;
88

9+
const int PRECISION = 1000000;
910

1011
double bell(double x, double m, double s);
1112
double polynomial(double x, double m, double s, double a);
@@ -17,4 +18,12 @@ std::vector<std::vector<double>> fastConv2D(std::vector<std::vector<double>> gri
1718
std::vector<std::vector<double>> fftShift(std::vector<std::vector<double>> input);
1819

1920
std::vector<std::vector<double>> roll(std::vector<std::vector<double>> grid, int start_row, int start_col);
20-
double* convertToDoublePointer(std::vector<std::vector<double>>& vec, int subVecIndex);
21+
double* convertToDoublePointer(std::vector<std::vector<double>>& vec, int subVecIndex);
22+
23+
double sigmoid(double x, double a, double b);
24+
25+
double Round(double x);
26+
27+
int RandomInt(int min, int max);
28+
29+
std::vector<std::vector<double>> convolve2D(const std::vector<std::vector<double>>& grid, const std::vector<std::vector<double>>& kernel);

include/lenia/Growth.hpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <cmath>
5+
6+
class Growth {
7+
public:
8+
int id;
9+
double mu;
10+
double sigma;
11+
double alpha;
12+
Growth(double mu, double sigma, double alpha, int id) : mu(mu), sigma(sigma), alpha(alpha), id(id) {}
13+
double apply(double x) {
14+
double r = abs(x - mu);
15+
double r2 = r * r;
16+
double k, k2, p, q; // Declare variables outside the switch
17+
switch (id) {
18+
case 0:
19+
k = 2.0 * sigma * sigma;
20+
return exp(-r2 / k) * 2.0 - 1.0;
21+
case 1:
22+
k2 = 9.0 * sigma * sigma;
23+
return r2 > k2 ? -1.0 : pow(1.0 - r2 / k2, alpha) * 2.0 - 1.0;
24+
case 2:
25+
p = sigma / 2.0;
26+
q = sigma * 2.0;
27+
return r <= p ? 1.0 : r <= q ? 2.0 * (q - r) / (q - p) - 1.0 : -1.0;
28+
case 3:
29+
return r <= sigma ? 1.0 : -1.0;
30+
}
31+
return 0.0;
32+
}
33+
};

include/lenia/Lenia.hpp

+25
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44
#include <FastConv2D.hpp>
55
#include <lenia/LeniaTemplate.h>
66

7+
#include <lenia/LeniaTaxonomyTree.hpp>
8+
9+
#include <string>
10+
711
#include <Math.hpp>
812

13+
#include <lenia/Growth.hpp>
14+
915
class Lenia : public Grid {
1016
public:
1117
Lenia(unsigned int width, unsigned int height, LeniaTemplate rule);
@@ -21,12 +27,31 @@ class Lenia : public Grid {
2127

2228
int updateFrequency = 10;
2329

30+
bool softClip = false;
31+
32+
void drawImGui() override;
33+
34+
void parse(std::string pattern) override;
35+
36+
std::string toString() const override;
37+
38+
2439
private:
2540
std::vector<std::vector<double>> delta;
2641

42+
std::vector<std::vector<double>> kernel;
43+
2744
FastConv2D* conv2d;
2845

2946
int NS;
3047

48+
LeniaTaxonomyTree tree;
49+
3150
double deltaFunc(double x);
51+
52+
void setRule(std::string rule);
53+
54+
void addCellArrray(std::vector<std::vector<std::string>> cells, int x1, int y1, int x2, int y2, double scale, double angle, int flip, int w, int h);
55+
56+
void drawTree(TreeNode* node, int level);
3257
};

include/lenia/LeniaTaxonomyTree.hpp

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
#include <fstream>
6+
#include <sstream>
7+
#include <iostream>
8+
#include <functional>
9+
#include <stack>
10+
11+
#include <nlohmann/json.hpp>
12+
13+
class TreeNode {
14+
public:
15+
std::string name;
16+
std::vector<TreeNode*> children;
17+
18+
std::string data;
19+
20+
bool isLeaf() const {
21+
return children.empty();
22+
}
23+
24+
TreeNode(const std::string& name) : name(name) {}
25+
26+
void addChild(TreeNode* child) {
27+
children.push_back(child);
28+
}
29+
30+
~TreeNode() {
31+
for (TreeNode* child : children) {
32+
delete child;
33+
}
34+
}
35+
};
36+
37+
class LeniaTaxonomyTree {
38+
public:
39+
TreeNode* root;
40+
41+
LeniaTaxonomyTree() {
42+
root = new TreeNode("Lenia");
43+
}
44+
45+
~LeniaTaxonomyTree() {
46+
delete root;
47+
}
48+
49+
void addPhylum(const std::string& phylum) {
50+
root->addChild(new TreeNode(phylum));
51+
}
52+
53+
void addClass(const std::string& phylum, const std::string& class_) {
54+
TreeNode* phylumNode = findNode(root, phylum);
55+
if (phylumNode == nullptr) {
56+
std::cerr << "Phylum not found: " << phylum << std::endl;
57+
return;
58+
}
59+
phylumNode->addChild(new TreeNode(class_));
60+
}
61+
62+
void addOrder(const std::string& phylum, const std::string& class_, const std::string& order) {
63+
TreeNode* phylumNode = findNode(root, phylum);
64+
if (phylumNode == nullptr) {
65+
std::cerr << "Phylum not found: " << phylum << std::endl;
66+
return;
67+
}
68+
TreeNode* classNode = findNode(phylumNode, class_);
69+
if (classNode == nullptr) {
70+
std::cerr << "Class not found: " << class_ << std::endl;
71+
return;
72+
}
73+
classNode->addChild(new TreeNode(order));
74+
}
75+
76+
void addFamily(const std::string& phylum, const std::string& class_, const std::string& order, const std::string& family) {
77+
TreeNode* phylumNode = findNode(root, phylum);
78+
if (phylumNode == nullptr) {
79+
std::cerr << "Phylum not found: " << phylum << std::endl;
80+
return;
81+
}
82+
TreeNode* classNode = findNode(phylumNode, class_);
83+
if (classNode == nullptr) {
84+
std::cerr << "Class not found: " << class_ << std::endl;
85+
return;
86+
}
87+
TreeNode* orderNode = findNode(classNode, order);
88+
if (orderNode == nullptr) {
89+
std::cerr << "Order not found: " << order << std::endl;
90+
return;
91+
}
92+
orderNode->addChild(new TreeNode(family));
93+
}
94+
95+
void addGenus(const std::string& phylum, const std::string& class_, const std::string& order, const std::string& family, const std::string& genus) {
96+
TreeNode* phylumNode = findNode(root, phylum);
97+
if (phylumNode == nullptr) {
98+
std::cerr << "Phylum not found: " << phylum << std::endl;
99+
return;
100+
}
101+
TreeNode* classNode = findNode(phylumNode, class_);
102+
if (classNode == nullptr) {
103+
std::cerr << "Class not found: " << class_ << std::endl;
104+
return;
105+
}
106+
TreeNode* orderNode = findNode(classNode, order);
107+
if (orderNode == nullptr) {
108+
std::cerr << "Order not found: " << order << std::endl;
109+
return;
110+
}
111+
TreeNode* familyNode = findNode(orderNode, family);
112+
if (familyNode == nullptr) {
113+
std::cerr << "Family not found: " << family << std::endl;
114+
return;
115+
}
116+
familyNode->addChild(new TreeNode(genus));
117+
}
118+
119+
void addSpecies(const std::string& phylum, const std::string& class_, const std::string& order, const std::string& family, const std::string& genus, const std::string& species, const std::string& data) {
120+
TreeNode* phylumNode = findNode(root, phylum);
121+
if (phylumNode == nullptr) {
122+
std::cerr << "Phylum not found: " << phylum << std::endl;
123+
return;
124+
}
125+
TreeNode* classNode = findNode(phylumNode, class_);
126+
if (classNode == nullptr) {
127+
std::cerr << "Class not found: " << class_ << std::endl;
128+
return;
129+
}
130+
TreeNode* orderNode = findNode(classNode, order);
131+
if (orderNode == nullptr) {
132+
std::cerr << "Order not found: " << order << std::endl;
133+
return;
134+
}
135+
TreeNode* familyNode = findNode(orderNode, family);
136+
if (familyNode == nullptr) {
137+
std::cerr << "Family not found: " << family << std::endl;
138+
return;
139+
}
140+
TreeNode* genusNode = findNode(familyNode, genus);
141+
if (genusNode == nullptr) {
142+
std::cerr << "Genus not found: " << genus << std::endl;
143+
return;
144+
}
145+
genusNode->addChild(new TreeNode(species));
146+
TreeNode* speciesNode = findNode(genusNode, species);
147+
speciesNode->data = data;
148+
}
149+
150+
void addSpecies(const std::string& phylum, const std::string& class_, const std::string& order, const std::string& family, const std::string& species, const std::string& data) {
151+
TreeNode* phylumNode = findNode(root, phylum);
152+
if (phylumNode == nullptr) {
153+
std::cerr << "Phylum not found: " << phylum << std::endl;
154+
return;
155+
}
156+
TreeNode* classNode = findNode(phylumNode, class_);
157+
if (classNode == nullptr) {
158+
std::cerr << "Class not found: " << class_ << std::endl;
159+
return;
160+
}
161+
TreeNode* orderNode = findNode(classNode, order);
162+
if (orderNode == nullptr) {
163+
std::cerr << "Order not found: " << order << std::endl;
164+
return;
165+
}
166+
TreeNode* familyNode = findNode(orderNode, family);
167+
if (familyNode == nullptr) {
168+
std::cerr << "Family not found: " << family << std::endl;
169+
return;
170+
}
171+
familyNode->addChild(new TreeNode(species));
172+
TreeNode* speciesNode = findNode(familyNode, species);
173+
speciesNode->data = data;
174+
}
175+
176+
void saveToFile(const std::string& filename) {
177+
nlohmann::json json;
178+
std::function<void(TreeNode*, nlohmann::json&)> serialize = [&](TreeNode* node, nlohmann::json& jsonNode) {
179+
jsonNode["name"] = node->name;
180+
jsonNode["data"] = node->data;
181+
if (!node->isLeaf()) {
182+
for (TreeNode* child : node->children) {
183+
nlohmann::json childNode;
184+
serialize(child, childNode);
185+
jsonNode["children"].push_back(childNode);
186+
}
187+
}
188+
};
189+
serialize(root, json);
190+
std::ofstream file(filename);
191+
file << json.dump(4);
192+
file.close();
193+
}
194+
195+
void loadFromFile(const std::string& filename) {
196+
std::ifstream file(filename);
197+
if (!file.is_open()) {
198+
std::cerr << "File not found: " << filename << std::endl;
199+
return;
200+
}
201+
std::stringstream buffer;
202+
buffer << file.rdbuf();
203+
file.close();
204+
nlohmann::json json = nlohmann::json::parse(buffer.str());
205+
std::function<TreeNode*(nlohmann::json&)> deserialize = [&](nlohmann::json& jsonNode) -> TreeNode* {
206+
TreeNode* node = new TreeNode(jsonNode["name"]);
207+
node->data = jsonNode["data"];
208+
for (nlohmann::json& child : jsonNode["children"]) {
209+
node->addChild(deserialize(child));
210+
}
211+
return node;
212+
};
213+
root = deserialize(json);
214+
}
215+
216+
void print() const {
217+
std::function<void(TreeNode*, int)> printNode = [&](TreeNode* node, int depth) {
218+
for (int i = 0; i < depth; i++) {
219+
std::cout << " ";
220+
}
221+
std::cout << "- " << node->name << std::endl;
222+
for (TreeNode* child : node->children) {
223+
printNode(child, depth + 1);
224+
}
225+
};
226+
printNode(root, 0);
227+
}
228+
229+
private:
230+
TreeNode* findNode(TreeNode* node, const std::string& name) {
231+
std::stack<TreeNode*> stack;
232+
stack.push(node);
233+
while (!stack.empty()) {
234+
TreeNode* current = stack.top();
235+
stack.pop();
236+
if (current->name == name) {
237+
return current;
238+
}
239+
for (TreeNode* child : current->children) {
240+
stack.push(child);
241+
}
242+
}
243+
return nullptr;
244+
}
245+
};

0 commit comments

Comments
 (0)