group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
physics Namespace Reference

Pure physics math — no ECS types, no registry. More...

Namespaces

namespace  detail
 Active world (runtime-switchable).

Classes

struct  MapCollisionData
 Collision data. More...
struct  MapLoadOptions
 Load options. More...
struct  HitscanHit
 Result of a hitscan raycast. More...
struct  HitboxHit
 Skeleton-driven hitbox raycast (capsule-based). More...
struct  Plane
 An infinite plane dividing free space from solid geometry. More...
struct  WorldAABB
 An axis-aligned box in world space, used as static collision geometry. More...
struct  WorldBrush
 A convex volume defined by bounding planes (for ramps, angled walls, etc.). More...
struct  WorldCylinder
 A vertical (Y-axis) cylinder in world space. More...
struct  WorldSphere
 A sphere in world space. More...
struct  BVHNode
 A single BVH node for spatial acceleration of triangle meshes. More...
struct  WorldTriMesh
 A triangle mesh with BVH acceleration for collision queries. More...
struct  WorldGeometry
 All world collision geometry for one tick. More...
struct  HitResult
 Result of a swept AABB collision query. More...
struct  SphereHitResult
 Result of a sphere-cast query (includes world-space hit point). More...
struct  WallDetectionResult
 Results of wall detection sphere casts. More...

Functions

bool loadMapCollision (const std::string &path, MapCollisionData &out, const MapLoadOptions &opts={})
 API.
bool loadPropCollision (const std::string &path, MapCollisionData &out, glm::vec3 position, float scale, bool decomposeNonConvex=false)
 Load collision for a standalone prop GLB and append to existing collision data.
glm::vec3 applyGravity (glm::vec3 vel, float dt)
 Apply gravity for one tick: subtracts k_gravity * dt from the Y component.
glm::vec3 applyGroundFriction (glm::vec3 vel, float dt)
 Apply Quake-style ground friction to horizontal (XZ) velocity.
glm::vec3 accelerate (glm::vec3 vel, glm::vec3 wishDir, float wishSpeed, float accel, float dt)
 Quake PM_Accelerate: accelerate toward wishDir up to wishSpeed.
glm::vec3 clipVelocity (glm::vec3 vel, glm::vec3 normal, float overbounce)
 Project velocity onto a collision surface to slide along it.
glm::vec3 computeWishDir (float yaw, bool forward, bool back, bool left, bool right)
 Compute the horizontal wish direction from yaw angle and WASD key state.
bool raycastAABB (glm::vec3 origin, glm::vec3 direction, const WorldAABB &box, float maxDistance, float &outDistance, glm::vec3 &outNormal)
 Ray vs axis-aligned box intersection (slab method).
bool raycastCylinder (glm::vec3 origin, glm::vec3 direction, const WorldCylinder &cyl, float maxDistance, float &outDistance, glm::vec3 &outNormal)
 Ray vs vertical cylinder intersection.
bool raycastSphere (glm::vec3 origin, glm::vec3 direction, const WorldSphere &sph, float maxDistance, float &outDistance, glm::vec3 &outNormal)
 Ray vs sphere intersection.
bool raycastTriMesh (glm::vec3 origin, glm::vec3 direction, const WorldTriMesh &mesh, float maxDistance, float &outDistance, glm::vec3 &outNormal)
 Raycast against a triangle mesh using BVH-accelerated Möller-Trumbore.
bool raycastBrush (glm::vec3 origin, glm::vec3 direction, const WorldBrush &brush, float maxDistance, float &outDistance, glm::vec3 &outNormal)
 Ray vs convex brush intersection (generalised slab method).
HitscanHit raycastWorld (glm::vec3 origin, glm::vec3 direction, const WorldGeometry &world)
 Raycast against all static world geometry (planes + boxes + cylinders + spheres).
HitscanHit raycastPlayers (Registry &registry, entt::entity shooter, glm::vec3 origin, glm::vec3 direction, float maxDistance)
 Raycast against all player hitboxes (axis-aligned capsule approximation).
