From 4d263a68547daaa560cdb9363ffe379df7a1076f Mon Sep 17 00:00:00 2001 From: aura Date: Thu, 5 Mar 2026 07:26:54 +0100 Subject: fix non-sweep traces, refactor some bsp, fix sprite crash in view2d --- src/editor/view2d.cpp | 24 ++++++--- src/game/physics/movement.cpp | 10 ++-- src/game/world/bsp.cpp | 2 + src/game/world/bsp.h | 18 +++++++ src/game/world/bsp_draw.cpp | 3 +- src/game/world/trace.cpp | 116 +++++++++++++++++++++--------------------- src/game/world/trace.h | 2 + 7 files changed, 103 insertions(+), 72 deletions(-) diff --git a/src/editor/view2d.cpp b/src/editor/view2d.cpp index b68846e..c1ef5ea 100644 --- a/src/editor/view2d.cpp +++ b/src/editor/view2d.cpp @@ -630,13 +630,23 @@ void gui_editor_2dview_draw_sprites( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { gui_draw_rect( pos.x - w/2 - 1, pos.y - h/2 - 1, w + 2, h + 2, CLR::WHITE( 0.5f ) ); } - gl_2d_textured_frect( - _gui.gl2d_font, - { (F32)((I32)pos.x - w/2), (F32)((I32)pos.y - h/2) }, - { (F32)w, (F32)h }, - s->tex, - s->clr - ); + else { + gl_2d_frect( + _gui.gl2d, + { (F32)((I32)pos.x - w/2), (F32)((I32)pos.y - h/2) }, + { (F32)w, (F32)h }, + s->clr + ); + } + if( s->tex ) { + gl_2d_textured_frect( + _gui.gl2d_font, + { (F32)((I32)pos.x - w/2), (F32)((I32)pos.y - h/2) }, + { (F32)w, (F32)h }, + s->tex, + s->clr + ); + } } ); } diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp index 9f1a7dd..d689096 100644 --- a/src/game/physics/movement.cpp +++ b/src/game/physics/movement.cpp @@ -154,7 +154,7 @@ U8 gmove_touch_ground_quadrants( BSP_TRACE* tr, VEC3 start, VEC3 end ) { void gmove_categorize_pos() { gmove->pl->surf_friction = 1.f; F32 offset = 2.f; - BSP_TRACE tr{}; + BSP_TRACE tr{ .hitmask = HG_MOVEMENT }; VEC3 point = gmove->pos; point.z -= offset; @@ -282,7 +282,7 @@ F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { } void gmove_check_stuck( VEC3* in_pos ) { - BSP_TRACE t; + BSP_TRACE t{ .hitmask = HG_MOVEMENT }; VEC3 pos = *in_pos; U32 i; if( vec_len( gmove->unstuck_vel ) < 0.f ) @@ -417,7 +417,7 @@ void gmove_friction() { } void gmove_stay_on_ground() { - BSP_TRACE tr{}; + BSP_TRACE tr{ .hitmask = HG_MOVEMENT }; VEC3 start = gmove->pos; VEC3 end = gmove->pos; @@ -547,7 +547,7 @@ void gmove_walk_move() { VEC3 dest = gmove->pos + gmove->velocity * TICK_INTERVAL; - BSP_TRACE tr{}; + BSP_TRACE tr{ .hitmask = HG_MOVEMENT }; bsp_trace( &tr, gmove->bsp, gmove->aabb, gmove->pos, dest ); defer( gmove_stay_on_ground() ); @@ -582,7 +582,7 @@ void gmove_air_move() { gmove_airaccelerate( wishdir, speed, var_getf( mv_airaccelerate ) ); - BSP_TRACE tr{}; + BSP_TRACE tr{ .hitmask = HG_MOVEMENT }; gmove_try_move( &tr, &gmove->pos, &gmove->velocity ); gmove_check_stuck( &gmove->pos ); } diff --git a/src/game/world/bsp.cpp b/src/game/world/bsp.cpp index 4894d1c..f5fb0e9 100644 --- a/src/game/world/bsp.cpp +++ b/src/game/world/bsp.cpp @@ -168,6 +168,7 @@ LIST bsp_map_faces_from_walls( WORLD_MAP* map ) { f.verts.push( vertices[1] ); f.verts.push( vertices[0] ); f.verts.push( vertices[3] ); + f.hitmask = HM_WORLD; ret.push( f ); }; @@ -188,6 +189,7 @@ LIST bsp_map_faces_from_planes( WORLD_MAP* map ) { f.verts.push( *start ); f.verts.push( *last ); f.verts.push( p->vertices[i] ); + f.hitmask = HM_WORLD; ret.push( f ); last = &p->vertices[i]; diff --git a/src/game/world/bsp.h b/src/game/world/bsp.h index fa06696..ac72e14 100644 --- a/src/game/world/bsp.h +++ b/src/game/world/bsp.h @@ -25,6 +25,23 @@ enum BspSide_t { BSP_SIDE_SPAN = 8, }; +enum HitMask_t { + HM_NONE = 0, + HM_WORLD = 1 << 1, + HM_PROP = 1 << 2, + HM_ENTITY = 1 << 3, + HM_PLAYER = 1 << 4, + HM_ANY = 0xffffffff +}; + +enum HitGroup_t { + HG_NONE = 0, + HG_MOVEMENT = HM_WORLD | HM_PROP, + HG_BULLET = HM_WORLD | HM_PROP | HM_ENTITY, + HG_SOLID = HM_WORLD | HM_PROP | HM_ENTITY, + HG_ANY = 0xffffffff +}; + struct BSP_FACE { I32 propid; I32 id; @@ -32,6 +49,7 @@ struct BSP_FACE { LIST render_verts{}; VEC3 mins; VEC3 maxs; + U32 hitmask; }; struct BSP_NODE { diff --git a/src/game/world/bsp_draw.cpp b/src/game/world/bsp_draw.cpp index 30e6731..3f5b067 100644 --- a/src/game/world/bsp_draw.cpp +++ b/src/game/world/bsp_draw.cpp @@ -2,6 +2,7 @@ #include "../../game.h" #include "../../render/gl_3d.h" #include "../objlist.h" +#include "bsp.h" #include "map.h" #include "trace.h" @@ -70,7 +71,7 @@ void bsp_draw_sprites( BSP* bsp, GAME_DATA* game ) { LIST* sprites = &game->state.map->sprites; for( U32 i = 0; i < sprites->size; ++i ) { MAP_SPRITE* sprite = &sprites->data[i]; - BSP_TRACE t; + BSP_TRACE t{ .hitmask = HG_SOLID }; t.in_start = player_get_view_pos( objl->pl ); t.in_end = sprite->pos; diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp index b1f91a3..893c679 100644 --- a/src/game/world/trace.cpp +++ b/src/game/world/trace.cpp @@ -3,13 +3,23 @@ #include "bsp.h" #include "map.h" +U8 bsp_trace_should_hit_face( BSP_TRACE* tr, BSP_FACE* face ) { + if( face->propid == MAPPROP_SKYBOX ) + return 0; + if( !(face->hitmask & tr->hitmask) ) + return 0; + + return 1; +} + // i have no idea how this works tbh i pasted this // todo : backface culling (return 0 if d < BSP_TRACE_EPSILON) -U8 bsp_segment_intersects_tri( +U8 bsp_trace_intersects_face( const VEC3& va, const VEC3& vb, const VEC3& v0, const VEC3& v1, const VEC3& v2, F32* fract, - VEC2* out_uv = 0 + VEC2* out_uv = 0, + I32 leaf_idx = 0 ) { VEC3 dir = vb - va; VEC3 e1 = v1 - v0, @@ -17,9 +27,10 @@ U8 bsp_segment_intersects_tri( VEC3 p = vec_cross( dir, e2 ); F32 d = vec_dot( e1, p ); + if( d < 0 ) + d *= -1.0f; - if( fabsf( d ) < BSP_TRACE_EPSILON ) { - // parallel + if( fabsf( d ) <= BSP_NORM_EPSILON ) { return 0; } @@ -52,7 +63,7 @@ U8 bsp_segment_intersects_tri( return 1; } -U8 bsp_trace_leaf_segment( BSP_TRACE* trace, BSP* bsp, I32 leafidx, const VEC3& va, const VEC3& vb ) { +U8 bsp_trace_leaf( BSP_TRACE* trace, BSP* bsp, I32 leafidx, const VEC3& start, const VEC3& end ) { BSP_LEAF* leaf = &bsp->leaves.data[leafidx]; U8 didhit = 0; F32 best = FLT_MAX; @@ -60,6 +71,9 @@ U8 bsp_trace_leaf_segment( BSP_TRACE* trace, BSP* bsp, I32 leafidx, const VEC3& for( U32 i = 0; i < leaf->count; ++i ) { BSP_FACE* face = &bsp->faces.data[leaf->first + i]; + if( !bsp_trace_should_hit_face( trace, face ) ) + continue; + // shouldnt happen if( face->verts.size < 3 ) continue; @@ -69,19 +83,17 @@ U8 bsp_trace_leaf_segment( BSP_TRACE* trace, BSP* bsp, I32 leafidx, const VEC3& VEC3 v1 = face->verts[t0].pos; VEC3 v2 = face->verts[t0 + 1].pos; - // todo : skip func for props - F32 t; VEC2 uv; - if( !bsp_segment_intersects_tri( va, vb, v0, v1, v2, &t, &uv ) ) + if( !bsp_trace_intersects_face( start, end, v0, v1, v2, &t, &uv, leafidx ) ) continue; if( t < best ) { best = t; trace->hit = didhit = 1; trace->frac = t; - trace->point = va + (vb - va) * t; + trace->point = start + (end - start) * t; trace->normal = vec_normalize( vec_cross( v1 - v0, v2 - v0 ) ); trace->propid = face->propid; trace->leafid = leafidx; @@ -93,43 +105,38 @@ U8 bsp_trace_leaf_segment( BSP_TRACE* trace, BSP* bsp, I32 leafidx, const VEC3& return didhit; } -U8 bsp_trace_segment( BSP_TRACE* trace, BSP* bsp, I32 nodeidx, const VEC3& va, const VEC3& vb ) { +U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, I32 nodeidx, const VEC3& start, const VEC3& end ) { if( bsp_is_leaf( nodeidx ) ) { I32 i = bsp_leaf_index( nodeidx ); - return bsp_trace_leaf_segment( trace, bsp, i, va, vb ); + return bsp_trace_leaf( trace, bsp, i, start, end ); } BSP_NODE* node = &bsp->nodes.data[nodeidx]; - F32 da = bsp_plane_dist( node->plane, va ); - F32 db = bsp_plane_dist( node->plane, vb ); + F32 da = bsp_plane_dist( node->plane, start ); + F32 db = bsp_plane_dist( node->plane, end ); if( da > BSP_TRACE_EPSILON && db > BSP_TRACE_EPSILON ) - return bsp_trace_segment( trace, bsp, node->front, va, vb ); + return bsp_trace( trace, bsp, node->front, start, end ); if( da < -BSP_TRACE_EPSILON && db < -BSP_TRACE_EPSILON ) - return bsp_trace_segment( trace, bsp, node->back, va, vb ); + return bsp_trace( trace, bsp, node->back, start, end ); - VEC3 dir = vb - va; + VEC3 dir = end - start; F32 denom = vec_dot( node->plane.normal, dir ); I32 near = (da >= 0.f) ? node->front : node->back; I32 far = (da >= 0.f) ? node->back : node->front; if( fabsf( denom ) < BSP_TRACE_EPSILON ) { - if( bsp_trace_segment( trace, bsp, near, va, vb ) ) + if( bsp_trace( trace, bsp, near, start, end ) ) return 1; - return bsp_trace_segment( trace, bsp, far, va, vb ); + return bsp_trace( trace, bsp, far, start, end ); } - F32 t = (node->plane.dist - vec_dot( node->plane.normal, va ) ) / denom; + F32 t = (node->plane.dist - vec_dot( node->plane.normal, start ) ) / denom; t = m_clamp( t, 0.f, 1.f ); - VEC3 iplane = va + dir * t; - if( bsp_trace_segment( trace, bsp, near, va, iplane ) ) + if( bsp_trace( trace, bsp, near, start, end ) ) return 1; - if( t <= BSP_TRACE_EPSILON || t >= 1.0f - BSP_TRACE_EPSILON ) { - return bsp_trace_segment( trace, bsp, far, iplane, vb ); - } - - return bsp_trace_segment( trace, bsp, far, iplane, vb ); + return bsp_trace( trace, bsp, far, start, end ); } // nudge the trace ends slightly to prevent exact-coplanar infinite recursion. @@ -170,7 +177,7 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp ) { VEC3 start = trace->in_start; VEC3 end = trace->in_end; - return bsp_trace_segment( trace, bsp, bsp->root, start, end ); + return bsp_trace( trace, bsp, bsp->root, start, end ); } F32 hull_proj_radius( const AABB& hull, VEC3 dir ) { @@ -225,10 +232,6 @@ inline U8 point_in_inflated_poly( ++axis; } - if( axis == 3 ) - continue; - - if( !axis ) { // project closest hull corner onto plane VEC3 diag = in; diag *= -1; @@ -252,8 +255,6 @@ U8 bsp_trace_sweep_aabb_to_face( BSP_TRACE* trace, const AABB& hull, BSP_FACE* face, - const VEC3& start, - const VEC3& end, U32 face_idx ) { if( face->verts.size < 3 ) @@ -275,11 +276,11 @@ U8 bsp_trace_sweep_aabb_to_face( 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 ) ) { + if( aabb_contains_point( fhullh, trace->in_start ) && point_in_inflated_poly( trace->in_start, face, hull, norm ) ) { trace->hit = 1; trace->frac = 0.f; trace->startsolid = 1; - trace->point = start; + trace->point = trace->in_start; trace->normal = norm; trace->propid = face->propid; trace->faceid = face_idx; @@ -315,8 +316,6 @@ 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 ) { @@ -331,8 +330,8 @@ U8 bsp_trace_sweep_aabb_to_leaf_edges( BSP_EDGE* e = &leaf->edges[i]; BSP_FACE* f = &bsp->faces.data[e->face]; - if( f->propid == MAPPROP_SKYBOX ) - continue; + if( !bsp_trace_should_hit_face( trace, f ) ) + continue; VEC3 n = e->plane.normal; F32 d = e->plane.dist; @@ -407,8 +406,6 @@ U8 bsp_trace_sweep_aabb_to_leaf( BSP* bsp, BSP_TRACE* trace, const AABB& hull, - const VEC3& start, - const VEC3& end, I32 leaf_idx ) { BSP_LEAF* leaf = &bsp->leaves.data[leaf_idx]; @@ -422,11 +419,11 @@ U8 bsp_trace_sweep_aabb_to_leaf( U32 face_idx = leaf->first + i; BSP_FACE* f = &bsp->faces.data[face_idx]; - if( f->propid == MAPPROP_SKYBOX ) + if( !bsp_trace_should_hit_face( trace, f ) ) continue; BSP_TRACE tr = *trace; - if( !bsp_trace_sweep_aabb_to_face( &tr, hull, f, start, end, face_idx ) ) + if( !bsp_trace_sweep_aabb_to_face( &tr, hull, f, face_idx ) ) continue; if( tr.frac < best ) { @@ -438,7 +435,7 @@ 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 ); + U8 ehit = bsp_trace_sweep_aabb_to_leaf_edges( bsp, &edgehit, hull, leaf_idx, &best ); if( hit || ehit ) { if( ehit && !hit ) *trace = edgehit; @@ -461,13 +458,13 @@ U8 bsp_trace_sweep_aabb( BSP_TRACE* trace, BSP* bsp, const AABB& hull, - const VEC3& start, - const VEC3& end, I32 node_idx ) { + VEC3 start = trace->in_start; + VEC3 end = trace->in_end; if( bsp_is_leaf( node_idx ) ) { I32 i = bsp_leaf_index( node_idx ); - return bsp_trace_sweep_aabb_to_leaf( bsp, trace, hull, start, end, i ); + return bsp_trace_sweep_aabb_to_leaf( bsp, trace, hull, i ); } BSP_NODE* node = &bsp->nodes.data[node_idx]; @@ -479,10 +476,10 @@ U8 bsp_trace_sweep_aabb( F32 offset = aabb_support_radius( hull, n ); if( s_dist > offset && e_dist > offset ) - return bsp_trace_sweep_aabb( trace, bsp, hull, start, end, node->front ); + return bsp_trace_sweep_aabb( trace, bsp, hull, node->front ); if( s_dist < -offset && e_dist < -offset ) - return bsp_trace_sweep_aabb( trace, bsp, hull, start, end, node->back ); + return bsp_trace_sweep_aabb( trace, bsp, hull, node->back ); VEC3 dir = end - start; F32 denom = ( e_dist - s_dist ); @@ -490,9 +487,9 @@ U8 bsp_trace_sweep_aabb( if( fabsf(denom) < BSP_TRACE_EPSILON ) { 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, end, near ) ) + if( bsp_trace_sweep_aabb( trace, bsp, hull, near ) ) return 1; - return bsp_trace_sweep_aabb( trace, bsp, hull, start, end, far ); + return bsp_trace_sweep_aabb( trace, bsp, hull, far ); } F32 tin = ( offset - s_dist) / denom; @@ -508,8 +505,8 @@ U8 bsp_trace_sweep_aabb( BSP_TRACE tr_near = *trace; BSP_TRACE tr_far = *trace; - U8 hit_near = bsp_trace_sweep_aabb( &tr_near, bsp, hull, start, end, near ); - U8 hit_far = bsp_trace_sweep_aabb( &tr_far , bsp, hull, start, end, far ); + U8 hit_near = bsp_trace_sweep_aabb( &tr_near, bsp, hull, near ); + U8 hit_far = bsp_trace_sweep_aabb( &tr_far , bsp, hull, far ); if( hit_near && hit_far ) { *trace = (tr_near.frac <= tr_far.frac) ? tr_near : tr_far; @@ -522,10 +519,11 @@ U8 bsp_trace_sweep_aabb( if( tin <= BSP_TRACE_EPSILON || tin >= 1.f - BSP_TRACE_EPSILON ) { F32 nudge = (denom >= 0.f ? 1.f : -1.f) * BSP_TRACE_EPSILON; VEC3 nudged = start + dir * nudge; - return bsp_trace_sweep_aabb( trace, bsp, hull, nudged, end, far ); + trace->in_start = nudged; + return bsp_trace_sweep_aabb( trace, bsp, hull, far ); } - return bsp_trace_sweep_aabb(trace, bsp, hull, start, end, far ); + return bsp_trace_sweep_aabb(trace, bsp, hull, far ); } U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, AABB hull ) { @@ -545,13 +543,13 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, AABB hull ) { trace->in_start += off; trace->in_end += off; - U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, trace->in_start, trace->in_end, bsp->root ); + U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, bsp->root ); - trace->in_start -= off; - trace->in_end -= off; + trace->in_start = start; + trace->in_end = end; if( !ret ) - trace->point = trace->in_end; + trace->point = end; else trace->point -= off; diff --git a/src/game/world/trace.h b/src/game/world/trace.h index d04ed6b..31ed28c 100644 --- a/src/game/world/trace.h +++ b/src/game/world/trace.h @@ -11,6 +11,8 @@ struct BSP_TRACE { VEC3 in_start; VEC3 in_end; + U32 hitmask = HM_ANY; + U8 hit; F32 frac; VEC3 point; -- cgit v1.2.3