summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-03-04 18:58:21 +0100
committeraura <nw@moneybot.cc>2026-03-04 18:58:21 +0100
commit73045b6642348c8d2fd8b45cae305bbf0344d444 (patch)
tree9898f64cc14f4e95b147e0fab4b9004e41109780 /src/game
parentfc12cd41c56bc123f01bc073b703fb151dfde814 (diff)
more collision improv
Diffstat (limited to 'src/game')
-rw-r--r--src/game/physics/movement.cpp10
-rw-r--r--src/game/world/bsp.cpp16
-rw-r--r--src/game/world/bsp.h10
-rw-r--r--src/game/world/trace.cpp44
4 files changed, 50 insertions, 30 deletions
diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp
index fce9d73..0b174e0 100644
--- a/src/game/physics/movement.cpp
+++ b/src/game/physics/movement.cpp
@@ -186,9 +186,6 @@ void gmove_categorize_pos() {
gmove->ground = objl->world;
}
}
-
- if( gmove->ground )
- gmove->velocity.z = 0.f;
}
VEC3 gmove_clip_velocity( VEC3 in, VEC3 norm, F32 overbounce ) {
@@ -433,8 +430,8 @@ void gmove_stay_on_ground() {
if( tr.frac > 0.f && tr.frac < 1.f && !tr.startsolid && tr.normal.z >= 0.7f ) {
F32 delta = fabs( gmove->pos.z - tr.point.z );
- if( delta > BSP_TRACE_EPSILON ) {
- gmove->pos = tr.point + tr.normal * BSP_TRACE_EPSILON * 2.f;
+ if( delta > BSP_TRACE_EPSILON * 0.5f ) {
+ gmove->pos = tr.point;
gmove_check_stuck( &gmove->pos );
}
}
@@ -636,6 +633,9 @@ void gmove_full_walk_move() {
gmove_categorize_pos();
gmove_end_gravity();
+ if( gmove->ground )
+ gmove->velocity.z = 0.f;
+
gmove_check_falling();
}
diff --git a/src/game/world/bsp.cpp b/src/game/world/bsp.cpp
index 7f72e52..c33cac1 100644
--- a/src/game/world/bsp.cpp
+++ b/src/game/world/bsp.cpp
@@ -417,6 +417,10 @@ I32 bsp_build_nodes(
}
U8 bsp_edge_is_shared( BSP* bsp, VEC3 edge1a, VEC3 edge1b, VEC3 center, VEC3 ecross, U32 facei ) {
+ BSP_FACE* face = &bsp->faces[facei];
+ VEC3 n = bsp_face_get_normal( face );
+ U8 aligned = bsp_face_is_axis_aligned( face );
+
for( U32 i = 0; i < bsp->faces.size; ++i ) {
if( facei == i )
continue;
@@ -425,6 +429,12 @@ U8 bsp_edge_is_shared( BSP* bsp, VEC3 edge1a, VEC3 edge1b, VEC3 center, VEC3 ecr
if( other->verts.size < 3 )
continue;
+ VEC3 othern = bsp_face_get_normal( face );
+ F32 d = vec_dot( n, othern );
+ // dont create edge planes for planes that are axis-aligned and directly perpendicular
+ if( aligned && (d < BSP_NORM_EPSILON || d > 1.f - BSP_NORM_EPSILON) )
+ continue;
+
VEC3 otherc{};
for( U32 vi = 0; vi < other->verts.size; ++vi )
otherc += other->verts[vi].pos;
@@ -487,9 +497,6 @@ void bsp_gen_leaf_edges( BSP* bsp, I32 leaf_idx ) {
if( fabsf( vec_dot( cross, facen ) ) > 0.995f )
continue;
- if( !bsp_edge_is_shared( bsp, a, b, center, cross, faceidx ) )
- continue;
-
F32 d = vec_dot( cross, a );
BSP_PLANE plane = { cross, d };
U8 dupe = 0;
@@ -500,6 +507,9 @@ void bsp_gen_leaf_edges( BSP* bsp, I32 leaf_idx ) {
if( dupe )
continue;
+ if( !bsp_edge_is_shared( bsp, a, b, center, cross, faceidx ) )
+ continue;
+
BSP_EDGE e;
e.plane = plane;
e.face = faceidx;
diff --git a/src/game/world/bsp.h b/src/game/world/bsp.h
index 8892108..3b84e07 100644
--- a/src/game/world/bsp.h
+++ b/src/game/world/bsp.h
@@ -125,6 +125,16 @@ inline VEC3 bsp_face_get_normal( BSP_FACE* f ){
return vec_normalize( vec_cross( v1 - v0, v2 - v0 ) );
}
+inline U8 bsp_face_is_axis_aligned( BSP_FACE* f ) {
+ VEC3 n = bsp_face_get_normal( f );
+ for( U32 i = 0; i < 3; ++i ) {
+ if( n[i] && fabsf( n[i] ) != 1.f )
+ return 0;
+ }
+
+ return 1;
+}
+
inline void bsp_face_calc_extents( BSP_FACE* f ) {
VEC3 mins{ +INFINITY, +INFINITY, +INFINITY }, maxs{ -INFINITY, -INFINITY, -INFINITY };
for( U32 i = 0; i < f->verts.size; ++i ) {
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp
index 1d32afe..25c0477 100644
--- a/src/game/world/trace.cpp
+++ b/src/game/world/trace.cpp
@@ -226,9 +226,7 @@ U8 bsp_trace_sweep_aabb_to_face(
if( face->verts.size < 3 )
return 0;
- VEC3 hullv = hull.max - hull.min;
- AABB fhull = { face->mins - hullv, face->maxs + hullv };
- AABB fhullh = { face->mins - hullv * 0.5f, face->maxs + hullv * 0.5f };
+
VEC3 norm = bsp_face_get_normal( face );
F32 d = vec_dot( norm, face->verts[0].pos );
F32 radius = aabb_support_radius( hull, norm );
@@ -237,19 +235,19 @@ U8 bsp_trace_sweep_aabb_to_face(
F32 s0 = vec_dot( norm, trace->in_start ) - d;
F32 ndir = vec_dot( norm, dir );
- F32 tdot = vec_dot( dir, norm );
- if( tdot >= 0 ) // dont collide with rear side
+ if( ndir >= 0 ) // dont collide with rear side
return 0;
+ VEC3 hullv = hull.max - hull.min;
+ for( U32 i = 0; i < 3; ++i ) hullv[i] += BSP_EDGE_TOLERANCE;
+ AABB fhullh = { face->mins - hullv * 0.5f, face->maxs + hullv * 0.5f };
+
if( fabsf( s0 ) <= radius + BSP_TRACE_EPSILON ) {
if( aabb_contains_point( fhullh, start ) && point_in_inflated_poly( start, face, hull, norm ) ) {
trace->hit = 1;
trace->frac = 0.f;
trace->startsolid = 1;
trace->point = start;
- trace->point.x = m_clamp( trace->point.x, fhullh.min.x, fhullh.max.x );
- trace->point.y = m_clamp( trace->point.y, fhullh.min.y, fhullh.max.y );
- trace->point.z = m_clamp( trace->point.z, fhullh.min.z, fhullh.max.z );
trace->normal = norm;
trace->propid = face->propid;
trace->faceid = face_idx;
@@ -266,16 +264,12 @@ U8 bsp_trace_sweep_aabb_to_face(
F32 t = m_clamp( t_enter, 0.f, 1.f );
VEC3 step = trace->in_start + dir * t;
- if( !aabb_contains_point( fhull, step ) )
+ if( !aabb_contains_point( fhullh, step ) )
return 0;
if( !point_in_inflated_poly( step, face, hull, norm ) )
return 0;
- step.x = m_clamp( step.x, fhullh.min.x, fhullh.max.x );
- step.y = m_clamp( step.y, fhullh.min.y, fhullh.max.y );
- step.z = m_clamp( step.z, fhullh.min.z, fhullh.max.z );
-
trace->hit = 1;
trace->frac = t;
trace->point = step;
@@ -320,7 +314,7 @@ U8 bsp_trace_sweep_aabb_to_leaf_edges(
F32 t_exit = (-r - s0) / ndir;
if( t_enter > t_exit ) { F32 tmp = t_enter; t_enter = t_exit; t_exit = tmp; }
- if( t_exit < -BSP_TRACE_EPSILON || t_enter > 1.f + BSP_TRACE_EPSILON )
+ if( t_exit < 0.f || t_enter > 1.f )
continue;
F32 t = m_clamp( t_enter, 0.f, 1.f );
@@ -335,12 +329,15 @@ U8 bsp_trace_sweep_aabb_to_leaf_edges(
F32 along = vec_dot( step - e->v1, edir );
VEC3 proj = e->v1 + edir * m_clamp( along, 0.f, elen );
F32 dist = vec_dist( proj, step );
+ VEC3 ec = vec_cross( edir, n );
+ F32 nlen = vec_len( ec );
+ if( nlen < 0.001f )
+ continue;
+ ec *= (1.f / nlen);
- F32 expand = aabb_support_radius( hull, n );
- if( dist > BSP_TRACE_EPSILON ) {
- if( dist > expand - BSP_EDGE_TOLERANCE )
- continue;
- }
+ F32 expand = aabb_support_radius( hull, ec );
+ if( dist - expand > r * 0.5f )
+ continue;
if( t < best ) {
best = t;
@@ -397,17 +394,20 @@ U8 bsp_trace_sweep_aabb_to_leaf(
}
}
+ best = FLT_MAX;
U8 ehit = bsp_trace_sweep_aabb_to_leaf_edges( bsp, &edgehit, hull, start, end, leaf_idx, &best );
-
if( hit || ehit ) {
if( ehit && !hit )
*trace = edgehit;
else if( !ehit && hit )
*trace = besthit;
- else if( edgehit.frac < besthit.frac )
+ else if( edgehit.frac <= besthit.frac + BSP_TRACE_EPSILON )
*trace = edgehit;
- else
+ else {
*trace = besthit;
+ if( edgehit.normal.z > besthit.normal.z )
+ trace->normal.z = edgehit.normal.z;
+ }
trace->hit = 1;
return 1;
}