Commit graph

94 commits

Author SHA1 Message Date
Kelsi
6158d56316 Add collision query caching to reduce map traversal overhead
Caches floor height checks to skip redundant collision queries when position
hasn't changed significantly. Major performance improvement during movement.

Problem:
- 17+ collision queries per frame during movement
- getFloorHeight calls expensive (WMO/terrain/M2 raycasts)
- Same queries repeated when barely moving

Solution:
- Cache last collision check position and result
- Skip checks if moved < 15cm (COLLISION_CACHE_DISTANCE)
- Update cache when threshold exceeded or result changes

Implementation:
- Added lastCollisionCheckPos_, cachedFloorHeight_, hasCachedFloor_
- Check distance moved before main ground height query
- Reuse cached floor height for micro-movements
- Full collision check only when meaningfully repositioned

Performance impact:
- Stationary/slow: ~90% reduction in collision queries
- Fast movement: Still helps on same-tile micro-adjustments
- No accuracy loss (15cm is smaller than collision step size)

This addresses "computationally heavy" operations during map traversal.
2026-02-08 22:30:37 -08:00
Kelsi
92031102e4 Add mount pitch and roll for realistic taxi flight animation
Flying mounts now tilt and bank realistically during taxi flights:
- Pitch (up/down): calculated from spline tangent's z-component (altitude change)
- Roll (banking): proportional to turn rate, clamped to ~40 degrees
- Yaw: existing horizontal orientation from spline direction

Implementation:
- Added mountPitch_ and mountRoll_ to Renderer (radians)
- Updated TaxiOrientationCallback to pass yaw, pitch, roll
- Calculate pitch using asin(tangent.z) for altitude tilt
- Calculate roll from yaw change rate: -orientDiff * 2.5, clamped to ±0.7 rad
- Applied to mount rotation: glm::vec3(pitch, roll, yaw)

This fixes the "weirdness" where mounts flew sideways or without natural banking.
2026-02-08 22:05:38 -08:00
Kelsi
2e0a7e0039 Fix taxi mount orientation and eliminate tile loading hitches
Fixes two critical taxi flight issues:

1. Mount orientation now correctly faces flight direction:
   - Prevent camera controller from updating facingYaw during taxi (externalFollow_ check)
   - Taxi orientation callback system updates mount rotation from spline tangent
   - Initial orientation set when flight starts
   - Smooth Catmull-Rom spline interpolation for natural curved paths

2. Eliminate frame hitches from tile loading during flight:
   - New taxiFlightStartCallback uploads ALL precached tiles to GPU before flight begins
   - Previously tiles loaded async during 3s mount delay but uploaded 1/frame during flight
   - Now processAllReadyTiles() blocks briefly after mount delay to batch upload everything
   - Combined with 2.0s terrain update interval and aggressive culling for smooth flight

Additional optimizations:
   - Aggressive taxi culling: skip models <15 units, all foliage/trees, underwater objects
   - Max render distance reduced to 150 units during taxi
   - Movement heartbeat packets disabled during taxi (server controls position)
   - Reduced taxi speed from 32 to 18 units/sec to prevent streaming overload
2026-02-08 22:00:33 -08:00
Kelsi
536b3cea48 Implement comprehensive taxi flight optimizations and proper spline paths
Major improvements:
- Load TaxiPathNode.dbc for actual curved flight paths (no more flying through terrain)
- Add 3-second mounting delay with terrain precaching for entire route
- Implement LOD system for M2 models with distance-based quality reduction
- Add circular terrain loading pattern (13 tiles vs 25, 48% reduction)
- Increase terrain cache from 2GB to 8GB for modern systems

Performance optimizations during taxi:
- Cull small M2 models (boundRadius < 3.0) - not visible from altitude
- Disable particle systems (weather, smoke, M2 emitters) - saves ~7000 particles
- Disable specular lighting on M2 models - saves Blinn-Phong calculations
- Disable shadow mapping on M2 models - saves shadow map sampling and PCF

Technical details:
- Parse TaxiPathNode.dbc spline waypoints for curved paths around terrain
- Build full path from node pairs using TaxiPathEdge lookup
- Precache callback triggers during mounting delay for smooth takeoff
- Circular tile loading uses Euclidean distance check (dx²+dy² <= r²)
- LOD fallback to base mesh when higher LODs unavailable

