feat(physics): physics entity now supports overlap

This commit is contained in:
Sara 2023-11-24 19:07:51 +01:00
parent 27d6c7e0d7
commit e7e952e57d
4 changed files with 62 additions and 19 deletions

View file

@ -81,9 +81,14 @@ void physics_entity_update(PhysicsEntity self) {
List* contacts = rigidbody_get_contacts(body); List* contacts = rigidbody_get_contacts(body);
if(contacts->len > 0) { if(contacts->len > 0) {
self.tc->collision_solver(self.data, contacts); if(rigidbody_get_overlap(body)) {
list_foreach(Contact*, contact, contacts) list_foreach(Contact*, contact, contacts)
self.tc->on_collision(self.data, contact->hit); self.tc->on_overlap(self.data, contact->hit.other);
} else {
self.tc->collision_solver(self.data, contacts);
list_foreach(Contact*, contact, contacts)
self.tc->on_collision(self.data, contact->hit);
}
} }
rigidbody_collect_contacts(body); rigidbody_collect_contacts(body);

View file

@ -8,15 +8,17 @@
typedef struct Collision Collision; typedef struct Collision Collision;
typedef struct RigidBody RigidBody; typedef struct RigidBody RigidBody;
typedef struct PhysicsEntity PhysicsEntity;
typedef struct { typedef struct IPhysicsEntity {
RigidBody* (*const get_rigidbody)(void* self); RigidBody* (*const get_rigidbody)(void* self);
Shape* (*const get_shape)(void* self); Shape* (*const get_shape)(void* self);
void(*const on_collision)(void* self, Collision collision); void(*const on_collision)(void* self, Collision collision);
void(*const on_overlap)(void* self, PhysicsEntity other);
void(*const collision_solver)(void* self, List* collisions); void(*const collision_solver)(void* self, List* collisions);
} IPhysicsEntity; } IPhysicsEntity;
typedef struct { typedef struct PhysicsEntity {
void* data; void* data;
IPhysicsEntity const* tc; IPhysicsEntity const* tc;
ITransformable const* transformable; ITransformable const* transformable;
@ -27,18 +29,20 @@ extern void physics_entity_solve_contacts(PhysicsEntity self, List* contacts);
extern void physics_entity_update(PhysicsEntity self); extern void physics_entity_update(PhysicsEntity self);
#define impl_PhysicsEntity_for(T, get_rigidbody_f, get_shape_f, on_collision_f, collision_solver_f)\ #define impl_PhysicsEntity_for(T, get_rigidbody_f, get_shape_f, on_collision_f, on_overlap_f, collision_solver_f)\
static inline PhysicsEntity T##_as_PhysicsEntity(T* x) {\ static inline PhysicsEntity T##_as_PhysicsEntity(T* x) {\
TC_FN_TYPECHECK(Transformable, T##_as_Transformable, T*);\ TC_FN_TYPECHECK(Transformable, T##_as_Transformable, T*);\
TC_FN_TYPECHECK(RigidBody*, get_rigidbody_f, T*);\ TC_FN_TYPECHECK(RigidBody*, get_rigidbody_f, T*);\
TC_FN_TYPECHECK(Shape*, get_shape_f, T*);\ TC_FN_TYPECHECK(Shape*, get_shape_f, T*);\
TC_FN_TYPECHECK(void, on_collision_f, T*, Collision);\ TC_FN_TYPECHECK(void, on_collision_f, T*, Collision);\
TC_FN_TYPECHECK(void, on_overlap_f, T*, PhysicsEntity);\
TC_FN_TYPECHECK(void, collision_solver_f, T*, List*);\ TC_FN_TYPECHECK(void, collision_solver_f, T*, List*);\
static IPhysicsEntity const tc = {\ static IPhysicsEntity const tc = {\
.get_rigidbody = (RigidBody*(*const)(void*)) get_rigidbody_f,\ .get_rigidbody = (RigidBody*(*const)(void*)) get_rigidbody_f,\
.get_shape = (Shape*(*const)(void*)) get_shape_f,\ .get_shape = (Shape*(*const)(void*)) get_shape_f,\
.on_collision = (void(*const)(void*,Collision)) on_collision_f,\ .on_collision = (void(*const)(void*,Collision)) on_collision_f,\
.collision_solver = (void(*const)(void*,List*)) collision_solver_f,\ .on_overlap = (void(*const)(void*,PhysicsEntity)) on_overlap_f\
.collision_solver = (void(*const)(void*,List*)) collision_solver_f,\
};\ };\
Transformable transformable = T##_as_Transformable(x);\ Transformable transformable = T##_as_Transformable(x);\
return (PhysicsEntity){.data = x, .tc = &tc, .transformable = transformable.tc};\ return (PhysicsEntity){.data = x, .tc = &tc, .transformable = transformable.tc};\

View file

@ -9,7 +9,6 @@ struct RigidBody {
Transformable transformable; Transformable transformable;
float mass; float mass;
float bounce; float bounce;
Vector last_linear_force; Vector last_linear_force;
@ -17,7 +16,10 @@ struct RigidBody {
Vector linear_velocity; Vector linear_velocity;
Transform internal_transform; Transform internal_transform;
int is_static; PhysicsMask layers;
PhysicsMask collision_mask;
int overlap;
List contacts; List contacts;
}; };
@ -36,7 +38,11 @@ RigidBody* rigidbody_make(Transformable transform) {
.internal_transform = *transform.tc->get_transform(transform.data), .internal_transform = *transform.tc->get_transform(transform.data),
.is_static = 0, .layers = 0x1,
.collision_mask = 0x1,
.overlap = 0,
.contacts = list_from_type(Contact), .contacts = list_from_type(Contact),
}; };
return self; return self;
@ -129,12 +135,28 @@ void rigidbody_accelerate(RigidBody* self, Vector force, int use_mass) {
self->next_linear_force = vaddf(self->next_linear_force, force); self->next_linear_force = vaddf(self->next_linear_force, force);
} }
int rigidbody_is_static(const RigidBody* self) { PhysicsMask rigidbody_get_layers(RigidBody* self) {
return self->is_static; return self->layers;
} }
void rigidbody_set_static(RigidBody* self, int is_static) { void rigidbody_set_layers(RigidBody* self, PhysicsMask layers) {
self->is_static = is_static; self->layers = layers;
}
PhysicsMask rigidbody_get_collision_mask(RigidBody* self) {
return self->collision_mask;
}
void rigidbody_set_collision_mask(RigidBody* self, PhysicsMask mask) {
self->collision_mask = mask;
}
int rigidbody_get_overlap(RigidBody* self) {
return self->overlap;
}
void rigidbody_set_overlap(RigidBody* self, int value) {
self->overlap = 1;
} }
Vector rigidbody_get_velocity(const RigidBody* self) { Vector rigidbody_get_velocity(const RigidBody* self) {

View file

@ -5,13 +5,19 @@
#include "transformable.h" #include "transformable.h"
#include "list.h" #include "list.h"
#include "collision.h" #include "collision.h"
#include "stdint.h"
typedef uint32_t PhysicsMask;
struct Collision; struct Collision;
typedef struct { typedef struct {
struct Collision hit; struct Collision hit;
float duration; float duration;
} Contact; } Contact;
typedef struct RigidBody RigidBody; typedef struct RigidBody RigidBody;
typedef struct PhysicsEntity PhysicsEntity;
typedef void (*CollisionHandlerFn)(void* obj, List* collisions); typedef void (*CollisionHandlerFn)(void* obj, List* collisions);
// Referenced transform is stored but not owned by the rigidbody. // Referenced transform is stored but not owned by the rigidbody.
@ -33,8 +39,14 @@ extern void rigidbody_set_bounce(RigidBody* self, float bounce);
extern void rigidbody_add_impulse(RigidBody* self, Vector force, int use_mass); extern void rigidbody_add_impulse(RigidBody* self, Vector force, int use_mass);
extern void rigidbody_accelerate(RigidBody* self, Vector force, int use_mass); extern void rigidbody_accelerate(RigidBody* self, Vector force, int use_mass);
extern int rigidbody_is_static(const RigidBody* self); extern PhysicsMask rigidbody_get_layers(RigidBody* self);
extern void rigidbody_set_static(RigidBody* self, int is_static); extern void rigidbody_set_layers(RigidBody* self, PhysicsMask layers);
extern PhysicsMask rigidbody_get_collision_mask(RigidBody* self);
extern void rigidbody_set_collision_mask(RigidBody* self, PhysicsMask mask);
extern int rigidbody_get_overlap(RigidBody* self);
extern void rigidbody_set_overlap(RigidBody* self, int value);
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);