Commit graph

356 commits

Author SHA1 Message Date
Kelsi
dab23f1895 Add ambient sound system and eliminate log spam
- Implement AmbientSoundManager with tavern/outdoor ambience
- Fix audio buffer limit (5s → 60s) for long ambient loops
- Set log level to INFO to eliminate DEBUG spam (130MB → 3.2MB logs)
- Remove excessive terrain/model/network logging
- Fix ambient sound timer sharing and pitch parameter bugs
2026-02-09 14:50:14 -08:00
Kelsi
4a7e599764 Fix NPC voices to use correct WAV format and gender detection
WotLK 3.3.5a uses .wav files for NPC voices, not .ogg as shown in retail Wowhead. Fixed audio engine to preserve original sample rate from WAV files (preventing chipmunk playback). Implemented race/gender detection using CreatureDisplayInfo.dbc and CreatureDisplayInfoExtra.dbc to play correct voice types for each NPC.
2026-02-09 02:22:20 -08:00
Kelsi
5f57a83332 Test forward slash paths for MPQ file access
MPQs may store files internally with forward slashes. Testing both:
- Sound/Creature/... (forward slashes)
- Sound\Creature\... (backslashes)

This should help identify the correct path format for accessing files.
2026-02-09 02:05:09 -08:00
Kelsi
609185f10f Expand NPC voice file search to test multiple path patterns
Tests various path structures to find where voice files actually exist:
- Wowhead StandardNPC paths
- Lowercase variations
- PC voice files (HumanVocMale/Female - player emotes)
- VO/Voice directories
- Simpler creature paths

This will help identify which files actually exist in the 3.3.5a MPQs.
2026-02-09 02:03:35 -08:00
Kelsi
c3c6ffeedb Add speech MPQ archives for NPC voices
Loads speech-enUS.MPQ, expansion-speech-enUS.MPQ, and lichking-speech-enUS.MPQ
which contain NPC voice/creature sound files. These MPQs were present but not
being loaded, causing all .ogg NPC greeting sounds to show as NOT FOUND.
2026-02-09 01:58:55 -08:00
Kelsi
838b82e503 Add complete NPC voice library from Wowhead database
Added all standard NPC greeting sounds for all playable races:
- Human (male/female): 6/5 greetings
- Dwarf (male): 6 greetings
- Gnome (male/female): 6/6 greetings
- Night Elf (male/female): 8/6 greetings
- Orc (male/female): 5/6 greetings
- Tauren (male/female): 5/5 greetings (note: male was missing from Wowhead, added anyway)
- Troll (male/female): 6/5 greetings
- Undead (male/female): 6/6 greetings

Paths from Wowhead: Sound\Creature\[Race][Gender]StandardNPC\
Note: Human male uses "Greetings" (plural), others use "Greeting" (singular)
2026-02-09 01:54:21 -08:00
Kelsi
44a75928ba Fix NPC voice paths to use Sound\Creature\ with .ogg format
NPC sounds are in Sound\Creature\[npctype]\ not Sound\Character\.
Changed to use correct paths like humanmalestandardnpc/humanfemalestandardnpc
with .ogg extension. This matches actual WoW 3.3.5a structure.
2026-02-09 01:52:07 -08:00
Kelsi
708142a8a4 Also initialize mount sound and NPC voice managers in loadTestTerrain
These managers were only being initialized in loadTerrainArea (online mode).
Added initialization in loadTestTerrain as well so they work in both modes.
Now the file probing should actually run and show which sound files exist.
2026-02-09 01:50:42 -08:00
Kelsi
b8375627e9 Fix NPC voice and mount sound managers not initializing in online mode
The cachedAssetManager was only set in loadTestTerrain() for single-player mode.
In online mode (loadTerrainArea), it was never set, so NPC voice and mount sound
managers never initialized. Now gets asset manager from Application instance if
not already cached. This will enable file probing and voice/sound loading.
2026-02-09 01:48:19 -08:00
Kelsi
ec457a37c8 Add MPQ file probing for NPC voices and tavern music
Tests various potential sound file paths at startup and logs which ones exist
in the MPQ. This will show us the correct file paths to use for both NPC
voices and tavern music.
2026-02-09 01:44:58 -08:00
Kelsi
ee52732350 Add debug logging for tavern music and NPC voices
Added extensive logging to diagnose issues:
- Logs WMO model IDs when entering WMOs (to identify correct tavern IDs)
- Logs when tavern music should be playing
- Logs NPC voice playGreeting calls and their results
- Logs which sound files are being played
- Added more emote variations (Hello, Yes) for NPC voices