HitscanHit resolveHitscan (Registry &registry, entt::entity shooter, glm::vec3 origin, glm::vec3 direction)
 Full hitscan resolution: world geometry first, then players (closest wins).
bool raycastCapsule (glm::vec3 origin, glm::vec3 dir, glm::vec3 A, glm::vec3 B, float r, float maxDist, float &outDist, glm::vec3 &outNormal)
 Ray vs capsule intersection.
HitboxHit raycastPlayerHitboxes (Registry &registry, entt::entity shooter, glm::vec3 origin, glm::vec3 direction, float maxDistance)
 Raycast against all player hitbox capsules (skeleton-driven).
HitboxHit resolveHitscanHitbox (Registry &registry, entt::entity shooter, glm::vec3 origin, glm::vec3 direction)
 Full hitscan with skeleton-driven hitboxes.
HitResult sweepAABB (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, std::span< const Plane > planes)
 Sweep an AABB along the path [start, end] against a list of infinite planes.
HitResult sweepAABBvsBox (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, const WorldAABB &box)
 Sweep an AABB against a static axis-aligned box.
HitResult sweepAABBvsBrush (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, const WorldBrush &brush)
 Sweep an AABB against a convex brush (set of bounding planes).
HitResult sweepAABBvsCylinder (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, const WorldCylinder &cyl)
 Sweep an AABB against a vertical cylinder.
HitResult sweepAABBvsSphere (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, const WorldSphere &sph)
 Sweep an AABB against a sphere.
HitResult sweepAll (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, const WorldGeometry &world)
 Sweep an AABB against all world geometry, returning the earliest hit.
SphereHitResult sphereCast (float radius, glm::vec3 start, glm::vec3 end, const WorldGeometry &world)
 Cast a sphere along the path [start, end] against all world geometry.
void buildTriMeshBVH (WorldTriMesh &mesh)
 Build the BVH for a WorldTriMesh.
HitResult sweepAABBvsTriMesh (glm::vec3 halfExtents, glm::vec3 start, glm::vec3 end, const WorldTriMesh &mesh)
 Sweep an AABB against a triangle mesh using BVH-accelerated SAT tests.
void depenetrateAABBvsTriMesh (glm::vec3 &pos, glm::vec3 &vel, glm::vec3 halfExtents, const WorldTriMesh &mesh, float pushback=0.03125f)
 Push an AABB out of a triangle mesh using per-triangle SAT MTV.
WallDetectionResult detectWalls (glm::vec3 pos, float yaw, glm::vec3 halfExtents, const WorldGeometry &world, float checkDist, float sphereRadius, glm::vec3 prevWallNormal=glm::vec3(0.0f))
 Detect walls to the left, right, and front of the player via sphere casts.
bool isWallNormal (glm::vec3 normal)
 Check if a surface normal represents a wall (not floor/ceiling).
void setActiveWorld (const WorldGeometry &geo)
 Set the world geometry that activeWorld() returns.
const WorldGeometryactiveWorld ()
 Return the world geometry most recently set via setActiveWorld(), or fall back to testWorld() if none has been set.
WorldBrush makeRamp (float xMin, float xMax, float zMin, float zMax, float height)
 Create a ramp brush that rises along +Z.
WorldBrush makeDiagonalWall (glm::vec3 center, float halfLen, float halfThick, float height, glm::vec3 dir)
 Create a diagonal wall brush from a centre, direction, and dimensions.
const WorldGeometrytestWorld ()
 The physics test playground.

Variables

constexpr float k_gravity = 1000.0f
 Downward acceleration (units/s^2). Faster than real-world for snappy arcs.
constexpr float k_jumpSpeed = 380.0f
 Initial upward velocity on jump (units/s). Gives apex ~ 72 units (~6 ft).
constexpr float k_groundAccel = 15.0f
 Ground acceleration constant. Higher = reaches max speed faster.
constexpr float k_airAccel
 Air acceleration constant. Higher than Quake (0.7) for Titanfall-style air control.
constexpr float k_airMaxSpeed
 Wish-speed cap in air (units/s). Does NOT cap total speed — existing momentum is preserved.
