Skip to content

Commit 2b212aa

Browse files
committed
a lot of stuff
1 parent 733ba39 commit 2b212aa

21 files changed

+804
-111
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CC := gcc
22
CXX := g++
33
CFLAGS := -std=c11 -Werror -g -Iinclude -MMD
4-
CXXFLAGS := -std=c++17 -Werror -g -Iinclude -MMD
5-
LDFLAGS := -lglfw -lGL -lX11 -lpthread -lXrandr -lXi -ldl
4+
CXXFLAGS := -std=c++17 -Werror -g -Iinclude -MMD -fopenmp
5+
LDFLAGS := -lglfw -lX11 -lpthread -lXrandr -lXi -ldl -lfftw3 -fopenmp
66
BIN_DIR := bin
77
SRC_DIR := src
88
OBJ_DIR := obj

assets/shaders/grid.fsh

+32-2
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,40 @@ vec3 TurboColormap(in float x) {
2323
dot(v4, kBlueVec4) + dot(v2, kBlueVec2));
2424
}
2525

26+
// https://www.shadertoy.com/view/XsSXDy
27+
vec4 powers(float x) {
28+
return vec4(x*x*x, x*x, x, 1.0);
29+
}
30+
31+
vec4 ca = vec4(3.0, -6.0, 0.0, 4.0) / 6.0;
32+
vec4 cb = vec4(-1.0, 6.0, -12.0, 8.0) / 6.0;
33+
34+
vec4 spline(float x, vec4 c0, vec4 c1, vec4 c2, vec4 c3) {
35+
return c0 * dot(cb, powers(x + 1.0)) +
36+
c1 * dot(ca, powers(x)) +
37+
c2 * dot(ca, powers(1.0 - x)) +
38+
c3 * dot(cb, powers(2.0 - x));
39+
}
40+
41+
#define SAM(a,b) texture(grid, (i+vec2(float(a),float(b))+0.5)/res, -99.0)
42+
43+
vec4 texture_Bicubic(sampler2D tex, vec2 t) {
44+
vec2 res = textureSize(tex, 0);
45+
vec2 p = res*t - 0.5;
46+
vec2 f = fract(p);
47+
vec2 i = floor(p);
48+
49+
return spline(f.y, spline(f.x, SAM(-1,-1), SAM(0,-1), SAM(1,-1), SAM(2,-1)),
50+
spline(f.x, SAM(-1, 0), SAM(0, 0), SAM(1, 0), SAM(2, 0)),
51+
spline(f.x, SAM(-1, 1), SAM(0, 1), SAM(1, 1), SAM(2, 1)),
52+
spline(f.x, SAM(-1, 2), SAM(0, 2), SAM(1, 2), SAM(2, 2)));
53+
}
54+
2655
void main() {
27-
float value = texture(grid, TexCoord).r;
56+
vec4 interpolatedValue = texture_Bicubic(grid, TexCoord);
57+
float value = interpolatedValue.r;
2858

2959
vec3 color = TurboColormap(value);
3060

3161
FragColor = vec4(color, 1.0);
32-
}
62+
}

include/App.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
class App {
44
public:
55
void run();
6+
private:
7+
bool paused = false;
68
};

include/Conv2D.hpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <cmath>
5+
6+
class Conv2D {
7+
public:
8+
Conv2D() = default;
9+
Conv2D(std::vector<std::vector<double>> kernel, int inputWidth, int inputHeight);
10+
11+
virtual std::vector<std::vector<double>> apply(std::vector<std::vector<double>> input);
12+
private:
13+
std::vector<std::vector<double>> kernel;
14+
};

include/FastConv2D.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <Conv2D.hpp>
4+
#include <fftw3.h>
5+
#include <complex>
6+
7+
class FastConv2D : public Conv2D {
8+
public:
9+
FastConv2D() = default;
10+
11+
FastConv2D(std::vector<std::vector<double>> kernel, int inputWidth, int inputHeight);
12+
~FastConv2D();
13+
14+
std::vector<std::vector<double>> apply(std::vector<std::vector<double>> input) override;
15+
private:
16+
fftw_complex* _kernel_fft;
17+
fftw_complex* _grid_fft;
18+
fftw_complex* _input_fft;
19+
fftw_plan _gridPlan;
20+
fftw_plan _inversePlan;
21+
};

include/Grid.hpp

