Commit graph

420 commits

Author SHA1 Message Date
Kelsi
8cb6311470 Make InvisibleTrap objects invisible and non-collidable
Event objects like Fire Festival Fury Trap and Mercutio Post use
SpellObject_InvisibleTrap.m2 models which were rendering as white
tiles using WHITE1.BLP texture. These are meant to be invisible
spell trigger objects that should not obstruct player movement.

Changes:
- Added isInvisibleTrap flag to M2ModelGPU struct
- Detect models with "invisibletrap" in name during loading
- Skip rendering invisible trap instances in render loop
- Disable all collision checks (floor/wall/occlusion) for invisible traps
- Objects remain functional for spell casting but are now invisible
2026-02-09 22:31:36 -08:00
Kelsi
fe728300a9 Add water height adjustment for Stormwind canal overflow
PROBLEM:
Canal water surfaces in Stormwind extend spatially beyond their intended
boundaries, causing water to appear in tunnels and buildings where it
shouldn't be visible. This is likely due to oversized water mesh extents
in the original WoW data.

SOLUTION:
Lower Stormwind canal water by 1 unit to hide it below tunnel/building floors
while keeping boats at reasonable floating height:
- Only affects water in Stormwind area (tiles 28-50, 28-52)
- Only affects water above 94 height (canal level)
- Moonwell exclusion: 20-unit radius around (-8755.9, 1108.9, 96.1)
  to preserve functional moonwell water

HARDCODED VALUES:
- Stormwind area bounds: tiles (28-50, 28-52)
- Height threshold: >94 units (canal level)
- Moonwell position: (-8755.9, 1108.9, 96.1) with 20-unit exclusion
- Lowering amount: 1 unit

WHY THIS IS HACKY:
- Zone-specific logic hardcoded for Stormwind coordinates
- Position-based moonwell exclusion uses hardcoded world coordinates
- Height threshold is a magic number tuned by trial
- Doesn't fix root cause (oversized water surface meshes)
- Some park water may still be visible

PROPER FIX WOULD BE:
- Trim water surface meshes to actual canal boundaries in ADT/WMO data
- Or implement spatial clipping of water surfaces at render time

This is a pragmatic workaround that improves the situation.
2026-02-09 21:39:33 -08:00
Kelsi
6523d99b91 Add zone-specific water filtering for Stormwind
- Filter terrain water in Stormwind area (tiles 28-35, 46-52) to 85-110 height range
- Conservative global WMO water filter (only removes water above 300 or below -100)
- Increase canal water opacity and add distance-based opacity
- Prevents floating/underground water in Stormwind without affecting other zones
2026-02-09 20:29:47 -08:00
Kelsi
0c590ac952 Disable collision for carpet and rug M2 models
- Add carpet/rug name detection in model loading
- Set collisionNoBlock flag for carpet and rug models
- Prevents slipping/sliding on decorative floor coverings
- Player can now walk through carpets without collision
2026-02-09 20:05:24 -08:00
Kelsi
b222b78734 Increase M2 frustum culling padding to prevent edge pop-out
- Increase padding from 1.2x to 2.5x model radius
- Add minimum 5 unit padding for small objects like lamps
- Fixes models disappearing at viewport edges during camera rotation
2026-02-09 20:02:52 -08:00
Kelsi
277c53d77c Fix Stormwind cathedral LOD shell and extend view distance
- Add distance-based + backface culling for STORMWIND.WMO LOD shell groups
- Hide floating cathedral shell when within 185 units of group center
- Enable backface culling for LOD shell to reduce artifacts from inside
- Increase WMO view distance from 160 to 500 units for better visibility
- Extend fog distances to 3000-4000 units for clearer long-range views
- Add fog support to water renderer matching WMO fog settings
2026-02-09 19:57:22 -08:00
Kelsi
7e69978f40 Refine LOD culling with combined Z and size threshold
Previous threshold (worldZ > 150) was too aggressive and hid Group 95
at worldZ=162 which is legitimate cathedral geometry.

New approach: Only hide groups that are BOTH:
- High: worldZ > 180
- Very tall: sizeZ > 100

This specifically targets ONLY the floating shell:
- Group 92: worldZ=225, sizeZ=251 ✓ culled
- Group 93: worldZ=201, sizeZ=165 ✓ culled

While preserving legitimate geometry:
- Group 95: worldZ=162, sizeZ=131 ✓ kept (Z < 180)
- All other groups: Z < 180 ✓ kept
2026-02-09 19:04:41 -08:00
Kelsi
4dfbcbb6f5 Fix floating cathedral by culling high-Z LOD shell groups
Identified the floating LOD shell from Z-position analysis:
- Group 92: worldZ=225 (flags=0x7d2, 251.5 units tall!)
- Group 93: worldZ=201.6 (flags=0x7e1, 165.4 units tall!)

