275std::weak_ptr<DynamicTileBuilder::AsyncTileResult> DynamicTileBuilder::BuildTile(
uint32 terrainMapId,
uint32 tileX,
uint32 tileY)
277 struct GameObjectModelWorkData
279 explicit GameObjectModelWorkData(std::shared_ptr<VMAP::WorldModel const> worldModel, G3D::Vector3
const& position,
float scale,
280 G3D::Quat
const& rotation,
GameObjectModel const* gameObject) : WorldModel(std::move(worldModel)),
Position(position),
281 Rotation(rotation), Scale(scale),
GameObject(gameObject) { }
283 std::shared_ptr<VMAP::WorldModel const> WorldModel;
290 std::vector<GameObjectModelWorkData> modelSpawns;
291 for (
GameObjectModel const* gameObjectModel : m_map->GetGameObjectModelsInGrid(tileX, tileY))
293 if (!gameObjectModel->IsIncludedInNavMesh())
296 std::shared_ptr<VMAP::WorldModel const> worldModel = gameObjectModel->GetWorldModel();
300 modelSpawns.emplace_back(std::move(worldModel), gameObjectModel->GetPosition(),
301 gameObjectModel->GetScale(), gameObjectModel->GetRotation(), gameObjectModel);
304 TileCacheKey cacheKey{ .TerrainMapId = terrainMapId, .X = tileX, .Y = tileY, .CachedHash = 0, .Objects = std::vector<TileCacheKeyObject>(modelSpawns.size()) };
305 for (std::size_t i = 0; i < modelSpawns.size(); ++i)
308 TileCacheKeyObject&
object = cacheKey.Objects[i];
311 object.Position = [](G3D::Vector3
const& pos) -> std::array<int16, 3>
319 std::ranges::sort(cacheKey.Objects);
321 cacheKey.CachedHash = std::hash<TileCacheKey>::Compute(cacheKey);
323 TileCache* tileCache = TileCache::Instance();
324 std::scoped_lock lock(tileCache->TilesMutex);
325 auto [itr, isNew] = tileCache->Tiles.try_emplace(std::move(cacheKey));
328 return itr->second.Data;
330 itr->second.Data = std::make_shared<AsyncTileResult>();
331 tileCache->StartTask([result = itr->second.Data, hash = cacheKey.CachedHash, selfRef = weak_from_this(), terrainMapId, tileX, tileY, modelSpawns = std::move(modelSpawns)]()
mutable
333 auto isReadyGuard = Trinity::make_unique_ptr_with_deleter<SetAsyncCallbackReady>(result.get());
335 std::shared_ptr<DynamicTileBuilder> self = selfRef.lock();
341 std::vector<OffMeshData> offMeshConnections;
342 if (MMapManager::parseNavMeshParamsFile(
sWorld->GetDataPath(), terrainMapId, &
params, &offMeshConnections) != LoadResult::Success)
345 std::unique_ptr<VMAP::VMapManager> vmapManager =
CreateVMapManager(terrainMapId);
350 self->m_terrainBuilder.loadMap(terrainMapId, tileX, tileY, meshData, vmapManager.get());
353 self->m_terrainBuilder.loadVMap(terrainMapId, tileX, tileY, meshData, vmapManager.get());
355 for (GameObjectModelWorkData
const& model : modelSpawns)
357 G3D::Vector3 position = model.Position;
358 position.x = -position.x;
359 position.y = -position.y;
361 G3D::Matrix3 invRotation = (G3D::Quat(0, 0, 1, 0) * model.Rotation).toRotationMatrix().inverse();
363 self->m_terrainBuilder.loadVMapModel(model.WorldModel.get(), position, invRotation, model.Scale,
364 meshData, vmapManager.get());
377 std::ranges::copy(meshData.
liquidVerts, allVerts.begin());
381 float bmin[3], bmax[3];
382 getTileBounds(tileX, tileY, allVerts.data(), allVerts.size() / 3, bmin, bmax);
384 self->m_terrainBuilder.loadOffMeshConnections(terrainMapId, tileX, tileY, meshData, offMeshConnections);
389 result->Result = self->buildMoveMapTile(terrainMapId, tileX, tileY, meshData, bmin, bmax, &
params);
390 if (self->m_debugOutput && result->Result.data)
391 self->saveMoveMapTileToFile(terrainMapId, tileX, tileY,
nullptr, result->Result, debugSuffix);
394 return itr->second.Data;