improvements to collision solvers

This commit is contained in:
Sara 2023-10-19 13:51:17 +02:00
parent 169fd63d9e
commit aa9a51dc76
4 changed files with 40 additions and 40 deletions

View file

@ -20,7 +20,7 @@ void player_input_v(int val) {
void player_spawn(Player* self, Vector at) { void player_spawn(Player* self, Vector at) {
player_start(self); player_start(self);
self->transform.position = at; rigidbody_get_transform(self->rigidbody)->position = at;
} }
void player_start(Player* self) { void player_start(Player* self) {
@ -37,6 +37,7 @@ void player_start(Player* self) {
sprite_set_origin(self->sprite, (Vector){0.25f, 1.f}); sprite_set_origin(self->sprite, (Vector){0.25f, 1.f});
self->rigidbody = rigidbody_make(Player_as_Transformable(self)); self->rigidbody = rigidbody_make(Player_as_Transformable(self));
rigidbody_set_mass(self->rigidbody, 10.f);
float ex_w = 0.1f; float ex_w = 0.1f;
float h = .75f; float h = .75f;
@ -56,8 +57,10 @@ void player_start(Player* self) {
void player_update(Player* self, float dt) { void player_update(Player* self, float dt) {
Vector velocity = rigidbody_get_velocity(self->rigidbody); Vector velocity = rigidbody_get_velocity(self->rigidbody);
Vector velocity_target = {directional.x, velocity.y}; Vector velocity_target = {directional.x, velocity.y};
rigidbody_accelerate(self->rigidbody, vmulff(vsubf(velocity_target, velocity), 20.f)); rigidbody_accelerate(self->rigidbody, vmulff(vsubf(velocity_target, velocity), 20.f), 0);
rigidbody_accelerate(self->rigidbody, (Vector){0.0f, 20.f}); rigidbody_accelerate(self->rigidbody, (Vector){0.0f, 20.f}, 0);
LOG_INFO("%f %f", self->transform.position.x, self->transform.position.y);
} }
void player_collision(Player* self, Collision hit) { void player_collision(Player* self, Collision hit) {
@ -71,6 +74,10 @@ Transform* player_get_transform(Player* self) {
return &self->transform; return &self->transform;
} }
Transform* player_get_rigidbody_transform(Player* self) {
return rigidbody_get_transform(self->rigidbody);
}
RigidBody* player_get_rigidbody(Player* self) { RigidBody* player_get_rigidbody(Player* self) {
return self->rigidbody; return self->rigidbody;
} }

View file

@ -25,6 +25,7 @@ extern void player_collision(Player* self, Collision hit);
extern Sprite* player_get_sprite(Player* sprite); extern Sprite* player_get_sprite(Player* sprite);
extern Transform* player_get_transform(Player* self); extern Transform* player_get_transform(Player* self);
extern Transform* player_get_rigidbody_transform(Player* self);
extern RigidBody* player_get_rigidbody(Player* self); extern RigidBody* player_get_rigidbody(Player* self);
extern Shape* player_get_shape(Player* self); extern Shape* player_get_shape(Player* self);

View file

@ -51,7 +51,6 @@ void rigidbody_destroy(RigidBody* self) {
} }
void rigidbody_add_contact(RigidBody* self, Collision hit) { void rigidbody_add_contact(RigidBody* self, Collision hit) {
LOG_INFO("contact between rigidbody %p and %p detected", self->transformable.data, hit.other.data);
// update an existing contact // update an existing contact
list_foreach(Contact, contact, &self->contacts) { list_foreach(Contact, contact, &self->contacts) {
if(contact->hit.other.data == hit.other.data) { if(contact->hit.other.data == hit.other.data) {
@ -70,9 +69,6 @@ void rigidbody_add_contact(RigidBody* self, Collision hit) {
.hit = hit, .hit = hit,
.warming = delta_time() .warming = delta_time()
}); });
Contact* c = list_at(&self->contacts, self->contacts.len - 1);
LOG_INFO("added contact %p with exp %d", c->hit.other.data, c->expiry);
} }
static inline static inline
@ -81,13 +77,11 @@ void _internal_rigidbody_collect_contacts(RigidBody* self) {
Contact* contact = list_at(&self->contacts, i); Contact* contact = list_at(&self->contacts, i);
if(contact->expiry <= 0) { if(contact->expiry <= 0) {
if(vdotf(vnormalizedf(self->linear_velocity), contact->hit.normal) >= -0.01f || contact->expiry <= -1) { list_erase(&self->contacts, i);
list_erase(&self->contacts, i); i--;
i--; } else {
continue; --(contact->expiry);
}
} }
--(contact->expiry);
} }
} }
@ -113,21 +107,18 @@ Vector _internal_calculate_contact_force(RigidBody* self, Contact* contact) {
if(vsqrmagnitudef(hit.penetration_vector) < powf(0.01f, 2)) if(vsqrmagnitudef(hit.penetration_vector) < powf(0.01f, 2))
return ZeroVector; return ZeroVector;
const float d = vmagnitudef(hit.penetration_vector);
const float warming = fminf(1.f, contact->warming * 1000.f); const float k = 0.5f;
const float d = 1.0f; const float b = 0.5f;
const float k = 0.3f; const Vector velocity = hit.velocity;
const float b = 0.3f;
const Vector damping = vmulff(hit.normal, k * d); const Vector damping = vmulff(hit.normal, k * d);
const Vector bounce = vmulff(hit.normal, b * vdotf(hit.normal, hit.velocity)); const Vector bounce = vmulff(vmulff(hit.normal, b), vdotf(hit.normal, velocity));
float dot = -vdotf(contact->hit.normal, vaddf(self->next_linear_force, self->linear_velocity)); // float dot = -vdotf(contact->hit.normal, vaddf(hit.velocity, self->last_linear_force)) * 0.5f;
if(dot < 0) // dot = fmaxf(dot, 0.0f);
dot = 0; // Vector counter_force = vmulff(contact->hit.normal, dot * vmagnitudef(hit.penetration_vector) * self->mass);
Vector counter_force = vmulff(contact->hit.normal, dot * vsqrmagnitudef(hit.penetration_vector)); return vmulff(vsubf(damping, bounce), self->mass);
return vaddf(vmulff(vsubf(damping, bounce), warming), counter_force);
} }
static inline static inline
@ -142,14 +133,8 @@ void _internal_rigidbody_solve_contact(RigidBody* self, Contact* contact, Vector
Vector force = _internal_calculate_contact_force(self, contact); Vector force = _internal_calculate_contact_force(self, contact);
float dot = vdotf(vnormalizedf(*solve_forces), force); float dot = vdotf(vnormalizedf(*solve_forces), force);
if (veqf(*solve_forces, ZeroVector) || dot * dot > vsqrmagnitudef(*solve_forces) || dot <= 0.0f) { if (veqf(*solve_forces, ZeroVector) || dot * dot > vsqrmagnitudef(*solve_forces) || dot <= 0.0f) {
#if !NDEBUG
LOG_INFO("warming: %f", contact->warming);
LOG_INFO("force: %f %f", force.x, force.y);
LOG_INFO("dot: %f", dot);
LOG_INFO("mag: %f", vmagnitudef(self->next_linear_force));
#endif
*solve_forces = vaddf(*solve_forces, force); *solve_forces = vaddf(*solve_forces, force);
rigidbody_add_impulse(self, force); rigidbody_add_impulse(self, force, 1);
} }
ASSERT_RETURN(!visnanf(force), , "Force contains NaN (1)"); ASSERT_RETURN(!visnanf(force), , "Force contains NaN (1)");
@ -174,13 +159,12 @@ void _internal_rigidbody_integrate_forces(RigidBody* self) {
Vector position = self->internal_transform.position; Vector position = self->internal_transform.position;
Vector velocity = self->linear_velocity; Vector velocity = self->linear_velocity;
Vector acceleration = vmulff(self->last_linear_force, 0.5f * dt*dt); Vector acceleration = vmulff(self->last_linear_force, 0.5f * dt * dt);
position = vaddf(position, vmulff(velocity, dt)); position = vaddf(position, vmulff(velocity, dt));
position = vaddf(position, acceleration); position = vaddf(position, acceleration);
velocity = vaddf(velocity, acceleration); acceleration = vmulff(vaddf(self->next_linear_force, acceleration), dt * 0.5f);
acceleration = vmulff(self->next_linear_force, dt/2);
velocity = vaddf(velocity, acceleration); velocity = vaddf(velocity, acceleration);
self->linear_velocity = velocity; self->linear_velocity = velocity;
@ -205,11 +189,13 @@ void rigidbody_set_mass(RigidBody* self, float mass) {
self->mass = mass; self->mass = mass;
} }
void rigidbody_add_impulse(RigidBody* self, Vector force) { void rigidbody_add_impulse(RigidBody* self, Vector force, int use_mass) {
rigidbody_accelerate(self, vmulff(force, 1.0f/delta_time())); rigidbody_accelerate(self, vmulff(force, 1.0f/delta_time()), use_mass);
} }
void rigidbody_accelerate(RigidBody* self, Vector force) { void rigidbody_accelerate(RigidBody* self, Vector force, int use_mass) {
if(use_mass)
force = vmulff(force, 1.0f / self->mass);
if(vsqrmagnitudef(force) > powf(0.01f, 2)) if(vsqrmagnitudef(force) > powf(0.01f, 2))
self->next_linear_force = vaddf(self->next_linear_force, force); self->next_linear_force = vaddf(self->next_linear_force, force);
} }
@ -231,6 +217,10 @@ void rigidbody_set_velocity(RigidBody* self, Vector velocity) {
self->linear_velocity = velocity; self->linear_velocity = velocity;
} }
Vector rigidbody_get_force(RigidBody* self) {
return self->last_linear_force;
}
void rigidbody_debug_draw_contacts(RigidBody* self) { void rigidbody_debug_draw_contacts(RigidBody* self) {
list_foreach(Contact, contact, &self->contacts) { list_foreach(Contact, contact, &self->contacts) {
_internal_debug_draw_collision_edge(contact->hit.edge_left, contact->hit.edge_right, contact->hit.normal); _internal_debug_draw_collision_edge(contact->hit.edge_left, contact->hit.edge_right, contact->hit.normal);

View file

@ -21,8 +21,8 @@ extern void rigidbody_apply_physics(RigidBody* self);
extern float rigidbody_get_mass(const RigidBody* self); extern float rigidbody_get_mass(const RigidBody* self);
extern void rigidbody_set_mass(RigidBody* self, float mass); extern void rigidbody_set_mass(RigidBody* self, float mass);
extern void rigidbody_add_impulse(RigidBody* self, Vector force); extern void rigidbody_add_impulse(RigidBody* self, Vector force, int use_mass);
extern void rigidbody_accelerate(RigidBody* self, Vector force); extern void rigidbody_accelerate(RigidBody* self, Vector force, int use_mass);
extern int rigidbody_is_static(const RigidBody* self); extern int rigidbody_is_static(const RigidBody* self);
extern void rigidbody_set_static(RigidBody* self, int is_static); extern void rigidbody_set_static(RigidBody* self, int is_static);
@ -30,6 +30,8 @@ extern void rigidbody_set_static(RigidBody* self, int is_static);
extern Vector rigidbody_get_velocity(const RigidBody* self); extern Vector rigidbody_get_velocity(const RigidBody* self);
extern void rigidbody_set_velocity(RigidBody* self, Vector velocity); extern void rigidbody_set_velocity(RigidBody* self, Vector velocity);
extern Vector rigidbody_get_force(RigidBody* self);
extern void rigidbody_debug_draw_contacts(RigidBody* self); extern void rigidbody_debug_draw_contacts(RigidBody* self);
extern Transform* rigidbody_get_transform(RigidBody* self); extern Transform* rigidbody_get_transform(RigidBody* self);