mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Tools/mmaps_generator: Save offmesh connections input together with navmesh params for each map
This commit is contained in:
@@ -97,6 +97,28 @@ namespace MMAP
|
||||
}
|
||||
|
||||
// load and init dtNavMesh - read parameters from file
|
||||
dtNavMeshParams params;
|
||||
if (LoadResult paramsResult = parseNavMeshParamsFile(basePath, mapId, ¶ms); paramsResult != LoadResult::Success)
|
||||
return paramsResult;
|
||||
|
||||
NavMeshPtr mesh(dtAllocNavMesh());
|
||||
ASSERT(mesh);
|
||||
if (dtStatusFailed(mesh->init(¶ms)))
|
||||
{
|
||||
TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:04}", mapId);
|
||||
return LoadResult::LibraryError;
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:04}.mmap", mapId);
|
||||
|
||||
// store inside our map list
|
||||
itr->second.reset(new MMapData(std::move(mesh)));
|
||||
return LoadResult::Success;
|
||||
}
|
||||
|
||||
LoadResult MMapManager::parseNavMeshParamsFile(std::string_view basePath, uint32 mapId, dtNavMeshParams* params,
|
||||
std::vector<OffMeshData>* offmeshConnections /*= nullptr*/)
|
||||
{
|
||||
std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, basePath, mapId);
|
||||
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "rb"));
|
||||
if (!file)
|
||||
@@ -105,26 +127,39 @@ namespace MMAP
|
||||
return LoadResult::FileNotFound;
|
||||
}
|
||||
|
||||
dtNavMeshParams params;
|
||||
uint32 count = uint32(fread(¶ms, sizeof(dtNavMeshParams), 1, file.get()));
|
||||
if (count != 1)
|
||||
MmapNavMeshHeader fileHeader;
|
||||
if (fread(&fileHeader, sizeof(MmapNavMeshHeader), 1, file.get()) != 1)
|
||||
{
|
||||
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '{}'", fileName);
|
||||
return LoadResult::ReadFromFileFailed;
|
||||
}
|
||||
|
||||
NavMeshPtr mesh(dtAllocNavMesh());
|
||||
ASSERT(mesh);
|
||||
if (dtStatusFailed(mesh->init(¶ms)))
|
||||
if (fileHeader.mmapMagic != MMAP_MAGIC)
|
||||
{
|
||||
TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:04} from file {}", mapId, fileName);
|
||||
return LoadResult::LibraryError;
|
||||
TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap {:04}.mmap", mapId);
|
||||
return LoadResult::VersionMismatch;
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:04}.mmap", mapId);
|
||||
if (fileHeader.mmapVersion != MMAP_VERSION)
|
||||
{
|
||||
TC_LOG_ERROR("maps", "MMAP:loadMap: {:04}.mmap was built with generator v{}, expected v{}",
|
||||
mapId, fileHeader.mmapVersion, MMAP_VERSION);
|
||||
return LoadResult::VersionMismatch;
|
||||
}
|
||||
|
||||
memcpy(params, &fileHeader.params, sizeof(dtNavMeshParams));
|
||||
|
||||
if (offmeshConnections)
|
||||
{
|
||||
offmeshConnections->resize(fileHeader.offmeshConnectionCount);
|
||||
if (fread(offmeshConnections->data(), sizeof(OffMeshData), offmeshConnections->size(), file.get()) != offmeshConnections->size())
|
||||
{
|
||||
offmeshConnections->clear();
|
||||
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read offmesh connections from file '{}'", fileName);
|
||||
return LoadResult::ReadFromFileFailed;
|
||||
}
|
||||
}
|
||||
|
||||
// store inside our map list
|
||||
itr->second.reset(new MMapData(std::move(mesh)));
|
||||
return LoadResult::Success;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#define _MMAP_MANAGER_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <DetourNavMesh.h>
|
||||
#include "MMapDefines.h"
|
||||
#include <DetourNavMeshQuery.h>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
@@ -58,6 +58,7 @@ namespace MMAP
|
||||
static MMapManager* instance();
|
||||
|
||||
void InitializeThreadUnsafe(std::unordered_map<uint32, std::vector<uint32>> const& mapData);
|
||||
static LoadResult parseNavMeshParamsFile(std::string_view basePath, uint32 mapId, dtNavMeshParams* params, std::vector<OffMeshData>* offmeshConnections = nullptr);
|
||||
LoadResult loadMap(std::string_view basePath, uint32 mapId, int32 x, int32 y);
|
||||
bool loadMapInstance(std::string_view basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
|
||||
bool unloadMap(uint32 mapId, int32 x, int32 y);
|
||||
|
||||
@@ -19,22 +19,29 @@
|
||||
#define MMapDefines_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "DetourNavMesh.h"
|
||||
#include <DetourNavMesh.h>
|
||||
|
||||
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
|
||||
#define MMAP_VERSION 15
|
||||
inline uint32 constexpr MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
|
||||
inline uint32 constexpr MMAP_VERSION = 16;
|
||||
|
||||
struct MmapNavMeshHeader
|
||||
{
|
||||
uint32 mmapMagic = MMAP_MAGIC;
|
||||
uint32 mmapVersion = MMAP_VERSION;
|
||||
dtNavMeshParams params = { };
|
||||
uint32 offmeshConnectionCount = 0;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MmapNavMeshHeader) == 40);
|
||||
|
||||
struct MmapTileHeader
|
||||
{
|
||||
uint32 mmapMagic;
|
||||
uint32 dtVersion;
|
||||
uint32 mmapVersion;
|
||||
uint32 size;
|
||||
char usesLiquids;
|
||||
char padding[3];
|
||||
|
||||
MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
|
||||
mmapVersion(MMAP_VERSION), size(0), usesLiquids(true), padding() { }
|
||||
uint32 mmapMagic = MMAP_MAGIC;
|
||||
uint32 dtVersion = DT_NAVMESH_VERSION;
|
||||
uint32 mmapVersion = MMAP_VERSION;
|
||||
uint32 size = 0;
|
||||
char usesLiquids = true;
|
||||
char padding[3] = { };
|
||||
};
|
||||
|
||||
// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
|
||||
@@ -60,7 +67,7 @@ enum NavArea
|
||||
NAV_AREA_ALL_MASK = 0x3F // max allowed value
|
||||
};
|
||||
|
||||
enum NavTerrainFlag
|
||||
enum NavTerrainFlag : uint16
|
||||
{
|
||||
NAV_EMPTY = 0x00,
|
||||
NAV_GROUND = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_GROUND),
|
||||
@@ -69,4 +76,22 @@ enum NavTerrainFlag
|
||||
NAV_MAGMA_SLIME = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_MAGMA_SLIME)
|
||||
};
|
||||
|
||||
enum OffMeshConnectionFlag : uint8
|
||||
{
|
||||
OFFMESH_CONNECTION_FLAG_BIDIRECTIONAL = 0x01
|
||||
};
|
||||
|
||||
struct OffMeshData
|
||||
{
|
||||
uint32 MapId;
|
||||
uint32 TileX;
|
||||
uint32 TileY;
|
||||
float From[3];
|
||||
float To[3];
|
||||
float Radius;
|
||||
OffMeshConnectionFlag ConnectionFlags;
|
||||
uint8 AreaId;
|
||||
NavTerrainFlag Flags;
|
||||
};
|
||||
|
||||
#endif // MMapDefines_h__
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace MMAP
|
||||
if (scanned < 10)
|
||||
continue;
|
||||
|
||||
offMesh.Bidirectional = true;
|
||||
offMesh.ConnectionFlags = OFFMESH_CONNECTION_FLAG_BIDIRECTIONAL;
|
||||
if (scanned < 12)
|
||||
offMesh.Flags = NAV_GROUND;
|
||||
|
||||
@@ -447,17 +447,16 @@ namespace MMAP
|
||||
/*** now create the navmesh ***/
|
||||
|
||||
// navmesh creation params
|
||||
dtNavMeshParams navMeshParams;
|
||||
memset(&navMeshParams, 0, sizeof(dtNavMeshParams));
|
||||
navMeshParams.tileWidth = GRID_SIZE;
|
||||
navMeshParams.tileHeight = GRID_SIZE;
|
||||
rcVcopy(navMeshParams.orig, bmin);
|
||||
navMeshParams.maxTiles = maxTiles;
|
||||
navMeshParams.maxPolys = maxPolysPerTile;
|
||||
MmapNavMeshHeader fileHeader;
|
||||
fileHeader.params.tileWidth = GRID_SIZE;
|
||||
fileHeader.params.tileHeight = GRID_SIZE;
|
||||
rcVcopy(fileHeader.params.orig, bmin);
|
||||
fileHeader.params.maxTiles = maxTiles;
|
||||
fileHeader.params.maxPolys = maxPolysPerTile;
|
||||
|
||||
navMesh = dtAllocNavMesh();
|
||||
TC_LOG_INFO("maps.mmapgen", "[Map {:04}] Creating navMesh...", mapID);
|
||||
if (!navMesh->init(&navMeshParams))
|
||||
if (!navMesh->init(&fileHeader.params))
|
||||
{
|
||||
TC_LOG_ERROR("maps.mmapgen", "[Map {:04}] Failed creating navmesh!", mapID);
|
||||
return;
|
||||
@@ -474,8 +473,14 @@ namespace MMAP
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<OffMeshData> offMeshConnections;
|
||||
std::ranges::copy_if(m_offMeshConnections, std::back_inserter(offMeshConnections), [mapID](OffMeshData const& offMeshData) { return offMeshData.MapId == mapID; });
|
||||
|
||||
fileHeader.offmeshConnectionCount = offMeshConnections.size();
|
||||
|
||||
// now that we know navMesh params are valid, we can write them to file
|
||||
fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file.get());
|
||||
fwrite(&fileHeader, sizeof(MmapNavMeshHeader), 1, file.get());
|
||||
fwrite(offMeshConnections.data(), sizeof(OffMeshData), offMeshConnections.size(), file.get());
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -800,7 +800,7 @@ namespace MMAP
|
||||
meshData.offMeshConnections.push_back(offMeshConnection.To[2]);
|
||||
meshData.offMeshConnections.push_back(offMeshConnection.To[0]);
|
||||
|
||||
meshData.offMeshConnectionDirs.push_back(offMeshConnection.Bidirectional ? 1 : 0);
|
||||
meshData.offMeshConnectionDirs.push_back(offMeshConnection.ConnectionFlags & OFFMESH_CONNECTION_FLAG_BIDIRECTIONAL);
|
||||
meshData.offMeshConnectionRads.push_back(offMeshConnection.Radius); // agent size equivalent
|
||||
// can be used same way as polygon flags
|
||||
meshData.offMeshConnectionsAreas.push_back(offMeshConnection.AreaId);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#ifndef _MMAP_TERRAIN_BUILDER_H
|
||||
#define _MMAP_TERRAIN_BUILDER_H
|
||||
|
||||
#include "MMapDefines.h"
|
||||
#include "WorldModel.h"
|
||||
#include <G3D/Vector3.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -61,19 +62,6 @@ namespace MMAP
|
||||
// contrib/extractor/system.cpp
|
||||
// src/game/Map.cpp
|
||||
|
||||
struct OffMeshData
|
||||
{
|
||||
uint32 MapId;
|
||||
uint32 TileX;
|
||||
uint32 TileY;
|
||||
float From[3];
|
||||
float To[3];
|
||||
bool Bidirectional;
|
||||
float Radius;
|
||||
uint8 AreaId;
|
||||
uint16 Flags;
|
||||
};
|
||||
|
||||
struct MeshData
|
||||
{
|
||||
std::vector<float> solidVerts;
|
||||
|
||||
@@ -125,9 +125,8 @@ namespace MMAP
|
||||
|
||||
// gather all mesh data for final data check, and bounds calculation
|
||||
std::vector<float> allVerts(meshData.liquidVerts.size() + meshData.solidVerts.size());
|
||||
auto allVertsOutput = allVerts.begin();
|
||||
allVertsOutput = std::ranges::copy(meshData.liquidVerts, allVertsOutput).out;
|
||||
allVertsOutput = std::ranges::copy(meshData.solidVerts, allVertsOutput).out;
|
||||
std::ranges::copy(meshData.liquidVerts, allVerts.begin());
|
||||
std::ranges::copy(meshData.solidVerts, allVerts.begin() + std::ssize(meshData.liquidVerts));
|
||||
|
||||
// get bounds of current tile
|
||||
float bmin[3], bmax[3];
|
||||
@@ -489,11 +488,11 @@ namespace MMAP
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void TileBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax)
|
||||
void TileBuilder::getTileBounds(uint32 tileX, uint32 tileY, float const* verts, std::size_t vertCount, float* bmin, float* bmax)
|
||||
{
|
||||
// this is for elevation
|
||||
if (verts && vertCount)
|
||||
rcCalcBounds(verts, vertCount, bmin, bmax);
|
||||
rcCalcBounds(verts, int(vertCount), bmin, bmax);
|
||||
else
|
||||
{
|
||||
bmin[1] = FLT_MIN;
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
virtual bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY) const;
|
||||
|
||||
static void getTileBounds(uint32 tileX, uint32 tileY,
|
||||
float* verts, int vertCount,
|
||||
float const* verts, std::size_t vertCount,
|
||||
float* bmin, float* bmax);
|
||||
|
||||
rcConfig GetMapSpecificConfig(uint32 mapID, float const (&bmin)[3], float const (&bmax)[3], TileConfig const& tileConfig) const;
|
||||
|
||||
Reference in New Issue
Block a user