From ed8e826b94233a6ef19290dfa3800d09ec265f2f Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Sun, 2 Mar 2025 23:19:27 +0300 Subject: [PATCH] /apps/demos/scenery: something... --- apps/demos/scenery/scenes/ingame.c | 118 +++++++++++++++++++---------- apps/demos/scenery/scenes/ingame.h | 2 +- 2 files changed, 79 insertions(+), 41 deletions(-) diff --git a/apps/demos/scenery/scenes/ingame.c b/apps/demos/scenery/scenes/ingame.c index 63e6fe1..b2f8d4d 100644 --- a/apps/demos/scenery/scenes/ingame.c +++ b/apps/demos/scenery/scenes/ingame.c @@ -53,17 +53,18 @@ static float heightmap[TERRAIN_DISTANCE][TERRAIN_DISTANCE]; /* else if length(v(o) + (F(o)/m)*t) <= (f(k)*x(n)*t), v(o) = 0 */ /* else, F = -unit(v(o)*f(k)*x(n)) */ -#define VEHICLE_MASS 200.0f +#define VEHICLE_MASS 150.0f #define VEHICLE_LENGTH 3.0f #define VEHICLE_WIDTH 1.7f #define VEHICLE_HEIGHT 1.3f /* spring constant */ -#define VEHICLE_SPRING_K 50000.0f +#define VEHICLE_SPRING_K 80000.0f /* damping constant */ -#define VEHICLE_SPRING_C 200.0f -#define VEHICLE_FRICTION_S 50000.0f -#define VEHICLE_FRICTION_K 700.0f +#define VEHICLE_SPRING_C 500.0f +#define VEHICLE_FRICTION_S 1000.0f +#define VEHICLE_FRICTION_K 100.0f +/* TODO: shock springs, that are more loose, which are used to simulate the wheels */ /* initial, ideal corner positions */ static const Vec3 vbpi[8] = { [0] = { 0, 0, 0 }, @@ -141,48 +142,83 @@ 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) { - /* displacement force */ + /* wheel processing */ + if (i == 0 || i == 3) { + if (scn->camera_mode == 2 && input_action_pressed("player_forward")) { + Vec3 const dir = i == 0 ? vec3_sub(vbp[0], vbp[1]) : vec3_sub(vbp[3], vbp[2]); + Facc[i] = vec3_add(Facc[i], vec3_scale(vec3_norm(dir), 18000)); + } + } + + /* normal force, for displacement */ Vec3 const n = normal_at(scn, (Vec2){ p.x, p.z }); float const xn = (h - p.y) * n.y; float const vn = vec3_dot(v, n); - Vec3 const Fd = vec3_scale(n, -VEHICLE_SPRING_K * xn - VEHICLE_SPRING_C * vn); - Facc[i] = vec3_sub(Facc[i], Fd); + Vec3 const Fn = vec3_scale(n, -VEHICLE_SPRING_K * xn - VEHICLE_SPRING_C * vn); - /* friction force, perpendicular to displacement */ - /* portions aligned to surface normal */ - Vec3 const vov = vec3_sub(v, vec3_scale(n, vn)); - draw_line_3d(vbp[i], vec3_add(vbp[i], vec3_scale(vov, 3)), 1, (Color){255, 0, 0, 255}); - float const vo = vec3_length(vov); - Vec3 const Fov = vec3_sub(Facc[i], vec3_scale(n, vec3_dot(Facc[i], n))); - float const Fo = vec3_length(Fov); - float const fkxn = VEHICLE_FRICTION_K * xn; - if (fabsf(0.0f - vo) <= 0.001f) { - /* cannot overcome static friction, zero force along the surface */ - if (Fo <= VEHICLE_FRICTION_S * xn) { - // Facc[i] = vec3_sub(Facc[i], Fov); - Facc[i] = (Vec3){0}; - } - /* apply kinematic friction */ - else { - Facc[i] = vec3_sub(Fov, vec3_scale(vec3_norm(Fov), fkxn)); - } - /* velocity with gain along the surface will not overcome */ - } else if (vec3_length(vec3_add(vov, vec3_scale(vec3_scale(Fov, (1.0f / VEHICLE_MASS)), ctx.frame_duration))) <= fkxn * ctx.frame_duration) { - // vbv[i] = vec3_sub(vbv[i], vov); + /* friction force, perpendicular to normal force */ + Vec3 const vo = vec3_sub(v, vec3_scale(n, vn)); + float const vol = vec3_length(vo); + Vec3 Fo = vec3_sub(Facc[i], vec3_scale(n, vec3_dot(Facc[i], n))); + /* portion of total force along the surface */ + float const Fol = vec3_length(Fo); + float const fkxn = VEHICLE_FRICTION_K * xn * 50; + /* 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) Fo = (Vec3){0}; + /* resist the force by friction, while starting to move */ + else Fo = vec3_sub(Fo, vec3_scale(vec3_norm(Fo), fkxn)); + /* not at rest, stop accelerating along the surface */ + } else if (vol + (Fol / VEHICLE_MASS) * ctx.frame_duration <= fkxn * ctx.frame_duration) { + log_info("test 1"); + // vbv[i] = vec3_sub(vbp[i], vo); vbv[i] = (Vec3){0}; + /* just apply friction */ } else { - Facc[i] = vec3_sub(Facc[i], vec3_scale(vec3_norm(vov), fkxn)); + log_info("test 2, depth: %f", xn); + Fo = vec3_add(Fo, vec3_scale(vec3_norm(vo), -fkxn * 100)); } + + /* total force, after ground interaction */ + Vec3 const Ft = vec3_add(vec3_scale(Fn, -1), Fo); + Vec3 vd = vec3_scale(vec3_scale(Ft, (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 { + /* in air */ + 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)); } } +} - /* integrate forces and velocity */ - for (size_t i = 0; i < 8; ++i) { - Vec3 vd = vec3_scale(vec3_scale(Facc[i], (1.0f / VEHICLE_MASS)), ctx.frame_duration); - if (vec3_length(vd) <= 0.02f) vd = (Vec3){0}; /* TODO: dirty hack... */ - vbv[i] = vec3_add(vbv[i], vd); - vbp[i] = vec3_add(vbp[i], vec3_scale(vbv[i], ctx.frame_duration)); - } + +static void process_vehicle_mode(State *state) { + SceneIngame *scn = (SceneIngame *)state->scene; + + Vec3 const top_center = vec3_sub(vbp[4], vec3_scale(vec3_sub(vbp[4], vbp[6]), 1.0f / 2.0f)); + // Vec3 const front_center = vec3_add(vbp[4], vec3_scale(vec3_sub(vbp[4], vbp[7]), 1.0f / 2.0f)); + // Vec3 const facing_direction = vec3_sub(top_center, front_center); + + float yawc, yaws, pitchc, pitchs; + sincosf(scn->yaw + (float)M_PI_2, &yaws, &yawc); + sincosf(scn->pitch, &pitchs, &pitchc); + + Vec3 const looking_direction = vec3_norm(((Vec3){ + yawc * pitchc, + pitchs, + yaws * pitchc, + })); + + Vec3 const orbit = vec3_sub(top_center, vec3_scale(looking_direction, 10)); + + draw_camera(orbit, looking_direction, (Vec3){0,1,0}, (float)M_PI_2 * 0.8f, 1, TERRAIN_RADIUS * sqrtf(3)); + + scn->looking_direction = looking_direction; + + scn->pos = top_center; } @@ -435,12 +471,14 @@ static void ingame_tick(State *state) { } if (input_action_just_pressed("toggle_camera_mode")) - scn->flying_camera = !scn->flying_camera; + scn->camera_mode = scn->camera_mode == 2 ? 0 : scn->camera_mode + 1; - if (scn->flying_camera) { + if (scn->camera_mode == 1) { process_fly_mode(state); - } else { + } else if (scn->camera_mode == 0) { process_ground_mode(state); + } else if (scn->camera_mode) { + process_vehicle_mode(state); } /* toggle mouse capture with end key */ diff --git a/apps/demos/scenery/scenes/ingame.h b/apps/demos/scenery/scenes/ingame.h index 797c387..74f51db 100644 --- a/apps/demos/scenery/scenes/ingame.h +++ b/apps/demos/scenery/scenes/ingame.h @@ -21,7 +21,7 @@ typedef struct SceneIngame { float roll; bool mouse_captured; - bool flying_camera; + int camera_mode; } SceneIngame;