Compare commits
10 commits
f4cae1e5c1
...
fa0d6291fe
Author | SHA1 | Date | |
---|---|---|---|
fa0d6291fe | |||
bb532ea5ef | |||
3b6b133001 | |||
9702382a16 | |||
1241bca52f | |||
55448bf44a | |||
c83039098c | |||
1f4565c0a5 | |||
109c94a865 | |||
6a5a7a3b95 |
9 changed files with 447 additions and 192 deletions
|
@ -25,11 +25,11 @@
|
|||
|
||||
// Declare functions
|
||||
|
||||
int cx_glinit(GLFWwindow **);
|
||||
int cx_glrun(GLFWwindow *);
|
||||
|
||||
int cx_glinit(GLFWwindow **);
|
||||
int cx_nninit(Neural_Network **);
|
||||
int cx_nnrun(Neural_Network *);
|
||||
|
||||
int cx_run(GLFWwindow *, Neural_Network *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
typedef struct _model {
|
||||
GLfloat *object;
|
||||
GLfloat *colors;
|
||||
GLfloat **transformations;
|
||||
Tensor **transformations;
|
||||
size_t bufsize;
|
||||
size_t transformation_count;
|
||||
size_t transformation_size;
|
||||
|
@ -22,6 +22,14 @@ int modelRegistry_register(ModelRegistry *, Model *);
|
|||
void modelRegistry_free(ModelRegistry *);
|
||||
GLfloat * model_applyTransformations(Model *);
|
||||
void model_colorFromPosition(Model *);
|
||||
void model_colorXYZ(Model *, int R, int G, int B);
|
||||
void model_colorRed(Model *);
|
||||
void model_colorGreen(Model *);
|
||||
void model_colorBlue(Model *);
|
||||
void model_colorWhite(Model *);
|
||||
void model_colorBlack(Model *);
|
||||
Model *model_circle(int, GLfloat);
|
||||
Model *model_line(GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,21 +3,25 @@
|
|||
|
||||
typedef struct _neuron {
|
||||
float value;
|
||||
float threshold;
|
||||
float **in_values;
|
||||
float *weights;
|
||||
ssize_t in_values_size;
|
||||
float *synapses; // Synapses of the neuron towards the next layer,
|
||||
// NULL if output layer
|
||||
} Neuron;
|
||||
|
||||
typedef struct _neural_layer {
|
||||
Neuron *neurons;
|
||||
size_t layer_size; // Neurons Per Layer
|
||||
size_t layer_size_next; // Neurons in next layer, 0 if output layer,
|
||||
} Neural_Layer;
|
||||
|
||||
typedef struct _neural_network {
|
||||
Neuron *n;
|
||||
ssize_t layer_size; // Neurons Per Layer
|
||||
ssize_t layers;
|
||||
Neural_Layer **layers;
|
||||
ssize_t layer_count;
|
||||
} Neural_Network;
|
||||
|
||||
Neural_Network *neural_new(size_t, size_t);
|
||||
Neural_Network *neural_new(size_t, size_t, size_t);
|
||||
void neural_randomize(Neural_Network *);
|
||||
float *neural_process(Neural_Network *, float *);
|
||||
int neural_getMesh(ModelRegistry *, Neural_Network *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
#ifndef MATRIX_H
|
||||
#define MATRIX_H
|
||||
#ifndef TENSOR_H
|
||||
#define TENSOR_H
|
||||
|
||||
float *matrix_new(void);
|
||||
typedef struct _tensor {
|
||||
float *data;
|
||||
size_t len;
|
||||
size_t width;
|
||||
} Tensor;
|
||||
|
||||
float *matrix_multip(float *, float *);
|
||||
Tensor *tensor_new(size_t, size_t);
|
||||
|
||||
float *matrix_transform(float *, int, float *);
|
||||
Tensor *tensor_fromVertexBuffer(float *, size_t);
|
||||
|
||||
Tensor *tensor_multip(Tensor *, Tensor *);
|
||||
|
||||
void tensor_free(Tensor *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
114
src/cx.c
114
src/cx.c
|
@ -1,5 +1,26 @@
|
|||
#include <cx.h>
|
||||
|
||||
static void
|
||||
cx_glBindBuffer(GLfloat *render_buffer, GLuint buffer_address,
|
||||
GLuint gl_index, GLint member_size, GLsizeiptr bufsize) {
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_address);
|
||||
glBufferData(GL_ARRAY_BUFFER, bufsize,
|
||||
render_buffer, GL_STATIC_DRAW);
|
||||
|
||||
// 1rst attribute buffer : vertices
|
||||
glEnableVertexAttribArray(gl_index);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_address);
|
||||
glVertexAttribPointer(
|
||||
gl_index, // attribute 0 in the pipeline
|
||||
member_size, // size
|
||||
GL_FLOAT, // type
|
||||
GL_FALSE, // normalized?
|
||||
0, // stride
|
||||
NULL // array buffer offset
|
||||
);
|
||||
}
|
||||
|
||||
static int
|
||||
cx_glrender(GLFWwindow *window, GLuint programID,
|
||||
ModelRegistry *mr) {
|
||||
|
@ -20,42 +41,17 @@ cx_glrender(GLFWwindow *window, GLuint programID,
|
|||
|
||||
for (int i = 0; i < mr->model_count; i++) {
|
||||
|
||||
// Allocate the render buffer
|
||||
// GL uses this to feed the GPU
|
||||
render_buffer = model_applyTransformations(mr->models[i]);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mr->models[i]->bufsize*4*sizeof(GLfloat),
|
||||
render_buffer, GL_STATIC_DRAW);
|
||||
|
||||
// 1rst attribute buffer : vertices
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
||||
glVertexAttribPointer(
|
||||
0, // attribute 0 in the pipeline
|
||||
4, // size
|
||||
GL_FLOAT, // type
|
||||
GL_FALSE, // normalized?
|
||||
0, // stride
|
||||
NULL // array buffer offset
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mr->models[i]->bufsize*3*sizeof(GLfloat),
|
||||
mr->models[i]->colors, GL_STATIC_DRAW);
|
||||
|
||||
// 1rst attribute buffer : vertices
|
||||
glEnableVertexAttribArray(2);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
|
||||
glVertexAttribPointer(
|
||||
2, // attribute 0 in the pipeline
|
||||
3, // size
|
||||
GL_FLOAT, // type
|
||||
GL_FALSE, // normalized?
|
||||
0, // stride
|
||||
NULL // array buffer offset
|
||||
);
|
||||
cx_glBindBuffer(render_buffer, vertexbuffer, 0, 4,
|
||||
mr->models[i]->bufsize*4*sizeof(GLfloat));
|
||||
cx_glBindBuffer(mr->models[i]->colors, colorbuffer, 2, 3,
|
||||
mr->models[i]->bufsize*3*sizeof(GLfloat));
|
||||
|
||||
// Draw!
|
||||
glDrawArrays(GL_TRIANGLES, 0, mr->models[i]->bufsize); // 3 indices starting at 0 -> 1 triangle
|
||||
glDrawArrays(GL_TRIANGLES, 0, mr->models[i]->bufsize);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(2);
|
||||
|
@ -126,41 +122,31 @@ cx_glinit(GLFWwindow **window) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cx_nnrun(Neural_Network *nn) {
|
||||
|
||||
// Establish a neural interface.
|
||||
float *input_buffer = malloc(64*sizeof(float));
|
||||
float *output_buffer;
|
||||
|
||||
output_buffer = neural_process(nn, input_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cx_glrun(GLFWwindow *window) {
|
||||
cx_run(GLFWwindow *window, Neural_Network *nn) {
|
||||
ModelRegistry *mr;
|
||||
GLuint VertexArrayID;
|
||||
GLuint programID;
|
||||
|
||||
if (cx_loadShaders(&VertexArrayID, &programID)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Establish a model registry
|
||||
ModelRegistry *mr;
|
||||
mr = modelRegistry_new();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// Load model to render from file
|
||||
Model *model = model_load("../3d_assets/triangle.obj");
|
||||
GLfloat *rotation_matrix = matrix_new();
|
||||
GLfloat *translation_matrix = matrix_new();
|
||||
|
||||
rotation_matrix[0] = cos(M_PI*2/256);
|
||||
rotation_matrix[8] = -sin(M_PI*2/256);
|
||||
rotation_matrix[2] = sin(M_PI*2/256);
|
||||
rotation_matrix[10] = cos(M_PI*2/256);
|
||||
|
||||
translation_matrix[3] = -0.5 + (0.5 * i);
|
||||
|
||||
model->transformations[0] = rotation_matrix;
|
||||
model->transformations[1] = translation_matrix;
|
||||
model->transformation_count = 2;
|
||||
model_colorFromPosition(model);
|
||||
|
||||
modelRegistry_register(mr, model);
|
||||
}
|
||||
|
||||
// Allocate the render buffer
|
||||
// GL uses this to feed the GPU
|
||||
|
||||
// Fill the model registry with mesh models
|
||||
neural_getMesh(mr, nn);
|
||||
|
||||
// Remainder from cursor experiments, might be useful later
|
||||
double xpos, ypos;
|
||||
|
@ -186,7 +172,7 @@ cx_glrun(GLFWwindow *window) {
|
|||
int
|
||||
cx_nninit(Neural_Network **nn) {
|
||||
// Allocate a Neural Network
|
||||
*nn = neural_new(64, 1);
|
||||
*nn = neural_new(64, 4, 8);
|
||||
if(!*nn) {
|
||||
fprintf(stderr, "Failed to initialize Neural Network.\n");
|
||||
return -1;
|
||||
|
@ -198,14 +184,4 @@ cx_nninit(Neural_Network **nn) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cx_nnrun(Neural_Network *nn) {
|
||||
|
||||
// Establish a neural interface.
|
||||
float *input_buffer = malloc(64*sizeof(float));
|
||||
float *output_buffer;
|
||||
|
||||
output_buffer = neural_process(nn, input_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,6 @@ main(void) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
retval = cx_glrun(window);
|
||||
retval = cx_run(window, nn);
|
||||
return retval;
|
||||
}
|
||||
|
|
163
src/model.c
163
src/model.c
|
@ -6,7 +6,7 @@ model_new(size_t size) {
|
|||
self->object = calloc((size ? size : 1) *4 , sizeof(GLfloat));
|
||||
self->colors = calloc((size ? size : 1) *3 , sizeof(GLfloat));
|
||||
self->bufsize = size;
|
||||
self->transformations = calloc(8 , sizeof(GLfloat*));
|
||||
self->transformations = calloc(8 , sizeof(Tensor *));
|
||||
self->transformation_size = 8;
|
||||
self->transformation_count = 0;
|
||||
return self;
|
||||
|
@ -16,6 +16,9 @@ int
|
|||
model_free(Model *self) {
|
||||
free(self->object);
|
||||
free(self->colors);
|
||||
for (int i = 0; i < self->transformation_count; i++) {
|
||||
tensor_free(self->transformations[i]);
|
||||
}
|
||||
free(self->transformations);
|
||||
free(self);
|
||||
return 0;
|
||||
|
@ -67,9 +70,7 @@ model_load(const char *path) {
|
|||
for (int j = 0; j < 3; j++) {
|
||||
for (int k = 0; k < 3; k++) {
|
||||
self->object[i*12+j*4+k] = vertices[(faces[i*3+j]-1)*3+k];
|
||||
printf("%f, ", vertices[(faces[i*3+j]-1)*3+k]);
|
||||
}
|
||||
printf("\n");
|
||||
self->object[i*12+j*4+3] = 1;
|
||||
}
|
||||
}
|
||||
|
@ -81,21 +82,34 @@ model_load(const char *path) {
|
|||
GLfloat *
|
||||
model_applyTransformations(Model *self) {
|
||||
// Temporary storage of transformation results
|
||||
GLfloat *temp_buffer[2] = {NULL};
|
||||
Tensor *temp_buffer[2] = {NULL};
|
||||
GLfloat *retval;
|
||||
|
||||
// BANANA, ROH-TAH-TEH
|
||||
temp_buffer[1] = malloc(self->bufsize * 4 * sizeof(GLfloat));
|
||||
memcpy(temp_buffer[1], self->object, self->bufsize * 4 * sizeof(GLfloat));
|
||||
temp_buffer[1] = tensor_fromVertexBuffer(self->object, self->bufsize);
|
||||
|
||||
// No transformation, create a GLfloat buffer and return the object data.
|
||||
if (!self->transformation_count) {
|
||||
retval = malloc(self->bufsize * 4 * sizeof(GLfloat));
|
||||
memcpy(retval, self->object, self->bufsize * 4 * sizeof(GLfloat));
|
||||
return retval;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
temp_buffer[i%2] = matrix_transform(temp_buffer[(i+1)%2],
|
||||
self->bufsize,
|
||||
self->transformations[i]);
|
||||
free(temp_buffer[(i+1)%2]);
|
||||
temp_buffer[i%2] = tensor_multip(self->transformations[i],
|
||||
temp_buffer[(i+1)%2]);
|
||||
tensor_free(temp_buffer[(i+1)%2]);
|
||||
} while (++i < self->transformation_count);
|
||||
|
||||
return temp_buffer[(i+1)%2];
|
||||
retval = malloc(self->bufsize * 4 * sizeof(GLfloat));
|
||||
for (int k = 0; k < self->bufsize; k++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
retval[k*4+j] = temp_buffer[(i+1)%2]
|
||||
->data[j*temp_buffer[(i+1)%2]->width+k];
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
|
@ -113,6 +127,55 @@ model_colorFromPosition(Model *self) {
|
|||
}
|
||||
}
|
||||
|
||||
void model_colorXYZ(Model *self, int R, int G, int B) {
|
||||
for (int i = 0; i < self->bufsize; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
switch(j) {
|
||||
case 0:
|
||||
self->colors[i*3+j] = R;
|
||||
break;
|
||||
case 1:
|
||||
self->colors[i*3+j] = G;
|
||||
break;
|
||||
case 2:
|
||||
self->colors[i*3+j] = B;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
model_colorRed(Model *self) {
|
||||
for (int i = 0; i < self->bufsize; i++) {
|
||||
self->colors[i*3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
model_colorGreen(Model *self) {
|
||||
for (int i = 0; i < self->bufsize; i++) {
|
||||
self->colors[i*3+1] = 1.0f;
|
||||
}
|
||||
}
|
||||
void
|
||||
model_colorBlue(Model *self) {
|
||||
for (int i = 0; i < self->bufsize; i++) {
|
||||
self->colors[i*3+2] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
model_colorWhite(Model *self) {
|
||||
for (int i = 0; i < self->bufsize; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
self->colors[i*3+j] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Model *
|
||||
model_triangle(Model *self, int detail) {
|
||||
if (self == NULL) {
|
||||
|
@ -122,19 +185,83 @@ model_triangle(Model *self, int detail) {
|
|||
}
|
||||
|
||||
Model *
|
||||
model_circle(Model *self, int detail) {
|
||||
model_circle(int detail, GLfloat scale) {
|
||||
Model *self;
|
||||
self = model_new(96);
|
||||
if (self == NULL) {
|
||||
self = model_new(36);
|
||||
return NULL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < 96; i++) {
|
||||
self->object[(i*4)+3] = 1.0f;
|
||||
if (!(i%3)) {
|
||||
continue;
|
||||
}
|
||||
if (!(k%2)) {
|
||||
self->object[(i*4)+0] = cos((M_PI*2/96)*((GLfloat)i-1.0)) * scale;
|
||||
self->object[(i*4)+1] = sin((M_PI*2/96)*((GLfloat)i-1.0)) * scale;
|
||||
} else {
|
||||
self->object[(i*4)+0] = cos((M_PI*2/96)*((GLfloat)i+1.0)) * scale;
|
||||
self->object[(i*4)+1] = sin((M_PI*2/96)*((GLfloat)i+1.0)) * scale;
|
||||
}
|
||||
|
||||
k++;
|
||||
self->object[(i*4)+3] = 1.0f;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
Model *
|
||||
model_line(Model *self, int detail) {
|
||||
model_line(float x1, float y1, float x2, float y2, float girth) {
|
||||
Model *self;
|
||||
float x_diff, y_diff, line_length;
|
||||
|
||||
x_diff = x2 - x1;
|
||||
y_diff = y2 - y1;
|
||||
line_length = sqrt((x_diff*x_diff) + (y_diff*y_diff));
|
||||
|
||||
float normal_x = (cos(M_PI/2) * x_diff
|
||||
-(sin(M_PI/2) * y_diff))
|
||||
/ line_length * girth / 2;
|
||||
|
||||
|
||||
float normal_y = (sin(M_PI/2) * x_diff
|
||||
+(cos(M_PI/2) * y_diff))
|
||||
/ line_length * girth / 2;
|
||||
|
||||
self = model_new(6);
|
||||
|
||||
if (self == NULL) {
|
||||
self = model_new(6);
|
||||
return NULL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
self->object[0] = x1 + normal_x;
|
||||
self->object[1] = y1 + normal_y;
|
||||
self->object[3] = 1;
|
||||
|
||||
self->object[4] = x1 - normal_x;
|
||||
self->object[5] = y1 - normal_y;
|
||||
self->object[7] = 1;
|
||||
|
||||
self->object[8] = x2 + normal_x;
|
||||
self->object[9] = y2 + normal_y;
|
||||
self->object[11] = 1;
|
||||
|
||||
self->object[12] = x1 - normal_x;
|
||||
self->object[13] = y1 - normal_y;
|
||||
self->object[15] = 1;
|
||||
|
||||
self->object[16] = x2 + normal_x;
|
||||
self->object[17] = y2 + normal_y;
|
||||
self->object[19] = 1;
|
||||
|
||||
self->object[20] = x2 - normal_x;
|
||||
self->object[21] = y2 - normal_y;
|
||||
self->object[23] = 1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
Model *
|
||||
|
@ -196,7 +323,7 @@ int
|
|||
modelRegistry_register(ModelRegistry *self, Model *model) {
|
||||
if (self->model_count >= self->size) {
|
||||
self->size *= 2;
|
||||
self->models = realloc(self->models, self->size);
|
||||
self->models = realloc(self->models, self->size * sizeof(Model *));
|
||||
if (self->models == NULL) {
|
||||
modelRegistry_free(self);
|
||||
return -1;
|
||||
|
|
210
src/neural.c
210
src/neural.c
|
@ -1,34 +1,50 @@
|
|||
#include <cx.h>
|
||||
#include <neural.h>
|
||||
|
||||
Neural_Network *
|
||||
neural_new(size_t layer_size, size_t layers) {
|
||||
Neural_Network *self = malloc(sizeof(Neural_Network));
|
||||
Neuron *n = NULL;
|
||||
static Neural_Layer *
|
||||
nl_new(size_t layer_size, size_t layer_size_next) {
|
||||
Neural_Layer *self;
|
||||
self = malloc(sizeof(Neural_Layer));
|
||||
self->neurons = calloc(layer_size, sizeof(Neuron));
|
||||
|
||||
for (int i = 0; i < layer_size; i++) {
|
||||
self->neurons[i].synapses = calloc(layer_size_next, sizeof(float));
|
||||
}
|
||||
|
||||
self->layer_size = layer_size;
|
||||
self->layers = layers;
|
||||
self->n = calloc(layer_size*layers, sizeof(Neuron));
|
||||
self->layer_size_next = layer_size_next;
|
||||
return self;
|
||||
}
|
||||
|
||||
for (int j = 0; j < layers; j++) {
|
||||
n = &(self->n[j*layer_size]);
|
||||
for (int i = 0; i < layers; i++) {
|
||||
n->value = 0;
|
||||
n->threshold = 0;
|
||||
if (j) {
|
||||
n->in_values = calloc(layer_size, sizeof(float *));
|
||||
n->weights = calloc(layer_size, sizeof(float));
|
||||
n->in_values_size = layer_size;
|
||||
for (int k = 0; k < layer_size; k++) {
|
||||
n->in_values[k] = &(self->n[(j-1)*layer_size + k].value);
|
||||
n->weights[k] = 0.5;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n->in_values = NULL;
|
||||
n->weights = NULL;
|
||||
}
|
||||
}
|
||||
static void
|
||||
nl_free(Neural_Layer *self) {
|
||||
free(self->neurons);
|
||||
free(self);
|
||||
}
|
||||
|
||||
Neural_Network *
|
||||
neural_new(size_t input_size, size_t output_size, size_t layer_count) {
|
||||
Neural_Network *self = malloc(sizeof(Neural_Network));
|
||||
if (!self) {
|
||||
// Failed to allocate.
|
||||
return NULL;
|
||||
}
|
||||
// The difference between layer sizes, hidden layers step between the two
|
||||
// sizes in linear fashion.
|
||||
ssize_t layer_diff;
|
||||
|
||||
self->layer_count = layer_count;
|
||||
self->layers = malloc(layer_count * sizeof(Neural_Layer *));
|
||||
layer_diff = (ssize_t) output_size - input_size;
|
||||
|
||||
// Calculate sizes of individual layers and allocate them.
|
||||
for (int i = 0; i < layer_count; i++) {
|
||||
self->layers[i] = nl_new(input_size
|
||||
+ (layer_diff * i / ((ssize_t)layer_count-1)),
|
||||
|
||||
i < (layer_count-1) ?
|
||||
(input_size + (layer_diff * (i+1)
|
||||
/ ((ssize_t)layer_count-1)))
|
||||
: 0);
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -36,35 +52,145 @@ neural_new(size_t layer_size, size_t layers) {
|
|||
|
||||
void
|
||||
neural_randomize(Neural_Network *self) {
|
||||
// Does not randomize, just sets 0.5, but it doesn't matter for now.
|
||||
for (int i = 0; i < self->layers; i++) {
|
||||
Neuron *n = &(self->n[i*self->layer_size]);
|
||||
for (int j = 0; j < self->layer_size; j++) {
|
||||
n[j].threshold = 0.5;
|
||||
FILE *f;
|
||||
Neural_Layer *nl;
|
||||
|
||||
f = fopen("/dev/urandom", "r");
|
||||
|
||||
for (int i = 0; i < self->layer_count; i++) {
|
||||
nl = self->layers[i];
|
||||
for (int j = 0; j < nl->layer_size; j++) {
|
||||
fread(nl->neurons[j].synapses, sizeof(float), nl->layer_size_next, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float *
|
||||
neural_loadData(Neural_Network *self, const char *filename) {
|
||||
Neural_Layer *nl;
|
||||
FILE *f;
|
||||
char *file_data;
|
||||
float *retval;
|
||||
int read_cursor = 0;
|
||||
|
||||
file_data = malloc(9*8 * sizeof(char));
|
||||
retval = malloc(8*8 * sizeof(float));
|
||||
|
||||
// Watch out, newlines!
|
||||
|
||||
f = fopen(filename, "r");
|
||||
|
||||
nl = self->layers[0];
|
||||
|
||||
fread(file_data, sizeof(char), 9*8, f); // 9*8 - 8*8 value matrix + newlines
|
||||
for (int i = 0; i < 8*8; i++) {
|
||||
if (file_data[read_cursor] == '\n') {
|
||||
read_cursor++;
|
||||
}
|
||||
switch (file_data[read_cursor]) {
|
||||
case '0':
|
||||
retval[i] = 0.0;
|
||||
break;
|
||||
case '1':
|
||||
retval[i] = 1.0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "It would really be nice to start testing now.\n");
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
float *
|
||||
neural_process(Neural_Network *self, float *input) {
|
||||
float *retval = NULL;
|
||||
Neural_Layer *nl = self->layers[0];
|
||||
Tensor *neural_vector, *synapse_matrix, *temp_buffer;
|
||||
|
||||
for (int i = 0; i < self->layer_size; i++) {
|
||||
self->n[i].value = input[i];
|
||||
for (int i = 0; i < self->layers[0]->layer_size; i++) {
|
||||
nl->neurons[i].value = input[i];
|
||||
}
|
||||
for (int i = 1; i < self->layers; i++) {
|
||||
float dot_prod = 0;
|
||||
for (int j = 0; j < self->layer_size; j++) {
|
||||
// MATH GOES BRRRRRRRR
|
||||
dot_prod += *(self->n[i*self->layer_size + j].in_values)[j] *
|
||||
self->n[i*self->layer_size + j].weights[j];
|
||||
neural_vector = tensor_new(1, nl->layer_size);
|
||||
for (int i = 0; i < self->layer_count; i++) {
|
||||
nl = self->layers[i];
|
||||
synapse_matrix = tensor_new(nl->layer_size_next, nl->layer_size);
|
||||
for (int j = 0; j < nl->layer_size; j++) {
|
||||
neural_vector->data[j] = nl->neurons[j].value;
|
||||
for (int k = 0; k < nl->layer_size_next; k++) {
|
||||
synapse_matrix->data[j*nl->layer_size_next+k] = nl->neurons[j].synapses[k];
|
||||
}
|
||||
}
|
||||
|
||||
temp_buffer = tensor_multip(synapse_matrix, neural_vector);
|
||||
tensor_free(neural_vector);
|
||||
tensor_free(synapse_matrix);
|
||||
neural_vector = temp_buffer;
|
||||
}
|
||||
|
||||
retval = malloc(self->layer_size * sizeof(float));
|
||||
for (int i = 0; i < self->layer_size; i++) {
|
||||
retval[i] = self->n[self->layer_size*(self->layers-1)].value;
|
||||
retval = malloc(nl->layer_size * sizeof(float));
|
||||
for (int i = 0; i < nl->layer_size; i++) {
|
||||
retval[i] = nl->neurons[i].value;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
neural_train(Neural_Network *self,
|
||||
const char *testdata,
|
||||
const float *testresult) {
|
||||
// Insert algorithm you lazy fuck.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
neural_getMesh(ModelRegistry *mr, Neural_Network *nn) {
|
||||
Model *model;
|
||||
for (int j = 0; j < nn->layer_count; j++) {
|
||||
Neural_Layer *nl = nn->layers[j];
|
||||
for (int i = 0; i < nl->layer_size; i++) {
|
||||
unsigned int brightness;
|
||||
for (int k = 0; k < nl->layer_size_next; k++) {
|
||||
model = model_line((-.90)
|
||||
+ ((GLfloat)2 * i * .90/(nl->layer_size-1)),
|
||||
|
||||
.90 - ((GLfloat)2 * j *.90/(nn->layer_count)),
|
||||
|
||||
(-.90)
|
||||
+ ((GLfloat)2 * k * .90/(nl->layer_size_next-1)),
|
||||
|
||||
.90 - ((GLfloat)2 * (j+1) *.90/(nn->layer_count)),
|
||||
|
||||
.001 // girth
|
||||
);
|
||||
brightness = nl->neurons[i].synapses[k] <= 1.0 ? nl->neurons[i].synapses[k] : 255;
|
||||
model_colorXYZ(model, brightness, 0, 0);
|
||||
modelRegistry_register(mr, model);
|
||||
}
|
||||
|
||||
model = model_circle(0, (GLfloat)1/64);
|
||||
brightness = nl->neurons[i].value <= 1.0 ? nl->neurons[i].value : 255;
|
||||
model_colorXYZ(model, 0, brightness, 0);
|
||||
Tensor *translation_matrix = tensor_new(4, 4);
|
||||
Tensor *aspectRatio_matrix = tensor_new(4, 4);
|
||||
aspectRatio_matrix->data[0] = (GLfloat)9/16;
|
||||
|
||||
translation_matrix->data[3] = (((GLfloat)-1*16/9)*.90)
|
||||
+ ((GLfloat)1/(nl->layer_size-1)*2 * i * (((GLfloat)16/9))*.90);
|
||||
|
||||
translation_matrix->data[7] = .90 - ((GLfloat)1/(nn->layer_count)*2 * j *.90);
|
||||
|
||||
model->transformations[0] = translation_matrix;
|
||||
model->transformations[1] = aspectRatio_matrix;
|
||||
model->transformation_count = 2;
|
||||
|
||||
modelRegistry_register(mr, model);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
94
src/tensor.c
94
src/tensor.c
|
@ -1,62 +1,68 @@
|
|||
#include "cx.h"
|
||||
|
||||
float *
|
||||
matrix_new() {
|
||||
float *mat;
|
||||
Tensor *
|
||||
tensor_new(size_t len, size_t width) {
|
||||
Tensor *mat;
|
||||
|
||||
mat = calloc(16, sizeof(float));
|
||||
mat = malloc(1 * sizeof(Tensor));
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mat[i*4+i] = 1;
|
||||
mat->data = calloc(width * len, sizeof(float));
|
||||
mat->len = len;
|
||||
mat->width = width;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
mat->data[i*width+(i % width)] = 1;
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
float *
|
||||
matrix_multip(float *mat1, float *mat2) {
|
||||
float *result;
|
||||
float dot_prod;
|
||||
Tensor *
|
||||
tensor_fromVertexBuffer(float *buffer, size_t bufsize) {
|
||||
int mat_width;
|
||||
Tensor *mat;
|
||||
|
||||
result = matrix_new();
|
||||
mat_width = bufsize;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mat = tensor_new(4, mat_width);
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
dot_prod = 0;
|
||||
for (int k = 0; k < 4; k++) {
|
||||
dot_prod += mat1[i*4+k] * mat2[j+k*4];
|
||||
}
|
||||
result[j+i*4] = dot_prod;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float *
|
||||
matrix_transform(float *vects, int vectcount,
|
||||
float *mat) {
|
||||
float dot_prod;
|
||||
float *result;
|
||||
|
||||
result = calloc(vectcount*4, sizeof(float));
|
||||
|
||||
for (int k = 0; k < vectcount; k++) {
|
||||
for (int i = 0; i < bufsize; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
dot_prod = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dot_prod += vects[k*4+i] * mat[i+j*4];
|
||||
}
|
||||
result[j+k*4] = dot_prod;
|
||||
}
|
||||
if (result[k*4+3] != 0.0f) {
|
||||
float div = result[k*4+3];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
result[k*4+i] /= div;
|
||||
}
|
||||
mat->data[j*mat_width+i] = buffer[i*4+j];
|
||||
}
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
Tensor *
|
||||
tensor_multip(Tensor *mat2, Tensor *mat1) {
|
||||
Tensor *result;
|
||||
float dot_prod;
|
||||
|
||||
result = tensor_new(mat2->len, mat1->width);
|
||||
|
||||
for (int i = 0; i < mat1->width; i++) {
|
||||
|
||||
for (int j = 0; j < mat2->len; j++) {
|
||||
dot_prod = 0;
|
||||
for (int k = 0; k < mat1->len; k++) {
|
||||
dot_prod += mat2->data[j*mat2->width+k] * mat1->data[i+(k*mat1->width)];
|
||||
}
|
||||
result->data[i+(j*mat1->width)] = dot_prod;
|
||||
}
|
||||
}
|
||||
|
||||
result->len = mat2->len;
|
||||
result->width = mat1->width;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
tensor_free(Tensor *self) {
|
||||
if (self) {
|
||||
free(self->data);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue