From 1bbe316b20c178e3b3ca860a8abd426e18b89119 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 16 Dec 2024 12:53:52 -0600 Subject: [PATCH] kinematic flag --- src/entity.h | 8 ++++++-- src/game.c | 53 +++++++++++++++++++++++++++++++++------------------- src/user.c | 4 ++-- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/entity.h b/src/entity.h index eb54bacb..927d417e 100644 --- a/src/entity.h +++ b/src/entity.h @@ -11,7 +11,9 @@ enum entity_prop { ENTITY_PROP_RELEASE_AT_END_OF_FRAME, - ENTITY_PROP_PHYSICAL, + ENTITY_PROP_PHYSICAL_DYNAMIC, + ENTITY_PROP_PHYSICAL_KINEMATIC, + ENTITY_PROP_CONTACT_CONSTRAINT, ENTITY_PROP_MOTOR_JOINT, ENTITY_PROP_MOUSE_JOINT, @@ -292,7 +294,7 @@ struct entity { /* ====================================================================== */ /* Physics */ - /* ENTITY_PROP_PHYSICAL */ + /* ENTITY_PROP_PHYSICAL_DYNAMIC */ //f32 density; /* Density in kg/m^2 */ @@ -318,6 +320,8 @@ struct entity { struct string sprite_span_name; u32 sprite_tint; + struct string sprite_collider_slice; /* Collider will sync to bounds of this slice if set */ + struct xform sprite_local_xform; /* Sprite transform in relation to entity */ /* ====================================================================== */ diff --git a/src/game.c b/src/game.c index b28a2251..f89bb84d 100644 --- a/src/game.c +++ b/src/game.c @@ -340,6 +340,7 @@ INTERNAL void spawn_test_entities(void) //e->sprite_span_name = STR("idle.unarmed"); //e->sprite_span_name = STR("idle.one_handed"); e->sprite_span_name = STR("idle.two_handed"); + e->sprite_collider_slice = STR("shape"); struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); //xf.bx.y = -1.f; @@ -355,7 +356,7 @@ INTERNAL void spawn_test_entities(void) e->control_torque = 1000; e->control_force_max_speed = 4; - entity_enable_prop(e, ENTITY_PROP_PHYSICAL); + entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC); player_ent = e; } @@ -371,8 +372,9 @@ INTERNAL void spawn_test_entities(void) entity_set_xform(e, xf); e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); + e->sprite_collider_slice = STR("shape"); - entity_enable_prop(e, ENTITY_PROP_PHYSICAL); + entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC); e->mass_unscaled = 10; e->inertia_unscaled = 10; e->linear_ground_friction = 250; @@ -426,7 +428,7 @@ INTERNAL void create_contacts(void) for (u64 check0_index = 0; check0_index < store->reserved; ++check0_index) { struct entity *check0 = &store->entities[check0_index]; if (!entity_is_valid_and_active(check0)) continue; - if (!entity_has_prop(check0, ENTITY_PROP_PHYSICAL)) continue; + if (!(entity_has_prop(check0, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(check0, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue; if (check0->local_collider.count <= 0) continue; struct xform check0_xf = entity_get_xform(check0); @@ -436,7 +438,7 @@ INTERNAL void create_contacts(void) struct entity *check1 = &store->entities[check1_index]; if (check1 == check0) continue; if (!entity_is_valid_and_active(check1)) continue; - if (!entity_has_prop(check1, ENTITY_PROP_PHYSICAL)) continue; + if (!(entity_has_prop(check1, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(check1, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue; if (check1->local_collider.count <= 0) continue; /* Deterministic entity order based on index */ @@ -529,7 +531,10 @@ INTERNAL void create_contacts(void) constraint_ent = entity_alloc(root); constraint_ent->contact_constraint_data.e1 = e1->handle; constraint_ent->contact_constraint_data.e0 = e0->handle; - constraint_ent->contact_constraint_data.skip_solve = entity_has_prop(e0, ENTITY_PROP_SENSOR) || entity_has_prop(e1, ENTITY_PROP_SENSOR); + + constraint_ent->contact_constraint_data.skip_solve = entity_has_prop(e0, ENTITY_PROP_SENSOR) || entity_has_prop(e1, ENTITY_PROP_SENSOR) + || !(entity_has_prop(e0, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e1, ENTITY_PROP_PHYSICAL_DYNAMIC)); + /* TODO: Should we recalculate normal as more contact points are added? */ entity_enable_prop(constraint_ent, ENTITY_PROP_CONTACT_CONSTRAINT); activate_now(constraint_ent); @@ -660,6 +665,15 @@ INTERNAL void prepare_contacts(void) constraint->inv_i0 = inv_i0; constraint->inv_i1 = inv_i1; + if (entity_has_prop(e0, ENTITY_PROP_PHYSICAL_KINEMATIC)) { + constraint->inv_m0 = 0; + constraint->inv_i0 = 0; + } + if (entity_has_prop(e1, ENTITY_PROP_PHYSICAL_KINEMATIC)) { + constraint->inv_m1 = 0; + constraint->inv_i1 = 0; + } + /* Update / insert returned contacts */ for (u32 i = 0; i < num_points; ++i) { struct contact_point *contact = &constraint->points[i]; @@ -710,6 +724,7 @@ INTERNAL void warm_start_contacts(void) u32 num_points = constraint->num_points; struct entity *e0 = entity_from_handle(store, constraint->e0); struct entity *e1 = entity_from_handle(store, constraint->e1); + if (num_points > 0 && entity_is_valid_and_active(e0) && entity_is_valid_and_active(e1) && !constraint->skip_solve) { struct xform e0_xf = entity_get_xform(e0); struct xform e1_xf = entity_get_xform(e1); @@ -1088,7 +1103,7 @@ INTERNAL void create_mouse_joints(struct game_cmd_array game_cmds) 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 (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) continue; struct collider_shape ent_collider = ent->local_collider; if (ent_collider.count > 0) { @@ -1110,7 +1125,6 @@ INTERNAL void create_mouse_joints(struct game_cmd_array game_cmds) joint_ent = entity_alloc(root); joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; - entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL); entity_enable_prop(joint_ent, ENTITY_PROP_MOUSE_JOINT); entity_enable_prop(joint_ent, ENTITY_PROP_ACTIVE); } @@ -1314,7 +1328,7 @@ INTERNAL void integrate_velocities_from_forces(f32 dt) 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 (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC) && !entity_has_prop(ent, ENTITY_PROP_PHYSICAL_KINEMATIC)) continue; struct xform xf = entity_get_xform(ent); f32 det_abs = math_fabs(xform_get_determinant(xf)); @@ -1342,7 +1356,7 @@ INTERNAL void integrate_positions_from_velocities(f32 dt) 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 (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC) && !entity_has_prop(ent, ENTITY_PROP_PHYSICAL_KINEMATIC)) continue; /* Clamp velocities */ ent->linear_velocity = v2_clamp_len(ent->linear_velocity, GAME_MAX_LINEAR_VELOCITY); @@ -1565,8 +1579,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) ent->sprite_local_xform = xf; } - /* Update collider */ - { + /* Update collider from sprite */ + if (ent->sprite_collider_slice.len > 0) { struct xform cxf = ent->sprite_local_xform; #if 0 @@ -1576,7 +1590,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) } #endif - struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame); + struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame); ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect))); #if 1 @@ -1803,6 +1817,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) //bullet->bullet_impulse = 1.f; bullet->mass_unscaled = 0.04f; bullet->inertia_unscaled = 0.00001f; + bullet->sprite_collider_slice = STR("shape"); entity_enable_prop(bullet, ENTITY_PROP_BULLET); entity_enable_prop(bullet, ENTITY_PROP_SENSOR); @@ -1836,7 +1851,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) joint_ent = entity_alloc(root); joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; - 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); ent->move_joint = joint_ent->handle; @@ -1875,7 +1889,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) joint_ent = entity_alloc(root); joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; - entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL); + entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL_KINEMATIC); /* Since we'll be setting velocity */ entity_enable_prop(joint_ent, ENTITY_PROP_MOTOR_JOINT); entity_enable_prop(joint_ent, ENTITY_PROP_ACTIVE); ent->aim_joint = joint_ent->handle; @@ -1953,7 +1967,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) 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 (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) continue; struct entity *joint_ent = entity_from_handle(store, ent->ground_friction_joint); @@ -1966,7 +1980,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) 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); @@ -2052,8 +2065,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) (UNUSED)target; entity_enable_prop(bullet, ENTITY_PROP_RELEASE_AT_END_OF_FRAME); - - /* Create test blood */ /* TODO: Remove this */ { @@ -2061,6 +2072,10 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) struct entity *decal = entity_alloc(root); decal->sprite = sprite_tag_from_path(STR("res/graphics/blood.ase")); entity_set_xform(decal, xf); + + entity_enable_prop(decal, ENTITY_PROP_PHYSICAL_KINEMATIC); + decal->linear_velocity = v2_mul(v2_norm(event->normal), 0.5f); + decal->angular_velocity = ((f32)sys_rand_u32() / (f32)U32_MAX); } } } @@ -2086,7 +2101,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) struct xform xf = XFORM_TRS(.t = pos, .r = v2_angle(impulse) + PI / 2); entity_set_xform(ent, xf); - entity_enable_prop(ent, ENTITY_PROP_PHYSICAL); + entity_enable_prop(ent, ENTITY_PROP_PHYSICAL_KINEMATIC); entity_apply_linear_impulse_to_center(ent, impulse); } diff --git a/src/user.c b/src/user.c index 7c5f3043..560ed1c9 100644 --- a/src/user.c +++ b/src/user.c @@ -967,7 +967,7 @@ INTERNAL void user_update(void) } #endif - if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL)) { + if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) { debug_draw_movement(ent); } @@ -1034,7 +1034,7 @@ INTERNAL void user_update(void) #endif /* Draw collider */ - if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL)) { + if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) { struct collider_shape collider = ent->local_collider; u32 color = ent->colliding > 0 ? RGBA_32_F(1, 1, 1, 0.5) : RGBA_32_F(1, 1, 0, 0.25); f32 thickness = 2;