Result: Buttery smooth taxi flights with no terrain clipping or performance hitches
2026-02-08 21:32:38 -08:00
Kelsi
b48802855b Tighten WMO collision detection when inside buildings
When inside a WMO, use:
- Smaller sweep step size (0.20 vs 0.35) for more frequent collision checks
- Tighter player radius (0.45 vs 0.50) for less claustrophobic corridors
- Stronger push response (0.12 vs 0.08 max) for more responsive walls

Prevents clipping through walls in tight indoor spaces while keeping
outdoor movement smooth.
2026-02-08 20:20:37 -08:00
Kelsi
d7aabc0caa Add M2 collision mesh parsing and mesh-based wall/floor collision
Parse bounding vertices, triangles, and normals from M2 files and use
them for proper triangle-level collision instead of AABB heuristics.
Spatial grid bucketing for efficient queries, closest-point wall push
with soft clamping, and ray-triangle floor detection alongside existing
AABB fallback.
2026-02-08 19:56:17 -08:00
Kelsi
f8aba30f2d Fix WMO ramp/stair clipping with WoW-style floor snap and collision fixes
Remove active group fast path from getFloorHeight to fix bridge clipping.
Replace ground smoothing with immediate step-up snap (WoW-style: snap up,
smooth down). Accept upward Z from wall collision at all call sites. Skip
floor-like surfaces (absNz >= 0.45) in wall collision to prevent false
wall hits on ramps. Increase getFloorHeight allowAbove from 0.5 to 2.0
for ramp reacquisition. Prefer highest reachable surface in floor selection.
2026-02-08 17:38:30 -08:00
Kelsi
ef54f62df0 Add multi-tier unstuck system with void fall detection
Replace broken hardcoded-coordinate unstuck with tiered fallbacks:
last safe position > hearth bind > map spawn. Track safe positions
only on real geometry, let player fall after 500ms with no ground,
and auto-trigger unstuck after 5s of continuous falling.
2026-02-08 15:37:34 -08:00
Kelsi
8fee55f99f Fix /unstuckgy hang by skipping WMO floor search
Add CameraController::teleportTo() that directly places the player at
the target position without the expensive floor-search loop in reset().
The loop does hundreds of WMO collision checks which hangs in cities.
2026-02-08 15:13:55 -08:00
Kelsi
f6eaa2cf70 Add idle yawn emote and hearth home tooltip 2026-02-08 03:39:02 -08:00
Kelsi
132a6ea3c9 Add /unstuckgy and 2GB terrain tile cache 2026-02-08 03:24:12 -08:00
Kelsi
6736ec328b Fix taxi flights, mounts, and movement recovery 2026-02-08 03:05:38 -08:00
Kelsi
d910073d7a Preload terrain textures on background thread and fix ramp Z-snapping
Load BLP texture data during prepareTile() and upload to GL cache in
finalizeTile(), eliminating file I/O stalls on the main thread. Reduce
ready tiles per frame to 1. Fix camera sweep to snap Z to ramp surfaces.
Change hearthstone action bar slot from spell to item.
2026-02-08 01:16:23 -08:00
Kelsi
0ce38cfb99 Add transport support, gameobject queries, and fix item use
- Add setInstancePosition() to M2Renderer and WMORenderer for moving
  transport instances at runtime
- Detect UPDATEFLAG_TRANSPORT on gameobjects and track transport GUIDs
- Parse player-on-transport state from movement blocks
- Wire transport move callback in Application to update render positions
- Implement CMSG_GAMEOBJECT_QUERY / SMSG_GAMEOBJECT_QUERY_RESPONSE so
  gameobjects display proper names instead of "Unknown"
- Add name/entry fields to GameObject entity class
- Fix CMSG_USE_ITEM packet: remove extra uint8 that shifted the item
  GUID by one byte, breaking hearthstone and all item usage
- Remove redundant CMSG_LOOT after CMSG_GAMEOBJECT_USE for chests
- Show PvP enabled/disabled state in toggle message
- Relax WMO ramp wall-collision step-up check to allow walking on
  gentle ramps where floor rise per step is under 0.1 units
