create ground friction joint dynamically
This commit is contained in:
parent
bfa1f1e065
commit
152656fbc5
@ -37,11 +37,8 @@
|
|||||||
#define GAME_PHYSICS_ENABLE_RELAXATION 1
|
#define GAME_PHYSICS_ENABLE_RELAXATION 1
|
||||||
|
|
||||||
#define USER_DRAW_MENKOWSKI 0
|
#define USER_DRAW_MENKOWSKI 0
|
||||||
#define GAME_PHYSICS_ENABLE_GROUND_FRICTION 1
|
|
||||||
#define GAME_PHYSICS_ENABLE_COLLISION 1
|
#define GAME_PHYSICS_ENABLE_COLLISION 1
|
||||||
#define GAME_SPAWN_LOTS 0
|
|
||||||
#define GAME_SPAWN_TESTENT 0
|
#define GAME_SPAWN_TESTENT 0
|
||||||
#define GAME_SPAWN_BOX 0
|
|
||||||
#define GAME_PLAYER_AIM 1
|
#define GAME_PLAYER_AIM 1
|
||||||
|
|
||||||
//#define GAME_MAX_LINEAR_VELOCITY 500
|
//#define GAME_MAX_LINEAR_VELOCITY 500
|
||||||
|
|||||||
@ -282,6 +282,7 @@ struct entity {
|
|||||||
f32 mass_unscaled; /* Mass of entity in kg before any transformations */
|
f32 mass_unscaled; /* Mass of entity in kg before any transformations */
|
||||||
f32 inertia_unscaled; /* Inertia of entity in kg*m^2 before any transformations */
|
f32 inertia_unscaled; /* Inertia of entity in kg*m^2 before any transformations */
|
||||||
|
|
||||||
|
struct entity_handle ground_friction_joint;
|
||||||
f32 linear_ground_friction;
|
f32 linear_ground_friction;
|
||||||
f32 angular_ground_friction;
|
f32 angular_ground_friction;
|
||||||
|
|
||||||
|
|||||||
236
src/game.c
236
src/game.c
@ -296,18 +296,12 @@ INTERNAL void reset_world(void)
|
|||||||
|
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
|
|
||||||
INTERNAL void spawn_test_entities(f32 offset)
|
INTERNAL void spawn_test_entities(void)
|
||||||
{
|
{
|
||||||
struct entity *root = entity_from_handle(G.tick.entity_store, G.tick.entity_store->root);
|
struct entity *root = entity_from_handle(G.tick.entity_store, G.tick.entity_store->root);
|
||||||
root->mass_unscaled = F32_INFINITY;
|
root->mass_unscaled = F32_INFINITY;
|
||||||
root->inertia_unscaled = F32_INFINITY;
|
root->inertia_unscaled = F32_INFINITY;
|
||||||
|
|
||||||
//const f32 offset_all = -20000;
|
|
||||||
//const f32 offset_all = -5000;
|
|
||||||
const f32 offset_all = 0;
|
|
||||||
(UNUSED)offset;
|
|
||||||
(UNUSED)offset_all;
|
|
||||||
|
|
||||||
/* Player */
|
/* Player */
|
||||||
struct entity *player_ent = entity_nil();
|
struct entity *player_ent = entity_nil();
|
||||||
//if (!G.extra_spawn) {
|
//if (!G.extra_spawn) {
|
||||||
@ -317,9 +311,6 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
|
|
||||||
struct v2 pos = V2(1, -1);
|
struct v2 pos = V2(1, -1);
|
||||||
|
|
||||||
pos = v2_add(pos, V2(0, offset));
|
|
||||||
pos = v2_add(pos, V2(0, offset_all));
|
|
||||||
|
|
||||||
//struct v2 size = V2(0.5, 0.5);
|
//struct v2 size = V2(0.5, 0.5);
|
||||||
//struct v2 size = V2(0.5, 0.25);
|
//struct v2 size = V2(0.5, 0.25);
|
||||||
struct v2 size = V2(1.0, 1.0);
|
struct v2 size = V2(1.0, 1.0);
|
||||||
@ -350,13 +341,13 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
//e->sprite_span_name = STR("idle.one_handed");
|
//e->sprite_span_name = STR("idle.one_handed");
|
||||||
e->sprite_span_name = STR("idle.two_handed");
|
e->sprite_span_name = STR("idle.two_handed");
|
||||||
|
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
//xf.bx.y = -1.f;
|
//xf.bx.y = -1.f;
|
||||||
|
|
||||||
entity_set_xform(e, xf);
|
entity_set_xform(e, xf);
|
||||||
|
|
||||||
e->linear_ground_friction = 250;e->angular_ground_friction = 200;
|
e->linear_ground_friction = 250;
|
||||||
|
e->angular_ground_friction = 200;
|
||||||
|
|
||||||
//e->control_force = 500;
|
//e->control_force = 500;
|
||||||
e->control_force = 500;
|
e->control_force = 500;
|
||||||
@ -367,99 +358,11 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
|
entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
|
||||||
|
|
||||||
player_ent = e;
|
player_ent = e;
|
||||||
|
|
||||||
#if 1
|
|
||||||
{
|
|
||||||
struct entity *joint_ent = entity_alloc(root);
|
|
||||||
entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL);
|
|
||||||
entity_enable_prop(joint_ent, ENTITY_PROP_MOTOR_JOINT);
|
|
||||||
entity_enable_prop(joint_ent, ENTITY_PROP_ACTIVE);
|
|
||||||
|
|
||||||
struct motor_joint_def def = ZI;
|
|
||||||
def.e0 = root->handle;
|
|
||||||
def.e1 = e->handle;
|
|
||||||
def.correction_rate = 0;
|
|
||||||
def.max_force = e->linear_ground_friction;
|
|
||||||
def.max_torque = e->angular_ground_friction;
|
|
||||||
joint_ent->motor_joint_data = motor_joint_from_def(def);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GAME_SPAWN_TESTENT
|
/* Player weapon */
|
||||||
{
|
|
||||||
struct entity *e = entity_alloc(root);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
//struct v2 pos = V2(0.25, -10);
|
|
||||||
//struct v2 pos = V2(0.25, -7);
|
|
||||||
//struct v2 pos = V2(0.25, -5.27);
|
|
||||||
struct v2 pos = V2(0.5, -1);
|
|
||||||
|
|
||||||
pos = v2_add(pos, V2(0, offset));
|
|
||||||
pos = v2_add(pos, V2(0, offset_all));
|
|
||||||
|
|
||||||
//struct v2 size = V2(1, 1);
|
|
||||||
struct v2 size = V2(0.5, 0.5);
|
|
||||||
//struct v2 size = V2(1.0, 0.5);
|
|
||||||
//f32 r = PI;
|
|
||||||
//f32 r = PI / 4;
|
|
||||||
//f32 r = PI / 3;
|
|
||||||
//f32 r = 0.05;
|
|
||||||
//f32 r = PI / 2;
|
|
||||||
f32 r = 0;
|
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
|
||||||
#else
|
|
||||||
struct xform xf = { .bx = {-0.108915359, -0.488007843}, .by = {0.488007843, -0.108915359}, .og = {1.62569654, -0.750172377}, };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
entity_set_xform(e, xf);
|
|
||||||
|
|
||||||
//e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/box.ase"));
|
|
||||||
//e->sprite_span_name = STR("idle.unarmed");
|
|
||||||
//e->sprite_span_name = STR("idle.one_handed");
|
|
||||||
e->sprite_span_name = STR("idle.two_handed");
|
|
||||||
|
|
||||||
//entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
|
||||||
//e->control_force = 4500;
|
|
||||||
//e->control_force = 1200;
|
|
||||||
e->control_force = 250;
|
|
||||||
e->control_torque = 10;
|
|
||||||
e->control.focus = V2(0, -1);
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
|
|
||||||
e->mass_unscaled = 100;
|
|
||||||
//e->inertia_unscaled = F32_INFINITY;
|
|
||||||
e->inertia_unscaled = 25;
|
|
||||||
e->linear_ground_friction = 1000;
|
|
||||||
e->angular_ground_friction = 100;
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_TEST);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Weapon */
|
|
||||||
#if 1
|
|
||||||
if (player_ent->valid) {
|
if (player_ent->valid) {
|
||||||
#if 0
|
|
||||||
struct v2 pos = V2(1, 0);
|
|
||||||
struct v2 size = V2(1, 1);
|
|
||||||
f32 r = PI / 4;
|
|
||||||
struct entity *e = entity_alloc(root);
|
|
||||||
#else
|
|
||||||
struct entity *e = entity_alloc(player_ent);
|
struct entity *e = entity_alloc(player_ent);
|
||||||
#endif
|
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase"));
|
e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase"));
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_ATTACHED);
|
entity_enable_prop(e, ENTITY_PROP_ATTACHED);
|
||||||
@ -470,44 +373,6 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
|
|
||||||
player_ent->equipped = e->handle;
|
player_ent->equipped = e->handle;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Box */
|
|
||||||
#if GAME_SPAWN_BOX
|
|
||||||
if (!G.extra_spawn) {
|
|
||||||
struct v2 pos = V2(0.5, 0);
|
|
||||||
//struct v2 pos = V2(0.5, 29);
|
|
||||||
//struct v2 pos = V2(0.5, 24);
|
|
||||||
//struct v2 pos = V2(1, -1);
|
|
||||||
#if 0
|
|
||||||
struct v2 size = V2(1, 1);
|
|
||||||
#else
|
|
||||||
//struct v2 size = V2(5000, 1);
|
|
||||||
struct v2 size = V2(50, 1);
|
|
||||||
//struct v2 size = V2(1, 1);
|
|
||||||
#endif
|
|
||||||
//f32 rot = PI / 4;
|
|
||||||
f32 rot = 0;
|
|
||||||
struct entity *e = entity_alloc(root);
|
|
||||||
|
|
||||||
pos = v2_add(pos, V2(0, offset_all));
|
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/box.ase"));
|
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
|
|
||||||
#if 0
|
|
||||||
e->mass_unscaled = 500;
|
|
||||||
e->inertia_unscaled = 500;
|
|
||||||
#else
|
|
||||||
e->mass_unscaled = F32_INFINITY;
|
|
||||||
e->inertia_unscaled = F32_INFINITY;
|
|
||||||
#endif
|
|
||||||
e->linear_ground_friction = 10000;
|
|
||||||
e->angular_ground_friction = 10000;
|
|
||||||
|
|
||||||
entity_set_xform(e, XFORM_TRS(.t = pos, .s = size, .r = rot));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Camera */
|
/* Camera */
|
||||||
if (!G.extra_spawn && player_ent->valid) {
|
if (!G.extra_spawn && player_ent->valid) {
|
||||||
@ -1202,6 +1067,7 @@ INTERNAL void create_mouse_joints(struct game_cmd_array game_cmds)
|
|||||||
entity_enable_prop(joint_ent, ENTITY_PROP_MOUSE_JOINT);
|
entity_enable_prop(joint_ent, ENTITY_PROP_MOUSE_JOINT);
|
||||||
entity_enable_prop(joint_ent, ENTITY_PROP_ACTIVE);
|
entity_enable_prop(joint_ent, ENTITY_PROP_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mouse_joint *joint = &joint_ent->mouse_joint_data;
|
struct mouse_joint *joint = &joint_ent->mouse_joint_data;
|
||||||
|
|
||||||
struct xform xf = entity_get_xform(target_ent);
|
struct xform xf = entity_get_xform(target_ent);
|
||||||
@ -1534,7 +1400,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
static b32 run = 0;
|
static b32 run = 0;
|
||||||
if (!run) {
|
if (!run) {
|
||||||
run = 1;
|
run = 1;
|
||||||
spawn_test_entities(0);
|
spawn_test_entities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1562,14 +1428,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
case GAME_CMD_KIND_SPAWN_TEST:
|
case GAME_CMD_KIND_SPAWN_TEST:
|
||||||
{
|
{
|
||||||
logf_info("Spawning (test)");
|
logf_info("Spawning (test)");
|
||||||
#if GAME_SPAWN_LOTS
|
spawn_test_entities();
|
||||||
//#if 0
|
|
||||||
for (u32 i = 0; i < 50; ++i) {
|
|
||||||
spawn_test_entities(-(f32)i);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
spawn_test_entities(0);
|
|
||||||
#endif
|
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
};
|
};
|
||||||
@ -1892,7 +1751,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
bullet->bullet_src = ent->handle;
|
bullet->bullet_src = ent->handle;
|
||||||
bullet->bullet_src_pos = rel_pos;
|
bullet->bullet_src_pos = rel_pos;
|
||||||
bullet->bullet_src_dir = rel_dir;
|
bullet->bullet_src_dir = rel_dir;
|
||||||
bullet->bullet_impulse = 0.25f;
|
bullet->bullet_impulse = 0.1f;
|
||||||
|
//bullet->bullet_impulse = 0.25f;
|
||||||
//bullet->bullet_impulse = 1.f;
|
//bullet->bullet_impulse = 1.f;
|
||||||
bullet->mass_unscaled = 0.04f;
|
bullet->mass_unscaled = 0.04f;
|
||||||
bullet->inertia_unscaled = 0.00001f;
|
bullet->inertia_unscaled = 0.00001f;
|
||||||
@ -2042,76 +1902,30 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
* Create ground friction force (gravity)
|
* Create ground friction force (gravity)
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#if 0
|
|
||||||
#if GAME_PHYSICS_ENABLE_GROUND_FRICTION
|
|
||||||
#if 0
|
|
||||||
/* TODO: Do this globally rather than creating entities for constant forces */
|
|
||||||
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
|
||||||
struct entity *ent = &store->entities[entity_index];
|
|
||||||
if (!entity_is_valid_and_active(ent)) continue;
|
|
||||||
if (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL)) continue;
|
|
||||||
if (ent->linear_ground_friction != 0) {
|
|
||||||
/* Linear velocity */
|
|
||||||
{
|
|
||||||
struct v2 linear_velocity = ent->linear_velocity;
|
|
||||||
if (!v2_is_zero(linear_velocity)) {
|
|
||||||
/* FIXME: Incorrect behavior at low FPS & low entity density */
|
|
||||||
const f32 clamp_epsilon = 0.01;
|
|
||||||
f32 linear_velocity_len = v2_len(linear_velocity);
|
|
||||||
if (linear_velocity_len >= clamp_epsilon) {
|
|
||||||
f32 force_len = -linear_velocity_len * ent->linear_ground_friction;
|
|
||||||
struct v2 force = v2_mul(v2_norm(linear_velocity), force_len);
|
|
||||||
entity_apply_force_to_center(ent, force);
|
|
||||||
} else {
|
|
||||||
/* If linear_velocity is below clamp_epsilon, stop entity movement. */
|
|
||||||
struct xform xf = entity_get_xform(ent);
|
|
||||||
f32 mass = ent->mass_unscaled * math_fabs(xform_get_determinant(xf));
|
|
||||||
struct v2 impulse = v2_mul(v2_neg(linear_velocity), mass);
|
|
||||||
entity_apply_linear_impulse_to_center(ent, impulse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ent->angular_ground_friction != 0) {
|
|
||||||
/* Angular velocity */
|
|
||||||
{
|
|
||||||
f32 angular_velocity = ent->angular_velocity;
|
|
||||||
if (angular_velocity != 0) {
|
|
||||||
/* FIXME: Incorrect (just testing) */
|
|
||||||
const f32 clamp_epsilon = 0.001;
|
|
||||||
if (math_fabs(angular_velocity) >= clamp_epsilon) {
|
|
||||||
f32 torque = -angular_velocity * ent->angular_ground_friction;
|
|
||||||
entity_apply_torque(ent, torque);
|
|
||||||
} else {
|
|
||||||
/* If angular_velocity is below clamp_epsilon, stop entity movement. */
|
|
||||||
struct xform xf = entity_get_xform(ent);
|
|
||||||
f32 inertia = ent->inertia_unscaled * math_fabs(xform_get_determinant(xf));
|
|
||||||
f32 impulse = -angular_velocity * inertia;
|
|
||||||
entity_apply_angular_impulse(ent, impulse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* TODO: Do this globally rather than creating entities for constant forces */
|
|
||||||
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
||||||
struct entity *ent = &store->entities[entity_index];
|
struct entity *ent = &store->entities[entity_index];
|
||||||
if (!entity_is_valid_and_active(ent)) continue;
|
if (!entity_is_valid_and_active(ent)) continue;
|
||||||
if (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL)) continue;
|
if (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL)) continue;
|
||||||
|
|
||||||
|
struct entity *joint_ent = entity_from_handle(store, ent->ground_friction_joint);
|
||||||
|
|
||||||
const f32 bla = 0.75f;
|
struct motor_joint_def def = ZI;
|
||||||
if (ent->linear_ground_friction != 0) {
|
def.e0 = root->handle;
|
||||||
ent->linear_velocity = v2_mul(ent->linear_velocity, bla);
|
def.e1 = ent->handle;
|
||||||
}
|
def.correction_rate = 0;
|
||||||
if (ent->angular_ground_friction != 0) {
|
def.max_force = ent->linear_ground_friction;
|
||||||
ent->angular_velocity *= bla;
|
def.max_torque = ent->angular_ground_friction;
|
||||||
|
if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) {
|
||||||
|
if (!entity_is_valid_and_active(joint_ent)) {
|
||||||
|
joint_ent = entity_alloc(root);
|
||||||
|
entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL);
|
||||||
|
entity_enable_prop(joint_ent, ENTITY_PROP_MOTOR_JOINT);
|
||||||
|
entity_enable_prop(joint_ent, ENTITY_PROP_ACTIVE);
|
||||||
|
joint_ent->motor_joint_data = motor_joint_from_def(def);
|
||||||
|
ent->ground_friction_joint = joint_ent->handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Physics
|
* Physics
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user