summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-02-27 04:43:15 +0100
committeraura <nw@moneybot.cc>2026-02-27 04:43:15 +0100
commitb24f37279bcc4b3abd92b697eadcec1feba8d276 (patch)
tree8fe58bee0ae000396d7d048a5630c15bf479af58
parentb384930de5044934207d1b2ceb4fa55705094f8b (diff)
fix edge collisions, update readme
-rw-r--r--README.md20
-rw-r--r--src/game/physics/movement.cpp58
-rw-r--r--src/game/player.cpp3
-rw-r--r--src/game/world/trace.cpp34
4 files changed, 95 insertions, 20 deletions
diff --git a/README.md b/README.md
index 868798b..f9961d1 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,23 @@
quake-based bsp renderer with a simple map editor
![screenshot](https://git.networkheaven.net/bsp3d/plain/assets/game.gif)
+
+current scope:
+
+* editor:
+- [ ] map tools
+- [ ] more convenient pickers for textures/colors when creating walls
+- [ ] 'paint' tool for textures/colors
+- [ ] horizontal 2d view
+- [ ] undo history
+- [ ] compiling/loading bsp to/from file
+* physics:
+- [ ] gamemovement
+- [ ] entity collisions
+- [ ] props in bsp mesh
+* render:
+- [ ] obj parser/render
+* general:
+- [ ] entity system
+- [ ] console
+- [ ] de-couple editor from game (IS_EDITOR define - compile without)
diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp
index c9b7688..ecee539 100644
--- a/src/game/physics/movement.cpp
+++ b/src/game/physics/movement.cpp
@@ -125,8 +125,6 @@ void gmove_accelerate( VEC3& wishdir, F32 wishspeed, F32 accel ) {
gmove->velocity += wishdir * accelspeed;
}
-// todo: player hull extends at center instead of at feet
-// should extend at feet
void gmove_stay_on_ground() {
BSP_TRACE tr{};
VEC3 start = gmove->pos;
@@ -155,9 +153,10 @@ void gmove_categorize_pos() {
}
-VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) {
- if( planes->size > 2 )
- vel = {};
+VEC3 gmove_clip_planes( VEC3 vel, VEC3* pos, LIST<VEC3>* planes, F32 overbounce ) {
+ if( planes->size > 2 ) {
+ return {};
+ }
planes->each( fn( VEC3* p ) {
vel = gmove_clip_velocity( vel, *p, overbounce );
@@ -168,6 +167,7 @@ VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) {
if( vec_dot( vel, planes->data[i] ) < 0.f ) {
VEC3 dir = vec_cross( planes->data[0], planes->data[1] );
F32 len = vec_len( dir );
+
if( len > 0.00001f ) {
dir *= 1.0f / len;
vel = dir * vec_dot( vel, dir );
@@ -183,6 +183,43 @@ VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) {
return vel;
}
+void gmove_check_stuck( VEC3* pos ) {
+ BSP_TRACE t;
+ bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos );
+ if( !t.hit )
+ return;
+
+ VEC3 p1 = *pos;
+
+ // try nudge away from wall
+ *pos = p1 + t.normal * BSP_TRACE_EPSILON * 2.f;
+ bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos );
+ if( !t.hit )
+ return;
+
+ // nudge +90deg away horizontal
+ *pos = p1 + VEC3{ -t.normal.y, t.normal.x, t.normal.z } * BSP_TRACE_EPSILON * 2.f;
+ bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos );
+ if( !t.hit )
+ return;
+
+ // nudge -90deg away horizontal
+ *pos = p1 + VEC3{ t.normal.y, -t.normal.x, t.normal.z } * BSP_TRACE_EPSILON * 2.f;
+ bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos );
+ if( !t.hit )
+ return;
+
+ // nudge -180deg away horizontal
+ *pos = p1 + VEC3{ t.normal.y, t.normal.x, -t.normal.z } * BSP_TRACE_EPSILON * 2.f;
+ bsp_trace( &t, gmove->bsp, gmove->aabb, *pos, *pos );
+ if( !t.hit )
+ return;
+
+ // todo : loop over every dir from current pos and incrementally increase distance.
+ // kinda like source
+ *pos = p1; // restore original pos - failed to unstuck
+}
+
F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) {
F32 dt = TICK_INTERVAL;
AABB aabb = gmove->aabb;
@@ -198,7 +235,8 @@ F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) {
*pos += wishmove * t->frac;
// nudge player away from wall
- *pos += t->normal * (BSP_TRACE_EPSILON * 2.f);
+ if( vec_dot( *vel, t->normal ) < 0.f )
+ *pos += t->normal * (BSP_TRACE_EPSILON * 2.f);
planes.push( t->normal );
@@ -206,7 +244,7 @@ F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) {
if( dt <= 0.0001f )
break;
- *vel = gmove_clip_planes( *vel, &planes, 1.f /* todo : surface friction */ );
+ *vel = gmove_clip_planes( *vel, pos, &planes, 1.f /* todo : surface friction */ );
}
return dt < 0 ? 0 : dt;
@@ -279,23 +317,23 @@ void gmove_walk_move() {
gmove_accelerate( wishdir, speed, var_getf( mv_accelerate ) );
speed = vec_len( vel );
+ defer( gmove_check_stuck( &gmove->pos ) );
if( speed < 1.f ) {
gmove->velocity = {};
return;
}
- VEC3 dest = gmove->pos + vel * TICK_INTERVAL;
+ VEC3 dest = gmove->pos + gmove->velocity * TICK_INTERVAL;
BSP_TRACE tr{};
bsp_trace( &tr, gmove->bsp, gmove->aabb, gmove->pos, dest );
+ defer( gmove_stay_on_ground() );
if( !tr.hit ) {
gmove->pos = dest;
- gmove_stay_on_ground();
return;
}
gmove_step_move( dest, &tr );
- gmove_stay_on_ground();
}
void gmove_full_walk_move() {
diff --git a/src/game/player.cpp b/src/game/player.cpp
index 74ecea2..c6bf385 100644
--- a/src/game/player.cpp
+++ b/src/game/player.cpp
@@ -6,8 +6,7 @@
#include <cmath>
#include "player.h"
-// todo : temporary
-F32 PLAYER_HULL_HEIGHT = 1.f;
+F32 PLAYER_HULL_HEIGHT = 48.f;
F32 PLAYER_HULL_WIDTH = 32.f;
PLAYER* player_create( VEC3 origin, F32 yaw ) {
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp
index fd6a03b..ba945f0 100644
--- a/src/game/world/trace.cpp
+++ b/src/game/world/trace.cpp
@@ -204,8 +204,8 @@ inline U8 point_in_inflated_poly(
in = in * -1.0f;
F32 dist = vec_dot( point - a, in );
- F32 expand = aabb_extend_at_feet( hull, in ).x;
- if( dist < -expand - BSP_TRACE_EPSILON )
+ F32 expand = aabb_support_radius( hull, in );
+ if( dist < -( expand - BSP_TRACE_EPSILON * 4.f ) )
return 0;
}
return 1;
@@ -226,9 +226,7 @@ U8 bsp_trace_sweep_aabb_to_face(
VEC3 norm = bsp_face_get_normal( face );
F32 d = vec_dot( norm, face->verts[0].pos );
- VEC2 feet = aabb_extend_at_feet( hull, norm );
- F32 pos_r = feet.x, neg_r = feet.y;
- F32 radius = norm.z >= 0 ? neg_r : pos_r;
+ F32 radius = aabb_support_radius( hull, norm );
VEC3 dir = end - start;
F32 s0 = vec_dot( norm, trace->in_start ) - d;
@@ -361,11 +359,22 @@ U8 bsp_trace_sweep_aabb(
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, mid, near ) )
+ BSP_TRACE tr_near = *trace;
+ BSP_TRACE tr_far = *trace;
+
+ U8 hit_near = bsp_trace_sweep_aabb( &tr_near, bsp, hull, start, mid, near );
+ U8 hit_far = bsp_trace_sweep_aabb( &tr_far , bsp, hull, mid, end, far );
+
+ if( hit_near && hit_far ) {
+ *trace = (tr_near.frac <= tr_far.frac) ? tr_near : tr_far;
return 1;
+ }
+
+ if( hit_near ) { *trace = tr_near; return 1; }
+ if( hit_far ) { *trace = tr_far; return 1; }
if( tin <= BSP_TRACE_EPSILON || tin >= 1.f - BSP_TRACE_EPSILON ) {
- F32 nudge = (denom >= 0.f ? 1.f : -1.f) * BSP_TRACE_EPSILON * 4.f;
+ F32 nudge = (denom >= 0.f ? 1.f : -1.f) * BSP_TRACE_EPSILON;
VEC3 nudged = mid + dir * nudge;
return bsp_trace_sweep_aabb( trace, bsp, hull, nudged, end, far );
}
@@ -380,10 +389,19 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, AABB hull ) {
trace->startsolid = 0;
trace->hit = 0;
bsp_trace_nudge( trace );
+
VEC3 start = trace->in_start;
VEC3 end = trace->in_end;
- U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, start, end, bsp->root );
+ // start hull at origin rather than in middle
+ trace->in_start.z += ( hull.max.z - hull.min.z );
+ trace->in_end.z += ( hull.max.z - hull.min.z );
+
+ U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, trace->in_start, trace->in_end, bsp->root );
+
+ trace->in_start = start;
+ trace->in_end = end;
+
if( !ret )
trace->point = trace->in_end;
return ret;