working on integrating a settings file
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 15 Nov 2020 19:27:33 +0000 (13:27 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 15 Nov 2020 19:27:33 +0000 (13:27 -0600)
Makefile
dummy.settings [new file with mode: 0644]
include/container.h
include/log.h
include/physics.h
include/settings.h [new file with mode: 0644]
src/physics.cpp
src/settings.cpp [new file with mode: 0644]
src/sim.cpp

index edeb4e3ede9be654f572193b308e398ccec57370..f5d17e98083e2f01d51e9a7351fe05dfc5b1535f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,7 @@ OBJ_FILES=\
        build/utils.o \
        build/vecmath.o \
        build/physics.o \
+       build/settings.o \
        build/ui.o \
        build/sim.o
 
diff --git a/dummy.settings b/dummy.settings
new file mode 100644 (file)
index 0000000..642fbd8
--- /dev/null
@@ -0,0 +1,43 @@
+# Determines the number of parallel execution units to be used.
+# This must be at least 2 (for now).
+thread_count 4
+
+# Determines the number of physics bodies in the simulation.
+body_count 2500
+
+# Determines the number of different types of bodies.
+# This must be specified before the body_color or interaction settings.
+body_type_count 4
+
+# Determines what the color is of each of the body types.
+# Uses standard RGB with values ranging from 0 to 1.
+#          Type#  R   G   B
+body_color 0      1.0 0.0 0.0
+body_color 1      0.0 1.0 0.0
+body_color 2      0.0 0.0 1.0
+body_color 3      1.0 1.0 1.0
+
+# Determines the range of values a bodies mass can be, sampled from
+# a uniform distribution.
+#               Type#  Min  Max
+body_mass_range 0      2.0  4.0
+body_mass_range 1      20.0 22.0
+body_mass_range 2      5.0  7.0
+body_mass_range 3      3.0  15.0
+
+# Determines the friction coeffient, u.
+# Equation of friction used:
+#     F = -u * v;
+# where v is the velocity of the body.
+# Set to 0.0 to watch very wild behavior.
+friction 6.0
+
+# Determines the scale of the interaction calcuations.
+# Mostly an implementation detail, but effectively, the "distance" column on
+# the interactions plus one, is multipled by this number and that is the maximum distance
+# two bodies will interact in terms of pixels.
+universe_scale 20.0
+
+# Determines how two bodies will interact. Note, that this is not a symmetric relation.
+#           Body Type#  Other Type#  Distance  Force
+interaction 0           1            5.0       200.0
index 5ced00c8feafbccede9d8da45c386da1558e9298..08bfb05bb981b3f532b088db2b1c48ac706beee1 100644 (file)
@@ -22,6 +22,14 @@ struct Array
         data = nullptr;
     }
 
