#include "utils.h"
#include "types.h"
+// NOTE(Brendan): This represents the piecewise function:
+//
+// F(d) = {
+// 0 < d < 1: (1 / d) - 1
+// 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;
+};
+
+internal f32
+get_force_magnitude_at_distance(BodyRelation br, f32 d)
+{
+ if (0 < d && d < 1)
+ {
+ return (1 / d) - 1;
+ }
+
+ if (1 <= d && d < br.distance_range + 1)
+ {
+ f32 tmp_x = d - (br.distance_range / 2) - 1;
+
+ return (-4 * br.max_force / (br.distance_range * br.distance_range))
+ * (tmp_x * tmp_x)
+ + br.max_force;
+ }
+
+ return 0;
+}
+
+internal const
+BodyRelation body_relations[BodyType_Count][BodyType_Count] = {
+ // Red Green Blue White
+ /* Red */ { { 1.0f, 2.0f }, { 0.0f, 0.0f }, { 5.0f, -2.0f }, { 0.0f, 0.0f } },
+ /* Green */ { { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f } },
+ /* Blue */ { { 2.0f, 3.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f } },
+ /* White */ { { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f } },
+};
+
internal bool
bodies_collide(Body* b1, Body* b2)
{
void
body_calculate_move(Body* body, const Array<Body> other_bodies, f64 dt)
{
- body->post_update_vel = V2f { 0.0f, 0.0f, };
+ // NOTE(Brendan): Old code for moving bodies randomly with collisions.
+ /* body->post_update_vel = V2f { 0.0f, 0.0f, };
if (body_can_move(body, other_bodies, V2f { (f32) (body->vel.x * dt), 0.0f }))
body->post_update_vel.x += body->vel.x * dt;
if (body_can_move(body, other_bodies, V2f { 0.0f, (f32) (body->vel.y * dt) }))
body->post_update_vel.y += body->vel.y * dt;
+*/
+
+ V2f force = { 0.0f, 0.0f };
+
+ For (other_bodies)
+ {
+ if (body == &it) continue;
+
+ auto norm_dir = body->pos - it.pos;
+ auto d = v2f_mag(norm_dir) / 25.0f;
+ norm_dir = v2f_norm(norm_dir);
+
+ f32 force_mag = get_force_magnitude_at_distance(body_relations[body->body_type][it.body_type], d);
+
+ force += norm_dir * force_mag;
+ }
+
+ force += body->vel * -5.f;
+
+ body->acc = force * (1.0f / body->mass);
+ body->vel += body->acc * dt;
+ body->move_vec = body->vel;
}
void
body_apply_move(Body* body)
{
- body->pos += body->post_update_vel;
+ body->pos += body->move_vec;
}
\ No newline at end of file
return program;
}
-
-
-struct SimState
-{
- Array<Body> bodies;
-};
-
-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(1024);
-
- foreach (i, 0, 1024)
- {
- Body tmp_body;
- tmp_body.pos = V2f{ randf(0, 800), randf(0, 800) };
- tmp_body.vel = V2f{ randf(-50.0f, 50.0f), randf(-50.0f, 50.0f) };
- tmp_body.mass = randf(2.0f, 10.0f);
- tmp_body.color_idx = rand() % 4;
- state->bodies.push(tmp_body);
- }
-}
-
-
-
#define CIRCLE_POINT_COUNT 36 // NOTE(Brendan): Treat a circle as a many-sided polygon.
// NOTE(Brendan): Returns the VAO where the mesh data was bound.
return vao;
}
+struct SimState
+{
+ Array<Body> bodies;
+};
+
+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(1024);
+
+ foreach (i, 0, 1024)
+ {
+ Body tmp_body;
+ tmp_body.pos = V2f{ randf(0, 800), randf(0, 800) };
+ tmp_body.vel = V2f{ 0.0f, 0.0f };
+ tmp_body.mass = randf(2.0f, 10.0f);
+ tmp_body.body_type = static_cast<BodyType> (rand() % 2) * 2;
+ state->bodies.push(tmp_body);
+ }
+}
+
// NOTE(Brendan): dt is expected to be in units of "per second".
internal void
update(SimState* state, f64 dt)
{
For (state->bodies)
{
- if (rand() % 50 == 0)
+ /*if (rand() % 50 == 0)
{
it.vel = V2f{ randf(-50.0f, 50.0f), randf(-50.0f, 50.0f) };
- }
+ }*/
body_calculate_move(&it, state->bodies, dt);
}
}
glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(Body), (void *) offsetof(Body, pos.x));
glVertexAttribPointer(2, 1, GL_FLOAT, false, sizeof(Body), (void *) offsetof(Body, mass));
- glVertexAttribPointer(3, 1, GL_BYTE, false, sizeof(Body), (void *) offsetof(Body, color_idx));
+ glVertexAttribPointer(3, 1, GL_BYTE, false, sizeof(Body), (void *) offsetof(Body, body_type));
glBindBuffer(GL_ARRAY_BUFFER, -1);
}