set aim joint correction rate dynamically based on dt

This commit is contained in:
jacob 2025-01-30 11:05:38 -06:00
parent aaaa7deb81
commit eea9c978c9
5 changed files with 25 additions and 22 deletions

View File

@ -33,6 +33,7 @@
#define SPACE_CELL_BUCKETS_SQRT (256) #define SPACE_CELL_BUCKETS_SQRT (256)
#define SPACE_CELL_SIZE 1.0f #define SPACE_CELL_SIZE 1.0f
#define GAME_FPS 50.0 #define GAME_FPS 50.0
#define GAME_TIMESCALE 1 #define GAME_TIMESCALE 1

View File

@ -229,7 +229,6 @@ INTERNAL void spawn_test_entities(void)
} }
/* Enemy */ /* Enemy */
#if 1
{ {
struct entity *e = entity_alloc(root); struct entity *e = entity_alloc(root);
@ -249,7 +248,6 @@ INTERNAL void spawn_test_entities(void)
e->linear_ground_friction = 250; e->linear_ground_friction = 250;
e->angular_ground_friction = 200; e->angular_ground_friction = 200;
} }
#endif
/* Big box */ /* Big box */
@ -984,12 +982,15 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct phys_motor_joint_def def = ZI; struct phys_motor_joint_def def = ZI;
def.e0 = joint_ent->handle; /* Re-using joint entity as e0 */ def.e0 = joint_ent->handle; /* Re-using joint entity as e0 */
def.e1 = ent->handle; def.e1 = ent->handle;
def.correction_rate = 0.1f;
def.max_force = 0; def.max_force = 0;
def.max_torque = ent->control_torque; def.max_torque = ent->control_torque;
joint_ent->motor_joint_data = motor_joint_from_def(def); joint_ent->motor_joint_data = motor_joint_from_def(def);
} }
/* Set correction rate dynamically since motor velocity is only set for one frame */
joint_ent->motor_joint_data.correction_rate = 10 * dt;
/* Solve for final angle using law of sines */ /* Solve for final angle using law of sines */
f32 new_angle; f32 new_angle;
{ {
@ -1039,6 +1040,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct xform joint_xf = entity_get_xform(joint_ent); struct xform joint_xf = entity_get_xform(joint_ent);
f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf)); f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
if (math_fabs(diff) > angle_error_allowed) { if (math_fabs(diff) > angle_error_allowed) {
/* Instantly snap joint ent to new angle */
new_vel = diff / dt; new_vel = diff / dt;
} }
} }

View File

@ -50,6 +50,5 @@ void mixer_set_listener(struct v2 pos, struct v2 dir);
/* Mixing */ /* Mixing */
struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_request_count); struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_request_count);
void mixer_advance(u64 frames_written_count);
#endif #endif

View File

