diff options
Diffstat (limited to 'src/game/world/trace.cpp')
| -rw-r--r-- | src/game/world/trace.cpp | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp index 6d1e8db..61e3da4 100644 --- a/src/game/world/trace.cpp +++ b/src/game/world/trace.cpp @@ -218,16 +218,18 @@ U8 bsp_trace_sweep_aabb_to_face( if( face->verts.size < 3 ) return 0; - VEC3 norm = bsp_face_get_normal( face ); - F32 d = vec_dot( norm, face->verts[0].pos ); - F32 radius = aabb_support_radius( hull, norm ); + VEC3 hullh = (hull.max - hull.min) * 0.5f; + AABB fhull = { face->mins - hullh, face->maxs + hullh }; + VEC3 norm = bsp_face_get_normal( face ); + F32 d = vec_dot( norm, face->verts[0].pos ); + F32 radius = aabb_support_radius( hull, norm ); - VEC3 dir = end - start; + VEC3 dir = trace->in_end - trace->in_start; F32 s0 = vec_dot( norm, trace->in_start ) - d; F32 ndir = vec_dot( norm, trace->in_end - trace->in_start ); if( fabsf( s0 ) <= radius + BSP_TRACE_EPSILON ) { - if( point_in_inflated_poly( start, face, hull, norm ) ) { + if( aabb_contains_point( fhull, start ) && point_in_inflated_poly( start, face, hull, norm ) ) { trace->hit = 1; trace->frac = 0.f; trace->startsolid = 1; @@ -250,7 +252,10 @@ U8 bsp_trace_sweep_aabb_to_face( return 0; F32 t = m_clamp( t_enter, 0.f, 1.f ); - VEC3 step = start + dir * t; + VEC3 step = trace->in_start + dir * t; + + if( !aabb_contains_point( fhull, step ) ) + return 0; if( !point_in_inflated_poly( step, face, hull, norm ) ) return 0; @@ -276,7 +281,7 @@ U8 bsp_trace_sweep_aabb_to_leaf_edges( BSP_LEAF* leaf = &bsp->leaves.data[leaf_idx]; U8 hit = 0; F32 best = *in_best; - + BSP_TRACE besthit = *trace; for( U32 i = 0; i < leaf->edges.size; ++i ) { BSP_EDGE* e = &leaf->edges[i]; @@ -294,15 +299,31 @@ U8 bsp_trace_sweep_aabb_to_leaf_edges( if( ndir >= 0.f ) continue; if( s0 < -(r + BSP_TRACE_EPSILON) ) continue; - - F32 t = (-r - s0) / ndir; - if( t < 0.f || t > 1.f ) continue; - t = m_clamp( t, 0.f, 1.f ); + + F32 t_enter = ( r - s0) / ndir; + 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 ) + continue; + F32 t = m_clamp( t_enter, 0.f, 1.f ); VEC3 step = start + (end - start) * t; - if( !point_in_inflated_poly( step, f, hull, n ) ) + VEC3 edir = e->v2 - e->v1; + F32 elen = vec_len( edir ); + if( elen < 0.001f ) continue; + edir *= (1.f / elen); + + 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 ); + if( dist > BSP_TRACE_EPSILON ) { + F32 expand = aabb_support_radius( hull, vec_normalize( step - proj ) ); + if( dist < -(expand) || dist > expand ) + continue; + } if( t < best ) { best = t; @@ -338,6 +359,7 @@ U8 bsp_trace_sweep_aabb_to_leaf( F32 best = FLT_MAX; BSP_TRACE besthit = *trace; + BSP_TRACE edgehit = *trace; for( U32 i = 0; i < leaf->count; ++i ) { U32 face_idx = leaf->first + i; @@ -358,14 +380,22 @@ U8 bsp_trace_sweep_aabb_to_leaf( } } - U8 ehit = bsp_trace_sweep_aabb_to_leaf_edges( bsp, trace, hull, start, end, leaf_idx, &best ); - if( !hit ) hit = ehit; - - if( hit ) { - *trace = besthit; + 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 ) + *trace = edgehit; + else + *trace = besthit; trace->hit = 1; + return 1; } - return hit; + + return 0; } U8 bsp_trace_sweep_aabb( |