These groups are positioned WAY above the normal cathedral geometry
(which sits at worldZ 98-122). They're the simplified distant shell
meant to make the cathedral look impressive from far away.

Fix: Skip rendering groups with worldZ > 150.0
This hides the floating shell while keeping all normal cathedral
geometry visible.

The threshold of 150 sits safely between:
- Normal cathedral: 98-122
- Floating shell: 200-225
2026-02-09 19:03:02 -08:00
Kelsi
252f29d29b Add Z-position logging and disable culling for debugging
Enhanced STORMWIND.WMO logging to show:
- centerZ: local Z position of group center
- sizeZ: height of the group
- worldZ: world Z position after transform

Removed all culling logic to see ALL groups rendering.

This will help identify which groups are positioned HIGH (floating shell).
User reports the shell is 'larger and floating above' the real cathedral,
so we need to find groups with unusually high Z positions.
2026-02-09 19:01:25 -08:00
Kelsi
2089853e97 Revise LOD culling: hide distant groups when near WMO
Changed culling strategy based on observation:
- Previous: Hide groups with <100 verts when close
- New: Hide groups >200 units away when you're <300 units from WMO

The floating cathedral is likely Groups 281/283/284/285 which are:
- High detail (23k-28k verts)
- Far away (200-569 units from camera)
- Meant to show the cathedral from a distance

When you're actually near/inside the cathedral (distToWMO < 300),
these distant views should be hidden and only the close-up geometry
(Group 257 at 20 units) should render.
2026-02-09 18:57:22 -08:00
Kelsi
ddd2e1aad7 Implement LOD shell culling to fix floating cathedral
Added distance-based culling for WMO LOD shell groups:
- Skip groups with <100 vertices when camera is within 500 units
- This hides the simplified 'distant shell' when you're close to buildings

Analysis from STORMWIND.WMO logs revealed:
- LOD shell: Groups 268/269/271/274 (24-72 verts, flags 0x19xx)
- Main cathedral: Group 257 (32,698 verts at 20 units distance)

The LOD shell groups are meant for distant viewing only but were
rendering at all distances, causing the 'floating cathedral' effect.

Fix: Compute distance from camera to each group center and skip
rendering low-vertex groups when close. This preserves performance
(LOD shells still render from far away) while fixing the visual bug.
2026-02-09 18:51:28 -08:00
Kelsi
20bd54f9d4 Add WMO group flag logging for STORMWIND.WMO LOD detection
Added detailed logging when rendering STORMWIND.WMO groups to identify
the distant LOD shell that's causing the floating cathedral:
- Group index
- Group flags (hex) - will reveal which flag marks distant-only groups
- Distance from camera to group center
- Vertex count (helps identify simplified LOD geometry)

Logs once per session to avoid spam. This will help us identify:
1. Which groups are the floating LOD shell
2. What flag value indicates 'distant view only'
3. Proper distance threshold for LOD culling

Next step: Use flag pattern to hide distant groups when camera is close.
2026-02-09 18:43:37 -08:00
Kelsi
411ee8b485 Fix WMO instance duplication causing 16x Stormwind rendering
Added deduplication for WMO instances based on uniqueId, matching the
existing M2 doodad deduplication logic. This prevents creating multiple
instances of the same WMO when it's referenced from multiple ADT tiles.

Before: STORMWIND.WMO (uniqueId=10047) was being rendered 16 times
        (one instance per ADT tile that references it)
After:  Only 1 instance is created and shared across all tiles

Changes:
- Added placedWmoIds set to TerrainManager (like placedDoodadIds)
- Check uniqueId before creating WMO instance
- Skip duplicate WMO placements across tile boundaries
- Log dedup statistics: 'X instances, Y dedup skipped'

This should fix the floating cathedral visual issue if it was caused by
rendering artifacts from 16x overdraw, and will massively improve
performance in Stormwind.
2026-02-09 18:38:45 -08:00
Kelsi
9ebfc9b21f Fix completely black WMO areas caused by zero vertex colors
The issue was that vertex colors (MOCV) were being multiplied directly into
the texture color BEFORE lighting calculation. When MOCV data contained
black (0,0,0) values, this zeroed out the texture color, making all
subsequent lighting multiplication also zero, resulting in pitch black areas
regardless of ambient light settings.

Fixed by:
1. Removed premature vertex color multiplication from texture sampling
2. Applied vertex colors as ambient occlusion AFTER lighting calculation
3. Clamped vertex colors to minimum 0.5 to prevent complete blackout