This will help identify why tavern music and NPC voices aren't working.
2026-02-09 01:43:20 -08:00
Kelsi
e1ecd13bcd Fix action bar not clickable: remove NoInputs flag
The ImGuiWindowFlags_NoInputs flag was blocking all input including mouse clicks.
Removed this flag to restore action bar clickability while keeping keyboard shortcuts functional.
2026-02-09 01:40:29 -08:00
Kelsi
becc94d4ba Fix NPC voices and add tavern music support
NPC voice fixes:
- Changed sound paths from "Greeting" to "Hello" emote (more reliable)
- Added warning log when no voice samples load
- Voice files should now play when clicking NPCs

Tavern music:
- Detect tavern WMOs by model ID (inn buildings)
- Play tavern-specific music when inside taverns
- Crossfade back to zone music when exiting taverns
- Adds cozy ambient music to inn/tavern buildings
2026-02-09 01:39:12 -08:00
Kelsi
e40ea0c47a Fix taxi window close auto-mounting player on griffin
Fixes issue where closing the flight map window would incorrectly mount the
player on a griffin at spawn point. Added taxiLandingCooldown when closing
taxi window to prevent UNIT_FLAG_TAXI_FLIGHT check from re-triggering mount.
2026-02-09 01:35:29 -08:00
Kelsi
42821604d3 Fix mount dust visibility: spawn above ground with stronger upward velocity
Fixes issue where dust particles were angling down into terrain and not visible.
Changes spawn position to fixed 0.2 units above ground, increases upward velocity
to 1.2-2.5 for clearer rise, and uses only horizontal velocity component for drift
to prevent Z component from pushing particles downward.
2026-02-09 01:32:40 -08:00
Kelsi
eb288d2064 Implement NPC greeting voice lines
Added NPC voice manager that plays greeting sounds when clicking on NPCs:

Features:
- Voice line library with multiple race/gender voice types (Human, Dwarf,
  Night Elf, etc.)
- 3D positional audio - voice comes from NPC location
- Cooldown system prevents spam clicking same NPC
- Randomized pitch/volume for variety
- Loads greeting sounds from character voice files in MPQ
- Generic fallback voices for NPCs without specific voice types

Voice lines trigger automatically when gossip window opens (SMSG_GOSSIP_MESSAGE).
Uses same audio system as other sound effects with ma_sound_set_position.
2026-02-09 01:29:44 -08:00
Kelsi
71c4fb3ae6 Fix crash in mount dust: add null check for camera pointer
The mount dust code was calling camera->getForward() without checking if
camera was null first, causing a crash that prevented mounting/dismounting.
Added camera null check to the condition.
2026-02-09 01:26:28 -08:00
Kelsi
c95c3db03a Add mount dust particle effects
Implemented dust cloud particles that spawn at mount feet when running
on the ground, similar to the original WoW. Features:

- Brownish/tan dust particles using point sprite rendering
- Spawn rate proportional to movement speed
- Particles rise up, drift backward, and fade out naturally
- Only active when mounted, moving, and on ground (not flying)
- Smooth particle animation with size growth and alpha fade

Uses similar particle system architecture as swim effects with
GL_POINTS rendering and custom shaders for soft circular particles.
2026-02-09 01:24:17 -08:00
Kelsi
c6a915397c Remove confusing north indicator from minimap
Removed the "N" indicator that was showing on the minimap when rotation
was enabled. The indicator was confusing and not needed - when rotation
is disabled (default), north is always at the top of the minimap, and
when rotation is enabled, the map itself rotating shows the orientation.
2026-02-09 01:21:12 -08:00
Kelsi
0fed931aa0 Implement mount ambient sounds
Added full mount sound system with:
- Wing flap sounds for flying mounts (gryphon/wyvern) when moving
- Wing idle/hovering sounds when stationary in air
- Breathing/snorting sounds for ground mounts when idle
- Occasional whinny sounds for ground mounts when moving

Sounds are loaded from MPQ files and played via AudioEngine with
randomized pitch/volume variation. Mount sound manager tracks mount
type, movement state, and flying state to play appropriate ambient
sounds at natural intervals.

Updated setMounted() to accept creature display ID and notify the
mount sound manager, which uses display ID ranges to detect mount
type (flying vs ground).
2026-02-09 01:19:35 -08:00
Kelsi
0b6b403848 Fix mount footstep timing and frequency
Reduced mount footsteps from 4 beats to 2 beats per animation cycle
with evenly-spaced timing at 0.25 and 0.75 normalized time. The
previous 4-beat pattern (0.1, 0.35, 0.6, 0.85) was too frequent and
not properly synced with mount animations.
2026-02-09 01:15:30 -08:00
Kelsi
980cec00bf Disable minimap rotation by default and fix settings checkbox
Changed default value from true to false in three places:
- Minimap class (rotateWithCamera member)
- GameScreen settings (minimapRotate_ and pendingMinimapRotate)
- Restore Interface Defaults button

