generated from rpuzonas/raylib-cpp-template
start reworking for checking looping neighbouring boids
This commit is contained in:
parent
f6d001e9de
commit
d1af945202
19
src/main.cpp
19
src/main.cpp
@ -19,6 +19,10 @@
|
||||
|
||||
static App g_app;
|
||||
|
||||
// TODO: Repeat visuals in looping walls mode
|
||||
|
||||
// TODO: Make WASM canvas resizable
|
||||
|
||||
// TODO: Add prompt for restarting program in WASM on crash
|
||||
|
||||
// TODO: Add controls window
|
||||
@ -73,14 +77,11 @@ static void profiling_test() {
|
||||
|
||||
SetRandomSeed(10);
|
||||
|
||||
for (int i = 0; i < 50000; i++) {
|
||||
Boid boid;
|
||||
boid_rand_init(&world, &boid, 5);
|
||||
world.boids.push_back(boid);
|
||||
}
|
||||
world_spawn_boids(&world, 50000);
|
||||
|
||||
for (int i = 0; i < FRAMERATE; i++) {
|
||||
// world_update(&world, TIME_PER_FRAME);
|
||||
arena_clear(&world.frame_arena);
|
||||
world_update(&world, TIME_PER_FRAME);
|
||||
}
|
||||
|
||||
printf("arena: %ld (%.03fMiB)\n", world.frame_arena.offset, (float)world.frame_arena.offset / 1024 / 1024);
|
||||
@ -89,8 +90,8 @@ static void profiling_test() {
|
||||
rprof_end();
|
||||
|
||||
printf("interactions: %d\n", g_prof_interactions);
|
||||
int expected_interactions = 40501984;
|
||||
if (g_prof_interactions != expected_interactions) { // 22 051 739
|
||||
int expected_interactions = 40134438;
|
||||
if (g_prof_interactions != expected_interactions) {
|
||||
printf("!!!!!! ITERACTIONS DONT MATCH, %d\n", g_prof_interactions - expected_interactions);
|
||||
}
|
||||
|
||||
@ -111,7 +112,7 @@ void UpdateDrawFrame() {
|
||||
world_update(&g_world, dt);
|
||||
}
|
||||
#else
|
||||
world_update(&g_app, &g_app.world, dt);
|
||||
world_update(&g_app.world, dt);
|
||||
#endif
|
||||
visuals_update(&g_app.world, &g_app.visuals);
|
||||
RPROF_STOP();
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "raycast.hpp"
|
||||
#include "raymath.hpp"
|
||||
|
||||
static float get_intersect_point(Vector2 ray_origin, Vector2 ray_dir, Vector2 line1, Vector2 line2) {
|
||||
Vector2 line_dir = Vector2Subtract(line2, line1);
|
||||
@ -17,8 +18,8 @@ static void set_nearest_hit(RayHitResult *nearest_hit, float hit, Vector2 line1,
|
||||
bool is_gotten_hit_better = (nearest_hit->hit < 0 || nearest_hit->hit > hit);
|
||||
if (got_hit && is_gotten_hit_better) {
|
||||
nearest_hit->hit = hit;
|
||||
nearest_hit->line1 = line1;
|
||||
nearest_hit->line2 = line2;
|
||||
// nearest_hit->line1 = line1;
|
||||
// nearest_hit->line2 = line2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,8 @@
|
||||
struct RayHitResult {
|
||||
float hit = -1;
|
||||
|
||||
// TODO: `line1` and `line2` are not used, maybe remove them?
|
||||
Vector2 line1;
|
||||
Vector2 line2;
|
||||
// Vector2 line1; // not used
|
||||
// Vector2 line2; // not used
|
||||
};
|
||||
|
||||
static float get_intersect_point(Vector2 ray_origin, Vector2 ray_dir, Vector2 line1, Vector2 line2);
|
||||
|
@ -13,6 +13,7 @@ static inline bool mm_is_zero(__simdi x) {
|
||||
#define mm_set1_ps(x) _mm256_set1_ps(x)
|
||||
#define mm_sub_ps(a, b) _mm256_sub_ps(a, b)
|
||||
#define mm_mul_ps(a, b) _mm256_mul_ps(a, b)
|
||||
#define mm_add_ps(a, b) _mm256_add_ps(a, b)
|
||||
#define mm_and_ps(a, b) _mm256_and_ps(a, b)
|
||||
#define mm_store_ps(a, b) _mm256_store_ps(a, b)
|
||||
#define mm_fmadd_ps(a, b, c) _mm256_fmadd_ps(a, b, c)
|
||||
@ -32,6 +33,7 @@ static inline bool mm_is_zero(__simdi x) {
|
||||
#define mm_set1_ps(x) _mm_set1_ps(x)
|
||||
#define mm_sub_ps(a, b) _mm_sub_ps(a, b)
|
||||
#define mm_mul_ps(a, b) _mm_mul_ps(a, b)
|
||||
#define mm_add_ps(a, b) _mm_add_ps(a, b)
|
||||
#define mm_and_ps(a, b) _mm_and_ps(a, b)
|
||||
#define mm_store_ps(a, b) _mm_store_ps(a, b)
|
||||
#define mm_fmadd_ps(a, b, c) _mm_add_ps(_mm_mul_ps(a, b), c)
|
||||
|
201
src/world.cpp
201
src/world.cpp
@ -239,27 +239,9 @@ static void app_cleanup(App *app) {
|
||||
|
||||
// --------------------- Utils -----------------------
|
||||
|
||||
void world_adjust_boid_count(World *world, int new_boid_count) {
|
||||
if (new_boid_count >= MAX_BOIDS) return;
|
||||
|
||||
int boid_count = world->boids.size();
|
||||
int diff = new_boid_count - boid_count;
|
||||
if (diff > 0) {
|
||||
for (int i = 0; i < diff; i++) {
|
||||
Boid boid;
|
||||
boid_rand_init(world, &boid, 5);
|
||||
world->boids.push_back(boid);
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
for (int i = 0; i < -diff ; i++) {
|
||||
world->boids.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void world_spawn_boids(World *world, size_t count) {
|
||||
float border = 0;
|
||||
if (world->looping_walls) {
|
||||
if (!world->looping_walls) {
|
||||
border = world->collision_avoidance_distance;
|
||||
}
|
||||
|
||||
@ -270,6 +252,25 @@ static void world_spawn_boids(World *world, size_t count) {
|
||||
}
|
||||
}
|
||||
|
||||
void world_adjust_boid_count(World *world, int new_boid_count) {
|
||||
if (new_boid_count >= MAX_BOIDS) return;
|
||||
|
||||
int boid_count = world->boids.size();
|
||||
int diff = new_boid_count - boid_count;
|
||||
if (diff > 0) {
|
||||
world_spawn_boids(world, diff);
|
||||
} else if (diff < 0) {
|
||||
for (int i = 0; i < -diff ; i++) {
|
||||
world->boids.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Enforce max view radius, so boid could not see himself in looping world
|
||||
// static float world_get_max_boid_view_radius(World *world) {
|
||||
// return MIN(world->size.x/2, world->size.y/2);
|
||||
// }
|
||||
|
||||
// --------------------- Update -----------------------
|
||||
|
||||
static size_t chunkgrid_get_idx(ChunkGrid *grid, int x, int y) {
|
||||
@ -306,9 +307,10 @@ static int nearest_multiple(int num, int divisor) {
|
||||
return (num / divisor + (num % divisor > 0 ? 1 : 0)) * divisor;
|
||||
}
|
||||
|
||||
struct boid_pair {
|
||||
struct boid_cmp {
|
||||
uboid_t from;
|
||||
uboid_t to;
|
||||
Vector2 to_offset;
|
||||
};
|
||||
|
||||
#ifdef SIMD256
|
||||
@ -323,7 +325,25 @@ struct boid_pair {
|
||||
boids[b2b_cmps[8*i+1].SIDE].FIELD, \
|
||||
boids[b2b_cmps[8*i+0].SIDE].FIELD \
|
||||
)
|
||||
#define GET_TO_OFFSET_FROM_CMPS(i, FIELD) \
|
||||
_mm256_set_ps( \
|
||||
b2b_cmps[8*i+7].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+6].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+5].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+4].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+3].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+2].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+1].to_offset.FIELD, \
|
||||
b2b_cmps[8*i+0].to_offset.FIELD \
|
||||
)
|
||||
#else
|
||||
#define GET_TO_OFFSET_FROM_CMPS(i, FIELD) \
|
||||
_mm_set_ps( \
|
||||
b2b_cmps[4*i+3].to_offset.FIELD, \
|
||||
b2b_cmps[4*i+2].to_offset.FIELD, \
|
||||
b2b_cmps[4*i+1].to_offset.FIELD, \
|
||||
b2b_cmps[4*i+0].to_offset.FIELD \
|
||||
)
|
||||
#define GET_F32_CHUNK_FROM_BOIDS(i, SIDE, FIELD) \
|
||||
_mm_set_ps( \
|
||||
boids[b2b_cmps[4*i+3].SIDE].FIELD, \
|
||||
@ -332,7 +352,7 @@ struct boid_pair {
|
||||
boids[b2b_cmps[4*i+0].SIDE].FIELD \
|
||||
)
|
||||
#endif
|
||||
static void world_calc_distances_and_angles(World *world, BoidList *local_boids, boid_pair *b2b_cmps, int *b2b_cmps_count) {
|
||||
static void world_calc_distances_and_angles(World *world, BoidList *local_boids, boid_cmp *b2b_cmps, int *b2b_cmps_count) {
|
||||
RPROF_START("Calc dot products and distances");
|
||||
// Simplified from:
|
||||
// float dot_threshold = Vector2DotProduct(dir, Vector2Rotate(dir, world->view_angle/2));
|
||||
@ -359,9 +379,15 @@ static void world_calc_distances_and_angles(World *world, BoidList *local_boids,
|
||||
__simd from_pos_x = GET_F32_CHUNK_FROM_BOIDS(i, from, pos.x);
|
||||
__simd from_pos_y = GET_F32_CHUNK_FROM_BOIDS(i, from, pos.y);
|
||||
|
||||
__simd to_offset_pos_x = GET_TO_OFFSET_FROM_CMPS(i, x);
|
||||
__simd to_offset_pos_y = GET_TO_OFFSET_FROM_CMPS(i, y);
|
||||
|
||||
__simd to_pos_x = GET_F32_CHUNK_FROM_BOIDS(i, to, pos.x);
|
||||
__simd to_pos_y = GET_F32_CHUNK_FROM_BOIDS(i, to, pos.y);
|
||||
|
||||
to_pos_x = mm_add_ps(to_pos_x, to_offset_pos_x);
|
||||
to_pos_y = mm_add_ps(to_pos_y, to_offset_pos_y);
|
||||
|
||||
__simd sub_x = mm_sub_ps(from_pos_x, to_pos_x);
|
||||
__simd sub_y = mm_sub_ps(from_pos_y, to_pos_y);
|
||||
|
||||
@ -418,7 +444,8 @@ static void world_calc_distances_and_angles(World *world, BoidList *local_boids,
|
||||
#define B2B_CAPACITY 1024*8
|
||||
#define B2B_THRESHOLD B2B_CAPACITY*0.25
|
||||
|
||||
static inline void append_b2b_cmp(World *world, BoidList *local_boids, boid_pair *b2b_cmps, int *b2b_cmps_count, boid_pair b2b_cmp) {
|
||||
// TODO: eeehh, a lot of parameters. Shorten?
|
||||
static inline void append_b2b_cmp(World *world, BoidList *local_boids, boid_cmp *b2b_cmps, int *b2b_cmps_count, boid_cmp b2b_cmp) {
|
||||
if ((*b2b_cmps_count) == B2B_CAPACITY) {
|
||||
world_calc_distances_and_angles(world, local_boids, b2b_cmps, b2b_cmps_count);
|
||||
}
|
||||
@ -426,12 +453,96 @@ static inline void append_b2b_cmp(World *world, BoidList *local_boids, boid_pair
|
||||
b2b_cmps[(*b2b_cmps_count)++] = b2b_cmp;
|
||||
}
|
||||
|
||||
// TODO: eeehh, a lot of parameters. Shorten?
|
||||
static inline void append_many_b2b_cmp(World *world, BoidList *local_boids, boid_cmp *b2b_cmps, int *b2b_cmps_count, Vector2 to_offset, uboid_t from_boid, uboid_t *to_boids, int to_boids_count) {
|
||||
for (int i = 0; i < to_boids_count; i++) {
|
||||
boid_cmp b2b_cmp = {
|
||||
.from = from_boid,
|
||||
.to = to_boids[i],
|
||||
.to_offset = to_offset
|
||||
};
|
||||
append_b2b_cmp(world, local_boids, b2b_cmps, b2b_cmps_count, b2b_cmp);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Dear god :O, this name.
|
||||
static inline void world_compute_local_boids_looping_top_edge(BoidList *local_boids, World *world, ChunkGrid *chunks, uboid_t **static_chunks, boid_cmp *b2b_cmps, int *b2b_cmps_count, int neighbour_y) {
|
||||
Vector2 to_offset = { 0, -world->size.y };
|
||||
|
||||
for (int x = 1; x < chunks->width; x++) {
|
||||
size_t chunk_idx = chunkgrid_get_idx(chunks, x, 0);
|
||||
BoidList *chunk = &chunks->data[chunk_idx];
|
||||
uboid_t *chunk_boids = static_chunks[chunk_idx];
|
||||
|
||||
for (int ox = -1; ox <= 1; ox++) {
|
||||
int neighbour_x = x+ox;
|
||||
if (neighbour_x < 0 || neighbour_x >= chunks->width) continue;
|
||||
size_t neighbour_idx = chunkgrid_get_idx(chunks, neighbour_x, neighbour_y);
|
||||
BoidList *neighbour_chunk = &chunks->data[neighbour_idx];
|
||||
uboid_t *neighbour_boids = static_chunks[neighbour_idx];
|
||||
|
||||
for (int i = 0; i < chunk->count; i++) {
|
||||
uboid_t from_boid = chunk_boids[i];
|
||||
append_many_b2b_cmp(world, local_boids, b2b_cmps, b2b_cmps_count, to_offset, chunk_boids[i], neighbour_boids, neighbour_chunk->count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Dear god :O, this name.
|
||||
static inline void world_compute_local_boids_looping_left_edge(BoidList *local_boids, World *world, ChunkGrid *chunks, uboid_t **static_chunks, boid_cmp *b2b_cmps, int *b2b_cmps_count, int neighbour_x) {
|
||||
Vector2 to_offset = { -world->size.x, 0 };
|
||||
|
||||
for (int y = 1; y < chunks->height; y++) {
|
||||
size_t chunk_idx = chunkgrid_get_idx(chunks, 0, y);
|
||||
BoidList *chunk = &chunks->data[chunk_idx];
|
||||
uboid_t *chunk_boids = static_chunks[chunk_idx];
|
||||
|
||||
for (int oy = -1; oy <= 1; oy++) {
|
||||
int neighbour_y = y+oy;
|
||||
if (neighbour_y < 0 || neighbour_y >= chunks->height) continue;
|
||||
size_t neighbour_idx = chunkgrid_get_idx(chunks, neighbour_x, neighbour_y);
|
||||
BoidList *neighbour_chunk = &chunks->data[neighbour_idx];
|
||||
uboid_t *neighbour_boids = static_chunks[neighbour_idx];
|
||||
|
||||
for (int i = 0; i < chunk->count; i++) {
|
||||
uboid_t from_boid = chunk_boids[i];
|
||||
append_many_b2b_cmp(world, local_boids, b2b_cmps, b2b_cmps_count, to_offset, chunk_boids[i], neighbour_boids, neighbour_chunk->count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Dear god :O, this name. PLEASE DO SOMETHING
|
||||
static inline void world_compute_local_boids_looping_top_left(BoidList *local_boids, World *world, ChunkGrid *chunks, uboid_t **static_chunks, boid_cmp *b2b_cmps, int *b2b_cmps_count, int neighbour_x) {
|
||||
Vector2 to_offset = { -world->size.x, 0 };
|
||||
|
||||
for (int y = 1; y < chunks->height; y++) {
|
||||
size_t chunk_idx = chunkgrid_get_idx(chunks, 0, y);
|
||||
BoidList *chunk = &chunks->data[chunk_idx];
|
||||
uboid_t *chunk_boids = static_chunks[chunk_idx];
|
||||
|
||||
for (int oy = -1; oy <= 1; oy++) {
|
||||
int neighbour_y = y+oy;
|
||||
if (neighbour_y < 0 || neighbour_y >= chunks->height) continue;
|
||||
size_t neighbour_idx = chunkgrid_get_idx(chunks, neighbour_x, neighbour_y);
|
||||
BoidList *neighbour_chunk = &chunks->data[neighbour_idx];
|
||||
uboid_t *neighbour_boids = static_chunks[neighbour_idx];
|
||||
|
||||
for (int i = 0; i < chunk->count; i++) {
|
||||
uboid_t from_boid = chunk_boids[i];
|
||||
append_many_b2b_cmp(world, local_boids, b2b_cmps, b2b_cmps_count, to_offset, chunk_boids[i], neighbour_boids, neighbour_chunk->count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void world_compute_local_boids(BoidList *local_boids, World *world, ChunkGrid *chunks) {
|
||||
Boid *boids = world->boids.data();
|
||||
int boid_count = world->boids.size();
|
||||
MemoryArena *arena = &world->frame_arena;
|
||||
|
||||
boid_pair *b2b_cmps = (boid_pair*)arena_malloc(arena, (B2B_CAPACITY + SIMD_32B_LANES)*sizeof(boid_pair));
|
||||
boid_cmp *b2b_cmps = (boid_cmp*)arena_malloc(arena, (B2B_CAPACITY + SIMD_32B_LANES)*sizeof(boid_cmp));
|
||||
int b2b_cmps_count = 0;
|
||||
|
||||
RPROF_START("Move chunk data to static arrays");
|
||||
@ -446,7 +557,7 @@ static void world_compute_local_boids(BoidList *local_boids, World *world, Chunk
|
||||
}
|
||||
RPROF_STOP();
|
||||
|
||||
RPROF_START("Iterate over chunks");
|
||||
RPROF_START("Iterate over chunks (for local boids)");
|
||||
for (int y = 0; y < chunks->height; y++) {
|
||||
for (int x = 0; x < chunks->width; x++) {
|
||||
size_t chunk_idx = chunkgrid_get_idx(chunks, x, y);
|
||||
@ -459,13 +570,7 @@ static void world_compute_local_boids(BoidList *local_boids, World *world, Chunk
|
||||
uboid_t *to_boids = &chunk_boids[i+1];
|
||||
uboid_t to_boids_count = chunk->count-i-1;
|
||||
|
||||
for (int j = 0; j < to_boids_count; j++) {
|
||||
boid_pair b2b_cmp = {
|
||||
.from = from_boid,
|
||||
.to = to_boids[j]
|
||||
};
|
||||
append_b2b_cmp(world, local_boids, b2b_cmps, &b2b_cmps_count, b2b_cmp);
|
||||
}
|
||||
append_many_b2b_cmp(world, local_boids, b2b_cmps, &b2b_cmps_count, { 0 }, from_boid, to_boids, to_boids_count);
|
||||
}
|
||||
|
||||
Vector2 neighbours[] = { { 1, 0 }, { 0, 1 }, { 1, 1 }, { -1, 1 } };
|
||||
@ -477,17 +582,11 @@ static void world_compute_local_boids(BoidList *local_boids, World *world, Chunk
|
||||
|
||||
size_t neighbour_idx = chunkgrid_get_idx(chunks, chunk_x, chunk_y);
|
||||
BoidList *neighbour_chunk = &chunks->data[neighbour_idx];
|
||||
if (neighbour_chunk->count == 0) continue;
|
||||
|
||||
uboid_t *neighbour_boids = static_chunks[neighbour_idx];
|
||||
for (int i = 0; i < chunk->count; i++) {
|
||||
for (int j = 0; j < neighbour_chunk->count; j++) {
|
||||
boid_pair b2b_cmp = {
|
||||
.from = chunk_boids[i],
|
||||
.to = neighbour_boids[j]
|
||||
};
|
||||
append_b2b_cmp(world, local_boids, b2b_cmps, &b2b_cmps_count, b2b_cmp);
|
||||
}
|
||||
uboid_t from_boid = chunk_boids[i];
|
||||
append_many_b2b_cmp(world, local_boids, b2b_cmps, &b2b_cmps_count, { 0 }, from_boid, neighbour_boids, neighbour_chunk->count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,6 +596,23 @@ static void world_compute_local_boids(BoidList *local_boids, World *world, Chunk
|
||||
}
|
||||
}
|
||||
|
||||
// For checking neighbours on the edge of the wall
|
||||
if (world->looping_walls) {
|
||||
// TODO: Rewrite a nicer version here.
|
||||
|
||||
// world_compute_local_boids_looping_top_edge(local_boids, world, chunks, static_chunks, b2b_cmps, &b2b_cmps_count, chunks->height-1);
|
||||
// world_compute_local_boids_looping_left_edge(local_boids, world, chunks, static_chunks, b2b_cmps, &b2b_cmps_count, chunks->width-1);
|
||||
//
|
||||
// if (fmod(world->size.y, chunks->chunk_size) >= 1) {
|
||||
// world_compute_local_boids_looping_top_edge(local_boids, world, chunks, static_chunks, b2b_cmps, &b2b_cmps_count, chunks->height-2);
|
||||
// }
|
||||
// if (fmod(world->size.x, chunks->chunk_size) >= 1) {
|
||||
// world_compute_local_boids_looping_left_edge(local_boids, world, chunks, static_chunks, b2b_cmps, &b2b_cmps_count, chunks->width-2);
|
||||
// }
|
||||
|
||||
// TODO: Check top left chunk
|
||||
}
|
||||
|
||||
if (b2b_cmps_count > 0) {
|
||||
world_calc_distances_and_angles(world, local_boids, b2b_cmps, &b2b_cmps_count);
|
||||
}
|
||||
@ -544,6 +660,7 @@ static BoidList* world_compute_local_boids(World *world) {
|
||||
}
|
||||
|
||||
static void aggregate_flock_modifiers(World *world, BoidList *flock, Boid *boid, Vector2 *center, Vector2 *heading, Vector2 *separation_force) {
|
||||
// TODO: use simd here
|
||||
*center = { 0, 0 };
|
||||
*heading = { 0, 0 };
|
||||
*separation_force = { 0, 0 };
|
||||
@ -564,14 +681,14 @@ static void aggregate_flock_modifiers(World *world, BoidList *flock, Boid *boid,
|
||||
*center = vector2_div_value(*center, flock->count);
|
||||
}
|
||||
|
||||
static void world_update(App *app, World *world, float dt) {
|
||||
if (world->freeze) return;
|
||||
|
||||
static void world_update(World *world, float dt) {
|
||||
Boid *boids = world->boids.data();
|
||||
int boid_count = world->boids.size();
|
||||
DEBUG_ASSERT(boid_count <= MAX_BOIDS);
|
||||
|
||||
world_place_boids_into_chunks(world);
|
||||
if (world->freeze) return;
|
||||
|
||||
BoidList *list_of_local_boids = world_compute_local_boids(world);
|
||||
|
||||
RPROF_START("Apply forces");
|
||||
|
Loading…
Reference in New Issue
Block a user