diff options
Diffstat (limited to 'src/game/world/trace.cpp')
| -rw-r--r-- | src/game/world/trace.cpp | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp index 3548fa8..6d1e8db 100644 --- a/src/game/world/trace.cpp +++ b/src/game/world/trace.cpp @@ -1,6 +1,7 @@ #include "trace.h" #include "../../util/math.h" #include "bsp.h" +#include "map.h" // i have no idea how this works tbh i pasted this // todo : backface culling (return 0 if d < BSP_TRACE_EPSILON) @@ -172,12 +173,7 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp ) { return bsp_trace_segment( trace, bsp, bsp->root, start, end ); } -inline VEC3 bsp_face_get_normal( const BSP_FACE* f ){ - const VEC3 v0 = f->verts.data[0].pos; - const VEC3 v1 = f->verts.data[1].pos; - const VEC3 v2 = f->verts.data[2].pos; - return vec_normalize( vec_cross( v1 - v0, v2 - v0 ) ); -} + inline U8 point_in_inflated_poly( const VEC3& point, @@ -268,6 +264,67 @@ U8 bsp_trace_sweep_aabb_to_face( return 1; } +U8 bsp_trace_sweep_aabb_to_leaf_edges( + BSP* bsp, + BSP_TRACE* trace, + const AABB& hull, + const VEC3& start, + const VEC3& end, + I32 leaf_idx, + F32* in_best +) { + 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]; + BSP_FACE* f = &bsp->faces.data[e->face]; + + if( f->propid == MAPPROP_SKYBOX ) + continue; + + VEC3 n = e->plane.normal; + F32 d = e->plane.dist; + F32 r = aabb_support_radius( hull, n ); + + F32 s0 = vec_dot( n, start ) - d; + F32 ndir = vec_dot( n, end - start ); + + 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 ); + + VEC3 step = start + (end - start) * t; + + if( !point_in_inflated_poly( step, f, hull, n ) ) + continue; + + if( t < best ) { + best = t; + *in_best = best; + besthit.frac = t; + besthit.point = step; + besthit.normal = n; + besthit.propid = f->propid; + besthit.faceid = e->face; + besthit.leafid = leaf_idx; + hit = 1; + } + } + + if( hit ) { + *trace = besthit; + trace->hit = 1; + } + + return hit; +} + U8 bsp_trace_sweep_aabb_to_leaf( BSP* bsp, BSP_TRACE* trace, @@ -301,6 +358,9 @@ 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; trace->hit = 1; |