constexpr float k_friction = 4.0f
 Ground friction coefficient (Quake default).
constexpr float k_stopSpeed = 150.0f
 Friction is amplified below this speed for a crisp stop.
constexpr float k_overbounceWall = 1.001f
 Separation impulse for walls/ceilings; prevents corner-sticking.
constexpr float k_overbounceFloor = 1.0f
 Floor overbounce — exactly 1.0 means no bounce.
constexpr float k_stepHeight = 18.0f
 Maximum obstacle height auto-stepped over without jumping (units).
constexpr float k_hitscanRange = 5000.0f
 Maximum hitscan distance in world units.
constexpr float k_parallelEpsilon = 1e-6f
 Epsilon for parallel-ray checks.

Detailed Description

Pure physics math — no ECS types, no registry.

Wall / climb / ledge detection via sphere casts.

Pure swept-collision math — no ECS types, no registry.

All physics tuning values in one place.

All functions take values in and return values out (no mutation via pointer). Constants come from PhysicsConstants.hpp.

Units: Quake units (1 unit ≈ 1 inch), Y-up coordinate system.

Starting values target a Titanfall-to-Quake movement feel. Tune iteratively — k_gravity and k_jumpSpeed must always be tuned together: jump height = k_jumpSpeed^2 / (2 × k_gravity).

Plane convention: dot(normal, p) > distance is free space; dot(normal, p) < distance is solid. The normal always points into free space.

Example planes (Y-up coordinate system):

  • Floor at y=0: { normal=(0,1,0), distance=0 }
  • Ceiling at y=512: { normal=(0,-1,0), distance=-512 }
  • Wall at x=256 (solid right): { normal=(-1,0,0), distance=-256 }

Used by the movement system each tick to detect nearby surfaces for wallrunning, climbing, and ledge grabbing.

Function Documentation

◆ accelerate()

glm::vec3 physics::accelerate ( glm::vec3 vel,
glm::vec3 wishDir,
float wishSpeed,
float accel,
float dt )

Quake PM_Accelerate: accelerate toward wishDir up to wishSpeed.

Does not cap total speed — only the projection of velocity onto wishDir is capped at wishSpeed. Existing momentum in any other direction is untouched. This property is what makes strafe jumping possible.

Parameters
velCurrent velocity.
wishDirNormalised desired movement direction (from InputSnapshot + yaw).
wishSpeedTarget speed (systems::currentWishSpeed on ground, k_airMaxSpeed in air).
accelAcceleration constant (k_groundAccel or k_airAccel).
dtDelta time in seconds.
Returns
New velocity with acceleration applied.
Here is the caller graph for this function:

◆ activeWorld()

const WorldGeometry & physics::activeWorld ( )
inline

Return the world geometry most recently set via setActiveWorld(), or fall back to testWorld() if none has been set.

This is the single entry point that all physics systems should use.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyGravity()

glm::vec3 physics::applyGravity ( glm::vec3 vel,
float dt )

Apply gravity for one tick: subtracts k_gravity * dt from the Y component.

Parameters
velCurrent velocity.
dtDelta time in seconds.
Returns
New velocity with gravity applied.
Note
Call every tick when the entity is airborne (not grounded).
Here is the caller graph for this function:

◆ applyGroundFriction()

glm::vec3 physics::applyGroundFriction ( glm::vec3 vel,
float dt )

Apply Quake-style ground friction to horizontal (XZ) velocity.

Uses k_stopSpeed as a minimum control speed so entities stop crisply rather than asymptotically approaching zero.

Parameters
velCurrent velocity.
dtDelta time in seconds.
Returns
New velocity with friction applied to XZ; Y is unchanged.
Note
Call every tick when the entity is grounded.
Here is the caller graph for this function:

◆ buildTriMeshBVH()

void physics::buildTriMeshBVH ( WorldTriMesh & mesh)

Build the BVH for a WorldTriMesh.

Must be called after vertices and indices are populated. Fills in bvhNodes, triIndices, boundsMin, and boundsMax.

◆ clipVelocity()

