Root cause of GPU crashes (VK_ERROR_DEVICE_LOST): every NPC placement
triggered a full clear+reload of ALL M2 models. After several cycles
the GPU state corrupted, causing vertex explosions and device lost.
Fixes:
- NPC placement now only updates cheap marker geometry (no M2 reload)
- Full M2 rebuild only happens when object COUNT changes (not every click)
- clearAllObjects() properly resets viewport, placer, spawner, markers,
and history in one call with vkDeviceWaitIdle fence
- New Terrain uses clearAllObjects() for consistent reset
- Clear All menu item calls clearAllObjects()
- M2 vertex validation: rejects models with NaN/infinite/extreme
vertex positions before GPU upload (prevents vertex explosions)
- NPC marker building extracted to updateNpcMarkers() method
(can be called independently without M2 rebuild)
- Ridge Generator: creates mountain ranges by setting start and end
points, with configurable width and height
- Cross-section uses quadratic falloff, along-axis uses sqrt taper
for natural mountain range silhouette (wider at center, tapering
at both ends)
- Same start/end workflow as river/road tools
- Hill Generator: creates smooth bell-curve hills at cursor position
with configurable radius and height
- Valley mode: same shape inverted, creates natural depressions
- Uses (1-t^2)^2 falloff for very smooth natural-looking slopes
- Two buttons: "Create Hill" and "Create Valley" for quick terrain
shaping without switching brush modes
- NPC markers now render with NO depth test (via gizmo pipeline) so
they're always visible even on sloped/rough terrain
- Mesa/Plateau generator: creates raised flat areas with steep cliff
edges — configurable radius, height, and edge steepness
- NPC markers drawn after gizmo in the render pipeline to guarantee
they appear on top of everything
- Fixes NPC visibility on non-flat terrain
- Crater Generator in Sculpt panel: creates a bowl-shaped depression
with configurable radius, depth, and raised rim height
- Parabolic bowl interior with sinusoidal rim and smooth outer falloff
- Perfect for creating lakes (fill with Water mode), arenas, or
impact craters for volcanic zones
- One click at cursor position, uses brush position for center
- Middle mouse drag orbits camera around the terrain point under cursor
(or 100 units ahead if no terrain hit)
- Maintains distance from pivot while rotating yaw/pitch
- Much more intuitive for inspecting terrain features, placed objects,
and NPC positions from different angles
- Works alongside right-drag (free look) and WASD (fly)
- Yellow circle on minimap shows current brush position and radius
- Scales proportionally with terrain tile size
- Visible in all brush-based modes (Sculpt/Paint/Water)
- Helps orient where you're working relative to the full tile
- "Reset to Flat" button in Noise Generator section: zeroes all heights
across entire tile for starting over without creating a new terrain
- Useful workflow: reset → noise → smooth → scale → clamp → auto-paint
- River/Road Carver section now has two modes:
- River: carves a channel below terrain (existing)
- Road: flattens terrain to interpolated height between start/end
- Road mode smoothly transitions height along the path with quadratic
falloff at edges for natural embankment shape
- Set Start → Set End + Apply workflow works for both modes
- Roads follow terrain slope by interpolating between start/end heights
- Pair with Paint mode to add cobblestone/dirt texture on the road
- "Find Valid Tile" button in Load dialog: auto-scans manifest for the
first available ADT tile of the selected map (checks center range
25-45 first for open world, then full 0-63 for dungeons)
- Fixes "wrong coords" issue — dungeons use different tile coords than
open world maps, now auto-detected
- Map name lowercased for manifest lookup consistency
- Tile check shows green "Tile found" or red "Tile not found" indicator
- NPC markers now 30 units tall with octagonal base, colored pole,
and yellow diamond at top — visible from any camera altitude
- Red pole = hostile, green pole = friendly, yellow top = all NPCs
- River/Path Carver: set start point, set end point, carves a channel
between them with configurable width and depth
- Smooth quadratic falloff at edges for natural riverbank shape
- Pair with Water mode to fill carved channels
- River Carver in Sculpt panel: carves a channel between two points
with configurable width and depth
- Set Start at cursor, then Set End + Carve to create the channel
- Smooth quadratic falloff at edges for natural riverbank shape
- Works by projecting each terrain vertex onto the line segment and
lowering height based on distance from center
- Auto-stitches chunk edges after carving
- Pair with Water mode to fill the carved channel with liquid
- "Create Flat Platform at Cursor" button in Sculpt panel
- Instantly flattens terrain under brush radius to cursor height
- Perfect for creating building sites, road beds, camp grounds
- Applies 30 iterations of flatten for a thorough result
- Restores previous brush mode after completion
- Quest giver and turn-in NPC now selected from a dropdown of placed
creatures instead of typing raw IDs — shows name + id for each
- Links quests directly to NPCs you've already placed on the map
- "None" option to unset NPC link
- Much more intuitive quest→NPC workflow
- Mirror X: copies left half of terrain to right half (mirrored)
- Mirror Y: copies top half to bottom half (mirrored)
- Useful for creating symmetric zones, arenas, or balanced landscapes
- Auto-stitches all chunk edges after mirror for seamless results
- UI buttons in Sculpt panel under "Mirror Terrain" section
- Auto-Paint by Height: automatically sets base texture per chunk based
on average height — configurable thresholds for sand/grass/rock/snow
- Uses Tanaris sand, Elwynn grass, Barrens rock, Dragonblight snow
- One-click to texture an entire procedurally generated terrain
- Adjustable height thresholds via drag floats
- Workflow: noise → smooth → clamp → auto-paint for instant biome
- Copy Stamp: captures all vertex heights within brush radius at cursor
position, storing relative offsets from center
- Paste Stamp: applies the copied height pattern at a new location,
finding nearest vertices and setting their heights
- Stamp status shown in panel ("Stamp ready" / "No stamp copied")
- Auto-stitches chunk edges after paste for seamless results
- Useful for replicating hills, craters, or other terrain features
- New Quest mode (key 6) with full quest creation panel:
- Title, description, required level
- Quest giver / turn-in NPC ID linkage
- Up to 4 objectives: Kill, Collect, Talk, Explore, Escort, Use Object
- Rewards: XP and gold
- Quest chain support via nextQuestId linking
- Quest list showing all created quests with level and objective count
- Save quests to JSON (included in Export Zone package)
- Foundation for campaign system: create quest chains across NPCs,
link objectives to placed creatures, build storylines
- Load dialog shows green "Tile found" / red "Tile not found" indicator
by checking the manifest before you attempt to load
- NPC marker build/render diagnostic logging to trace rendering issues
- Map browser and tile checker work together for easy existing zone loading
- Load Map Tile dialog now shows a searchable list of all available
maps from the manifest (Azeroth, Kalimdor, Outland, dungeons, etc.)
- Click a map name to select it, then pick tile X/Y coordinates
- Helpful tile range hints shown below coordinates
- Maps indexed from WDT files in the manifest on startup
- Foundation for loading and modifying sections of existing WoW maps
- Colored diamond markers rendered at every NPC position on terrain:
red for hostile, green for friendly, with vertical pillar for height
- Renders through water pipeline (alpha-blended, depth-tested)
- Always visible regardless of whether M2 creature model renders
- Scales with NPC scale setting for consistent visual size
- This guarantees you can always see where NPCs are placed
- Info panel now shows M2 renderer stats: model count, instance count,
draw call count — visible in real-time to diagnose NPC rendering issues
- When placing NPCs: if models=0/instances=0, the model failed to load
If models>0 but draws=0, it's a culling/frame-sync issue
If draws>0, the model IS rendering but may be too small to see
- Clamp Heights: sets min/max height bounds across entire tile
(DragFloatRange2 slider for min/max, -500 to 2000 range)
- Useful workflow: Generate noise → Smooth → Clamp to desired range
- Prevents terrain from going underground or too high
- All affected chunks marked dirty for mesh regeneration
- "Center on Terrain" (Home key or View menu): resets camera to center
of loaded tile at 300 units altitude with 45-degree downward pitch.
Essential for recovering when camera gets lost in empty space.
- Toast confirmation on center action
- Scroll wheel now zooms camera (moves along look direction) instead
of adjusting speed. Much more intuitive for terrain editing.
- Shift+scroll adjusts camera speed (old behavior preserved)
- Click on minimap to teleport camera to that location on the terrain
- Zoom speed scales with current camera speed for consistent feel
- Loading an existing ADT now imports its MDDF (doodad) and MODF (WMO)
placements into the object placer with correct position/rotation/scale
- Allows editing zones that already have objects placed in them
- Mutable getObjects() accessor for bulk import operations
- Log shows imported doodad + WMO count on load
- Brush mode tooltips: hover over the mode combo to see what each does
(Raise/Lower/Smooth/Flatten/Level/Erode descriptions)
- Chunk texture inspector: Paint panel shows which texture layers are
on the chunk under the cursor (base + blended layers with filenames)
- Helps identify what textures you're painting over before blending
- About dialog: Help > About shows editor version, capabilities, and
supported format (WoW 3.3.5a compatible)
- Info panel now shows texture count, water chunk count, hole chunk count
- Status bar shows object/NPC counts alongside map name
- Better at-a-glance overview of zone composition without opening panels
- Loading an ADT now auto-loads objects.json and creatures.json from
the output directory if they exist (full session persistence)
- Toolbar buttons now highlight active mode in blue (clearer visual)
- Number keys 1-5 switch modes: 1=Sculpt 2=Paint 3=Objects 4=Water 5=NPCs
- Toast shows loaded object/NPC count on zone open
- White crosshair on minimap shows camera position in real-time
- Bulk Operations section in Object panel:
- "Delete All in Radius": removes all objects within brush radius
- "Snap All to Ground": raycasts every object downward to terrain
(fixes all floating objects in one click)
- Minimap legend updated with camera indicator
- Useful for cleaning up scattered objects or fixing placement height
- NPC default scale changed from 1.0 to 3.0 so creatures are visible
from typical editing altitude (WoW creature models are very small at
scale 1.0)
- Properties/Info panel uses ImGuiCond_Always for position so it stays
pinned to the right edge when the window is resized (was getting lost
off-screen before)
- Clear All now actually removes all objects and NPCs (was only clearing
selections before). Uses new ObjectPlacer::clearAll() method.
- New Terrain clears all objects/NPCs and resets viewport before creating
fresh terrain. Fixes stale state from previous session.
- Right-click context menu works on both objects AND NPCs with
appropriate options for each (Move/Rotate/Scale for objects,
Fly To/Duplicate for NPCs)
- Gizmo drag: left-click now confirms the transform (ends drag) instead
of requiring mouse-up. Right-click cancels. Camera no longer steals
mouse events while gizmo is active.
- Right-click on unselected area passes through to camera correctly
- "Fly To" button on selected objects and NPCs: moves camera 30 units
above the selected item for quick navigation on large zones
- Export now generates README.txt with zone summary: map name, tile
coords, object/NPC counts, and file listing
- Complete export package: zone.json + WDT + ADT + objects.json +
creatures.json + README.txt
- Object placer save/load: objects.json persists placed M2/WMO objects
across sessions (path, position, rotation, scale, type)
- Fixed Duplicate button in Object panel: now actually creates a copy
with correct path/type/scale instead of being a no-op stub
- Export Zone now saves objects.json alongside ADT/WDT/creatures/manifest
- Object JSON loader parses all fields for full round-trip
- Minimap now shows placed objects (yellow dots) and NPCs (red=hostile,
green=friendly) at their world positions on the height grid
- NPC Duplicate button: copies selected creature with 10-unit offset
for quick population of similar spawns
- Minimap legend: colored dots showing Object/Hostile/Friendly markers
- All positions correctly mapped from world coords to minimap UV space
- Zone manifest (zone.json): generated on export with map name, map ID,
tile list, biome, creature flag, and file paths. This is what the
wowee client will read to discover and load custom zones.
- Export workflow now produces a complete loadable zone package:
zone.json + MapName.wdt + MapName_X_Y.adt + creatures.json
- ZoneManifest class with save/load (JSON format)
- Custom map IDs start at 9000+ to avoid conflicting with retail maps
- New Terrain dialog shows helper text for map name format