separate physics logic from game.c
This commit is contained in:
parent
f4d8ec73e7
commit
0716ebd398
@ -20,6 +20,7 @@
|
||||
#include "draw.h"
|
||||
#include "math.h"
|
||||
#include "renderer.h"
|
||||
#include "phys.h"
|
||||
|
||||
struct exit_callback {
|
||||
app_exit_callback_func *func;
|
||||
@ -213,7 +214,8 @@ void app_entry_point(void)
|
||||
struct mixer_startup_receipt mixer_sr = mixer_startup();
|
||||
struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr);
|
||||
struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr);
|
||||
struct game_startup_receipt game_sr = game_startup(&mixer_sr, &sprite_sr, &sound_sr);
|
||||
struct phys_startup_receipt phys_sr = phys_startup();
|
||||
struct game_startup_receipt game_sr = game_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr);
|
||||
struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &game_sr, &asset_cache_sr, &mixer_sr, &window);
|
||||
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
|
||||
|
||||
|
||||
@ -852,6 +852,88 @@ struct collider_closest_points_result collider_closest_points(struct collider_sh
|
||||
return res;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Time of impact
|
||||
* ========================== */
|
||||
|
||||
/* Takes 2 shapes and their xforms at t=0 and t=1.
|
||||
* Returns time of impact in range [0, 1]. */
|
||||
f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1,
|
||||
struct xform xf0_t0, struct xform xf1_t0,
|
||||
struct xform xf0_t1, struct xform xf1_t1,
|
||||
f32 tolerance, u32 max_iterations)
|
||||
{
|
||||
f32 t0 = 0;
|
||||
f32 t1 = 1;
|
||||
f32 t0_sep = 0;
|
||||
f32 t1_sep = 0;
|
||||
f32 t = 0;
|
||||
f32 t_sep = F32_INFINITY;
|
||||
|
||||
/* Find direction p0 -> p1 at t=0 */
|
||||
struct v2 dir;
|
||||
struct v2 dir_neg;
|
||||
{
|
||||
struct collider_closest_points_result closest_points_res = collider_closest_points(c0, c1, xf0_t0, xf1_t0);
|
||||
if (closest_points_res.colliding) {
|
||||
/* Shapes are penetrating at t=0 */
|
||||
return 0;
|
||||
}
|
||||
dir = v2_sub(closest_points_res.p1, closest_points_res.p0);
|
||||
t0_sep = v2_len(dir);
|
||||
dir = v2_div(dir, t0_sep); /* Normalize */
|
||||
dir_neg = v2_neg(dir);
|
||||
}
|
||||
|
||||
{
|
||||
struct v2 p0 = collider_support_point(c0, xf0_t1, dir);
|
||||
struct v2 p1 = collider_support_point(c1, xf1_t1, dir_neg);
|
||||
t1_sep = v2_dot(dir, v2_sub(p1, p0));
|
||||
if (t1_sep > 0) {
|
||||
/* Shapes are not penetrating at t=1 */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
u32 iteration = 0;
|
||||
while (math_fabs(t_sep) > tolerance) {
|
||||
if (iteration >= max_iterations) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Use mix of bisection & false position method to find root
|
||||
* (as described in https://box2d.org/files/ErinCatto_ContinuousCollision_GDC2013.pdf) */
|
||||
if (iteration & 1) {
|
||||
/* Bisect */
|
||||
t = (t1 + t0) / 2.0;
|
||||
} else {
|
||||
/* False position (fastest for linear case) */
|
||||
f32 m = (t1_sep - t0_sep) / (t1 - t0);
|
||||
t = (-t1_sep / m) + t1;
|
||||
}
|
||||
|
||||
struct xform xf0 = xform_lerp(xf0_t0, xf0_t1, t);
|
||||
struct xform xf1 = xform_lerp(xf1_t0, xf1_t1, t);
|
||||
|
||||
struct v2 p0 = collider_support_point(c0, xf0, dir);
|
||||
struct v2 p1 = collider_support_point(c1, xf1, dir_neg);
|
||||
t_sep = v2_dot(dir, v2_sub(p1, p0));
|
||||
|
||||
/* Update bracket */
|
||||
if (t_sep > 0) {
|
||||
t0 = t;
|
||||
t0_sep = t_sep;
|
||||
} else {
|
||||
t1 = t;
|
||||
t1_sep = t_sep;
|
||||
}
|
||||
|
||||
++iteration;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Debug functions
|
||||
* TODO: Remove these
|
||||
|
||||
@ -5,13 +5,6 @@
|
||||
extern u32 collider_debug_steps;
|
||||
#endif
|
||||
|
||||
struct v2 collider_support_point(struct collider_shape *a, struct xform xf, struct v2 dir);
|
||||
|
||||
#if 0
|
||||
/* Returns simple true or false indicating shape collision */
|
||||
b32 collider_collision_boolean(struct collider_shape *shape0, struct collider_shape *shape1);
|
||||
#endif
|
||||
|
||||
struct collider_menkowski_point {
|
||||
struct v2 p; /* Menkowski difference point */
|
||||
struct v2 s0; /* Support point of first shape in dir */
|
||||
@ -47,8 +40,6 @@ struct collider_collision_points_result {
|
||||
struct v2 a0, b0, a1, b1; /* Clipping faces */
|
||||
};
|
||||
|
||||
struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
||||
|
||||
struct collider_closest_points_result {
|
||||
struct v2 p0, p1;
|
||||
b32 colliding;
|
||||
@ -59,8 +50,14 @@ struct collider_closest_points_result {
|
||||
struct collider_prototype prototype;
|
||||
};
|
||||
|
||||
struct v2 collider_support_point(struct collider_shape *a, struct xform xf, struct v2 dir);
|
||||
|
||||
struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
||||
|
||||
struct collider_closest_points_result collider_closest_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
||||
|
||||
f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1, struct xform xf0_t0, struct xform xf1_t0, struct xform xf0_t1, struct xform xf1_t1, f32 tolerance, u32 max_iterations);
|
||||
|
||||
struct v2_array menkowski(struct arena *arena, struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, u32 detail);
|
||||
struct v2_array cloud(struct arena *arena, struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
||||
|
||||
|
||||
@ -491,6 +491,11 @@ struct renderer_handle {
|
||||
u64 v[1];
|
||||
};
|
||||
|
||||
struct entity_handle {
|
||||
u64 idx;
|
||||
u64 gen;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Tag structs
|
||||
* ========================== */
|
||||
|
||||
122
src/entity.c
122
src/entity.c
@ -397,3 +397,125 @@ void entity_unlink_parent(struct entity *ent)
|
||||
ent->prev = entity_nil_handle();
|
||||
ent->next = entity_nil_handle();
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Entity lookup
|
||||
* ========================== */
|
||||
|
||||
struct entity_lookup entity_lookup_alloc(u64 num_buckets)
|
||||
{
|
||||
ASSERT(num_buckets > 0);
|
||||
struct entity_lookup l = ZI;
|
||||
l.arena = arena_alloc(GIGABYTE(64));
|
||||
l.buckets = arena_push_array_zero(&l.arena, struct entity_lookup_bucket, num_buckets);
|
||||
l.num_buckets = num_buckets;
|
||||
return l;
|
||||
}
|
||||
|
||||
void entity_lookup_release(struct entity_lookup *l)
|
||||
{
|
||||
arena_release(&l->arena);
|
||||
}
|
||||
|
||||
struct entity_lookup_entry *entity_lookup_get(struct entity_lookup *l, struct entity_lookup_key key)
|
||||
{
|
||||
u64 index = key.hash % l->num_buckets;
|
||||
struct entity_lookup_bucket *bucket = &l->buckets[index];
|
||||
struct entity_lookup_entry *res = NULL;
|
||||
for (struct entity_lookup_entry *e = bucket->first; e; e = e->next) {
|
||||
if (e->key.hash == key.hash) {
|
||||
res = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void entity_lookup_set(struct entity_lookup *l, struct entity_lookup_key key, struct entity_handle handle)
|
||||
{
|
||||
u64 index = key.hash % l->num_buckets;
|
||||
struct entity_lookup_bucket *bucket = &l->buckets[index];
|
||||
|
||||
struct entity_lookup_entry *prev = NULL;
|
||||
struct entity_lookup_entry **slot = &bucket->first;
|
||||
while (*slot) {
|
||||
if ((*slot)->key.hash == key.hash) {
|
||||
break;
|
||||
}
|
||||
prev = *slot;
|
||||
slot = &(*slot)->next;
|
||||
}
|
||||
|
||||
struct entity_lookup_entry *entry = *slot;
|
||||
if (entry) {
|
||||
/* Set existing entry */
|
||||
entry->entity = handle;
|
||||
} else {
|
||||
/* Allocate entry */
|
||||
if (l->first_free_entry) {
|
||||
entry = l->first_free_entry;
|
||||
l->first_free_entry->prev = NULL;
|
||||
l->first_free_entry = entry->next;
|
||||
} else {
|
||||
entry = arena_push(&l->arena, struct entity_lookup_entry);
|
||||
}
|
||||
MEMZERO_STRUCT(entry);
|
||||
|
||||
entry->key = key;
|
||||
entry->entity = handle;
|
||||
if (prev) {
|
||||
entry->prev = prev;
|
||||
prev->next = entry;
|
||||
}
|
||||
|
||||
bucket->last = entry;
|
||||
*slot = entry;
|
||||
}
|
||||
}
|
||||
|
||||
void entity_lookup_remove(struct entity_lookup *l, struct entity_lookup_entry *entry)
|
||||
{
|
||||
struct entity_lookup_bucket *bucket = &l->buckets[entry->key.hash % l->num_buckets];
|
||||
struct entity_lookup_entry *prev = entry->prev;
|
||||
struct entity_lookup_entry *next = entry->next;
|
||||
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
} else {
|
||||
bucket->first = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
} else {
|
||||
bucket->last = prev;
|
||||
}
|
||||
|
||||
if (l->first_free_entry) {
|
||||
l->first_free_entry->prev = entry;
|
||||
}
|
||||
entry->next = l->first_free_entry;
|
||||
entry->prev = NULL;
|
||||
l->first_free_entry = entry;
|
||||
}
|
||||
|
||||
struct entity_lookup_key entity_lookup_key_from_two_handles(struct entity_handle h0, struct entity_handle h1)
|
||||
{
|
||||
struct entity_lookup_key key = ZI;
|
||||
struct buffer b0 = BUFFER_FROM_STRUCT(&h0);
|
||||
struct buffer b1 = BUFFER_FROM_STRUCT(&h1);
|
||||
key.hash = hash_fnv64(HASH_FNV64_BASIS, b0);
|
||||
key.hash = hash_fnv64(key.hash, b1);
|
||||
return key;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Activate
|
||||
* ========================== */
|
||||
|
||||
void entity_activate(struct entity *ent, u64 current_tick_id)
|
||||
{
|
||||
entity_enable_prop(ent, ENTITY_PROP_ACTIVE);
|
||||
ent->activation_tick = current_tick_id;
|
||||
++ent->continuity_gen;
|
||||
}
|
||||
|
||||
202
src/entity.h
202
src/entity.h
@ -3,6 +3,7 @@
|
||||
|
||||
#include "sprite.h"
|
||||
#include "mixer.h"
|
||||
#include "phys.h"
|
||||
|
||||
enum entity_prop {
|
||||
ENTITY_PROP_NONE,
|
||||
@ -44,11 +45,6 @@ enum entity_prop {
|
||||
ENTITY_PROP_COUNT
|
||||
};
|
||||
|
||||
struct entity_handle {
|
||||
u64 idx;
|
||||
u64 gen;
|
||||
};
|
||||
|
||||
struct entity_store {
|
||||
struct arena arena;
|
||||
u64 allocated;
|
||||
@ -58,154 +54,29 @@ struct entity_store {
|
||||
struct entity *entities;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: Remove this */
|
||||
#include "collider.h"
|
||||
#include "math.h"
|
||||
|
||||
struct contact_point {
|
||||
/* Contact point in local space of each entity */
|
||||
struct v2 point_local_e0;
|
||||
struct v2 point_local_e1;
|
||||
|
||||
u32 id; /* ID generated during clipping */
|
||||
f32 starting_separation; /* How far are original points along normal */
|
||||
f32 normal_impulse; /* Accumulated impulse along normal */
|
||||
f32 tangent_impulse; /* Accumulated impulse along tangent */
|
||||
|
||||
f32 inv_normal_mass;
|
||||
f32 inv_tangent_mass;
|
||||
|
||||
/* Debugging */
|
||||
struct v2 dbg_pt;
|
||||
struct entity_lookup_key {
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
struct contact_constraint {
|
||||
u64 last_updated_tick; /* To avoid checking collisions for the same constraint twice in one tick */
|
||||
b32 skip_solve;
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
f32 inv_i1;
|
||||
|
||||
struct v2 normal; /* Normal vector of collision from e0 -> e1 */
|
||||
u64 last_iteration;
|
||||
struct contact_point points[2];
|
||||
u32 num_points;
|
||||
|
||||
f32 friction;
|
||||
|
||||
struct math_spring_result softness;
|
||||
f32 pushout_velocity;
|
||||
struct entity_lookup_entry {
|
||||
struct entity_lookup_key key;
|
||||
struct entity_handle entity;
|
||||
struct entity_lookup_entry *next;
|
||||
struct entity_lookup_entry *prev;
|
||||
};
|
||||
|
||||
struct collision_debug {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
struct collider_collision_points_result res;
|
||||
|
||||
struct contact_point points[2];
|
||||
u32 num_points;
|
||||
|
||||
struct v2 closest0;
|
||||
struct v2 closest1;
|
||||
|
||||
struct xform xf0;
|
||||
struct xform xf1;
|
||||
struct entity_lookup_bucket {
|
||||
struct entity_lookup_entry *first;
|
||||
struct entity_lookup_entry *last;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct motor_joint_def {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
struct entity_lookup {
|
||||
struct arena arena;
|
||||
struct entity_lookup_bucket *buckets;
|
||||
u64 num_buckets;
|
||||
struct entity_lookup_entry *first_free_entry;
|
||||
};
|
||||
|
||||
struct motor_joint {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
f32 inv_i1;
|
||||
|
||||
struct v2 linear_impulse;
|
||||
f32 angular_impulse;
|
||||
|
||||
struct v2 point_local_e0;
|
||||
struct v2 point_local_e1;
|
||||
|
||||
struct xform linear_mass_xf;
|
||||
f32 angular_mass;
|
||||
};
|
||||
|
||||
INLINE struct motor_joint motor_joint_from_def(struct motor_joint_def def)
|
||||
{
|
||||
struct motor_joint res = ZI;
|
||||
res.e0 = def.e0;
|
||||
res.e1 = def.e1;
|
||||
res.correction_rate = clamp_f32(def.correction_rate, 0, 1);
|
||||
res.max_force = def.max_force;
|
||||
res.max_torque = def.max_torque;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct mouse_joint {
|
||||
struct entity_handle target;
|
||||
struct v2 point_local_start;
|
||||
struct v2 point_local_end;
|
||||
struct math_spring_result linear_softness;
|
||||
struct math_spring_result angular_softness;
|
||||
f32 max_force;
|
||||
|
||||
f32 inv_m;
|
||||
f32 inv_i;
|
||||
|
||||
struct v2 linear_impulse;
|
||||
f32 angular_impulse;
|
||||
|
||||
struct xform linear_mass_xf;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct hit_event {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
struct v2 point;
|
||||
struct v2 normal;
|
||||
struct v2 vrel; /* Relative velocity */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct entity {
|
||||
/* ====================================================================== */
|
||||
/* Metadata */
|
||||
@ -229,50 +100,38 @@ struct entity {
|
||||
struct entity_handle first;
|
||||
struct entity_handle last;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: Remove this (testing) */
|
||||
i32 colliding;
|
||||
struct collision_debug collision_debug_data;
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Collider */
|
||||
|
||||
struct collider_shape local_collider;
|
||||
|
||||
#if COLLIDER_DEBUG
|
||||
i32 colliding;
|
||||
struct phys_collision_debug collision_debug_data;
|
||||
#endif
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Contact constraint */
|
||||
|
||||
/* ENTITY_PROP_CONSTRAINT_CONTACT */
|
||||
struct contact_constraint contact_constraint_data;
|
||||
struct phys_contact_constraint contact_constraint_data;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Motor joint */
|
||||
|
||||
/* ENTITY_PROP_MOTOR_JOINT */
|
||||
struct motor_joint motor_joint_data;
|
||||
struct phys_motor_joint motor_joint_data;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Mouse joint */
|
||||
|
||||
/* ENTITY_PROP_MOUSE_JOINT */
|
||||
struct mouse_joint mouse_joint_data;
|
||||
struct phys_mouse_joint mouse_joint_data;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Hit event */
|
||||
|
||||
struct hit_event hit_event;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct phys_hit_event hit_event;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Activation */
|
||||
@ -503,4 +362,15 @@ struct entity *entity_find_first_match_all(struct entity_store *store, struct en
|
||||
void entity_link_parent(struct entity *parent, struct entity *child);
|
||||
void entity_unlink_parent(struct entity *ent);
|
||||
|
||||
/* Lookup */
|
||||
struct entity_lookup entity_lookup_alloc(u64 num_buckets);
|
||||
void entity_lookup_release(struct entity_lookup *l);
|
||||
struct entity_lookup_entry *entity_lookup_get(struct entity_lookup *l, struct entity_lookup_key key);
|
||||
void entity_lookup_set(struct entity_lookup *l, struct entity_lookup_key key, struct entity_handle handle);
|
||||
void entity_lookup_remove(struct entity_lookup *l, struct entity_lookup_entry *entry);
|
||||
struct entity_lookup_key entity_lookup_key_from_two_handles(struct entity_handle h0, struct entity_handle h1);
|
||||
|
||||
/* Activate */
|
||||
void entity_activate(struct entity *ent, u64 current_tick_id);
|
||||
|
||||
#endif
|
||||
|
||||
1459
src/game.c
1459
src/game.c
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ struct world;
|
||||
struct mixer_startup_receipt;
|
||||
struct sprite_startup_receipt;
|
||||
struct sound_startup_receipt;
|
||||
struct phys_startup_receipt;
|
||||
|
||||
enum game_cmd_state {
|
||||
GAME_CMD_STATE_STOP = -1,
|
||||
@ -53,7 +54,8 @@ struct game_cmd_array {
|
||||
struct game_startup_receipt { i32 _; };
|
||||
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
||||
struct sprite_startup_receipt *sheet_sr,
|
||||
struct sound_startup_receipt *sound_sr);
|
||||
struct sound_startup_receipt *sound_sr,
|
||||
struct phys_startup_receipt *phys_sr);
|
||||
|
||||
void game_get_latest_tick(struct world *dest);
|
||||
u64 game_get_latest_tick_id(void);
|
||||
|
||||
1134
src/phys.c
Normal file
1134
src/phys.c
Normal file
File diff suppressed because it is too large
Load Diff
171
src/phys.h
Normal file
171
src/phys.h
Normal file
@ -0,0 +1,171 @@
|
||||
#ifndef PHYS_H
|
||||
#define PHYS_H
|
||||
|
||||
#include "collider.h"
|
||||
#include "math.h"
|
||||
|
||||
struct entity_store;
|
||||
struct entity_lookup;
|
||||
|
||||
struct phys_hit_event {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
struct v2 point;
|
||||
struct v2 normal;
|
||||
struct v2 vrel; /* Relative velocity */
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
struct phys_startup_receipt { i32 _; };
|
||||
struct phys_startup_receipt phys_startup(void);
|
||||
|
||||
/* ========================== *
|
||||
* Contact
|
||||
* ========================== */
|
||||
|
||||
struct phys_contact_point {
|
||||
/* Contact point in local space of each entity */
|
||||
struct v2 point_local_e0;
|
||||
struct v2 point_local_e1;
|
||||
|
||||
u32 id; /* ID generated during clipping */
|
||||
f32 starting_separation; /* How far are original points along normal */
|
||||
f32 normal_impulse; /* Accumulated impulse along normal */
|
||||
f32 tangent_impulse; /* Accumulated impulse along tangent */
|
||||
|
||||
f32 inv_normal_mass;
|
||||
f32 inv_tangent_mass;
|
||||
|
||||
/* Debugging */
|
||||
struct v2 dbg_pt;
|
||||
};
|
||||
|
||||
struct phys_contact_constraint {
|
||||
u64 last_updated_tick; /* To avoid checking collisions for the same constraint twice in one tick */
|
||||
b32 skip_solve;
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
f32 inv_i1;
|
||||
|
||||
struct v2 normal; /* Normal vector of collision from e0 -> e1 */
|
||||
u64 last_iteration;
|
||||
struct phys_contact_point points[2];
|
||||
u32 num_points;
|
||||
|
||||
f32 friction;
|
||||
|
||||
struct math_spring_result softness;
|
||||
f32 pushout_velocity;
|
||||
};
|
||||
|
||||
struct phys_collision_debug {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
struct collider_collision_points_result res;
|
||||
|
||||
struct phys_contact_point points[2];
|
||||
u32 num_points;
|
||||
|
||||
struct v2 closest0;
|
||||
struct v2 closest1;
|
||||
|
||||
struct xform xf0;
|
||||
struct xform xf1;
|
||||
};
|
||||
|
||||
void phys_create_contacts(struct entity_store *store, struct entity_lookup *contact_lookup, struct entity_lookup *debug_lookup, u64 tick_id);
|
||||
void phys_prepare_contacts(struct entity_store *store, struct entity_lookup *contact_lookup, struct entity_lookup *debug_lookup);
|
||||
void phys_warm_start_contacts(struct entity_store *store);
|
||||
void phys_solve_contacts(struct entity_store *store, f32 dt, b32 apply_bias);
|
||||
|
||||
/* ========================== *
|
||||
* Motor joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_motor_joint_def {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
};
|
||||
|
||||
struct phys_motor_joint {
|
||||
struct entity_handle e0;
|
||||
struct entity_handle e1;
|
||||
f32 correction_rate;
|
||||
f32 max_force;
|
||||
f32 max_torque;
|
||||
|
||||
f32 inv_m0;
|
||||
f32 inv_m1;
|
||||
f32 inv_i0;
|
||||
f32 inv_i1;
|
||||
|
||||
struct v2 linear_impulse;
|
||||
f32 angular_impulse;
|
||||
|
||||
struct v2 point_local_e0;
|
||||
struct v2 point_local_e1;
|
||||
|
||||
struct xform linear_mass_xf;
|
||||
f32 angular_mass;
|
||||
};
|
||||
|
||||
struct phys_motor_joint motor_joint_from_def(struct phys_motor_joint_def def);
|
||||
void phys_prepare_motor_joints(struct entity_store *store);
|
||||
void phys_warm_start_motor_joints(struct entity_store *store);
|
||||
void phys_solve_motor_joints(struct entity_store *store, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Mouse joint
|
||||
* ========================== */
|
||||
|
||||
struct phys_mouse_joint {
|
||||
struct entity_handle target;
|
||||
struct v2 point_local_start;
|
||||
struct v2 point_local_end;
|
||||
struct math_spring_result linear_softness;
|
||||
struct math_spring_result angular_softness;
|
||||
f32 max_force;
|
||||
|
||||
f32 inv_m;
|
||||
f32 inv_i;
|
||||
|
||||
struct v2 linear_impulse;
|
||||
f32 angular_impulse;
|
||||
|
||||
struct xform linear_mass_xf;
|
||||
};
|
||||
|
||||
void phys_create_mouse_joints(struct entity_store *store, struct v2 cursor, b32 start_dragging, b32 stop_dragging);
|
||||
void phys_prepare_mouse_joints(struct entity_store *store);
|
||||
void phys_warm_start_mouse_joints(struct entity_store *store);
|
||||
void phys_solve_mouse_joints(struct entity_store *store, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Earliest time of impact
|
||||
* ========================== */
|
||||
|
||||
f32 phys_determine_earliest_toi_for_bullets(struct entity_store *store, f32 step_dt, f32 tolerance, u32 max_iterations);
|
||||
|
||||
/* ========================== *
|
||||
* Integration
|
||||
* ========================== */
|
||||
|
||||
void phys_integrate_forces(struct entity_store *store, f32 dt);
|
||||
void phys_integrate_velocities(struct entity_store *store, f32 dt);
|
||||
|
||||
/* ========================== *
|
||||
* Step
|
||||
* ========================== */
|
||||
|
||||
void phys_step(struct entity_store *store, f32 step_dt, struct entity_lookup *contact_lookup, struct entity_lookup *collision_debug_lookup, u64 tick_id, struct v2 dbg_cursor_pos, b32 dbg_start_dragging, b32 dbg_stop_dragging);
|
||||
|
||||
#endif
|
||||
@ -1072,11 +1072,11 @@ INTERNAL void user_update(void)
|
||||
/* Draw constraint */
|
||||
#if 1
|
||||
if (entity_has_prop(ent, ENTITY_PROP_COLLISION_DEBUG)) {
|
||||
struct collision_debug *data = &ent->collision_debug_data;
|
||||
struct phys_collision_debug *data = &ent->collision_debug_data;
|
||||
struct collider_collision_points_result collider_res = data->res;
|
||||
|
||||
//struct contact_constraint *data = &entity_from_handle(store, data->contact_constraint_ent)->contact_constraint_data;
|
||||
//struct contact_constraint *data = &data->contact_constraint_data;
|
||||
//struct phys_contact_constraint *data = &entity_from_handle(store, data->contact_constraint_ent)->contact_constraint_data;
|
||||
//struct phys_contact_constraint *data = &data->contact_constraint_data;
|
||||
struct entity *e0 = entity_from_handle(store, data->e0);
|
||||
struct entity *e1 = entity_from_handle(store, data->e1);
|
||||
struct collider_shape e0_collider = e0->local_collider;
|
||||
@ -1216,7 +1216,7 @@ INTERNAL void user_update(void)
|
||||
{
|
||||
f32 radius = 5;
|
||||
for (u32 i = 0; i < data->num_points; ++i) {
|
||||
struct contact_point point = data->points[i];
|
||||
struct phys_contact_point point = data->points[i];
|
||||
#if 0
|
||||
struct v2 p0 = xform_mul_v2(e0_xf, contact.point_local_e0);
|
||||
struct v2 p1 = xform_mul_v2(e1_xf, contact.point_local_e1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user