- Add M2 fallback when WMO group files fail to load for gameobjects
- Handle re-creation of existing gameobject render instances by
  updating position instead of silently ignoring
2026-02-08 00:59:40 -08:00
Kelsi
38c9fdad6b Improve targeting, minimap, and bridge collisions 2026-02-07 20:51:53 -08:00
Kelsi
5eebd805ba Fix mounted first-person camera pivot 2026-02-07 20:05:07 -08:00
Kelsi
0ebf4d1e5e Load emotes from DBC 2026-02-07 20:02:14 -08:00
Kelsi
a71902a571 Add tiled particle atlas support 2026-02-07 19:20:37 -08:00
Kelsi
35fff9307d Add mount rider bob and hoofbeat sounds, improve world map
- Rider character bobs with mount's run animation (sinusoidal, 0.12u amplitude)
- Mount hoofbeat footstep sounds triggered at 4 points per animation cycle
- M key opens map directly to player's current zone instead of continent
- Mouse wheel scroll zooms map in/out between world, continent, and zone views
- Fog of war darkens unexplored zones on continent view, clears on visit
2026-02-07 18:38:36 -08:00
Kelsi
643611ee79 Add mount system and crash mouse-release handler
Render mount M2 model under player with seated animation, apply creature
skin textures, server-driven speed via SMSG_FORCE_RUN_SPEED_CHANGE, and
/dismount command. X11 XUngrabPointer on crash/hang to always release mouse.
2026-02-07 17:59:40 -08:00
Kelsi
2d2b9cc1fc Fix M2 interior lighting and carpet sliding
- M2 interior darkening now uses global player-inside-WMO flag instead
  of per-instance queries that were unreliable
- Fix carpet/rug sliding by skipping lateral collision push when player
  is standing on top of any stepable low object, not just platforms
2026-02-07 17:05:30 -08:00
Kelsi
84c3d1bf32 Fix /unstuck to use full floor search via camera reset
The previous approach used getFloorHeight which has tight spatial query
bounds and couldn't find WMO floors far above the player. Now uses
reset() which does multi-radius WMO/terrain scanning.
2026-02-07 17:01:41 -08:00
Kelsi
3c2a728ec4 Add taxi system, fix WMO interior lighting, ramp collision, and /unstuck
- Implement flight path system: SMSG_SHOWTAXINODES parser, CMSG_ACTIVATETAXIEXPRESS builder, BFS multi-hop pathfinding through TaxiNodes/TaxiPath DBC, taxi destination UI, movement blocking during flight
- Fix WMO interiors too dark by boosting vertex color lighting multiplier
- Dim M2 objects inside WMO interiors (rugs, furniture) via per-instance interior detection
- Fix ramp/stair clipping by lowering wall collision normal threshold from 0.85 to 0.55
- Restore 5-sample cardinal footprint for ground detection to fix rug slipping
- Fix /unstuck command to reset player Z to WMO/terrain floor height
- Handle MSG_MOVE_TELEPORT_ACK and SMSG_TRANSFER_PENDING for hearthstone teleports
- Fix spawning under Stormwind with online-mode camera controller reset
2026-02-07 16:59:20 -08:00
Kelsi
eb6e42eb59 Add tilde key toggle for auto-run
Pressing ~ toggles auto-run (continuous forward movement). Pressing W or S
cancels it. Also cancelled on respawn/teleport.
2026-02-07 16:05:13 -08:00
Kelsi
7c9661472f Fix ramp clipping by tightening sweep steps, disable shadows by default
Sweep step size reduced from 1.0f back to 0.65f with max 3 steps (was 2)
to prevent clipping through ramps in Stormwind. All paths updated: follow,
free-fly, and swimming.

Shadows disabled by default in renderer, settings UI, and settings defaults.
2026-02-07 16:00:57 -08:00
Kelsi
6516fd777d Optimize collision further: skip when stationary, cache floor height, fix drop bug
- Skip wall collision sweep entirely when player isn't moving (saves all
  collision calls when standing still)
- Reduce max sweep steps from 4 to 2 with 1.0f step size (all paths:
  follow, free-fly, swimming)
