#include <stdio.h>
#include <stdlib.h>
#include "../structs.h"
+#include "../utils.h"
worker_arg warg;
int waiting_workers;
-extern FVec2 ** grid;
-extern FVec2 ** grid_prime;
-extern FVec2 ** grid_temp;
-extern IVec2 grid_size;
-
pthread_t* threads;
pthread_mutex_t mutex;
pthread_barrier_t barrier;
/* TODO: This should go in a header, platforms don't care. */
-float rd_a_prime(FVec2 **source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B);
+float rd_a_prime(FVec2** source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B);
float rd_b_prime(FVec2** source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B);
void* iterator(void* _arg)
{
+ printf("starting a worker\n");
+ GenerationInfo *ginfo = &generation_info;
+
worker_arg* warg = (worker_arg*)_arg;
RD_Opts opts = warg->opts;
int start_x = warg->start_x;
for (warg->iterations = 0; warg->iterations < warg->max_iterations; warg->iterations++)
{
- for (int x = start_x; x < w + start_x && x < grid_size.x; x++)
+ for (int x = start_x; x < w + start_x && x < ginfo->rd_grid_size.x; x++)
{
- for (int y = start_y; y < h + start_y && y < grid_size.y; y++)
+ for (int y = start_y; y < h + start_y && y < ginfo->rd_grid_size.y; y++)
{
- FVec2 each = grid[x][y];
+ FVec2 each = ginfo->grid[x][y];
if (each.c >= 0.5f)
{
each.b = 1.0f;
each.c -= 5.0f/((float)(opts.max_iterations/100.0f));
}
- grid_prime[x][y].a = rd_a_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b);
- grid_prime[x][y].b = rd_b_prime(grid, opts, x, y, laplacian_kernel, each.a, each.b);
+ ginfo->grid_prime[x][y].a = rd_a_prime(ginfo->grid, opts, x, y, laplacian_kernel, each.a, each.b);
+ ginfo->grid_prime[x][y].b = rd_b_prime(ginfo->grid, opts, x, y, laplacian_kernel, each.a, each.b);
}
}
pthread_mutex_lock(&mutex);
if (++waiting_workers == warg->worker_count)
{
- grid_temp = grid;
- grid = grid_prime;
- grid_prime = grid_temp;
+ ginfo->grid_temp = ginfo->grid;
+ ginfo->grid = ginfo->grid_prime;
+ ginfo->grid_prime = ginfo->grid_temp;
waiting_workers = 0;
- resource_generation_progress = ((float)warg->iterations/(float)warg->max_iterations);
+ ginfo->generation_progress = ((float)warg->iterations/(float)warg->max_iterations);
}
+
pthread_mutex_unlock(&mutex);
pthread_barrier_wait(&barrier);
}
return _arg;
}
-void start(int worker_count, RD_Opts active_opt)
+void start()
{
+ GenerationInfo ginfo = generation_info;
+
worker_arg warg = (worker_arg){
- active_opt, grid, grid_prime,
- 0, 0, (grid_size.x), (grid_size.y),
- .worker_count = worker_count,
- .max_iterations = active_opt.max_iterations
+ ginfo.rd_opt, ginfo.grid, ginfo.grid_prime,
+ 0, 0, (ginfo.rd_grid_size.x), (ginfo.rd_grid_size.y),
+ .worker_count = ginfo.worker_count,
+ .max_iterations = ginfo.rd_opt.max_iterations
};
- threads = (pthread_t*)malloc(sizeof(pthread_t) * worker_count);
+ threads = (pthread_t*)malloc(sizeof(pthread_t) * ginfo.worker_count);
pthread_mutex_init(&mutex, NULL);
pthread_barrier_init(&barrier, NULL, warg.worker_count);
- worker_arg wargs[worker_count];
+ worker_arg wargs[ginfo.worker_count];
for (int t = 0; t < warg.worker_count; t++)
{
- wargs[t] = warg;
+ wargs[t] = warg;
wargs[t].worker_id = t;
- wargs[t].width = (grid_size.x/worker_count) + ((t == worker_count-1) ? 0 : 4);
- wargs[t].start_x = (wargs[t].width * t);
+ wargs[t].width = (ginfo.rd_grid_size.x/ginfo.worker_count) + ((t == ginfo.worker_count-1) ? 0 : 4);
+ wargs[t].start_x = (wargs[t].width * t);
pthread_create(&threads[t], NULL, iterator, &wargs[t]);
}
}
}
/* TODO: Actually this probably shouldn't be freeing resources allocated outside of the unit. */
- free(grid);
- free(grid_prime);
free(threads);
+ deinitialize_generation_info();
return 0;
}
#include <sys/stat.h>
#include <time.h>
+#include "utils.h"
#include "structs.h"
#include "platform.h"
#define V3_UNROLL(v3) v3.x, v3.y, v3.z
#define V3_FORMAT(v3) #v3 ":{%.4f %.4f %.4f}"
-FVec2 ** grid;
-FVec2 ** grid_prime;
-FVec2 ** grid_temp;
-IVec2 grid_size;
-
float iv2_inverse_sqrt(IVec2 a, IVec2 b)
{
return 1.0f/sqrt(pow(a.x-b.x, 2) + pow(a.y-b.y, 2));
}
float rd_a_prime(FVec2 **source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B) {
+ GenerationInfo ginfo = generation_info;
float a_prime = 1.0f;
int x_less = (x - 1 < 0) ? x : x - 1;
int y_less = (y - 1 < 0) ? y : y - 1;
- int x_more = (x + 1 == grid_size.x) ? x : x + 1;
- int y_more = (y + 1 == grid_size.y) ? y : y + 1;
+ int x_more = (x + 1 == ginfo.rd_grid_size.x) ? x : x + 1;
+ int y_more = (y + 1 == ginfo.rd_grid_size.y) ? y : y + 1;
// Use species A in the convolution, b_prime will need B
// For now we won't iterate over edge rows and columns to avoid special case
// vomit
Mat3 source = {
.v = {
- {grid[x_less][y_less].a, grid[x][y_less].a, grid[x_more][y_less].a},
- {grid[x_less][y + 0].a, grid[x][y + 0].a, grid[x_more][y + 0].a},
- {grid[x_less][y_more].a, grid[x][y_more].a, grid[x_more][y_more].a},
+ {ginfo.grid[x_less][y_less].a, ginfo.grid[x][y_less].a, ginfo.grid[x_more][y_less].a},
+ {ginfo.grid[x_less][y + 0].a, ginfo.grid[x][y + 0].a, ginfo.grid[x_more][y + 0].a},
+ {ginfo.grid[x_less][y_more].a, ginfo.grid[x][y_more].a, ginfo.grid[x_more][y_more].a},
}};
a_prime = A + (opts.diff_a * (kernel_sum(kernel, source)) - (A * B * B) +
float rd_b_prime(FVec2** source_grid, RD_Opts opts, int x, int y, Mat3 kernel, float A, float B)
{
+ GenerationInfo ginfo = generation_info;
float b_prime = 1.0f;
int x_less = (x-1 < 0) ? x : x-1;
int y_less = (y-1 < 0) ? y : y-1;
- int x_more = (x+1 == grid_size.x) ? x : x+1;
- int y_more = (y+1 == grid_size.y) ? y : y+1;
+ int x_more = (x+1 == ginfo.rd_grid_size.x) ? x : x+1;
+ int y_more = (y+1 == ginfo.rd_grid_size.y) ? y : y+1;
// Use species A in the convolution, b_prime will need B
Mat3 source =
{
.v =
{
- {grid[x_less][y_less].b, grid[x][y_less].b, grid[x_more][y_less].b},
- {grid[x_less][y+0].b, grid[x][y+0].b, grid[x_more][y+0].b},
- {grid[x_less][y_more].b, grid[x][y_more].b, grid[x_more][y_more].b},
+ {ginfo.grid[x_less][y_less].b, ginfo.grid[x][y_less].b, ginfo.grid[x_more][y_less].b},
+ {ginfo.grid[x_less][y+0].b, ginfo.grid[x][y+0].b, ginfo.grid[x_more][y+0].b},
+ {ginfo.grid[x_less][y_more].b, ginfo.grid[x][y_more].b, ginfo.grid[x_more][y_more].b},
}
};
return b_prime;
}
-int initialize(int worker_count, RD_Opts active_opt)
+int initialize_grid()
{
- grid_prime = (FVec2**)malloc(grid_size.x * sizeof(FVec2*));
- for (int n = 0; n < grid_size.x; n++)
- {
- grid_prime[n] = (FVec2*)malloc(grid_size.y * sizeof(FVec2));
- }
-
+ GenerationInfo ginfo = generation_info;
srand(time(NULL));
/* Set up as a circle */
- float barrow_radius = grid_size.x/2.1f;
- int center_x = grid_size.x/2;
- int center_y = grid_size.y/2;
+ float barrow_radius = ginfo.rd_grid_size.x/2.1f;
+ int center_x = ginfo.rd_grid_size.x/2;
+ int center_y = ginfo.rd_grid_size.y/2;
float central_chamber_radius = barrow_radius/6;
- for (int x = 0; x < grid_size.x; x++)
+ for (int x = 0; x < ginfo.rd_grid_size.x; x++)
{
- for (int y = 0; y < grid_size.y; y++)
+ for (int y = 0; y < ginfo.rd_grid_size.y; y++)
{
- grid[x][y].a = 1.0f;
- grid[x][y].b = 0.0f;
+ ginfo.grid[x][y].a = 1.0f;
+ ginfo.grid[x][y].b = 0.0f;
- if ((sqrtf(((x-center_x)*(x-center_x))+((y-center_y)*(y-center_y))) < barrow_radius))
- {
- grid[x][y].c = 0.0f;
- }
- /* Outside the barrow walls */
- else
- {
- grid[x][y].c = 1.0f;
- }
+ /* Keep C high outside of the barrow radius, else low inside. */
+ ginfo.grid[x][y].c = (float)!(sqrtf(((x-center_x)*(x-center_x))+((y-center_y)*(y-center_y))) < barrow_radius);
const float distance_from_center = sqrtf(((x-center_x)*(x-center_x))+((y-center_y)*(y-center_y)));
if ((distance_from_center < central_chamber_radius) ||
- ((abs(x-center_x) < 1.0f) && (abs(y-center_y) < (central_chamber_radius*1.5f))))
+ ((abs(x-center_x) < 1.0f) && (abs(y-center_y) < (central_chamber_radius*1.8f))))
{
- grid[x][y].c = 1.0f;
+ ginfo.grid[x][y].c = 1.0f;
}
}
}
/* Set up seed-points to create connected rooms */
- const int seed_count = playtime.room_count;
+ const int seed_count = ginfo.room_count;
const float small_room_radius = 8.0f;
const float phase = ((rand() % 360)/(float)360) * (M_PI*2);
float dist_offset = ((rand() % 14) + 1);
angle += phase;
- int seed_x = ((cosf(angle) * (dist_offset + (grid_size.x/4.0f))) + (grid_size.x/2.0f));
- int seed_y = ((sinf(angle) * (dist_offset + (grid_size.y/4.0f))) + (grid_size.y/2.0f));
+ int seed_x = ((cosf(angle) * (dist_offset + (ginfo.rd_grid_size.x/4.0f))) + (ginfo.rd_grid_size.x/2.0f));
+ int seed_y = ((sinf(angle) * (dist_offset + (ginfo.rd_grid_size.y/4.0f))) + (ginfo.rd_grid_size.y/2.0f));
// Swap dimensions prepping for rendering
playtime.room_positions[n] = (Vector3){.x = seed_y, .y = 0.0f, .z = seed_x};
// mirror this across axis
- playtime.room_positions[n].z = grid_size.y - playtime.room_positions[n].z;
+ playtime.room_positions[n].z = ginfo.rd_grid_size.y - playtime.room_positions[n].z;
printf("Set room %d to {%f %f %f}\n", n, V3_UNROLL(playtime.room_positions[n]));
- grid[seed_x][seed_y].b = 1.0f;
- grid[seed_x][seed_y].c = 0.0f;
+ ginfo.grid[seed_x][seed_y].b = 1.0f;
+ ginfo.grid[seed_x][seed_y].c = 0.0f;
const float x_start = (seed_x-((small_room_radius)));
const float y_start = (seed_y-((small_room_radius)));
const float distance_from_center = sqrtf(((x-center_x)*(x-center_x))+((y-center_y)*(y-center_y)));
if (distance_from_center >= distance_seed_to_center)
{
- grid[x][y].c = 1.0f;
+ ginfo.grid[x][y].c = 1.0f;
}
}
}
}
void* generate_rd(void* args)
-//int generate_rd(int worker_count, RD_Opts active_opt, FVec2 **grid_buffer, IVec2 pgrid_size)
{
- GeneratorArgs* garg = (GeneratorArgs*)args;
- grid = garg->grid;
- grid_size = garg->grid_size;
+ GenerationInfo ginfo = generation_info;
- initialize(garg->worker_count, garg->rd_opts);
- start(garg->worker_count, garg->rd_opts);
+ initialize_grid();
+ start();
while(!playtime.generation_finished){}
+
//printf("Opts: {\nIterations: %d\nTime delta: %f\nDiffA: %f\nDiffB: %f\nFeed: %f\nKill: %f\n\n}\n", active_opt.max_iterations, active_opt.delta_t, active_opt.diff_a, active_opt.diff_b, active_opt.feed, active_opt.kill);
/* png for the heightmap */
- unsigned char barrow_mesh_buffer[grid_size.x][grid_size.y];
- unsigned char floor_mesh_buffer[grid_size.x][grid_size.y];
- unsigned char large_barrow_mesh_buffer[grid_size.x*img_export_scale.x][grid_size.y*img_export_scale.y];
- unsigned char large_floor_mesh_buffer[grid_size.x*img_export_scale.x][grid_size.y*img_export_scale.y];
+ unsigned char barrow_mesh_buffer[ginfo.rd_grid_size.x][ginfo.rd_grid_size.y];
+ unsigned char floor_mesh_buffer[ginfo.rd_grid_size.x][ginfo.rd_grid_size.y];
+ unsigned char large_barrow_mesh_buffer[ginfo.rd_grid_size.x*ginfo.img_export_scale.x][ginfo.rd_grid_size.y*ginfo.img_export_scale.y];
+ unsigned char large_floor_mesh_buffer[ginfo.rd_grid_size.x*ginfo.img_export_scale.x][ginfo.rd_grid_size.y*ginfo.img_export_scale.y];
/* png for albedo buffer */
- uint32_t albedo_buffer[grid_size.x][grid_size.y];
- uint32_t large_albedo_buffer[grid_size.x*img_export_scale.x][grid_size.y*img_export_scale.y];
+ uint32_t albedo_buffer[ginfo.rd_grid_size.x][ginfo.rd_grid_size.y];
+ uint32_t large_albedo_buffer[ginfo.rd_grid_size.x*ginfo.img_export_scale.x][ginfo.rd_grid_size.y*ginfo.img_export_scale.y];
- for (int x = 0; x < grid_size.x; x++)
+ for (int x = 0; x < ginfo.rd_grid_size.x; x++)
{
- for (int y = 0; y < grid_size.y; y++)
+ for (int y = 0; y < ginfo.rd_grid_size.y; y++)
{
- float a = round(-0.05f + grid[x][y].a);
+
+ float barrow_radius = ginfo.rd_grid_size.x/2.1f;
+ int center_x = ginfo.rd_grid_size.x/2;
+ int center_y = ginfo.rd_grid_size.y/2;
+
+ if (sqrtf(((x-center_x)*(x-center_x))+((y-center_y)*(y-center_y))) > barrow_radius)
+ {
+ ginfo.grid[x][y].a = 1.0f;
+ }
+
+ float a = round(-0.05f + ginfo.grid[x][y].a);
barrow_mesh_buffer[x][y] = (uint8_t)(255.0f * a);
floor_mesh_buffer[x][y] = barrow_mesh_buffer[x][y];
/* ABGR */
/* Color everything stone */
/* If it's below some height threshold, color it dirt */
- a = grid[x][y].a;
+ a = ginfo.grid[x][y].a;
albedo_buffer[x][y] = 0xFF848484;
if(a < 0.4)
{
char floor_mesh_name[64] = {0};
char albedo_name[64] = {0};
char floor_albedo_name[64] = {0};
- sprintf(mesh_name, "./%s.png", garg->rd_opts.name);
- sprintf(albedo_name, "./%s_albedo.png", garg->rd_opts.name);
+ sprintf(mesh_name, "./%s.png", ginfo.rd_opt.name);
+ sprintf(albedo_name, "./%s_albedo.png", ginfo.rd_opt.name);
sprintf(floor_mesh_name, "./floor.png");
sprintf(floor_albedo_name, "./floor_albedo.png");
stbir_resize_uint8_linear(
- (unsigned char*)barrow_mesh_buffer, grid_size.x, grid_size.y, sizeof(uint8_t) * grid_size.x,
- (unsigned char*)large_barrow_mesh_buffer, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, sizeof(uint8_t) * grid_size.x * img_export_scale.x,
+ (unsigned char*)barrow_mesh_buffer, ginfo.rd_grid_size.x, ginfo.rd_grid_size.y, sizeof(uint8_t) * ginfo.rd_grid_size.x,
+ (unsigned char*)large_barrow_mesh_buffer, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, sizeof(uint8_t) * ginfo.rd_grid_size.x * ginfo.img_export_scale.x,
STBIR_1CHANNEL);
stbir_resize_uint8_linear(
- (unsigned char*)floor_mesh_buffer, grid_size.x, grid_size.y, sizeof(uint8_t) * grid_size.x,
- (unsigned char*)large_floor_mesh_buffer, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, sizeof(uint8_t) * grid_size.x * img_export_scale.x,
+ (unsigned char*)floor_mesh_buffer, ginfo.rd_grid_size.x, ginfo.rd_grid_size.y, sizeof(uint8_t) * ginfo.rd_grid_size.x,
+ (unsigned char*)large_floor_mesh_buffer, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, sizeof(uint8_t) * ginfo.rd_grid_size.x * ginfo.img_export_scale.x,
STBIR_1CHANNEL);
stbir_resize_uint8_linear(
- (unsigned char*)albedo_buffer, grid_size.x, grid_size.y, sizeof(uint32_t) * grid_size.x,
- (unsigned char*)large_albedo_buffer, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, sizeof(uint32_t) * grid_size.x * img_export_scale.x,
+ (unsigned char*)albedo_buffer, ginfo.rd_grid_size.x, ginfo.rd_grid_size.y, sizeof(uint32_t) * ginfo.rd_grid_size.x,
+ (unsigned char*)large_albedo_buffer, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, sizeof(uint32_t) * ginfo.rd_grid_size.x * ginfo.img_export_scale.x,
STBIR_RGBA);
- stbi_write_png(mesh_name, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, 1, large_barrow_mesh_buffer, grid_size.x * sizeof(uint8_t)*img_export_scale.x);
- stbi_write_png(albedo_name, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, 4, large_albedo_buffer, grid_size.x * sizeof(uint32_t)*img_export_scale.x);
+ stbi_write_png(mesh_name, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, 1, large_barrow_mesh_buffer, ginfo.rd_grid_size.x * sizeof(uint8_t)*ginfo.img_export_scale.x);
+ stbi_write_png(albedo_name, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, 4, large_albedo_buffer, ginfo.rd_grid_size.x * sizeof(uint32_t)*ginfo.img_export_scale.x);
stbi_flip_vertically_on_write(1);
- stbi_write_png(floor_mesh_name, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, 1, large_floor_mesh_buffer, grid_size.x * sizeof(uint8_t)*img_export_scale.x);
- stbi_write_png(floor_albedo_name, grid_size.x*img_export_scale.x, grid_size.y*img_export_scale.y, 4, large_albedo_buffer, grid_size.x * sizeof(uint32_t)*img_export_scale.x);
+ stbi_write_png(floor_mesh_name, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, 1, large_floor_mesh_buffer, ginfo.rd_grid_size.x * sizeof(uint8_t)*ginfo.img_export_scale.x);
+ stbi_write_png(floor_albedo_name, ginfo.rd_grid_size.x*ginfo.img_export_scale.x, ginfo.rd_grid_size.y*ginfo.img_export_scale.y, 4, large_albedo_buffer, ginfo.rd_grid_size.x * sizeof(uint32_t)*ginfo.img_export_scale.x);
cleanup();
playtime.resources_ready = 1;
return success;
}
+bool initialize_generation_info(const IVec2 pgrid_size, const int pworker_count)
+{
+ bool response = false;
+ IVec2 grid_size = pgrid_size;
+
+ generation_info.img_export_scale = (IVec2){.x = 2.0f, .y = 2.0f};
+ generation_info.rd_grid_size = pgrid_size;
+ generation_info.generation_progress = 0.0f;
+ generation_info.worker_count = pworker_count;
+ generation_info.rd_opt = barrow;
+ generation_info.room_count = 4;
+
+ response |= !(generation_info.grid = (FVec2**)malloc(grid_size.x * sizeof(FVec2*)));
+ for (int n = 0; n < grid_size.x; n++)
+ {
+ response |= !(generation_info.grid[n] = (FVec2*)malloc(grid_size.y * sizeof(FVec2)));
+ }
+
+ response |= !(generation_info.grid_prime = (FVec2**)malloc(grid_size.x * sizeof(FVec2*)));
+ for (int n = 0; n < grid_size.x; n++)
+ {
+ response |= !(generation_info.grid_prime[n] = (FVec2*)malloc(grid_size.y * sizeof(FVec2)));
+ }
+
+ return response;
+}
+
+bool deinitialize_generation_info()
+{
+ free(generation_info.grid);
+ free(generation_info.grid_prime);
+ generation_info.grid_temp = NULL;
+
+ return true;
+}
+