diff options
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/physics/movement.cpp | 58 | ||||
| -rw-r--r-- | src/game/player.cpp | 3 | ||||
| -rw-r--r-- | src/game/world/trace.cpp | 34 |
3 files changed, 75 insertions, 20 deletions
diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp index c9b7688..ecee539 100644 --- a/src/game/physics/movement.cpp +++ b/src/game/physics/movement.cpp @@ -125,8 +125,6 @@ void gmove_accelerate( VEC3& wishdir, F32 wishspeed, F32 accel ) { gmove->velocity += wishdir * accelspeed; } -// todo: player hull extends at center instead of at feet -// should extend at feet void gmove_stay_on_ground() { BSP_TRACE tr{}; VEC3 start = gmove->pos; @@ -155,9 +153,10 @@ void gmove_categorize_pos() { } -VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) { - if( planes->size > 2 ) - vel = {}; +VEC3 gmove_clip_planes( VEC3 vel, VEC3* pos, LIST<VEC3>* planes, F32 overbounce ) { + if( planes->size > 2 ) { + return {}; + } planes->each( fn( VEC3* p ) { vel = gmove_clip_velocity( vel, *p, overbounce ); @@ -168,6 +167,7 @@ VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) { if( vec_dot( vel, planes->data[i] ) < 0.f ) { VEC3 dir = vec_cross( planes->data[0], planes->data[1] ); F32 len = vec_len( dir ); + if( len > 0.00001f ) { dir *= 1.0f / len; vel = dir * vec_dot( vel, dir ); @@ -183,6 +183,43 @@ VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) { return vel; } +void gmove_check_stuck( VEC3* pos ) { + BSP_TRACE t; + bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos ); + if( !t.hit ) + return; + + VEC3 p1 = *pos; + + // try nudge away from wall + *pos = p1 + t.normal * BSP_TRACE_EPSILON * 2.f; + bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos ); + if( !t.hit ) + return; + + // nudge +90deg away horizontal + *pos = p1 + VEC3{ -t.normal.y, t.normal.x, t.normal.z } * BSP_TRACE_EPSILON * 2.f; + bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos ); + if( !t.hit ) + return; + + // nudge -90deg away horizontal + *pos = p1 + VEC3{ t.normal.y, -t.normal.x, t.normal.z } * BSP_TRACE_EPSILON * 2.f; + bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos ); + if( !t.hit ) + return; + + // nudge -180deg away horizontal + *pos = p1 + VEC3{ t.normal.y, t.normal.x, -t.normal.z } * BSP_TRACE_EPSILON * 2.f; + bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos ); + if( !t.hit ) + return; + + // todo : loop over every dir from current pos and incrementally increase distance. + // kinda like source + *pos = p1; // restore original pos - failed to unstuck +} + F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { F32 dt = TICK_INTERVAL; AABB aabb = gmove->aabb; @@ -198,7 +235,8 @@ F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { *pos += wishmove * t->frac; // nudge player away from wall - *pos += t->normal * (BSP_TRACE_EPSILON * 2.f); + if( vec_dot( *vel, t->normal ) < 0.f ) + *pos += t->normal * (BSP_TRACE_EPSILON * 2.f); planes.push( t->normal ); @@ -206,7 +244,7 @@ F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { if( dt <= 0.0001f ) break; - *vel = gmove_clip_planes( *vel, &planes, 1.f /* todo : surface friction */ ); + *vel = gmove_clip_planes( *vel, pos, &planes, 1.f /* todo : surface friction */ ); } return dt < 0 ? 0 : dt; @@ -279,23 +317,23 @@ void gmove_walk_move() { gmove_accelerate( wishdir, speed, var_getf( mv_accelerate ) ); speed = vec_len( vel ); + defer( gmove_check_stuck( &gmove->pos ) ); if( speed < 1.f ) { gmove->velocity = {}; return; } - VEC3 dest = gmove->pos + vel * TICK_INTERVAL; + VEC3 dest = gmove->pos + gmove->velocity * TICK_INTERVAL; BSP_TRACE tr{}; bsp_trace( &tr, gmove->bsp, gmove->aabb, gmove->pos, dest ); + defer( gmove_stay_on_ground() ); if( !tr.hit ) { gmove->pos = dest; - gmove_stay_on_ground(); return; } gmove_step_move( dest, &tr ); - gmove_stay_on_ground(); } void gmove_full_walk_move() { diff --git a/src/game/player.cpp b/src/game/player.cpp index 74ecea2..c6bf385 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -6,8 +6,7 @@ #include <cmath> #include "player.h" -// todo : temporary -F32 PLAYER_HULL_HEIGHT = 1.f; +F32 PLAYER_HULL_HEIGHT = 48.f; F32 PLAYER_HULL_WIDTH = 32.f; PLAYER* player_create( VEC3 origin, F32 yaw ) { diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp index fd6a03b..ba945f0 100644 --- a/src/game/world/trace.cpp +++ b/src/game/world/trace.cpp @@ -204,8 +204,8 @@ inline U8 point_in_inflated_poly( in = in * -1.0f; F32 dist = vec_dot( point - a, in ); - F32 expand = aabb_extend_at_feet( hull, in ).x; - if( dist < -expand - BSP_TRACE_EPSILON ) + F32 expand = aabb_support_radius( hull, in ); + if( dist < -( expand - BSP_TRACE_EPSILON * 4.f ) ) return 0; } return 1; @@ -226,9 +226,7 @@ U8 bsp_trace_sweep_aabb_to_face( VEC3 norm = bsp_face_get_normal( face ); F32 d = vec_dot( norm, face->verts[0].pos ); - VEC2 feet = aabb_extend_at_feet( hull, norm ); - F32 pos_r = feet.x, neg_r = feet.y; - F32 radius = norm.z >= 0 ? neg_r : pos_r; + F32 radius = aabb_support_radius( hull, norm ); VEC3 dir = end - start; F32 s0 = vec_dot( norm, trace->in_start ) - d; @@ -361,11 +359,22 @@ U8 bsp_trace_sweep_aabb( I32 near = (s_dist > 0.f) ? node->front : node->back; I32 far = (s_dist > 0.f) ? node->back : node->front; - if( bsp_trace_sweep_aabb( trace, bsp, hull, start, mid, near ) ) + BSP_TRACE tr_near = *trace; + BSP_TRACE tr_far = *trace; + + U8 hit_near = bsp_trace_sweep_aabb( &tr_near, bsp, hull, start, mid, near ); + U8 hit_far = bsp_trace_sweep_aabb( &tr_far , bsp, hull, mid, end, far ); + + if( hit_near && hit_far ) { + *trace = (tr_near.frac <= tr_far.frac) ? tr_near : tr_far; return 1; + } + + if( hit_near ) { *trace = tr_near; return 1; } + if( hit_far ) { *trace = tr_far; return 1; } if( tin <= BSP_TRACE_EPSILON || tin >= 1.f - BSP_TRACE_EPSILON ) { - F32 nudge = (denom >= 0.f ? 1.f : -1.f) * BSP_TRACE_EPSILON * 4.f; + F32 nudge = (denom >= 0.f ? 1.f : -1.f) * BSP_TRACE_EPSILON; VEC3 nudged = mid + dir * nudge; return bsp_trace_sweep_aabb( trace, bsp, hull, nudged, end, far ); } @@ -380,10 +389,19 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, AABB hull ) { trace->startsolid = 0; trace->hit = 0; bsp_trace_nudge( trace ); + VEC3 start = trace->in_start; VEC3 end = trace->in_end; - U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, start, end, bsp->root ); + // start hull at origin rather than in middle + trace->in_start.z += ( hull.max.z - hull.min.z ); + trace->in_end.z += ( hull.max.z - hull.min.z ); + + U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, trace->in_start, trace->in_end, bsp->root ); + + trace->in_start = start; + trace->in_end = end; + if( !ret ) trace->point = trace->in_end; return ret; |