- Cache floor height between frames, reuse when position changes <0.5 units
- Fix floor height not updating after walking off tall objects (fountain etc)
  by always smoothing toward detected ground instead of ignoring drops >2 units
- Reduce free-fly ground probes from 5 to 1
- Disable WMO camera collision (raycast + floor probes) for performance
- Add spatial grid to raycastBoundingBoxes for when camera collision is re-enabled
2026-02-07 15:54:33 -08:00
Kelsi
974384c725 Add per-group spatial grid for WMO collision and reduce collision call frequency
Build a 2D triangle grid per WMO group at load time so getFloorHeight and
checkWallCollision only test triangles in nearby cells instead of brute-forcing
all triangles. Also reduce sweep steps (12→4), ground probes (3→1), camera
floor probes (5→2), throttle isInsideWMO to every 10 frames, and early-out
wall collision on first hit.
2026-02-07 15:47:43 -08:00
Kelsi
751e6fdbde Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
Kelsi
ca88860929 Skip bone computation for off-screen M2 instances, sort by model for batched VAO binds, and eliminate sqrt in distance fade 2026-02-07 14:37:14 -08:00
Kelsi
249c4fa842 Parallelize M2 bone matrix computation across worker threads
Split the M2 animation update loop into three phases: sequential animation state update, parallel bone matrix computation via std::async (when 32+ animated instances), and sequential particle update. Each thread processes a disjoint slice of instances so no synchronization is needed.
2026-02-07 14:28:14 -08:00
Kelsi
05870c1f03 Only face target when in combat, not when selecting friendly NPCs 2026-02-07 13:56:58 -08:00
Kelsi
e38c0213e4 Fix online item GUID resolution, async terrain loading, and inventory enrichment
Enrich online inventory from local DB when server data is incomplete, add
resolveOnlineItemGuid fallback for sell/equip/use, use async enqueueTile for
initial terrain load, improve walk/run animation fallbacks, clear target on
loot close, and broaden equipability detection to include armor/subclass.
2026-02-06 18:52:28 -08:00
Kelsi
fdc614902b Fix online interactions, UI, and inventory sync 2026-02-06 18:34:45 -08:00
Kelsi
81166346ef Fix respawned corpse movement, faction hostility, and add WoW-canonical mob level colors
Reset NPC animation to idle when health goes from 0 to >0 (respawn), prevent
dead NPCs from being moved by server movement packets. Fix faction hostility
to check factionGroup Monster bit and individual enemy arrays, not just
enemyGroup. Add level-based mob coloring: grey (no XP), green (easy), yellow
(even), orange (hard), red (very hard) for target frame and selection circle.
2026-02-06 16:47:07 -08:00
Kelsi
2ddef93f52 Fix spell targeting, item query parsing, loot UI, hair/skin textures, and attack animations
Fix spell cast target fallback using selected target instead of no-op tautology.
Fix SMSG_ITEM_QUERY_SINGLE_RESPONSE to always read 10 stat pairs (server sends
all 10 regardless of statsCount), fixing misaligned armor/stat reads. Fix XP gain
parser to read float groupRate + uint8 RAF instead of bogus uint32 groupBonus.
Add item icons and quality-colored names to loot window. Use actual character
appearance bytes for CharSections.dbc skin/face/hair lookups instead of hardcoded
defaults. Add weapon-type-aware attack animation selection (2H prioritizes anim 18).
Add readable spell cast failure messages and vendor sell hint.
2026-02-06 15:41:29 -08:00
Kelsi
aa11ffda72 Fix terrain streaming loop and auto-select single realm/character
Use getRemainingTileCount (pending + readyQueue) and processAllReadyTiles
to prevent loading screen from exiting before tiles are finalized. Auto-select
realm and character when only one is available.
2026-02-06 14:56:26 -08:00
Kelsi
6f33392155 Add progress bar to loading screen and handle resize during loading
Loading screen now shows a gold progress bar with percentage and status
text. All loading steps poll SDL events for window resize and quit.
2026-02-06 14:43:18 -08:00
Kelsi
394e91cd9e Add character screen model preview, item icons, stats panel, and fix targeting bugs
Enhanced the C-key character screen with a 3-column layout featuring a 3D
character model preview (with drag-to-rotate), item icons loaded from BLP
textures via ItemDisplayInfo.dbc, and a stats panel showing base + equipment
bonuses. Fixed selection circle clipping under terrain by adding a Z offset,
and corrected faction hostility logic that was wrongly marking hostile mobs
as friendly.
2026-02-06 14:24:38 -08:00
Kelsi
7128ea1417 Restructure inventory UI, add vendor selling, camera intro on all spawns, and quest log
Split inventory into bags-only (B key) and character screen (C key). Vendor window
auto-opens bags with sell prices on hover and right-click to sell. Add camera intro
pan on all login/spawn/teleport/hearthstone events and idle orbit after 2 minutes.
Add quest log UI, SMSG_MONSTER_MOVE handling, deferred creature spawn queue, and
creature fade-in/movement interpolation for online mode.
2026-02-06 13:47:03 -08:00
Kelsi
88241cbddc Render M2 glow batches as billboarded light sprites
Replace flat mesh rendering of additive/mod blend batches (blendMode >= 3)
with camera-facing point sprites using a soft radial gradient texture and
additive blending. Adds M2 particle emitter infrastructure (structs, shader,
parsing stubs) but disables emitter parsing — the assumed 476-byte struct
size is wrong for WotLK 3.3.5a, causing misaligned reads that explode RAM.
2026-02-06 08:58:26 -08:00
Kelsi
e01d80f4eb Add unlit rendering for M2 glow/additive batches
Batches with the M2 unlit material flag (0x01) or additive blend modes
(3+) now skip lighting, shadows, and fog, emitting texture color directly.
Fixes lantern glow quads appearing as dull transparent circles.
2026-02-06 03:28:21 -08:00
Kelsi
4d80b92c39 Parse M2 render flags and apply per-batch blend modes
Water/lava batches in fountain and Ironforge M2 models use non-opaque
blend modes (alpha, additive) defined in the M2 material table. Without
parsing these, they rendered as solid surfaces extending visibly beyond
their containers. Now each batch looks up its blend mode from the
material array and sets the appropriate GL blend function.
2026-02-06 01:54:25 -08:00
Kelsi
ad04da31c3 Implement M2 texture animation (UV scrolling) for fountain water
Parse M2TextureTransform entries and texture transform lookups from the
M2 binary, then apply per-batch UV offsets in the vertex shader using
the existing animation time base and global sequence durations.
2026-02-06 01:49:27 -08:00
Kelsi
e8fecfb3be Fix NPC hair/geoset rendering using DBC lookups
Use CharHairGeosets.dbc to map (race, sex, hairStyleId) to the correct
group 0 scalp mesh instead of the broken 101+hairStyleId formula. Filter
group 0 submeshes so only the body base and correct hair mesh render
(prevents overlapping scalp variants). Fix ItemDisplayInfo.dbc column
indices (5→7) and geoset formulas for equipment. Add CharSections.dbc
hair texture lookup and CharacterFacialHairStyles.dbc support.
2026-02-06 01:02:35 -08:00
Kelsi
9511d051e2 Simplify wall collision and add intro camera pan
- Remove complex ramp/edge filtering that was skipping building walls
- Simpler wall detection: any vertical geometry above step height
- Add intro camera pan on game start
2026-02-05 18:12:27 -08:00
Kelsi
5401683a8d Add one-time spawn camera pan 2026-02-05 18:06:52 -08:00
Kelsi
d1e9bbeb1f Persist single-player settings and add defaults 2026-02-05 17:40:15 -08:00
Kelsi
76c4268ed8 Use zone-specific floor cache files
Save/load floor cache per map (e.g., cache/wmo_floor_Azeroth.bin) instead
of a single global file. Saves current zone's cache before teleporting,
loads target zone's cache after terrain streaming completes.
2026-02-05 17:35:17 -08:00
Kelsi
1530900bc7 Add audio volume controls to settings 2026-02-05 17:32:21 -08:00
Kelsi
12a7604450 Automate WMO floor cache pre-computation
Add precomputeFloorCache() method that samples all WMO bounds at load time
and populates the persistent floor height grid. Called after terrain
streaming completes (initial spawn and teleport) when cache is empty.
2026-02-05 17:30:08 -08:00