@ -717,23 +717,23 @@ void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt)
f32 w0 = e0->angular_velocity; f32 w0 = e0->angular_velocity;
f32 w1 = e1->angular_velocity; f32 w1 = e1->angular_velocity;
f32 correction_rate = joint->correction_rate / dt; f32 correction_rate = joint->correction_rate;
f32 inv_dt = 1.f / dt;
/* Angular constraint */ /* Angular constraint */
{ {
f32 max_impulse = joint->max_torque * dt; f32 max_impulse = joint->max_torque * dt;
f32 angular_separation = math_unwind_angle(xform_get_rotation(e1_xf) - xform_get_rotation(e0_xf)); f32 angular_separation = math_unwind_angle(xform_get_rotation(e1_xf) - xform_get_rotation(e0_xf));
f32 angular_bias = angular_separation * correction_rate;
f32 impulse = -joint->angular_mass * (w1 - w0 + angular_bias); f32 angular_bias = angular_separation * correction_rate * inv_dt;
f32 old_impulse = joint->angular_impulse; f32 old_impulse = joint->angular_impulse;
joint->angular_impulse = clamp_f32(joint->angular_impulse + impulse, -max_impulse, max_impulse); f32 new_impulse = clamp_f32(old_impulse + (-joint->angular_mass * (w1 - w0 + angular_bias)), -max_impulse, max_impulse);
impulse = joint->angular_impulse - old_impulse; joint->angular_impulse = new_impulse;
w0 -= impulse * inv_i0; f32 delta = new_impulse - old_impulse;
w1 += impulse * inv_i1; w0 -= delta * inv_i0;
w1 += delta * inv_i1;
} }
/* Linear constraint */ /* Linear constraint */
@ -744,19 +744,20 @@ void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt)
f32 max_impulse = joint->max_force * dt; f32 max_impulse = joint->max_force * dt;
struct v2 linear_separation = v2_sub(v2_add(e1_xf.og, vcp1), v2_add(e0_xf.og, vcp0)); struct v2 linear_separation = v2_sub(v2_add(e1_xf.og, vcp1), v2_add(e0_xf.og, vcp0));
struct v2 linear_bias = v2_mul(linear_separation, correction_rate); struct v2 linear_bias = v2_mul(linear_separation, correction_rate * inv_dt);
struct v2 vrel = v2_sub(v2_add(v1, v2_perp_mul(vcp1, w1)), v2_add(v0, v2_perp_mul(vcp0, w0))); struct v2 vrel = v2_sub(v2_add(v1, v2_perp_mul(vcp1, w1)), v2_add(v0, v2_perp_mul(vcp0, w0)));
struct v2 impulse = v2_neg(xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vrel, linear_bias))); struct v2 impulse = v2_neg(xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vrel, linear_bias)));
struct v2 old_impulse = joint->linear_impulse; struct v2 old_impulse = joint->linear_impulse;
joint->linear_impulse = v2_clamp_len(v2_add(joint->linear_impulse, impulse), max_impulse); struct v2 new_impulse = v2_clamp_len(v2_add(old_impulse, impulse), max_impulse);
impulse = v2_sub(joint->linear_impulse, old_impulse); joint->linear_impulse = new_impulse;
v0 = v2_sub(v0, v2_mul(impulse, inv_m0)); struct v2 delta = v2_sub(new_impulse, old_impulse);
v1 = v2_add(v1, v2_mul(impulse, inv_m1)); v0 = v2_sub(v0, v2_mul(delta, inv_m0));
w0 -= v2_wedge(vcp0, impulse) * inv_i0; v1 = v2_add(v1, v2_mul(delta, inv_m1));
w1 += v2_wedge(vcp1, impulse) * inv_i1; w0 -= v2_wedge(vcp0, delta) * inv_i0;
w1 += v2_wedge(vcp1, delta) * inv_i1;
} }
entity_set_linear_velocity(e0, v0); entity_set_linear_velocity(e0, v0);

View File

@ -936,7 +936,7 @@ INTERNAL void user_update(void)
b32 skip_debug_draw = !G.debug_camera && ent == active_camera; b32 skip_debug_draw = !G.debug_camera && ent == active_camera;
b32 skip_debug_draw_transform = entity_has_prop(ent, ENTITY_PROP_CAMERA); b32 skip_debug_draw_transform = entity_has_prop(ent, ENTITY_PROP_CAMERA);
skip_debug_draw_transform = true; //skip_debug_draw_transform = true;
struct xform sprite_xform = xf; struct xform sprite_xform = xf;
@ -1005,8 +1005,8 @@ INTERNAL void user_update(void)
/* Draw xform */ /* Draw xform */
if (!skip_debug_draw_transform) { if (!skip_debug_draw_transform) {
u32 color_x = RGBA_32_F(1, 0, 0, 0.3); u32 color_x = RGBA_32_F(1, 0, 0, 0.5);
u32 color_y = RGBA_32_F(0, 1, 0, 0.3); u32 color_y = RGBA_32_F(0, 1, 0, 0.5);
debug_draw_xform(xf, color_x, color_y); debug_draw_xform(xf, color_x, color_y);
} }