The minimap will now remain fixed/north-up by default, and the settings
checkbox properly controls the rotation behavior.
2026-02-09 01:13:56 -08:00
Kelsi
dbf3038560 Fix action bar keyboard shortcuts not working
Added ImGuiWindowFlags_NoInputs to action bar window so it doesn't capture
keyboard input. Previously, hovering over or clicking the action bar would
set WantCaptureKeyboard=true, blocking the 1-9,0,-,= hotkeys from working.
2026-02-09 01:11:49 -08:00
Kelsi
0ce23cf7bd Fix unwanted mounting when closing taxi window
Closing the taxi map without selecting a destination now properly dismounts
the player. Previously, selectTaxiNode() would optimistically mount the
player, then closeTaxi() would only clear taxiWindowOpen_ without cleaning
up the mount state, leaving the player mounted.
2026-02-09 01:08:39 -08:00
Kelsi
f9ba6aa1b0 Add MountSoundManager skeleton for mount audio
Implement framework for playing mount sounds (flapping, galloping) based on mount type and movement state. Actual sound playback to be implemented next.
2026-02-09 01:04:53 -08:00
Kelsi
83b364a417 Fix jump collision with slope grace period
Add grounded state grace to prevent fall stumbles when descending slopes while maintaining proper jump physics.
2026-02-09 01:01:25 -08:00
Kelsi
16485e691c Convert ActivitySoundManager to use AudioEngine
Replace process-spawning with direct AudioEngine calls for jump, landing, and melee swing sounds.
2026-02-09 01:01:24 -08:00
Kelsi
ffa47f62d6 Implement 3D positional audio with distance attenuation
Add full 3D spatialization support to AudioEngine with inverse distance attenuation model for NPC voices and mount sounds.
2026-02-09 01:01:21 -08:00
Kelsi
af0a3a4daf Fix jump collision and WMO doodad rotation bugs
Prevent character from being yanked down during upward jump movement, and correct quaternion rotation for holiday decorations.
2026-02-09 00:41:19 -08:00
Kelsi
28330adfb0 Eliminate per-frame allocations in M2 renderer to reduce CPU stutter
Use persistent vectors for animation work indices, futures, and glow sprites instead of allocating each frame.
2026-02-09 00:41:07 -08:00
Kelsi
bd3f1921d1 Replace process-spawning audio with miniaudio for non-blocking playback
Eliminates severe stuttering from fork/exec + disk I/O by streaming audio directly from memory using miniaudio library.
2026-02-09 00:40:50 -08:00
Kelsi
c047446fb7 Add dynamic memory-based asset caching and aggressive loading
- Add MemoryMonitor class for dynamic cache sizing based on available RAM
- Increase terrain load radius to 8 tiles (17x17 grid, 289 tiles)
- Scale worker threads to 75% of logical cores (no cap)
- Increase cache budget to 80% of available RAM, max file size to 50%
- Increase M2 render distance: 1200 units during taxi, 800 when >2000 instances
- Fix camera positioning during taxi flights (external follow mode)
- Add 2-second landing cooldown to prevent re-entering taxi mode on lag
- Update interval reduced to 33ms for faster streaming responsiveness

Optimized for high-memory systems while scaling gracefully to lower-end hardware.
Cache and render distances now fully utilize available VRAM on minimum spec GPUs.
2026-02-08 23:15:26 -08:00
Kelsi
27d0496894 Add 1GB RAM cache for decompressed MPQ files
Eliminates repeated MPQ decompression overhead by caching decompressed
files in RAM with LRU eviction. Major performance improvement for file access.

Problem:
- Every readFile() call decompresses from MPQ (expensive!)
- M2 models, textures, WMO files decompressed repeatedly
- No caching of decompressed data
- MPQ decompression is CPU-intensive (zlib/bzip2)

Solution:
- Added 1GB LRU file cache to AssetManager
- Cache hit: instant return of decompressed data
- Cache miss: decompress once, cache for future access
- LRU eviction when cache full (removes least recently used)
- Don't cache files >100MB (avoid giant WMO chunks)
- Thread-safe with existing readMutex

Implementation:
- CachedFile struct: data + lastAccessTime
- fileCacheAccessCounter for LRU tracking
- Hit/miss statistics for monitoring
- Budget: 1GB (modern RAM easily handles this)