glm::vec3 physics::clipVelocity ( glm::vec3 vel,
glm::vec3 normal,
float overbounce )

Project velocity onto a collision surface to slide along it.

Parameters
velCurrent velocity.
normalSurface normal at the contact point.
overbounceSeparation scalar: use k_overbounceFloor for floors, k_overbounceWall for walls/ceilings.
Returns
Clipped velocity that slides along the surface.
Here is the caller graph for this function:

◆ computeWishDir()

glm::vec3 physics::computeWishDir ( float yaw,
bool forward,
bool back,
bool left,
bool right )

Compute the horizontal wish direction from yaw angle and WASD key state.

Parameters
yawPlayer's current yaw in radians.
forwardTrue when W is held.
backTrue when S is held.
leftTrue when A is held.
rightTrue when D is held.
Returns
Normalised XZ direction vector, or (0,0,0) if no keys are pressed.
Note
Y component is always 0 — vertical movement is handled separately.
Here is the caller graph for this function:

◆ depenetrateAABBvsTriMesh()

void physics::depenetrateAABBvsTriMesh ( glm::vec3 & pos,
glm::vec3 & vel,
glm::vec3 halfExtents,
const WorldTriMesh & mesh,
float pushback = 0.03125f )

Push an AABB out of a triangle mesh using per-triangle SAT MTV.

For each triangle the AABB overlaps (BVH-accelerated leaf search), computes the minimum-translation-vector that separates the AABB from the triangle and applies it. More accurate than depenetrating against leaf-AABB proxies: curved surfaces (cylinders, spheres) feel curved instead of cubical.

Velocity is updated to cancel the component flowing into the surface, so the entity slides along the contact rather than re-penetrating next frame.

Trade-off: at sharp triangle edges where adjacent face normals fight, the per-triangle pushes can briefly disagree. In practice this is rare and the pushback bias keeps the entity off the surface.

