From 01d36388354dff46629dd9af17ad1c2b51f1a2fe Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 5 May 2026 12:12:26 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20WOB=E2=86=92WMO=20conversion=20and=20lo?= =?UTF-8?q?ading=20in=20client=20terrain=20manager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - WoweeBuildingLoader::toWMOModel() converts WOB groups to WMOModel with vertices, indices, normals, texCoords, and vertex colors - TerrainManager now loads WOB files from custom_zones/buildings/ and converts to WMOModel for the WMO renderer pipeline - WMOGroup indices converted from uint32 to uint16 for renderer compat Client open format support — 4 of 6 now loading: - FULL: WOT/WHM terrain, PNG textures, WOM models - LOAD: WOB buildings (converts to WMOModel, render pipeline TODO) - DETECT: zone.json (scanned), JSON DBC (scanned) --- include/pipeline/wowee_building.hpp | 3 +++ src/pipeline/wowee_building.cpp | 35 +++++++++++++++++++++++++++++ src/rendering/terrain_manager.cpp | 9 +++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/pipeline/wowee_building.hpp b/include/pipeline/wowee_building.hpp index d124316d..98e9d625 100644 --- a/include/pipeline/wowee_building.hpp +++ b/include/pipeline/wowee_building.hpp @@ -53,6 +53,9 @@ public: static WoweeBuilding load(const std::string& basePath); static bool save(const WoweeBuilding& building, const std::string& basePath); static bool exists(const std::string& basePath); + + // Convert WOB to WMOModel for the client's WMO renderer + static bool toWMOModel(const WoweeBuilding& building, class WMOModel& outModel); }; } // namespace pipeline diff --git a/src/pipeline/wowee_building.cpp b/src/pipeline/wowee_building.cpp index 23538b46..74ca4ac6 100644 --- a/src/pipeline/wowee_building.cpp +++ b/src/pipeline/wowee_building.cpp @@ -1,4 +1,5 @@ #include "pipeline/wowee_building.hpp" +#include "pipeline/wmo_loader.hpp" #include "core/logger.hpp" #include #include @@ -161,5 +162,39 @@ bool WoweeBuildingLoader::save(const WoweeBuilding& bld, const std::string& base return true; } +bool WoweeBuildingLoader::toWMOModel(const WoweeBuilding& building, WMOModel& outModel) { + if (building.groups.empty()) return false; + + outModel.nGroups = static_cast(building.groups.size()); + outModel.groups.clear(); + + for (const auto& grp : building.groups) { + WMOGroup wmoGroup; + wmoGroup.name = grp.name; + + // Convert vertices + wmoGroup.vertices.reserve(grp.vertices.size()); + for (const auto& v : grp.vertices) { + WMOVertex wv; + wv.position = v.position; + wv.normal = v.normal; + wv.texCoord = v.texCoord; + wv.color = v.color; + wmoGroup.vertices.push_back(wv); + } + + // Convert indices + wmoGroup.indices.reserve(grp.indices.size()); + for (uint32_t idx : grp.indices) + wmoGroup.indices.push_back(static_cast(idx)); + + outModel.groups.push_back(std::move(wmoGroup)); + } + + // WMOModel uses isValid() = nGroups > 0 && !groups.empty() + // Both are now set, so isValid() will return true + return true; +} + } // namespace pipeline } // namespace wowee diff --git a/src/rendering/terrain_manager.cpp b/src/rendering/terrain_manager.cpp index af2db97f..ad4b4d6e 100644 --- a/src/rendering/terrain_manager.cpp +++ b/src/rendering/terrain_manager.cpp @@ -605,7 +605,14 @@ std::shared_ptr TerrainManager::prepareTile(int x, int y) { std::vector wobPrefixes = {"custom_zones/buildings/", "output/" + mapName + "/buildings/"}; for (const auto& prefix : wobPrefixes) { if (pipeline::WoweeBuildingLoader::exists(prefix + wobBase)) { - LOG_INFO("WOB building found: ", prefix + wobBase, " (loading not yet implemented)"); + auto wob = pipeline::WoweeBuildingLoader::load(prefix + wobBase); + if (wob.isValid()) { + pipeline::WMOModel wobAsWmo; + if (pipeline::WoweeBuildingLoader::toWMOModel(wob, wobAsWmo)) { + LOG_INFO("Loaded WOB building: ", prefix + wobBase); + // TODO: feed wobAsWmo into the WMO render pipeline + } + } break; } }