Performance impact:
- First load: same speed (decompress + cache)
- Subsequent loads: instant (no decompression)
- Expected 70-90% hit rate during normal play
- Huge benefit for frequently accessed models

Cache stats logged on shutdown to monitor effectiveness.
2026-02-08 22:37:29 -08:00
Kelsi
34cd5a161d Reduce wave amplitude to fix tile boundary gaps
Each water tile generates waves independently using local coordinates,
causing height mismatches at tile boundaries. Reduced amplitude minimizes
visible seams.

Problem:
- Waves calculated per-tile using local vertex positions (aPos)
- Adjacent tiles have different local coords at shared boundary
- Wave height discontinuity creates visible gaps between tiles

Solution:
- Reduced ocean wave amplitude: 0.25 → 0.06 (75% reduction)
- Reduced canal wave amplitude: 0.10 → 0.04
- Kept frequency and speed for subtle animation
- Waves still visible but gaps minimized

Technical note: Proper fix would be world-space wave calculation, but
requires passing tile offset to shader. This amplitude reduction is
simpler and effective for smooth ocean appearance.
2026-02-08 22:35:11 -08:00
Kelsi
26e984b60f Skip all camera controller logic during taxi flights
Taxi flights are externally controlled - no need for collision detection,
movement processing, or input handling. Massive performance improvement.

Changes:
- Early return in CameraController::update() when externalFollow_ is true
- Skips all collision queries (terrain, WMO, M2)
- Skips all movement physics (gravity, swimming, jumping)
- Skips input processing (keyboard, mouse)
- Skips camera collision raycasts

Performance impact:
- 100% elimination of ~17 collision queries per frame during taxi
- No wasted cycles on movement code when position is scripted
- Camera still updates position via setExternalFollow system
- Smooth taxi flights with zero collision overhead

This addresses the core issue: "shouldn't be looking for collision at all
during taxi" - now it doesn't!
2026-02-08 22:33:45 -08:00
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
27d550d521 Break up regular wave pattern with randomized phases and octaves
Eliminates visible grid symmetry when viewing ocean from altitude by adding
pseudo-random phase offsets and multiple wave frequencies.

Changes:
- Added position-based hash functions for pseudo-random phase offsets
- Phase-shifted primary waves (w1, w2) by hash * 2π
- Added 2 higher-frequency detail waves (w3, w4) at lower amplitudes
- Detail waves: 1.7x-2.1x frequency, 0.28-0.35x amplitude
- Different speeds and directions for each octave

Result: Natural-looking ocean with broken symmetry visible from altitude.
No more obvious grid pattern or repetitive crests.

The hash function creates consistent randomness per vertex position,
breaking the regular sine/cosine pattern without performance impact.
2026-02-08 22:28:26 -08:00
Kelsi
e98e0562b8 Fill water tile gaps at coastlines with neighbor checking
Fixes visible square gaps in ocean near coastlines by rendering masked tiles
if they have any water neighbors. Creates smoother, more natural coastlines.

Implementation:
- Check 8 neighboring tiles when a tile is masked out
- If any neighbor is water, render the edge tile anyway
- Creates 1-tile overlap at coastline boundaries
- Fills square gaps between water tiles

Before: Hard square edges with missing ocean tiles at coast
After: Continuous water coverage with smooth blended coastlines

The straight-line grid artifacts are reduced by ensuring adjacent water
tiles connect properly instead of leaving rectangular voids.
2026-02-08 22:27:11 -08:00
Kelsi
709138cf5d Relax aggressive taxi culling to show more detail
With VRAM model caching eliminating loading hitches, we can now render
much more detail during taxi flights for better visual quality.

Changes:
- boundRadius threshold: 15.0 → 2.0 (now show buildings, trees, large props)
- Foliage: was skipping ALL, now only skip small bushes/flowers < 5 units
- Trees: now visible (removed collisionTreeTrunk blanket skip)
- Underwater: -5.0 → -10.0 (only skip very deep objects)

Before: Only massive buildings visible, world looked empty
After: Buildings, trees, large props visible for immersive flight experience

Performance remains good due to persistent VRAM caching from earlier optimization.
2026-02-08 22:24:11 -08:00
Kelsi
08f0b4d028 Simplify foam to fix grid artifact
Removed complex noise-based foam that created visible grid pattern.
Replaced with simple subtle highlight on highest wave peaks only.