Parameters
posAABB centre — modified in place to push out of overlaps.
velVelocity — modified in place to cancel inward motion.
halfExtentsAABB half-extents.
meshTriangle mesh to depenetrate from.
pushbackTiny extra distance added to each push to avoid hairline contact (matches Quake's DIST_EPSILON of 1/32 unit).
Here is the caller graph for this function:

◆ detectWalls()

WallDetectionResult physics::detectWalls ( glm::vec3 pos,
float yaw,
glm::vec3 halfExtents,
const WorldGeometry & world,
float checkDist,
float sphereRadius,
glm::vec3 prevWallNormal = glm::vec3(0.0f) )

Detect walls to the left, right, and front of the player via sphere casts.

Also probes downward to measure ground distance (used for wallrun/climb min height).

Parameters
posPlayer AABB centre position.
yawPlayer facing direction (radians).
halfExtentsPlayer AABB half-extents (for offset calculations).
worldWorld collision geometry.
checkDistHow far sideways/forward to trace (u).
sphereRadiusRadius of the trace sphere (u).
prevWallNormalPrevious tick's wall normal (zero if not wallrunning). When non-zero, an additional trace is cast toward -prevWallNormal to track curved surfaces (cylinders, concave walls) whose normal rotates as the player moves.
Returns
Detection results for all directions.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isWallNormal()

bool physics::isWallNormal ( glm::vec3 normal)
inline

Check if a surface normal represents a wall (not floor/ceiling).

Walls have normals that are roughly horizontal (|normal.y| < 0.3).

Here is the caller graph for this function:

◆ loadMapCollision()

bool physics::loadMapCollision ( const std::string & path,
MapCollisionData & out,
const MapLoadOptions & opts = {} )

API.

Extract collision geometry from a map .glb file.

Walks the Assimp scene graph. For each mesh node, determines whether it belongs to the collision collection (by checking ancestor node names) or, in prototype mode, always. Collision meshes are converted to per-object axis-aligned bounding boxes.

This function does not produce visual / renderable data — use the existing Renderer::loadSceneModel() path for that.

Parameters
pathAbsolute or relative path to the .glb file.
outFilled with extracted collision primitives on success.
optsLoading options (scale, collection name, prototype mode).
Returns
True on success; false on any Assimp load error (logged via SDL_Log).
Here is the caller graph for this function:

◆ loadPropCollision()

bool physics::loadPropCollision ( const std::string & path,
MapCollisionData & out,
glm::vec3 position,
float scale,
bool decomposeNonConvex = false )

Load collision for a standalone prop GLB and append to existing collision data.

Loads the GLB, applies the given transform (position + uniform scale), runs auto-detection on each mesh, and appends the resulting primitives to out. Call setActiveWorld(out.geometry()) after all props are loaded to update the physics world.

Parameters
pathAbsolute path to the .glb file.
outExisting collision data to append to.
positionWorld-space position of the prop.
scaleUniform scale factor.
decomposeNonConvexWhen true, non-convex meshes inside the prop are run through V-HACD convex decomposition (each becomes a small set of WorldBrushes) instead of falling back to WorldTriMesh. Smoother runtime collision on irregular shapes (a bottle, a bent metal pallet) at the cost of seconds-per-mesh load time. Default false because a prop GLB can hold dozens of sub- meshes and decomposing every one of them blows up startup.
Returns
True on success.
Here is the caller graph for this function:

◆ makeDiagonalWall()

WorldBrush physics::makeDiagonalWall ( glm::vec3 center,
float halfLen,
float halfThick,
float height,
glm::vec3 dir )
inline

Create a diagonal wall brush from a centre, direction, and dimensions.

Parameters
centerCentre of the wall base (y=0).
halfLenHalf-length along dir.
halfThickHalf-thickness perpendicular to dir in XZ.
heightWall height (from y=0 to y=height).
dirNormalised direction along the wall in XZ.
Here is the caller graph for this function:

◆ makeRamp()

WorldBrush physics::makeRamp ( float xMin,
float xMax,
float zMin,
float zMax,
float height )
inline

Create a ramp brush that rises along +Z.

The wedge shape goes from (xMin, 0, zMin) at ground level to (xMax, height, zMax) at the back-top edge.

Here is the caller graph for this function:

◆ raycastAABB()

bool physics::raycastAABB ( glm::vec3 origin,
glm::vec3 direction,
const WorldAABB & box,
float maxDistance,
float & outDistance,
glm::vec3 & outNormal )
inline

Ray vs axis-aligned box intersection (slab method).

Here is the caller graph for this function:

◆ raycastBrush()

bool physics::raycastBrush ( glm::vec3 origin,
glm::vec3 direction,
const WorldBrush & brush,
float maxDistance,
float & outDistance,
glm::vec3 & outNormal )
inline

Ray vs convex brush intersection (generalised slab method).

A WorldBrush is the intersection of half-spaces defined by planes with outward normals; the solid interior satisfies dot(n, p) <= distance for every plane. A ray hits the brush at the latest plane it enters from outside, provided that t doesn't exceed the earliest plane it exits. Mirrors the logic in sweepAABBvsBrush but for a point-ray instead of a swept AABB.

Here is the caller graph for this function:

◆ raycastCapsule()

bool physics::raycastCapsule ( glm::vec3 origin,
glm::vec3 dir,
glm::vec3 A,
glm::vec3 B,
float r,
float maxDist,
float & outDist,
glm::vec3 & outNormal )
inline

Ray vs capsule intersection.

A capsule is the Minkowski sum of the line segment AB and a sphere of radius r. Decomposed into: (1) ray vs infinite cylinder along AB, clamped to the segment, then (2) ray vs hemisphere endcaps.

Returns
True if the ray hits the capsule within maxDist.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ raycastCylinder()

bool physics::raycastCylinder ( glm::vec3 origin,
glm::vec3 direction,
const WorldCylinder & cyl,
float maxDistance,
float & outDistance,
glm::vec3 & outNormal )
inline

Ray vs vertical cylinder intersection.

Here is the caller graph for this function:

◆ raycastPlayerHitboxes()

HitboxHit physics::raycastPlayerHitboxes ( Registry & registry,
entt::entity shooter,
glm::vec3 origin,
glm::vec3 direction,
float maxDistance )
inline

Raycast against all player hitbox capsules (skeleton-driven).

Uses a broad-phase AABB check (CollisionShape) before testing individual capsules, so only nearby players pay the narrow-phase cost.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ raycastPlayers()

HitscanHit physics::raycastPlayers ( Registry & registry,
entt::entity shooter,
glm::vec3 origin,
glm::vec3 direction,
float maxDistance )
inline

Raycast against all player hitboxes (axis-aligned capsule approximation).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ raycastSphere()

bool physics::raycastSphere ( glm::vec3 origin,
glm::vec3 direction,
const WorldSphere & sph,
float maxDistance,
float & outDistance,
glm::vec3 & outNormal )
inline

Ray vs sphere intersection.

Here is the caller graph for this function:

◆ raycastTriMesh()

bool physics::raycastTriMesh ( glm::vec3 origin,
glm::vec3 direction,
const WorldTriMesh & mesh,
float maxDistance,
float & outDistance,
glm::vec3 & outNormal )
inline

Raycast against a triangle mesh using BVH-accelerated Möller-Trumbore.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ raycastWorld()

HitscanHit physics::raycastWorld ( glm::vec3 origin,
glm::vec3 direction,
const WorldGeometry & world )
inline

Raycast against all static world geometry (planes + boxes + cylinders + spheres).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveHitscan()

HitscanHit physics::resolveHitscan ( Registry & registry,
entt::entity shooter,
glm::vec3 origin,
glm::vec3 direction )
inline

Full hitscan resolution: world geometry first, then players (closest wins).

Here is the call graph for this function:

◆ resolveHitscanHitbox()

HitboxHit physics::resolveHitscanHitbox ( Registry & registry,
entt::entity shooter,
glm::vec3 origin,
glm::vec3 direction )
inline

Full hitscan with skeleton-driven hitboxes.

World geometry first, then player hitbox capsules (closest wins). Falls back to the old AABB path for players without HitboxInstance.

Here is the call graph for this function:

◆ setActiveWorld()

void physics::setActiveWorld ( const WorldGeometry & geo)
inline

Set the world geometry that activeWorld() returns.

The caller retains ownership of the memory behind the spans — the pointed-to data must outlive every call to activeWorld(). Typically backed by a MapCollisionData whose vectors live for the duration of the game.

Both client and server must call this with identical data before the first physics tick to maintain prediction parity.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sphereCast()

SphereHitResult physics::sphereCast ( float radius,
glm::vec3 start,
glm::vec3 end,
const WorldGeometry & world )

Cast a sphere along the path [start, end] against all world geometry.

Uses the Minkowski-sum approach: geometry is expanded by the sphere radius, then the sweep becomes a point (ray) test against the expanded geometry.

Parameters
radiusSphere radius (u).
startWorld-space start of sweep (sphere centre).
endWorld-space end of sweep (sphere centre).
worldWorld collision geometry to test against.
Returns
Earliest hit, or SphereHitResult{hit=false} if clear.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweepAABB()

HitResult physics::sweepAABB ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
std::span< const Plane > planes )