+    void init(u32 initial_capacity)
+    {
+        count = 0;
+        capacity = 0;
+        data = nullptr;
+        this->ensure_capacity(initial_capacity);
+    }
+
     T& operator[](i32 elem)
     {
 #if defined(DEBUG)
index f23d3e8a67c6362a3781ab3160c5ea8b6a034a15..0d4856ec34c2320fc4276fcd8800ed0a26ed7fd6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef LOG_H
 #define LOG_H
 
+#include <stdarg.h>
+
 enum LogLevel
 {
     LOG_LEVEL_INFO,
@@ -17,4 +19,4 @@ extern LogLevel LOG_LEVEL_MINIMUM;
 void logprint(LogLevel level, const char* format, ...);
 void logvprint(LogLevel level, const char* format, va_list va);
 
-#endif //LOG_H
\ No newline at end of file
+#endif //LOG_H
index 18cfb56059c416746acb734c8823aa15427b6bbe..d2ac939a6a47c992c743066ed225a38f1a34086d 100644 (file)
@@ -5,29 +5,32 @@
 #include "container.h"
 #include "utils.h"
 
-enum struct BodyType : u8
-{
-    Red    = 0,
-    Green  = 1,
-    Blue   = 2,
-    White  = 3,
-    
-    Count
-};
-
 struct Body
 {
     V2f pos;
     V2f vel;
     V2f acc;
-    
+
     f32 mass;
-    
-    BodyType body_type;
+
+    u32 body_type;
+};
+
+// NOTE(Brendan): This represents the piecewise function:
+//
+// F(d) = {
+//     0 < d < 1:                      r * (1 - d) / d
+//     1 <= d < distance_range + 1:    (-4 * max_force / (distance_range ^ 2)) * (d - (distance_range / 2) - 1) ^ 2 + max_force,
+//     otherwise:                      0
+// }
+struct BodyRelation
+{
+    f32 distance_range;
+    f32 max_force;
 };
 
 void nocheckin_init_other_bodies();
 void body_accumulate_move(Body* body, QuadTree<Body>* qt_bodies, f64 dt);
 void body_apply_move(Body* body, f64 dt);
 
-#endif //PHYSICS_H
\ No newline at end of file
+#endif //PHYSICS_H
diff --git a/include/settings.h b/include/settings.h
new file mode 100644 (file)
index 0000000..ec5b8d5
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include "container.h"
+#include "log.h"
+#include "utils.h"
+#include "physics.h"
+
+struct BodyColor
+{
+    f32 r, g, b;
+};
+
+struct BodyMassRange
+{
+    f32 min, max;
+};
+
+struct SimSettings
+{
+    u32 body_count;
+    u32 body_type_count;
+
+    Array<BodyColor> body_colors;
+    Array<BodyMassRange> body_mass_range;
+
+    // NOTE(Brendan): This is effectively a 2D array.
+    // Accessed using [b1 * num_bodies + b2]
+    Array<BodyRelation> body_relations;
+
+    f32 friction;
+    f32 near_repulsive_force;
+    f32 universe_scale;
+    u32 thread_count;
+};
+
+extern SimSettings global_settings;
+
+void load_settings_from_file(SimSettings* settings, const char* filename);
+void save_settings_to_file(SimSettings* settings, const char* filename);
+void generate_random_settings(SimSettings* settings);
+
+#endif
index 38de5f898885f368e662ee6387c5c0a8c89bd898..4270996cf189f0f33f1b6ef7a51935074c3e61c9 100644 (file)
@@ -1,27 +1,14 @@
 #include "physics.h"
 #include "utils.h"
 #include "types.h"
-
-// NOTE(Brendan): This represents the piecewise function:
-//
-// F(d) = {
-//     0 < d < 1:                      r * (1 - d) / d
-//     1 <= d < distance_range + 1:    (-4 * max_force / (distance_range ^ 2)) * (d - (distance_range / 2) - 1) ^ 2 + max_force,
-//     otherwise:                      0
-// }
-struct BodyRelation
-{
-    f32 distance_range;
-    f32 max_force;
-};
+#include "settings.h"
 
 internal f32
 get_force_magnitude_at_distance(BodyRelation br, f32 d)
 {
     if (0 < d && d < 1)
     {
-        persist const f32 repulsion_force = 100.0f; // :ArbitraryConstant
-        return repulsion_force * (1 - d) / d;
+        return global_settings.near_repulsive_force * (1 - d) / d;
     }
 
     if (1 <= d && d < br.distance_range + 1)
@@ -36,8 +23,6 @@ get_force_magnitude_at_distance(BodyRelation br, f32 d)
     return 0;
 }
 
-internal BodyRelation body_relations[(i32) BodyType::Count][(i32) BodyType::Count];
-
 internal bool
 bodies_collide(Body* b1, Body* b2)
 {
@@ -67,15 +52,6 @@ body_can_move(Body* body, const Array<Body> other_bodies, V2f d)
 thread_local internal Array<Body *> other_bodies;
 void nocheckin_init_other_bodies()
 {
-    foreach (i, 0, (i32) BodyType::Count)
-    {
-        foreach (j, 0, (i32) BodyType::Count)
-        {
-            body_relations[i][j].max_force = randf(-200.0f, 200.0f);
-            body_relations[i][j].distance_range = randf(4.0f, 7.0f);
-        }
-    }
-
     other_bodies.ensure_capacity(1024);
 }
 
@@ -92,16 +68,16 @@ body_accumulate_move(Body* body, QuadTree<Body>* qt_bodies, f64 dt)
         if (body == it) continue;
 
         auto norm_dir = body->pos - it->pos;
-        auto d = v2f_mag(norm_dir) / 20.0f; // :ArbitraryConstant
+        auto d = v2f_mag(norm_dir) / global_settings.universe_scale;
         norm_dir = v2f_norm(norm_dir);
 
-        auto br = body_relations[static_cast<i32>(body->body_type)][static_cast<i32>(it->body_type)];
+        auto br = global_settings.body_relations[static_cast<i32>(body->body_type) * global_settings.body_type_count + static_cast<i32>(it->body_type)];
         f32 force_mag = get_force_magnitude_at_distance(br, d);
 
         force += norm_dir * force_mag;
     }
 
-    force += body->vel * -6.f; // :ArbitraryConstant
+    force += body->vel * -global_settings.friction;
 
     body->acc = force * (1.0f / body->mass);
     body->vel += body->acc * dt;
diff --git a/src/settings.cpp b/src/settings.cpp
new file mode 100644 (file)
index 0000000..c6a51f3
--- /dev/null
@@ -0,0 +1,57 @@
+#include "settings.h"
+
+SimSettings global_settings;
+
+void
+load_settings_from_file(SimSettings* settings, const char* filename)
+{
+    FILE* file = fopen(filename, "r");
+    defer { fclose(file); };
+
+
+}
+
+void
+save_settings_to_file(SimSettings* settings, const char* filename)
+{
+}
+
+void
+generate_random_settings(SimSettings* settings)
+{
+    settings->body_count = 2500;
+
+    const u32 num_body_types = 4;
+    settings->body_type_count = num_body_types;
+
+    settings->body_colors.init(num_body_types);
+    settings->body_colors[0] = { 1.0, 0.0, 0.0 };
+    settings->body_colors[1] = { 0.0, 1.0, 0.0 };
+    settings->body_colors[2] = { 0.0, 0.0, 1.0 };
+    settings->body_colors[3] = { 1.0, 1.0, 1.0 };
+
+    settings->body_mass_range.init(num_body_types);
+    settings->body_mass_range[0] = { 4.0, 6.0 };
+    settings->body_mass_range[1] = { 4.0, 6.0 };
+    settings->body_mass_range[2] = { 4.0, 6.0 };
+    settings->body_mass_range[3] = { 4.0, 6.0 };
+
+    settings->friction = 6.0;
+    settings->near_repulsive_force = 100.0;
+    settings->universe_scale = 20.0;
+
+    settings->thread_count = 4;
+
+    settings->body_relations.init(num_body_types * num_body_types);
+    foreach (i, 0, num_body_types)
+    {
+        foreach (j, 0, num_body_types)
+        {
+            settings->body_relations[i * num_body_types] =
+            {
+                .distance_range = randf(4.0f, 7.0f),
+                .max_force = randf(-200.0f, 200.0f),
+            };
+        }
+    }
+}
index 76462f377eef20cc27b11ea026241c3ba7f9af43..75b4a46971ae3936fab305a6933519e611175ae0 100644 (file)
 #include "physics.h"
 #include "ui.h"
 #include "log.h"
-
-// :ArbitraryConstant
-#define PARTICLE_COUNT 2500
-
-// :ArbitraryConstant
-#define NUM_THREADS 2
+#include "settings.h"
 
 // TODO(Brendan): Maybe this can be removed because it isn't really necessary?
 internal void
@@ -131,19 +126,18 @@ struct SimState
     Camera camera;
 
     pthread_barrier_t thread_sync_barrier;
-    pthread_t threads[NUM_THREADS - 1];
-    ThreadData thread_data[NUM_THREADS - 1];
+    Array<pthread_t> threads;
+    Array<ThreadData> thread_data;
 };
 
+// @CLEANUP
 internal f64 TEMP_dt = 0;
 
 internal void
 update_bodies_partial(SimState *state, i32 index)
 {
-    i32 low  = index * (PARTICLE_COUNT / NUM_THREADS);
-    i32 high = (index + 1) * (PARTICLE_COUNT / NUM_THREADS);
-
-    persist const f64 step = 0.01;
+    i32 low  = index * (global_settings.body_count / global_settings.thread_count);
+    i32 high = (index + 1) * (global_settings.body_count / global_settings.thread_count);
 
     foreach (i, low, high) body_accumulate_move(&state->bodies[i], &state->qt_bodies, TEMP_dt);
     pthread_barrier_wait(&state->thread_sync_barrier);
@@ -177,29 +171,35 @@ internal void
 sim_state_init(SimState* state)
 {
     // NOTE(Brendan): Need to initialize the array since it does not get constructed because I refuse to use the 'new' keyword. alloc<T> uses malloc under the hood and cannot initialize the result.
-    state->bodies.init();
-    state->bodies.ensure_capacity(PARTICLE_COUNT);
+    state->bodies.init(global_settings.body_count);
 
-    foreach (i, 0, PARTICLE_COUNT)
+    foreach (i, 0, global_settings.body_count)
     {
         Body tmp_body;
+        tmp_body.body_type = (rand() % global_settings.body_type_count);
         tmp_body.pos = V2f{ randf(-1000, 1000), randf(-1000, 1000) };
         tmp_body.vel = V2f{ 0.0f, 0.0f };
-        tmp_body.mass = randf(3.0f, 6.0f);
-        tmp_body.body_type = static_cast<BodyType> ((rand() % 4));
+
+        BodyMassRange bmr = global_settings.body_mass_range[tmp_body.body_type];
+        tmp_body.mass = randf(bmr.min, bmr.max);
+
         state->bodies.push(tmp_body);
     }
 
-    state->qt_body_allocator.init(PARTICLE_COUNT);
+    state->qt_body_allocator.init(global_settings.body_count);
     state->qt_bodies.init(AABB { -2000, -2000, 4000, 4000 });
 
     state->camera.scale = 1.0f;
 
-    pthread_barrier_init(&state->thread_sync_barrier, NULL, NUM_THREADS);
+    pthread_barrier_init(&state->thread_sync_barrier, NULL, global_settings.thread_count);
+
+    state->threads.init(global_settings.thread_count);
+    state->threads.count = global_settings.thread_count;
 
-    foreach (i, 0, NUM_THREADS - 1)
+    state->thread_data.init(global_settings.thread_count);
+    foreach (i, 0, global_settings.thread_count - 1)
     {
-        state->thread_data[i] = ThreadData { i, state };
+        state->thread_data.push(ThreadData { i, state });
         pthread_create(&state->threads[i], NULL, thread_start, (void *) &state->thread_data[i]);
     }
 }
@@ -316,6 +316,8 @@ main(i32 argc, char* argv[])
 {
     srand(time(NULL));
 
+    generate_random_settings(&global_settings);
+
     init_glfw();
     defer { deinit_glfw(); };