summaryrefslogtreecommitdiff
path: root/src/game/world/trace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/world/trace.cpp')
-rw-r--r--src/game/world/trace.cpp116
1 files changed, 57 insertions, 59 deletions
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;