Sweep an AABB along the path [start, end] against a list of infinite planes.

Uses the Minkowski-sum approach: each plane is expanded outward by the AABB half-extents, reducing the problem to a ray-vs-expanded-plane intersection.

Parameters
halfExtentsHalf-dimensions of the AABB.
startWorld-space start position (AABB centre).
endWorld-space end position (AABB centre).
planesWorld collision planes to test against.
Returns
Earliest hit within the sweep, or HitResult{hit=false} if the path is clear.
Note
Entities that start already inside a plane are skipped. Depenetration is handled separately by CollisionSystem before calling this.
Here is the caller graph for this function:

◆ sweepAABBvsBox()

HitResult physics::sweepAABBvsBox ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
const WorldAABB & box )

Sweep an AABB against a static axis-aligned box.

Expands the static box by the moving AABB's half-extents (Minkowski sum) and performs a ray-slab intersection test on the swept centre point. Entities starting inside the box are skipped (depenetration handles that).

Here is the caller graph for this function:

◆ sweepAABBvsBrush()

HitResult physics::sweepAABBvsBrush ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
const WorldBrush & brush )

Sweep an AABB against a convex brush (set of bounding planes).

Finds the time at which the AABB enters all half-spaces simultaneously. Entities starting inside the brush are skipped (depenetration handles that).