+18-9
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,41 @@
99
class Grid {
1010
private:
1111
unsigned int VAO, VBO, EBO;
12-
unsigned int width, height;
1312
std::vector<float> vertices;
1413
std::vector<unsigned int> indices;
1514
Shader shader;
1615
unsigned int texture;
1716

18-
std::vector<float> grid;
17+
void normalize();
1918

20-
std::vector<float> rowVec;
19+
float* getData();
2120

22-
void normalize();
21+
protected:
22+
unsigned int width, height;
23+
std::vector<std::vector<double>> data;
2324

2425
public:
2526
Grid(unsigned int width, unsigned int height);
27+
virtual ~Grid();
2628
void draw();
27-
void update();
29+
virtual void update() {}
2830
void setWidth(unsigned int width);
2931
void setHeight(unsigned int height);
3032
unsigned int getWidth() const;
3133
unsigned int getHeight() const;
3234

33-
float& operator()(unsigned int x, unsigned int y);
35+
void reset();
36+
void randomize();
37+
38+
void randomizePatches();
39+
40+
std::vector<double>& operator[](unsigned int row);
41+
const std::vector<double>& operator[](unsigned int row) const;
3442

35-
std::vector<float>& operator[](unsigned int row);
43+
void set(unsigned int x, unsigned int y, double value);
44+
double get(unsigned int x, unsigned int y) const;
3645

37-
void set(unsigned int x, unsigned int y, float value);
38-
float get(unsigned int x, unsigned int y) const;
46+
int randomPatches;
47+
int randomPatchSize;
3948
};
4049

include/Kernel.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include <vector>
4+
5+
double _kernelCoreFunction(double r, double alpha, int coreId);
6+
7+
double _kernelFunction(double r, int layerId, std::vector<double> b, int bDiv, double alpha , int coreId);
8+
9+
std::vector<std::vector<double>> buildKernel(int size, int nSize, int coreId, int layerId, std::vector<double> b, double alpha);

include/Math.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <cmath>
5+
#include <fftw3.h>
6+
7+
const double EPSILON = 0.0000001;
8+
9+
10+
double bell(double x, double m, double s);
11+
double polynomial(double x, double m, double s, double a);
12+
int wrap(int x, int n);
13+
double wrapD(double x, double n);
14+
double clip(double x, double a, double b);
15+
std::vector<std::vector<double>> ogrid(int xStart, int xEnd, int yStart, int yEnd);
16+
std::vector<std::vector<double>> fastConv2D(std::vector<std::vector<double>> grid);
17+
std::vector<std::vector<double>> fftShift(std::vector<std::vector<double>> input);
18+
19+
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);

include/defines.h

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#pragma once
2+
// #define OPENMP

include/lenia/Lenia.hpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include <Grid.hpp>
4+
#include <FastConv2D.hpp>
5+
#include <lenia/LeniaTemplate.h>
6+
7+
#include <Math.hpp>
8+
9+
class Lenia : public Grid {
10+
public:
11+
Lenia(unsigned int width, unsigned int height, LeniaTemplate rule);
12+
void update() override;
13+
14+
double mu = 0.15;
15+
16+
double sigma = 0.017;
17+
18+
double alpha = 4.0;
19+
20+
int deltaId = 0;
21+
22+
int updateFrequency = 10;
23+
24+
private:
25+
std::vector<std::vector<double>> delta;
26+
27+
FastConv2D* conv2d;
28+
29+
int NS;
30+
31+
double deltaFunc(double x);
32+
};

include/lenia/LeniaTemplate.h

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include <vector>
4+
5+
typedef struct {
6+
int kernelRadius;
7+
int updateFrequency;
8+
double mu;
9+
double sigma;
10+
std::vector<double> kernel_B;
11+
std::vector<double> kernel_E; // unused
12+
int coreId;
13+
int layerId;
14+
int deltaId; // TODO: implement
15+
double alpha;
16+
bool limitValue; // unused
17+
} LeniaTemplate;

include/lenia/Parser.hpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <lenia/LeniaTemplate.h>
5+
#include <string>
6+
#include <regex>
7+
8+
LeniaTemplate ParseRule(std::string rule);
9+
10+
std::vector<std::string> split(std::string st, std::regex re);
11+
12+
bool endsWith(std::string st, std::string suffix);
13+
14+
bool startsWith(std::string st, std::string prefix);

libs/libglfw3.a

762 KB
Binary file not shown.

src/App.cpp

+111-17
Large diffs are not rendered by default.

src/Conv2D.cpp

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <Conv2D.hpp>
2+
#include <defines.h>
3+
4+
#ifdef OPENMP
5+
#include <omp.h>
6+
#endif
7+
8+
Conv2D::Conv2D(std::vector<std::vector<double>> kernel, int inputWidth, int inputHeight) {
9+
this->kernel = kernel;
10+
}
11+
12+
#ifdef OPENMP
13+
std::vector<std::vector<double>> Conv2D::apply(std::vector<std::vector<double>> input) {
14+
std::vector<std::vector<double>> output(input.size(), std::vector<double>(input[0].size(), 0.0f));
15+
16+
#pragma omp parallel for
17+
for (int y = 0; y < static_cast<int>(input.size()); y++) {
18+
for (unsigned int x = 0; x < input[0].size(); x++) {
19+
for (unsigned int ky = 0; ky < kernel.size(); ky++) {
20+
for (unsigned int kx = 0; kx < kernel[0].size(); kx++) {
21+
int dx = x + kx - kernel[0].size() / 2;
22+
int dy = y + ky - kernel.size() / 2;
23+
24+
if (dx >= 0 && dx < static_cast<int>(input[0].size()) && dy >= 0 && dy < static_cast<int>(input.size())) {
25+
output[y][x] += input[dy][dx] * kernel[ky][kx];
26+
}
27+
}
28+
}
29+
}
30+
}
31+
32+
return output;
33+
}
34+
#else
35+
std::vector<std::vector<double>> Conv2D::apply(std::vector<std::vector<double>> input) {
36+
std::vector<std::vector<double>> output(input.size(), std::vector<double>(input[0].size(), 0.0f));
37+
38+
for (unsigned int y = 0; y < input.size(); y++) {
39+
for (unsigned int x = 0; x < input[0].size(); x++) {
40+
for (unsigned int ky = 0; ky < kernel.size(); ky++) {
41+
for (unsigned int kx = 0; kx < kernel[0].size(); kx++) {
42+
int dx = x + kx - kernel[0].size() / 2;
43+
int dy = y + ky - kernel.size() / 2;
44+
45+
if (dx >= 0 && dx < input[0].size() && dy >= 0 && dy < input.size()) {
46+
output[y][x] += input[dy][dx] * kernel[ky][kx];
47+
}
48+
}
49+
}
50+
}
51+
}
52+
53+
return output;
54+
}
55+
#endif