Now even areas with black MOCV data will render at 50% brightness minimum,
while properly lit areas remain bright. This preserves the AO effect without
causing invisible geometry.
2026-02-09 18:13:05 -08:00
Kelsi
3f7da35fb8 Add WMO diagnostic logging and increase ambient light
Added detailed logging for WMO vertex data to diagnose pitch black areas:
- Log MOCV (vertex colors) chunk presence and first color value
- Log MONR (normals) chunk presence and first normal vector
- Log WMO group flags to identify interior vs exterior groups

Increased WMO ambient light from (0.4, 0.4, 0.5) to (0.55, 0.55, 0.6) to
make shadowed/dark areas more visible. This addresses pitch black areas in
Stormwind and other locations where diffuse lighting may be insufficient.

The diagnostic output will help identify if black areas are caused by:
- Missing or incorrect vertex color data (MOCV)
- Missing or incorrect normal data (MONR)
- Groups incorrectly flagged as interior (0x2000 flag)
2026-02-09 18:08:40 -08:00
Kelsi
1603456120 Add body type selection for nonbinary characters and reduce preview rotation sensitivity
Nonbinary characters can now choose between masculine and feminine body types in character creation, with real-time preview updates and full appearance customization. Body type preference is saved to character config and persists across sessions. Also reduces character preview drag-to-rotate sensitivity from 0.5 to 0.2 for better control.
2026-02-09 17:56:04 -08:00
Kelsi
0071c24713 Add nonbinary gender support with pronoun system and server compatibility
Extends gender system beyond WoW's binary male/female to support nonbinary characters with proper they/them pronouns. Implements client-side gender mapping (nonbinary→male) for 3.3.5a server compatibility while preserving player identity through local config persistence. Adds pronoun placeholders ($p/$o/$s/$S) and three-option gender text parsing ($g<male>:<female>:<nonbinary>;) for inclusive quest and dialog text.
2026-02-09 17:39:21 -08:00
Kelsi
9741c8ee7c Implement comprehensive audio control panel with tabbed settings interface
Adds complete audio volume controls for all 11 audio systems with master volume. Reorganizes settings window into Video, Audio, and Gameplay tabs for better UX.

Audio Features:
- Master volume control affecting all audio systems
- Individual volume sliders for: Music, Ambient, UI, Combat, Spell, Movement, Footsteps, NPC Voices, Mounts, Activity sounds
- Real-time volume adjustment with master volume multiplier
- Restore defaults button per tab

Technical Changes:
- Added getVolumeScale() getters to all audio managers
- Integrated all 10 audio managers into renderer (UI, Combat, Spell, Movement added)
- Expanded game_screen.hpp with 11 pending volume variables
- Reorganized settings window using ImGui tab bars (Video/Audio/Gameplay)
- Audio settings uses scrollable child window for 11 volume controls
- Settings window expanded to 520x720px to accommodate comprehensive controls
2026-02-09 17:07:22 -08:00
Kelsi
d6f0c2ec46 Add comprehensive weather, water, and zone ambient audio systems
Implemented three new ambient audio systems with automatic day/night transitions:

Weather ambience:
- Rain sounds (light/medium/heavy intensity based on weather system)
- Snow sounds (light/medium/heavy intensity)
- Automatically syncs with visual weather system in renderer
- Different loop intervals based on intensity (18-30s)
- Disabled indoors

Water ambience:
- Underwater swimming sounds (18s loop)
- Ocean surface sounds
- State tracking for entering/exiting water

Zone ambience:
- Forest (normal and snow variants)
- Beach sounds
- Grasslands
- Jungle
- Marsh/swamp
- Desert (canyon and plains variants)
- All zones have separate day/night sound files
- 30s loop interval for subtle background atmosphere
- Disabled indoors

Technical details:
- Added WeatherType enum (NONE, RAIN/SNOW LIGHT/MEDIUM/HEAVY)
- Added ZoneType enum (NONE, FOREST_NORMAL, FOREST_SNOW, BEACH, GRASSLANDS, JUNGLE, MARSH, DESERT_CANYON, DESERT_PLAINS)
- Loads 26 new sound files from Sound\Ambience\Weather and Sound\Ambience\ZoneAmbience
- Weather intensity thresholds: <0.33 = light, 0.33-0.66 = medium, >0.66 = heavy
- Renderer automatically converts Weather::Type + intensity to AmbientSoundManager::WeatherType
- All ambience respects volumeScale_ and indoor state
- State change logging for debugging transitions
2026-02-09 16:12:06 -08:00
Kelsi
251f0ac246 Increase blacksmith hammer sound pitch to 1.6x
Raises pitch from 1.4f to 1.6f for more distinct metallic clink in blacksmith ambience.
2026-02-09 15:21:07 -08:00
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
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
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
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
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
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
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
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
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