Here is the caller graph for this function:

◆ sweepAABBvsCylinder()

HitResult physics::sweepAABBvsCylinder ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
const WorldCylinder & cyl )

Sweep an AABB against a vertical cylinder.

Minkowski-expands the cylinder by the AABB half-extents: the radius grows by the XZ extent and the height caps grow by the Y extent. The sweep then reduces to a 2D ray-vs-circle test (XZ) clamped by the expanded Y slab.

Here is the caller graph for this function:

◆ sweepAABBvsSphere()

HitResult physics::sweepAABBvsSphere ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
const WorldSphere & sph )

Sweep an AABB against a sphere.

Minkowski-expands the sphere radius by the AABB half-extents (approximation: uses the max half-extent component, making it slightly conservative at corners). Then performs a ray-vs-sphere test on the swept centre.

Here is the caller graph for this function:

◆ sweepAABBvsTriMesh()

HitResult physics::sweepAABBvsTriMesh ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
const WorldTriMesh & mesh )

Sweep an AABB against a triangle mesh using BVH-accelerated SAT tests.

Here is the caller graph for this function:

◆ sweepAll()

HitResult physics::sweepAll ( glm::vec3 halfExtents,
glm::vec3 start,
glm::vec3 end,
const WorldGeometry & world )

Sweep an AABB against all world geometry, returning the earliest hit.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ testWorld()

const WorldGeometry & physics::testWorld ( )
inline

The physics test playground.

Layout along the +Z axis (forward from spawn at origin):

z ~ 400 : Reference cube (64^3) z ~ 800 : Small steppable box (64x16x64) and large jumpable box (80x64x80) z ~ 1000 : Gentle ramp (15deg, left) and steep ramp (40deg, right) z ~ 1500 : Stairs (5 steps rising along +Z) z ~ 1900 : Axis-aligned wall, diagonal wall, pole z ~ 2100 : Elevated thin walkway

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ k_airAccel

float physics::k_airAccel
constexpr
Initial value:
=
2000.0f

Air acceleration constant. Higher than Quake (0.7) for Titanfall-style air control.

◆ k_airMaxSpeed

float physics::k_airMaxSpeed
constexpr
Initial value:
=
30.0f

Wish-speed cap in air (units/s). Does NOT cap total speed — existing momentum is preserved.

◆ k_friction

float physics::k_friction = 4.0f
constexpr

Ground friction coefficient (Quake default).

◆ k_gravity

float physics::k_gravity = 1000.0f
constexpr

Downward acceleration (units/s^2). Faster than real-world for snappy arcs.

◆ k_groundAccel

float physics::k_groundAccel = 15.0f
constexpr

Ground acceleration constant. Higher = reaches max speed faster.

◆ k_hitscanRange

float physics::k_hitscanRange = 5000.0f
inlineconstexpr

Maximum hitscan distance in world units.

◆ k_jumpSpeed

float physics::k_jumpSpeed = 380.0f
constexpr

Initial upward velocity on jump (units/s). Gives apex ~ 72 units (~6 ft).

◆ k_overbounceFloor

float physics::k_overbounceFloor = 1.0f
constexpr

Floor overbounce — exactly 1.0 means no bounce.

◆ k_overbounceWall

float physics::k_overbounceWall = 1.001f
constexpr

Separation impulse for walls/ceilings; prevents corner-sticking.

◆ k_parallelEpsilon

float physics::k_parallelEpsilon = 1e-6f
inlineconstexpr

Epsilon for parallel-ray checks.

◆ k_stepHeight

float physics::k_stepHeight = 18.0f
constexpr

Maximum obstacle height auto-stepped over without jumping (units).

◆ k_stopSpeed

float physics::k_stopSpeed = 150.0f
constexpr

Friction is amplified below this speed for a crisp stop.