From 787977b74752a4d39d19b9e91e07db9ddb670be5 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Wed, 5 Mar 2025 05:26:05 +0300 Subject: [PATCH] /apps/demos/scenery: drift ! steer ! --- apps/demos/scenery/scenes/ingame.c | 79 ++++++++++++++++++++++-------- include/twn_vec.h | 4 ++ 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/apps/demos/scenery/scenes/ingame.c b/apps/demos/scenery/scenes/ingame.c index 26f58ee..37f31ac 100644 --- a/apps/demos/scenery/scenes/ingame.c +++ b/apps/demos/scenery/scenes/ingame.c @@ -65,6 +65,7 @@ static float heightmap[TERRAIN_DISTANCE][TERRAIN_DISTANCE]; #define VEHICLE_SPRING_GC 100.0f #define VEHICLE_FRICTION_S 1000.0f #define VEHICLE_FRICTION_K 100.0f +#define VEHICLE_FRICTION_V 4000.0f /* TODO: shock springs, that are more loose, which are used to simulate the wheels */ /* initial, ideal corner positions */ @@ -97,7 +98,10 @@ static uint8_t vbs[28][2] = { {0, 6}, {1, 7}, {2, 4}, {3, 5}, }; - +/* ackermann steering geometry */ +static float vehicle_turning_extend; +static float vehicle_turning_speed = 0.12f; +static float vehicle_turning_extend_limit = VEHICLE_WIDTH * 1.75f; static float height_at(SceneIngame *scn, Vec2 position); static Vec3 normal_at(SceneIngame *scn, Vec2 position); @@ -117,6 +121,15 @@ static void process_vehicle(SceneIngame *scn) { /* apply gravity */ Vec3 Facc[8] = {0}; + /* steering */ + if (input_action_pressed("player_left")) + vehicle_turning_extend -= vehicle_turning_speed; + + if (input_action_pressed("player_right")) + vehicle_turning_extend += vehicle_turning_speed; + + vehicle_turning_extend = clampf(vehicle_turning_extend, -vehicle_turning_extend_limit, vehicle_turning_extend_limit); + Vec3 const Fg = { .y = -VEHICLE_MASS * G_CONST }; for (size_t i = 0; i < 8; ++i) Facc[i] = vec3_add(Facc[i], Fg); @@ -144,12 +157,15 @@ static void process_vehicle(SceneIngame *scn) { Vec3 const v = vbv[i]; float const h = height_at(scn, (Vec2){ p.x, p.z }); if (h >= p.y) { - /* wheel processing */ + /* back wheel processing: acceleration */ if (i == 0 || i == 3 || i == 4 || i == 7) { - if (scn->camera_mode == 2 && input_action_pressed("player_forward")) { - Vec3 dir = i == 0 ? vec3_sub(vbp[1], vbp[0]) : vec3_sub(vbp[2], vbp[3]); - Facc[i] = vec3_add(Facc[i], vec3_scale(vec3_norm(dir), 6500)); - } + float scale = 0; + if (scn->camera_mode == 2 && input_action_pressed("player_forward")) + scale += 1; + if (scn->camera_mode == 2 && input_action_pressed("player_backward")) + scale -= 1; + Vec3 const dir = vec3_sub(vbp[1], vbp[0]); + Facc[i] = vec3_add(Facc[i], vec3_scale(vec3_norm(dir), 6500 * scale)); } /* normal force, for displacement */ @@ -162,41 +178,64 @@ static void process_vehicle(SceneIngame *scn) { /* friction force, perpendicular to normal force */ /* TODO: is it right? aren't vn+vol should be = |v| */ Vec3 const von = vec3_norm(vec3_cross(n, vec3_cross(v, n))); - draw_line_3d(vbp[i], vec3_add(vbp[i], von), 1, (Color){255,255,0,255}); Vec3 const vo = vec3_scale(vec3_scale(von, vec3_length(v) - vn), -1); float const vol = vec3_length(vo); Vec3 const Fon = vec3_norm(vec3_cross(n, vec3_cross(Facc[i], n))); Vec3 Fo = vec3_scale(vec3_scale(Fon, vec3_length(Facc[i]) - vec3_dot(Facc[i], n)), -1); - draw_line_3d(vbp[i], vec3_add(vbp[i], Fon), 1, (Color){255,255,0,255}); /* portion of total force along the surface */ float const Fol = vec3_length(Fo); float const fkxn = VEHICLE_FRICTION_K * xn; /* at rest, might want to start moving */ if (fabsf(0.0f - vol) <= 0.0001f) { /* cannot overcome static friction, force along the surface is zeroed */ - if (Fol <= VEHICLE_FRICTION_S * xn) {log_info("test 0"); Fo = vec3_scale(Fo, -1);} + if (Fol <= VEHICLE_FRICTION_S * xn) { Fo = vec3_scale(Fo, -1);} /* resist the force by friction, while starting to move */ - else {log_info("test 1"); Fo = vec3_sub(Fo, vec3_scale(von, fkxn));} + else { Fo = vec3_sub(Fo, vec3_scale(von, fkxn));} /* not at rest, stop accelerating along the surface */ } else if (vol + (Fol / VEHICLE_MASS) * ctx.frame_duration <= fkxn * ctx.frame_duration * 2) { /* ugh ... */ vbv[i] = vec3_add(vbv[i], vo); - log_info("test 2"); /* just apply friction */ } else { Fo = vec3_scale(von, -fkxn * 400); } Facc[i] = vec3_add(Facc[i], Fo); - // Facc[i] = vec3_sub(Fo, Fn); - // Facc[i] = vec3_sub(Fo, Fn); - Vec3 vd = vec3_scale(vec3_scale(Facc[i], (1.0f / VEHICLE_MASS)), ctx.frame_duration); - vbv[i] = vec3_add(vbv[i], vd); - vbp[i] = vec3_add(vbp[i], vec3_scale(vbv[i], ctx.frame_duration)); - } else { - Vec3 vd = vec3_scale(vec3_scale(Facc[i], (1.0f / VEHICLE_MASS)), ctx.frame_duration); - vbv[i] = vec3_add(vbv[i], vd); - vbp[i] = vec3_add(vbp[i], vec3_scale(vbv[i], ctx.frame_duration)); + + /* front wheel processing */ + if (i == 1 || i == 5 || i == 2 || i == 6) { + /* steering influences "center of turning", which is a point */ + /* laying on line defined by rear axle */ + /* front arms are rotated to be perpendicular to center of turning, */ + /* which then are used to dissipate forces, thus providing control */ + Vec3 const rear_bar = vec3_sub(vbp[0], vbp[3]); + Vec3 const rear_center = vec3_add(vbp[3], vec3_scale(rear_bar, 0.5)); + Vec3 a, b, r; + if (i == 1) { + a = vec3_sub(vbp[3], vbp[2]); + b = vec3_sub(rear_center, vbp[2]); + r = vbp[2]; + } else { + a = vec3_sub(vbp[0], vbp[1]); + b = vec3_sub(rear_center, vbp[1]); + r = vbp[1]; + } + + float const arm_angle = vec3_angle(a, b); + Vec3 const turn_center = vec3_add(rear_center, vec3_scale(vec3_norm(rear_bar), vehicle_turning_extend)); + Vec3 const arm = vec3_sub(r, turn_center); + Vec3 const n = vec3_norm(vec3_cross(a, b)); + Vec3 const wheel = vec3_norm(vec3_rotate(arm, -arm_angle, n)); + Vec3 const p = vec3_norm(vec3_cross(wheel, n)); + draw_line_3d(r, vec3_add(r, wheel), 1, (Color){0,255,255,255}); + + Vec3 const Fp = vec3_scale(p, vec3_dot(vbv[i], p) * -VEHICLE_FRICTION_V); + Facc[i] = vec3_add(Facc[i], Fp); + } } + + Vec3 vd = vec3_scale(vec3_scale(Facc[i], (1.0f / VEHICLE_MASS)), ctx.frame_duration); + vbv[i] = vec3_add(vbv[i], vd); + vbp[i] = vec3_add(vbp[i], vec3_scale(vbv[i], ctx.frame_duration)); } } diff --git a/include/twn_vec.h b/include/twn_vec.h index 3ca3936..032510d 100644 --- a/include/twn_vec.h +++ b/include/twn_vec.h @@ -86,6 +86,10 @@ static inline Vec3 vec3_norm(Vec3 a) { return vec3_scale(a, 1.0f / n); } +static inline float vec3_angle(Vec3 a, Vec3 b) { + return acosf(vec3_dot(vec3_norm(a), vec3_norm(b))); +} + static inline Vec3 vec3_rotate(Vec3 v, float angle, Vec3 axis) { /* from cglm */ Vec3 v1, v2, k;