src/FastConv2D.cpp

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <FastConv2D.hpp>
2+
3+
#include <Math.hpp>
4+
5+
#include <iostream>
6+
#include <stdexcept>
7+
8+
FastConv2D::FastConv2D(std::vector<std::vector<double>> kernel, int inputWidth, int inputHeight) : Conv2D(kernel, inputWidth, inputHeight) {
9+
int kernelWidth = kernel.size();
10+
int kernelHeight = kernel[0].size();
11+
12+
fftw_complex* kernelIn = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * inputWidth * inputHeight);
13+
_kernel_fft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * inputWidth * inputHeight);
14+
fftw_plan kernelPlan = fftw_plan_dft_2d(inputWidth, inputHeight, kernelIn, _kernel_fft, FFTW_FORWARD, FFTW_PATIENT);
15+
if (kernelWidth != inputWidth || kernelHeight != inputHeight) {
16+
throw std::invalid_argument("Kernel size must match input size for FastConv2D");
17+
}
18+
for (int x = 0; x < inputWidth; x++) {
19+
for (int y = 0; y < inputHeight; y++) {
20+
kernelIn[x * inputHeight + y][0] = kernel[x][y];
21+
kernelIn[x * inputHeight + y][1] = 0;
22+
}
23+
}
24+
25+
fftw_execute(kernelPlan);
26+
fftw_destroy_plan(kernelPlan);
27+
fftw_free(kernelIn);
28+
29+
_grid_fft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * inputWidth * inputHeight);
30+
_input_fft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * inputWidth * inputHeight);
31+
32+
_gridPlan = fftw_plan_dft_2d(inputWidth, inputHeight, _input_fft, _grid_fft, FFTW_FORWARD, FFTW_PATIENT);
33+
_inversePlan = fftw_plan_dft_2d(inputWidth, inputHeight, _grid_fft, _input_fft, FFTW_BACKWARD, FFTW_PATIENT);
34+
}
35+
36+
FastConv2D::~FastConv2D() {
37+
fftw_destroy_plan(_gridPlan);
38+
fftw_destroy_plan(_inversePlan);
39+
fftw_free(_grid_fft);
40+
fftw_free(_input_fft);
41+
fftw_free(_kernel_fft);
42+
}
43+
44+
std::vector<std::vector<double>> FastConv2D::apply(std::vector<std::vector<double>> input) {
45+
int inputWidth = input.size();
46+
int inputHeight = input[0].size();
47+
48+
for (int x = 0; x < inputWidth; x++) {
49+
for (int y = 0; y < inputHeight; y++) {
50+
_input_fft[x * inputHeight + y][0] = input[x][y];
51+
_input_fft[x * inputHeight + y][1] = 0;
52+
}
53+
}
54+
55+
fftw_execute(_gridPlan);
56+
57+
for (int x = 0; x < inputWidth; x++) {
58+
for (int y = 0; y < inputHeight; y++) {
59+
double real = _grid_fft[x * inputHeight + y][0] * _kernel_fft[x * inputHeight + y][0] - _grid_fft[x * inputHeight + y][1] * _kernel_fft[x * inputHeight + y][1];
60+
double imag = _grid_fft[x * inputHeight + y][0] * _kernel_fft[x * inputHeight + y][1] + _grid_fft[x * inputHeight + y][1] * _kernel_fft[x * inputHeight + y][0];
61+
_grid_fft[x * inputHeight + y][0] = real;
62+
_grid_fft[x * inputHeight + y][1] = imag;
63+
}
64+
}
65+
66+
fftw_execute(_inversePlan);
67+
68+
std::vector<std::vector<double>> output(inputWidth, std::vector<double>(inputHeight));
69+
for (int x = 0; x < inputWidth; x++) {
70+
for (int y = 0; y < inputHeight; y++) {
71+
output[x][y] = _input_fft[x * inputHeight + y][0] / (inputWidth * inputHeight);
72+
}
73+
}
74+
75+
return roll(output, -1, -1);
76+
}

0 commit comments

Comments
 (0)