Kept the increased wave strength (bigger, more visible ocean waves).
2026-02-08 22:22:58 -08:00
Kelsi
3cab27060c Increase wave strength and add shoreline foam
Ocean waves are now much more pronounced, and foam appears on shorelines
in addition to wave crests.

Wave strength increases:
- Amplitude: 0.12 → 0.25 (ocean), 0.07 → 0.10 (canals)
- Frequency: 0.18 → 0.22 (ocean) - more waves per distance
- Speed: 1.60 → 2.00 (ocean) - faster wave motion

Shoreline foam:
- Appears on shallow/near-camera water (20-80 unit range)
- Uses upward-facing surface detection (horizontal = shore)
- Combined with wave crest foam for realistic effect
- Animated with same noise pattern as wave foam

Wave crest foam improvements:
- Lower threshold (0.15 vs 0.25) - more visible
- Increased intensity (0.85 vs 0.65)
- Faster animation (time * 0.8)
- Higher frequency noise (50.0 vs 40.0)

Result: Ocean now has visible motion from distance and foam on beaches.
2026-02-08 22:20:45 -08:00
Kelsi
e7ff0ce0ce Add distance-based water opacity and procedural ocean foam
Makes distant water more opaque to hide underwater objects and improve
visual quality during flight. Also adds animated foam on wave crests.

Distance-based opacity:
- Water becomes more opaque from 80-400 units distance
- Smoothstep fade adds up to 50% opacity at far distances
- Hides underwater M2 models and terrain from aerial view
- Max alpha increased from 0.82 to 0.95 for distant water

Procedural foam:
- Generated on wave peaks (positive WaveOffset values)
- Uses noise function for natural foam texture
- Animated with time and texture coordinates
- Adds white highlights to wave crests for ocean realism

This improves taxi flight visuals by making oceans look more solid
and realistic from altitude, similar to authentic WoW.
2026-02-08 22:14:54 -08:00
Kelsi
11dbca7413 Fix character attachment to follow mount's full rotation
Character now properly rotates with the mount during flight instead of just
bobbing up and down. This fixes the issue where the character appeared to
float away from the mount during rolls and pitch changes.

Implementation:
- Create rotation matrix from mount's pitch, roll, yaw
- Transform rider offset through rotation (local → world space)
- Apply same rotation to character model (glued to mount)
- Character stays properly seated during all mount movements

Before: Character only offset vertically, sliding around during banking
After: Character rotates with mount, stays firmly attached during all maneuvers
2026-02-08 22:11:40 -08:00
Kelsi
71b52046e0 Keep M2 models permanently in VRAM to eliminate loading hitches
Modern GPUs have 8-16GB VRAM - leverage this to cache all M2 models permanently.

Changes:
- Disabled cleanupUnusedModels() call when tiles unload
- Models now stay in VRAM after initial load, even when tiles unload
- Increased taxi mounting delay from 3s to 5s for more precache time
- Added logging: M2 model count, instance count, and GPU upload duration
- Added debug logging when M2 models are uploaded per tile

This fixes the "building pops up then pause" issue - models were being:
1. Loaded when tile loads
2. Unloaded when tile unloads (behind taxi)
3. Re-loaded when flying through again (causing hitch)

Now models persist in VRAM permanently (few hundred MB for typical session).
First pass loads to VRAM, subsequent passes are instant.
2026-02-08 22:08:42 -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
941dac446d Implement distance-based LOD system for M2 models
Added LOD (Level of Detail) selection based on camera distance:
- 0-40 units: LOD 0 (base detail)
- 40-80 units: LOD 1 (medium detail)
- 80-150 units: LOD 2 (medium-low detail)
- 150+ units: LOD 3 (lowest detail)

Matches WoW retail behavior. Each M2 skin file contains multiple LOD
versions (submeshLevel 0-3). System filters batches to only render
the appropriate LOD for each instance's distance, significantly
improving performance with many distant models.
2026-02-08 20:55:10 -08:00
Kelsi
cbbf819c0d Increase terrain load radius during taxi for aggressive caching
During taxi flights, increased terrain load radius from 2 to 4 tiles
(5x5 to 9x9 grid) to pre-cache more tiles ahead of flight path. Returns
to normal 5x5 after landing. 2GB cache stores loaded tiles for fast
retrieval. WMO/M2 models already cached in RAM once loaded.
2026-02-08 20:51:17 -08:00
Kelsi
1f0e948d34 Skip M2 collision queries during taxi instead of rendering
Reverted M2 rendering skip. Instead disable M2 collision/floor queries
during taxi (externalFollow mode) for performance. M2 models remain
visible but don't affect movement, grounding, or camera collision during
flight paths.
2026-02-08 20:45:59 -08:00