aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/Management/MMapFactory.cpp18
-rw-r--r--src/server/collision/Management/MMapFactory.h8
-rw-r--r--src/server/collision/Management/MMapManager.cpp175
-rw-r--r--src/server/collision/Management/MMapManager.h29
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp4
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.h8
-rw-r--r--src/server/game/Maps/Map.cpp20
-rw-r--r--src/server/game/Maps/MapInstanced.cpp2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/PathGenerator.cpp834
-rw-r--r--src/server/game/Movement/PathGenerator.h65
-rw-r--r--src/server/game/Spells/Spell.cpp1
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp2
-rw-r--r--src/server/scripts/Commands/cs_mmaps.cpp257
-rw-r--r--src/tools/CMakeLists.txt1
-rw-r--r--src/tools/mesh_extractor/ADT.cpp7
-rw-r--r--src/tools/mesh_extractor/Cache.h20
-rw-r--r--src/tools/mesh_extractor/Chunk.cpp16
-rw-r--r--src/tools/mesh_extractor/Chunk.h8
-rw-r--r--src/tools/mesh_extractor/ChunkedData.cpp40
-rw-r--r--src/tools/mesh_extractor/ChunkedData.h7
-rw-r--r--src/tools/mesh_extractor/Constants.h2
-rw-r--r--src/tools/mesh_extractor/ContinentBuilder.cpp140
-rw-r--r--src/tools/mesh_extractor/ContinentBuilder.h64
-rw-r--r--src/tools/mesh_extractor/DBC.cpp42
-rw-r--r--src/tools/mesh_extractor/DBC.h14
-rw-r--r--src/tools/mesh_extractor/DoodadHandler.cpp44
-rw-r--r--src/tools/mesh_extractor/DoodadHandler.h21
-rw-r--r--src/tools/mesh_extractor/Geometry.cpp14
-rw-r--r--src/tools/mesh_extractor/Geometry.h2
-rw-r--r--src/tools/mesh_extractor/LiquidHandler.cpp75
-rw-r--r--src/tools/mesh_extractor/LiquidHandler.h4
-rw-r--r--src/tools/mesh_extractor/MPQ.cpp14
-rw-r--r--src/tools/mesh_extractor/MPQ.h17
-rw-r--r--src/tools/mesh_extractor/MPQManager.cpp95
-rw-r--r--src/tools/mesh_extractor/MPQManager.h13
-rw-r--r--src/tools/mesh_extractor/MapChunk.cpp18
-rw-r--r--src/tools/mesh_extractor/MapChunk.h2
-rw-r--r--src/tools/mesh_extractor/MeshExtractor.cpp108
-rw-r--r--src/tools/mesh_extractor/Model.cpp31
-rw-r--r--src/tools/mesh_extractor/Model.h3
-rw-r--r--src/tools/mesh_extractor/ObjectDataHandler.h1
-rw-r--r--src/tools/mesh_extractor/Stream.cpp47
-rw-r--r--src/tools/mesh_extractor/Stream.h59
-rw-r--r--src/tools/mesh_extractor/TileBuilder.cpp45
-rw-r--r--src/tools/mesh_extractor/TileBuilder.h6
-rw-r--r--src/tools/mesh_extractor/Utils.cpp496
-rw-r--r--src/tools/mesh_extractor/Utils.h81
-rw-r--r--src/tools/mesh_extractor/WDT.cpp21
-rw-r--r--src/tools/mesh_extractor/WDT.h4
-rw-r--r--src/tools/mesh_extractor/WorldModelGroup.cpp72
-rw-r--r--src/tools/mesh_extractor/WorldModelGroup.h4
-rw-r--r--src/tools/mesh_extractor/WorldModelHandler.cpp78
-rw-r--r--src/tools/mesh_extractor/WorldModelHandler.h6
-rw-r--r--src/tools/mesh_extractor/WorldModelRoot.cpp28
-rw-r--r--src/tools/mesh_extractor/WorldModelRoot.h2
59 files changed, 1709 insertions, 1492 deletions
diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp
index 43c726d9989..b08cd92d638 100644
--- a/src/server/collision/Management/MMapFactory.cpp
+++ b/src/server/collision/Management/MMapFactory.cpp
@@ -25,14 +25,14 @@ namespace MMAP
{
// ######################## MMapFactory ########################
// our global singleton copy
- MMapManager* _manager = NULL;
+ MMapManager* g_MMapManager = NULL;
- MMapManager* MMapFactory::CreateOrGetMMapManager()
+ MMapManager* MMapFactory::createOrGetMMapManager()
{
- if (_manager == NULL)
- _manager = new MMapManager();
+ if (g_MMapManager == NULL)
+ g_MMapManager = new MMapManager();
- return _manager;
+ return g_MMapManager;
}
bool MMapFactory::IsPathfindingEnabled(uint32 mapId)
@@ -41,12 +41,12 @@ namespace MMAP
&& !DisableMgr::IsDisabledFor(DISABLE_TYPE_MMAP, mapId, NULL, MMAP_DISABLE_PATHFINDING);
}
- void MMapFactory::Clear()
+ void MMapFactory::clear()
{
- if (_manager)
+ if (g_MMapManager)
{
- delete _manager;
- _manager = NULL;
+ delete g_MMapManager;
+ g_MMapManager = NULL;
}
}
} \ No newline at end of file
diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h
index 890befdff04..837c893f038 100644
--- a/src/server/collision/Management/MMapFactory.h
+++ b/src/server/collision/Management/MMapFactory.h
@@ -20,6 +20,10 @@
#define _MMAP_FACTORY_H
#include "MMapManager.h"
+#include "UnorderedMap.h"
+#include "DetourAlloc.h"
+#include "DetourNavMesh.h"
+#include "DetourNavMeshQuery.h"
namespace MMAP
{
@@ -36,8 +40,8 @@ namespace MMAP
class MMapFactory
{
public:
- static MMapManager* CreateOrGetMMapManager();
- static void Clear();
+ static MMapManager* createOrGetMMapManager();
+ static void clear();
static bool IsPathfindingEnabled(uint32 mapId);
};
}
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp
index 6c6e39eeda2..cbb10923fe0 100644
--- a/src/server/collision/Management/MMapManager.cpp
+++ b/src/server/collision/Management/MMapManager.cpp
@@ -22,29 +22,32 @@
namespace MMAP
{
+ // ######################## MMapManager ########################
MMapManager::~MMapManager()
{
- for (MMapDataSet::iterator i = _loadedMaps.begin(); i != _loadedMaps.end(); ++i)
+ for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i)
delete i->second;
+
+ // by now we should not have maps loaded
+ // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost!
}
- bool MMapManager::LoadMap(uint32 mapId)
+ bool MMapManager::loadMapData(uint32 mapId)
{
- // Do not load a map twice.
- if (_loadedMaps.find(mapId) != _loadedMaps.end())
+ // we already have this map loaded?
+ if (loadedMMaps.find(mapId) != loadedMMaps.end())
return true;
// load and init dtNavMesh - read parameters from file
- std::string basePath = sWorld->GetDataPath();
- uint32 pathLen = basePath.length() + strlen("mmaps/%03i.mmap") + 1;
- char* fileName = new char[pathLen];
- snprintf(fileName, pathLen, (basePath + "mmaps/%03i.mmap").c_str(), mapId);
+ uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1;
+ char *fileName = new char[pathLen];
+ snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId);
FILE* file = fopen(fileName, "rb");
if (!file)
{
- TC_LOG_DEBUG("maps", "MMAP::LoadMap: Error: Could not open mmap file '%s'", fileName);
- delete[] fileName;
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName);
+ delete [] fileName;
return false;
}
@@ -53,75 +56,80 @@ namespace MMAP
fclose(file);
if (count != 1)
{
- TC_LOG_DEBUG("maps", "MMAP::LoadMap: Error: Could not read params from file '%s'", fileName);
- delete[] fileName;
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName);
+ delete [] fileName;
return false;
}
dtNavMesh* mesh = dtAllocNavMesh();
+ ASSERT(mesh);
if (dtStatusFailed(mesh->init(&params)))
{
dtFreeNavMesh(mesh);
- TC_LOG_ERROR("maps", "MMAP::LoadMap: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName);
- delete[] fileName;
+ TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName);
+ delete [] fileName;
return false;
}
- delete[] fileName;
+ delete [] fileName;
- TC_LOG_INFO("maps", "MMAP::LoadMap: Loaded %03i.mmap", mapId);
+ TC_LOG_INFO("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
// store inside our map list
- MMapData* mmapData = new MMapData(mesh);
- mmapData->_loadedTiles.clear();
+ MMapData* mmap_data = new MMapData(mesh);
+ mmap_data->mmapLoadedTiles.clear();
- _loadedMaps.insert(std::pair<uint32, MMapData*>(mapId, mmapData));
+ loadedMMaps.insert(std::pair<uint32, MMapData*>(mapId, mmap_data));
return true;
}
- bool MMapManager::LoadMapTile(uint32 mapId, int32 x, int32 y)
+ uint32 MMapManager::packTileID(int32 x, int32 y)
+ {
+ return uint32(x << 16 | y);
+ }
+
+ bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y)
{
// make sure the mmap is loaded and ready to load tiles
- if (!LoadMap(mapId))
+ if (!loadMapData(mapId))
return false;
// get this mmap data
- MMapData* mmap = _loadedMaps[mapId];
+ MMapData* mmap = loadedMMaps[mapId];
ASSERT(mmap->navMesh);
- // Check if we already have this tile loaded
- uint32 pos = PackTileId(x, y);
- if (mmap->_loadedTiles.find(pos) != mmap->_loadedTiles.end())
+ // check if we already have this tile loaded
+ uint32 packedGridPos = packTileID(x, y);
+ if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end())
return false;
- std::string basePath = sWorld->GetDataPath();
- uint32 pathLen = basePath.length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1;
- char* fileName = new char[pathLen];
+ // load this tile :: mmaps/MMMXXYY.mmtile
+ uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
+ char *fileName = new char[pathLen];
- snprintf(fileName, pathLen, (basePath + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
+ snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
FILE* file = fopen(fileName, "rb");
if (!file)
{
- TC_LOG_DEBUG("maps", "MMAP::LoadMapTile: Could not open mmtile file '%s'", fileName);
- delete[] fileName;
+ TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName);
+ delete [] fileName;
return false;
}
-
- delete[] fileName;
+ delete [] fileName;
// read header
MmapTileHeader fileHeader;
if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC)
{
- TC_LOG_ERROR("maps", "MMAP::LoadMapTile: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
fclose(file);
return false;
}
if (fileHeader.mmapVersion != MMAP_VERSION)
{
- TC_LOG_ERROR("maps", "MMAP::LoadMapTile: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
+ TC_LOG_ERROR("maps", "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
fclose(file);
return false;
@@ -131,9 +139,9 @@ namespace MMAP
ASSERT(data);
size_t result = fread(data, fileHeader.size, 1, file);
- if (result != 1)
+ if (!result)
{
- TC_LOG_ERROR("maps", "MMAP::LoadMapTile: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
fclose(file);
return false;
}
@@ -146,14 +154,14 @@ namespace MMAP
// memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
{
- mmap->_loadedTiles.insert(std::pair<uint32, dtTileRef>(pos, tileRef));
- ++_loadedTiles;
- TC_LOG_INFO("maps", "MMAP::LoadMapTile: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y);
+ mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
+ ++loadedTiles;
+ TC_LOG_INFO("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y);
return true;
}
else
{
- TC_LOG_ERROR("maps", "MMAP::LoadMapTile: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
dtFree(data);
return false;
}
@@ -161,26 +169,28 @@ namespace MMAP
return false;
}
- bool MMapManager::UnloadMapTile(uint32 mapId, int32 x, int32 y)
+ bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
{
- // Do not attempt to remove tiles from a not-loaded map
- if (_loadedMaps.find(mapId) == _loadedMaps.end())
+ // check if we have this map loaded
+ if (loadedMMaps.find(mapId) == loadedMMaps.end())
{
- TC_LOG_DEBUG("maps", "MMAP::UnloadMapTile: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y);
+ // file may not exist, therefore not loaded
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y);
return false;
}
- MMapData* mmap = _loadedMaps[mapId];
+ MMapData* mmap = loadedMMaps[mapId];
// check if we have this tile loaded
- uint32 pos = PackTileId(x, y);
- if (mmap->_loadedTiles.find(pos) == mmap->_loadedTiles.end())
+ uint32 packedGridPos = packTileID(x, y);
+ if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end())
{
- TC_LOG_DEBUG("maps", "MMAP::UnloadMapTile: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
+ // file may not exist, therefore not loaded
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
return false;
}
- dtTileRef tileRef = mmap->_loadedTiles[pos];
+ dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos];
// unload, and mark as non loaded
if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL)))
@@ -188,106 +198,107 @@ namespace MMAP
// this is technically a memory leak
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
// we cannot recover from this error - assert out
- TC_LOG_ERROR("maps", "MMAP::UnloadMapTile: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
ASSERT(false);
}
else
{
- mmap->_loadedTiles.erase(pos);
- --_loadedTiles;
- TC_LOG_INFO("maps", "MMAP::UnloadMapTile: Unloaded mmtile [%02i, %02i] from %03i", x, y, mapId);
+ mmap->mmapLoadedTiles.erase(packedGridPos);
+ --loadedTiles;
+ TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
return true;
}
return false;
}
- bool MMapManager::UnloadMap(uint32 mapId)
+ bool MMapManager::unloadMap(uint32 mapId)
{
- if (_loadedMaps.find(mapId) == _loadedMaps.end())
+ if (loadedMMaps.find(mapId) == loadedMMaps.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP::UnloadMap: Asked to unload not loaded navmesh map %03u", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId);
return false;
}
// unload all tiles from given map
- MMapData* mmap = _loadedMaps[mapId];
- for (MMapTileSet::iterator i = mmap->_loadedTiles.begin(); i != mmap->_loadedTiles.end(); ++i)
+ MMapData* mmap = loadedMMaps[mapId];
+ for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i)
{
uint32 x = (i->first >> 16);
uint32 y = (i->first & 0x0000FFFF);
if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL)))
- TC_LOG_ERROR("maps", "MMAP::UnloadMap: Could not unload %03u%02u%02u.mmtile from navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
else
{
- --_loadedTiles;
- TC_LOG_INFO("maps", "MMAP::UnloadMap: Unloaded mmtile [%02u, %02u] from %03u", x, y, mapId);
+ --loadedTiles;
+ TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
}
}
delete mmap;
- _loadedMaps.erase(mapId);
- TC_LOG_INFO("maps", "MMAP::UnloadMap: Unloaded %03u.mmap", mapId);
+ loadedMMaps.erase(mapId);
+ TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
return true;
}
- bool MMapManager::UnloadMapInstance(uint32 mapId, uint32 instanceId)
+ bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId)
{
// check if we have this map loaded
- if (_loadedMaps.find(mapId) == _loadedMaps.end())
+ if (loadedMMaps.find(mapId) == loadedMMaps.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP::UnloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId);
return false;
}
- MMapData* mmap = _loadedMaps[mapId];
- if (mmap->_navMeshQueries.find(instanceId) == mmap->_navMeshQueries.end())
+ MMapData* mmap = loadedMMaps[mapId];
+ if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
- TC_LOG_DEBUG("maps", "MMAP::UnloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
return false;
}
- dtNavMeshQuery* query = mmap->_navMeshQueries[instanceId];
+ dtNavMeshQuery* query = mmap->navMeshQueries[instanceId];
dtFreeNavMeshQuery(query);
- mmap->_navMeshQueries.erase(instanceId);
- TC_LOG_INFO("maps", "MMAP::UnloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
+ mmap->navMeshQueries.erase(instanceId);
+ TC_LOG_INFO("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
return true;
}
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId)
{
- if (_loadedMaps.find(mapId) == _loadedMaps.end())
+ if (loadedMMaps.find(mapId) == loadedMMaps.end())
return NULL;
- return _loadedMaps[mapId]->navMesh;
+ return loadedMMaps[mapId]->navMesh;
}
dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
{
- if (_loadedMaps.find(mapId) == _loadedMaps.end())
+ if (loadedMMaps.find(mapId) == loadedMMaps.end())
return NULL;
- MMapData* mmap = _loadedMaps[mapId];
- if (mmap->_navMeshQueries.find(instanceId) == mmap->_navMeshQueries.end())
+ MMapData* mmap = loadedMMaps[mapId];
+ if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
// allocate mesh query
dtNavMeshQuery* query = dtAllocNavMeshQuery();
- if (dtStatusFailed(query->init(mmap->navMesh, 2048)))
+ ASSERT(query);
+ if (dtStatusFailed(query->init(mmap->navMesh, 1024)))
{
dtFreeNavMeshQuery(query);
- TC_LOG_ERROR("maps", "MMAP::GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
return NULL;
}
TC_LOG_INFO("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
- mmap->_navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
+ mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
}
- return mmap->_navMeshQueries[instanceId];
+ return mmap->navMeshQueries[instanceId];
}
}
diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h
index 87bb4702dd2..8b0d42b83cd 100644
--- a/src/server/collision/Management/MMapManager.h
+++ b/src/server/collision/Management/MMapManager.h
@@ -36,7 +36,7 @@ namespace MMAP
MMapData(dtNavMesh* mesh) : navMesh(mesh) { }
~MMapData()
{
- for (NavMeshQuerySet::iterator i = _navMeshQueries.begin(); i != _navMeshQueries.end(); ++i)
+ for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
dtFreeNavMeshQuery(i->second);
if (navMesh)
@@ -46,8 +46,8 @@ namespace MMAP
dtNavMesh* navMesh;
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe
- NavMeshQuerySet _navMeshQueries; // instanceId to query
- MMapTileSet _loadedTiles; // maps [map grid coords] to [dtTile]
+ NavMeshQuerySet navMeshQueries; // instanceId to query
+ MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile]
};
@@ -58,27 +58,26 @@ namespace MMAP
class MMapManager
{
public:
- MMapManager() : _loadedTiles(0) {}
-
+ MMapManager() : loadedTiles(0) { }
~MMapManager();
- bool LoadMapTile(uint32 mapId, int32 x, int32 y);
- bool UnloadMapTile(uint32 mapId, int32 x, int32 y);
- bool UnloadMap(uint32 mapId);
- bool UnloadMapInstance(uint32 mapId, uint32 instanceId);
+ bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y);
+ bool unloadMap(uint32 mapId, int32 x, int32 y);
+ bool unloadMap(uint32 mapId);
+ bool unloadMapInstance(uint32 mapId, uint32 instanceId);
// the returned [dtNavMeshQuery const*] is NOT threadsafe
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
dtNavMesh const* GetNavMesh(uint32 mapId);
- uint32 GetLoadedTilesCount() const { return _loadedTiles; }
- uint32 GetLoadedMapsCount() const { return _loadedMaps.size(); }
+ uint32 getLoadedTilesCount() const { return loadedTiles; }
+ uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
private:
- bool LoadMap(uint32 mapId);
- uint32 PackTileId(int32 x, int32 y) { return uint32(x << 16 | y); }
+ bool loadMapData(uint32 mapId);
+ uint32 packTileID(int32 x, int32 y);
- MMapDataSet _loadedMaps;
- uint32 _loadedTiles;
+ MMapDataSet loadedMMaps;
+ uint32 loadedTiles;
};
}
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index c46d9002604..e37e6847bdd 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -164,11 +164,7 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId)
void InstanceSaveManager::UnloadInstanceSave(uint32 InstanceId)
{
if (InstanceSave* save = GetInstanceSave(InstanceId))
- {
save->UnloadIfEmpty();
- if (save->m_toDelete)
- delete save;
- }
}
InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset)
diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h
index 1d753ebaa48..7a89e6488f0 100644
--- a/src/server/game/Instances/InstanceSaveMgr.h
+++ b/src/server/game/Instances/InstanceSaveMgr.h
@@ -115,16 +115,16 @@ class InstanceSave
but that would depend on a lot of things that can easily change in future */
Difficulty GetDifficulty() const { return m_difficulty; }
- typedef std::list<Player*> PlayerListType;
- typedef std::list<Group*> GroupListType;
- private:
- bool UnloadIfEmpty();
/* used to flag the InstanceSave as to be deleted, so the caller can delete it */
void SetToDelete(bool toDelete)
{
m_toDelete = toDelete;
}
+ typedef std::list<Player*> PlayerListType;
+ typedef std::list<Group*> GroupListType;
+ private:
+ bool UnloadIfEmpty();
/* the only reason the instSave-object links are kept is because
the object-instSave links need to be broken at reset time */
/// @todo: Check if maybe it's enough to just store the number of players/groups
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 10ed0e804a7..79e63cf2035 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -66,9 +66,7 @@ Map::~Map()
if (!m_scriptSchedule.empty())
sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size());
- MMAP::MMapManager* manager = MMAP::MMapFactory::CreateOrGetMMapManager();
- manager->UnloadMapInstance(GetId(), i_InstanceId); // Delete the dtNavMeshQuery
- manager->UnloadMap(GetId()); // Unload the loaded tiles and delete the dtNavMesh
+ MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId);
}
bool Map::ExistMap(uint32 mapid, int gx, int gy)
@@ -121,16 +119,12 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy)
void Map::LoadMMap(int gx, int gy)
{
- bool mmapLoadResult = false;
- if (GetEntry()->Instanceable())
- mmapLoadResult = MMAP::MMapFactory::CreateOrGetMMapManager()->LoadMapTile(GetId(), 0, 0); // Ignore the tile entry for instances, as they only have 1 tile.
- else
- mmapLoadResult = MMAP::MMapFactory::CreateOrGetMMapManager()->LoadMapTile(GetId(), gx, gy);
+ bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy);
if (mmapLoadResult)
- TC_LOG_INFO("maps", "MMAP loaded name: %s, id: %d, x: %d, y: %d", GetMapName(), GetId(), gx, gy);
+ TC_LOG_INFO("maps", "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
else
- TC_LOG_INFO("maps", "Could not load MMAP name: %s, id: %d, x: %d, y: %d", GetMapName(), GetId(), gx, gy);
+ TC_LOG_INFO("maps", "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
}
void Map::LoadVMap(int gx, int gy)
@@ -232,9 +226,9 @@ i_gridExpiry(expiry),
i_scriptLock(false)
{
m_parentMap = (_parent ? _parent : this);
- for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
+ for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{
- for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)
+ for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j)
{
//z code
GridMaps[idx][j] =NULL;
@@ -1342,7 +1336,7 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll)
delete GridMaps[gx][gy];
}
VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy);
- MMAP::MMapFactory::CreateOrGetMMapManager()->UnloadMapTile(GetId(), gx, gy);
+ MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy);
}
else
((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy));
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index d8f93cbe293..e914a5c3eee 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -260,7 +260,7 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
if (m_InstancedMaps.size() <= 1 && sWorld->getBoolConfig(CONFIG_GRID_UNLOAD))
{
VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId());
- MMAP::MMapFactory::CreateOrGetMMapManager()->UnloadMap(itr->second->GetId());
+ MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(itr->second->GetId());
// in that case, unload grids of the base map, too
// so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
Map::UnloadAll();
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 69d4cf847ac..75e190ed20d 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -4068,7 +4068,7 @@ enum PartyResult
};
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
-#define MMAP_VERSION 5
+#define MMAP_VERSION 4
struct MmapTileHeader
{
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
index e7a3c6de33c..61f3a04bc5d 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
@@ -86,6 +86,7 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
unit->MovePositionToFirstCollision(pos, dest, 0.0f);
PathGenerator path(unit);
+ path.SetPathLengthLimit(30.0f);
bool result = path.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
if (!result || (path.GetPathType() & PATHFIND_NOPATH))
{
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index c351aeecd51..572d65b07c7 100644
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -59,6 +59,7 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
}
PathGenerator path(owner);
+ path.SetPathLengthLimit(30.0f);
bool result = path.CalculatePath(x, y, z);
if (!result || (path.GetPathType() & PATHFIND_NOPATH))
{
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index 9f16b6b8771..d8a300a2bab 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -27,19 +27,21 @@
#include "DetourCommon.h"
#include "DetourNavMeshQuery.h"
-float PathGenerator::MinWallDistance = 2.5f;
-
////////////////// PathGenerator //////////////////
PathGenerator::PathGenerator(const Unit* owner) :
- _type(PATHFIND_BLANK), _endPosition(G3D::Vector3::zero()),
- _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL)
+ _polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false),
+ _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH),
+ _endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(NULL),
+ _navMeshQuery(NULL)
{
- TC_LOG_DEBUG("maps", "PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow());
+ memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
+
+ TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow());
uint32 mapId = _sourceUnit->GetMapId();
if (MMAP::MMapFactory::IsPathfindingEnabled(mapId))
{
- MMAP::MMapManager* mmap = MMAP::MMapFactory::CreateOrGetMMapManager();
+ MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager();
_navMesh = mmap->GetNavMesh(mapId);
_navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId());
}
@@ -49,23 +51,16 @@ PathGenerator::PathGenerator(const Unit* owner) :
PathGenerator::~PathGenerator()
{
- TC_LOG_DEBUG("maps", "PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow());
}
bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest)
{
- // Clear the previous path, just in case that the same PathGenerator instance is being used
- _pathPoints.clear();
-
float x, y, z;
_sourceUnit->GetPosition(x, y, z);
if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z))
- {
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() called with invalid map coords, destX: %f destY: %f destZ: %f x: %f y: %f z: %f for creature %u", destX, destY, destZ, x, y, z, _sourceUnit->GetGUIDLow());
- _type = PATHFIND_NOPATH;
return false;
- }
G3D::Vector3 dest(destX, destY, destZ);
SetEndPosition(dest);
@@ -73,103 +68,463 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
G3D::Vector3 start(x, y, z);
SetStartPosition(start);
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow());
+ _forceDestination = forceDest;
+
+ TC_LOG_DEBUG("maps", "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow());
// make sure navMesh works - we can run on map w/o mmap
// check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
- if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING))
+ if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) ||
+ !HaveTile(start) || !HaveTile(dest))
{
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() navmesh is not initialized for %u \n", _sourceUnit->GetGUIDLow());
+ BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- _pathPoints.push_back(start);
- _pathPoints.push_back(dest);
return true;
}
UpdateFilter();
- float startPos[3];
- startPos[0] = -y;
- startPos[1] = z;
- startPos[2] = -x;
+ BuildPolyPath(start, dest);
+ return true;
+}
- float endPos[3];
- endPos[0] = -destY;
- endPos[1] = destZ;
- endPos[2] = -destX;
+dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* point, float* distance) const
+{
+ if (!polyPath || !polyPathSize)
+ return INVALID_POLYREF;
- float polyPickExt[3];
- polyPickExt[0] = 2.5f;
- polyPickExt[1] = 2.5f;
- polyPickExt[2] = 2.5f;
+ dtPolyRef nearestPoly = INVALID_POLYREF;
+ float minDist2d = FLT_MAX;
+ float minDist3d = 0.0f;
- //
- dtPolyRef startRef;
- dtPolyRef endRef;
+ for (uint32 i = 0; i < polyPathSize; ++i)
+ {
+ float closestPoint[VERTEX_SIZE];
+ if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)))
+ continue;
- float nearestPt[3];
+ float d = dtVdist2DSqr(point, closestPoint);
+ if (d < minDist2d)
+ {
+ minDist2d = d;
+ nearestPoly = polyPath[i];
+ minDist3d = dtVdistSqr(point, closestPoint);
+ }
- _navMeshQuery->findNearestPoly(startPos, polyPickExt, &_filter, &startRef, nearestPt);
- _navMeshQuery->findNearestPoly(endPos, polyPickExt, &_filter, &endRef, nearestPt);
+ if (minDist2d < 1.0f) // shortcut out - close enough for us
+ break;
+ }
+
+ if (distance)
+ *distance = dtSqrt(minDist3d);
+
+ return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF;
+}
- if (!startRef || !endRef)
+dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) const
+{
+ // first we check the current path
+ // if the current path doesn't contain the current poly,
+ // we need to use the expensive navMesh.findNearestPoly
+ dtPolyRef polyRef = GetPathPolyByPosition(_pathPolyRefs, _polyLength, point, distance);
+ if (polyRef != INVALID_POLYREF)
+ return polyRef;
+
+ // we don't have it in our old path
+ // try to get it by findNearestPoly()
+ // first try with low search box
+ float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area
+ float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f};
+ if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF)
{
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u no polygons found for start and end locations\n", _sourceUnit->GetGUIDLow());
- _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- _pathPoints.push_back(start);
- _pathPoints.push_back(dest);
- return false;
+ *distance = dtVdist(closestPoint, point);
+ return polyRef;
}
- int hops;
- dtPolyRef* hopBuffer = new dtPolyRef[8192];
- dtStatus status = _navMeshQuery->findPath(startRef, endRef, startPos, endPos, &_filter, hopBuffer, &hops, 8192);
+ // still nothing ..
+ // try with bigger search box
+ // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly)
+ extents[1] = 50.0f;
- if (!dtStatusSucceed(status))
+ if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF)
{
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u no path found for start and end locations\n", _sourceUnit->GetGUIDLow());
- _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- _pathPoints.push_back(start);
- _pathPoints.push_back(dest);
- return false;
+ *distance = dtVdist(closestPoint, point);
+ return polyRef;
}
- int resultHopCount;
- float* straightPath = new float[2048 * 3];
- unsigned char* pathFlags = new unsigned char[2048];
- dtPolyRef* pathRefs = new dtPolyRef[2048];
+ return INVALID_POLYREF;
+}
+
+void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos)
+{
+ // *** getting start/end poly logic ***
+
+ float distToStartPoly, distToEndPoly;
+ float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x};
+ float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x};
+
+ dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly);
+ dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly);
- status = _navMeshQuery->findStraightPath(startPos, endPos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048);
- if (!dtStatusSucceed(status))
+ // we have a hole in our mesh
+ // make shortcut path and mark it as NOPATH ( with flying and swimming exception )
+ // its up to caller how he will use this info
+ if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
{
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u no straight path found for start and end locations\n", _sourceUnit->GetGUIDLow());
- _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- _pathPoints.push_back(start);
- _pathPoints.push_back(dest);
- return false;
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n");
+ BuildShortcut();
+ bool path = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanFly();
+
+ bool waterPath = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanSwim();
+ if (waterPath)
+ {
+ // Check both start and end points, if they're both in water, then we can *safely* let the creature move
+ for (uint32 i = 0; i < _pathPoints.size(); ++i)
+ {
+ ZLiquidStatus status = _sourceUnit->GetBaseMap()->getLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL);
+ // One of the points is not in the water, cancel movement.
+ if (status == LIQUID_MAP_NO_WATER)
+ {
+ waterPath = false;
+ break;
+ }
+ }
+ }
+
+ _type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH;
+ return;
}
- SmoothPath(polyPickExt, resultHopCount, straightPath); // Separate the path from the walls
+ // we may need a better number here
+ bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f);
+ if (farFromPoly)
+ {
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly);
- for (uint32 i = 0; i < resultHopCount; ++i)
+ bool buildShotrcut = false;
+ if (_sourceUnit->GetTypeId() == TYPEID_UNIT)
+ {
+ Creature* owner = (Creature*)_sourceUnit;
+
+ G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos;
+ if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z))
+ {
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: underWater case\n");
+ if (owner->CanSwim())
+ buildShotrcut = true;
+ }
+ else
+ {
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: flying case\n");
+ if (owner->CanFly())
+ buildShotrcut = true;
+ }
+ }
+
+ if (buildShotrcut)
+ {
+ BuildShortcut();
+ _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
+ return;
+ }
+ else
+ {
+ float closestPoint[VERTEX_SIZE];
+ // we may want to use closestPointOnPolyBoundary instead
+ if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)))
+ {
+ dtVcopy(endPoint, closestPoint);
+ SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1]));
+ }
+
+ _type = PATHFIND_INCOMPLETE;
+ }
+ }
+
+ // *** poly path generating logic ***
+
+ // start and end are on same polygon
+ // just need to move in straight line
+ if (startPoly == endPoly)
{
- _pathPoints.push_back(G3D::Vector3(-straightPath[i * 3 + 2], -straightPath[i * 3 + 0], straightPath[i * 3 + 1]));
- TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u path point %u: (%f, %f, %f)", _sourceUnit->GetGUIDLow(), i, _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z);
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPoly == endPoly)\n");
+
+ BuildShortcut();
+
+ _pathPolyRefs[0] = startPoly;
+ _polyLength = 1;
+
+ _type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL;
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: path type %d\n", _type);
+ return;
}
- _type = PATHFIND_NORMAL;
- return true;
+ // look for startPoly/endPoly in current path
+ /// @todo we can merge it with getPathPolyByPosition() loop
+ bool startPolyFound = false;
+ bool endPolyFound = false;
+ uint32 pathStartIndex = 0;
+ uint32 pathEndIndex = 0;
+
+ if (_polyLength)
+ {
+ for (; pathStartIndex < _polyLength; ++pathStartIndex)
+ {
+ // here to carch few bugs
+ ASSERT(_pathPolyRefs[pathStartIndex] != INVALID_POLYREF);
+
+ if (_pathPolyRefs[pathStartIndex] == startPoly)
+ {
+ startPolyFound = true;
+ break;
+ }
+ }
+
+ for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex)
+ if (_pathPolyRefs[pathEndIndex] == endPoly)
+ {
+ endPolyFound = true;
+ break;
+ }
+ }
+
+ if (startPolyFound && endPolyFound)
+ {
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n");
+
+ // we moved along the path and the target did not move out of our old poly-path
+ // our path is a simple subpath case, we have all the data we need
+ // just "cut" it out
+
+ _polyLength = pathEndIndex - pathStartIndex + 1;
+ memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef));
+ }
+ else if (startPolyFound && !endPolyFound)
+ {
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n");
+
+ // we are moving on the old path but target moved out
+ // so we have atleast part of poly-path ready
+
+ _polyLength -= pathStartIndex;
+
+ // try to adjust the suffix of the path instead of recalculating entire length
+ // at given interval the target cannot get too far from its last location
+ // thus we have less poly to cover
+ // sub-path of optimal path is optimal
+
+ // take ~80% of the original length
+ /// @todo play with the values here
+ uint32 prefixPolyLength = uint32(_polyLength * 0.8f + 0.5f);
+ memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef));
+
+ dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
+
+ // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
+ float suffixEndPoint[VERTEX_SIZE];
+ if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)))
+ {
+ // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that
+ // try to recover by using prev polyref
+ --prefixPolyLength;
+ suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
+ if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)))
+ {
+ // suffixStartPoly is still invalid, error state
+ BuildShortcut();
+ _type = PATHFIND_NOPATH;
+ return;
+ }
+ }
+
+ // generate suffix
+ uint32 suffixPolyLength = 0;
+ dtStatus dtResult = _navMeshQuery->findPath(
+ suffixStartPoly, // start polygon
+ endPoly, // end polygon
+ suffixEndPoint, // start position
+ endPoint, // end position
+ &_filter, // polygon search filter
+ _pathPolyRefs + prefixPolyLength - 1, // [out] path
+ (int*)&suffixPolyLength,
+ MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path
+
+ if (!suffixPolyLength || dtStatusFailed(dtResult))
+ {
+ // this is probably an error state, but we'll leave it
+ // and hopefully recover on the next Update
+ // we still need to copy our preffix
+ TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow());
+ }
+
+ TC_LOG_DEBUG("maps", "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n", _polyLength, prefixPolyLength, suffixPolyLength);
+
+ // new path = prefix + suffix - overlap
+ _polyLength = prefixPolyLength + suffixPolyLength - 1;
+ }
+ else
+ {
+ TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n");
+
+ // either we have no path at all -> first run
+ // or something went really wrong -> we aren't moving along the path to the target
+ // just generate new path
+
+ // free and invalidate old path data
+ Clear();
+
+ dtStatus dtResult = _navMeshQuery->findPath(
+ startPoly, // start polygon
+ endPoly, // end polygon
+ startPoint, // start position
+ endPoint, // end position
+ &_filter, // polygon search filter
+ _pathPolyRefs, // [out] path
+ (int*)&_polyLength,
+ MAX_PATH_LENGTH); // max number of polygons in output path
+
+ if (!_polyLength || dtStatusFailed(dtResult))
+ {
+ // only happens if we passed bad data to findPath(), or navmesh is messed up
+ TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow());
+ BuildShortcut();
+ _type = PATHFIND_NOPATH;
+ return;
+ }
+ }
+
+ // by now we know what type of path we can get
+ if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE))
+ _type = PATHFIND_NORMAL;
+ else
+ _type = PATHFIND_INCOMPLETE;
+
+ // generate the point-path out of our up-to-date poly-path
+ BuildPointPath(startPoint, endPoint);
+}
+
+void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint)
+{
+ float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
+ uint32 pointCount = 0;
+ dtStatus dtResult = DT_FAILURE;
+ if (_useStraightPath)
+ {
+ dtResult = _navMeshQuery->findStraightPath(
+ startPoint, // start position
+ endPoint, // end position
+ _pathPolyRefs, // current path
+ _polyLength, // lenth of current path
+ pathPoints, // [out] path corner points
+ NULL, // [out] flags
+ NULL, // [out] shortened path
+ (int*)&pointCount,
+ _pointPathLimit); // maximum number of points/polygons to use
+ }
+ else
+ {
+ dtResult = FindSmoothPath(
+ startPoint, // start position
+ endPoint, // end position
+ _pathPolyRefs, // current path
+ _polyLength, // length of current path
+ pathPoints, // [out] path corner points
+ (int*)&pointCount,
+ _pointPathLimit); // maximum number of points
+ }
+
+ if (pointCount < 2 || dtStatusFailed(dtResult))
+ {
+ // only happens if pass bad data to findStraightPath or navmesh is broken
+ // single point paths can be generated here
+ /// @todo check the exact cases
+ TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount);
+ BuildShortcut();
+ _type = PATHFIND_NOPATH;
+ return;
+ }
+ else if (pointCount == _pointPathLimit)
+ {
+ TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, _pointPathLimit);
+ BuildShortcut();
+ _type = PATHFIND_SHORT;
+ return;
+ }
+
+ _pathPoints.resize(pointCount);
+ for (uint32 i = 0; i < pointCount; ++i)
+ _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]);
+
+ NormalizePath();
+
+ // first point is always our current location - we need the next one
+ SetActualEndPosition(_pathPoints[pointCount-1]);
+
+ // force the given destination, if needed
+ if (_forceDestination &&
+ (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 1.0f, 1.0f)))
+ {
+ // we may want to keep partial subpath
+ if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.3f * Dist3DSqr(GetStartPosition(), GetEndPosition()))
+ {
+ SetActualEndPosition(GetEndPosition());
+ _pathPoints[_pathPoints.size()-1] = GetEndPosition();
+ }
+ else
+ {
+ SetActualEndPosition(GetEndPosition());
+ BuildShortcut();
+ }
+
+ _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
+ }
+
+ TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength);
+}
+
+void PathGenerator::NormalizePath()
+{
+ for (uint32 i = 0; i < _pathPoints.size(); ++i)
+ _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z);
+}
+
+void PathGenerator::BuildShortcut()
+{
+ TC_LOG_DEBUG("maps", "++ BuildShortcut :: making shortcut\n");
+
+ Clear();
+
+ // make two point path, our curr pos is the start, and dest is the end
+ _pathPoints.resize(2);
+
+ // set start and a default next position
+ _pathPoints[0] = GetStartPosition();
+ _pathPoints[1] = GetActualEndPosition();
+
+ NormalizePath();
+
+ _type = PATHFIND_SHORTCUT;
}
void PathGenerator::CreateFilter()
{
- uint16 includeFlags = POLY_FLAG_WALK | POLY_FLAG_SWIM;
+ uint16 includeFlags = 0;
uint16 excludeFlags = 0;
- if (_sourceUnit->GetTypeId() == TYPEID_UNIT && !_sourceUnit->ToCreature()->CanSwim())
+ if (_sourceUnit->GetTypeId() == TYPEID_UNIT)
{
- includeFlags = POLY_FLAG_WALK;
- excludeFlags = POLY_FLAG_SWIM;
+ Creature* creature = (Creature*)_sourceUnit;
+ if (creature->CanWalk())
+ includeFlags |= NAV_GROUND; // walk
+
+ // creatures don't take environmental damage
+ if (creature->CanSwim())
+ includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim
+ }
+ else // assume Player
+ {
+ // perfect support not possible, just stay 'safe'
+ includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME);
}
_filter.setIncludeFlags(includeFlags);
@@ -180,130 +535,275 @@ void PathGenerator::CreateFilter()
void PathGenerator::UpdateFilter()
{
+ // allow creatures to cheat and use different movement types if they are moved
+ // forcefully into terrain they can't normally move in
+ if (_sourceUnit->IsInWater() || _sourceUnit->IsUnderWater())
+ {
+ uint16 includedFlags = _filter.getIncludeFlags();
+ includedFlags |= GetNavTerrain(_sourceUnit->GetPositionX(),
+ _sourceUnit->GetPositionY(),
+ _sourceUnit->GetPositionZ());
+ _filter.setIncludeFlags(includedFlags);
+ }
}
-float PathGenerator::GetTriangleArea(float* verts, int nv)
+NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z)
{
- float area = 0;
- for (int i = 0; i < nv - 1; i++)
- area += verts[i * 3] * verts[i * 3 + 5] - verts[i * 3 + 3] * verts[i * 3 + 2];
- area += verts[(nv - 1) * 3] * verts[2] - verts[0] * verts[(nv - 1) * 3 + 2];
- return area * 0.5f;
-}
+ LiquidData data;
+ ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data);
+ if (liquidStatus == LIQUID_MAP_NO_WATER)
+ return NAV_GROUND;
-bool PathGenerator::PointInPoly(float* pos, float* verts, int nv, float err)
-{
- // Poly area
- float area = abs(PathGenerator::GetTriangleArea(verts, nv));
-
- // Calculate each area of the triangles
- float testTri[9];
- memcpy(testTri, pos, sizeof(float) * 3);
- float area1 = 0;
- for(int i = 0; i < nv - 1; ++i)
+ switch (data.type_flags)
{
- memcpy(&testTri[3], &verts[i * 3], sizeof(float) * 3);
- memcpy(&testTri[6], &verts[i * 3 + 3], sizeof(float) * 3);
- area1 += abs(PathGenerator::GetTriangleArea(testTri, 3));
- if (area1 - err > area)
- return false;
+ case MAP_LIQUID_TYPE_WATER:
+ case MAP_LIQUID_TYPE_OCEAN:
+ return NAV_WATER;
+ case MAP_LIQUID_TYPE_MAGMA:
+ return NAV_MAGMA;
+ case MAP_LIQUID_TYPE_SLIME:
+ return NAV_SLIME;
+ default:
+ return NAV_GROUND;
}
-
- // Last one
- memcpy(&testTri[3], verts, sizeof(float) * 3);
- memcpy(&testTri[6], &verts[nv * 3 - 3] , sizeof(float) * 3);
- area1 += abs(PathGenerator::GetTriangleArea(testTri, 3));
-
- return abs(area1 - area) < err;
}
-float PathGenerator::DistanceToWall(float* polyPickExt, float* pos, float* hitPos, float* hitNormal)
+bool PathGenerator::HaveTile(const G3D::Vector3& p) const
{
- float distanceToWall = 0;
- dtPolyRef ref;
+ int tx = -1, ty = -1;
+ float point[VERTEX_SIZE] = {p.y, p.z, p.x};
- dtStatus status = _navMeshQuery->findNearestPoly(pos, polyPickExt, &_filter, &ref, 0);
+ _navMesh->calcTileLoc(point, &tx, &ty);
- if (!dtStatusSucceed(status) || ref == 0)
- return -1;
+ /// Workaround
+ /// For some reason, often the tx and ty variables wont get a valid value
+ /// Use this check to prevent getting negative tile coords and crashing on getTileAt
+ if (tx < 0 || ty < 0)
+ return false;
- const dtMeshTile* tile = 0;
- const dtPoly* poly = 0;
- if (dtStatusFailed(_navMesh->getTileAndPolyByRef(ref, &tile, &poly)))
- return -1;
+ return (_navMesh->getTileAt(tx, ty, 0) != NULL);
+}
- // Collect vertices.
- float verts[DT_VERTS_PER_POLYGON * 3];
- int nv = 0;
- for (unsigned char i = 0; i < poly->vertCount; ++i)
+uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited)
+{
+ int32 furthestPath = -1;
+ int32 furthestVisited = -1;
+
+ // Find furthest common polygon.
+ for (int32 i = npath-1; i >= 0; --i)
{
- dtVcopy(&verts[nv * 3], &tile->verts[poly->verts[i] * 3]);
- nv++;
+ bool found = false;
+ for (int32 j = nvisited-1; j >= 0; --j)
+ {
+ if (path[i] == visited[j])
+ {
+ furthestPath = i;
+ furthestVisited = j;
+ found = true;
+ }
+ }
+ if (found)
+ break;
}
- bool inside = PathGenerator::PointInPoly(pos, verts, nv, 0.05f);
- if (!inside)
- return -1;
+ // If no intersection found just return current path.
+ if (furthestPath == -1 || furthestVisited == -1)
+ return npath;
+
+ // Concatenate paths.
+
+ // Adjust beginning of the buffer to include the visited.
+ uint32 req = nvisited - furthestVisited;
+ uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath;
+ uint32 size = npath > orig ? npath - orig : 0;
+ if (req + size > maxPath)
+ size = maxPath-req;
- if (!dtStatusSucceed(_navMeshQuery->findDistanceToWall(ref, pos, 100.0f, &_filter, &distanceToWall, hitPos, hitNormal)))
- return -1;
+ if (size)
+ memmove(path + req, path + orig, size * sizeof(dtPolyRef));
- return distanceToWall;
+ // Store visited
+ for (uint32 i = 0; i < req; ++i)
+ path[i] = visited[(nvisited - 1) - i];
+
+ return req+size;
}
-void PathGenerator::SmoothPath(float* polyPickExt, int pathLength, float*& straightPath)
+bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos,
+ float minTargetDist, dtPolyRef const* path, uint32 pathSize,
+ float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef)
{
- float hitPos[3];
- float hitNormal[3];
- float testPos[3];
- float distanceToWall = 0;
- float up[]= { 0, 1, 0 };
- float origDis = 0;
-
- for (int i = 1; i < pathLength - 1; ++i)
+ // Find steer target.
+ static const uint32 MAX_STEER_POINTS = 3;
+ float steerPath[MAX_STEER_POINTS*VERTEX_SIZE];
+ unsigned char steerPathFlags[MAX_STEER_POINTS];
+ dtPolyRef steerPathPolys[MAX_STEER_POINTS];
+ uint32 nsteerPath = 0;
+ dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize,
+ steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
+ if (!nsteerPath || dtStatusFailed(dtResult))
+ return false;
+
+ // Find vertex far enough to steer to.
+ uint32 ns = 0;
+ while (ns < nsteerPath)
{
- dtPolyRef pt;
- float* curPoi = &straightPath[i * 3];
- distanceToWall = DistanceToWall(polyPickExt, curPoi, hitPos, hitNormal);
+ // Stop at Off-Mesh link or when point is further than slop away.
+ if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
+ !InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f))
+ break;
+ ns++;
+ }
+ // Failed to find good point to steer to.
+ if (ns >= nsteerPath)
+ return false;
+
+ dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]);
+ steerPos[1] = startPos[1]; // keep Z value
+ steerPosFlag = steerPathFlags[ns];
+ steerPosRef = steerPathPolys[ns];
- if (distanceToWall < PathGenerator::MinWallDistance && distanceToWall >= 0)
+ return true;
+}
+
+dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPos,
+ dtPolyRef const* polyPath, uint32 polyPathSize,
+ float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize)
+{
+ *smoothPathSize = 0;
+ uint32 nsmoothPath = 0;
+
+ dtPolyRef polys[MAX_PATH_LENGTH];
+ memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize);
+ uint32 npolys = polyPathSize;
+
+ float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE];
+ if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)))
+ return DT_FAILURE;
+
+ if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)))
+ return DT_FAILURE;
+
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
+ nsmoothPath++;
+
+ // Move towards target a small advancement at a time until target reached or
+ // when ran out of memory to store the path.
+ while (npolys && nsmoothPath < maxSmoothPathSize)
+ {
+ // Find location to steer towards.
+ float steerPos[VERTEX_SIZE];
+ unsigned char steerPosFlag;
+ dtPolyRef steerPosRef = INVALID_POLYREF;
+
+ if (!GetSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef))
+ break;
+
+ bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END);
+ bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION);
+
+ // Find movement delta.
+ float delta[VERTEX_SIZE];
+ dtVsub(delta, steerPos, iterPos);
+ float len = dtSqrt(dtVdot(delta, delta));
+ // If the steer target is end of path or off-mesh link, do not move past the location.
+ if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE)
+ len = 1.0f;
+ else
+ len = SMOOTH_PATH_STEP_SIZE / len;
+
+ float moveTgt[VERTEX_SIZE];
+ dtVmad(moveTgt, iterPos, delta, len);
+
+ // Move
+ float result[VERTEX_SIZE];
+ const static uint32 MAX_VISIT_POLY = 16;
+ dtPolyRef visited[MAX_VISIT_POLY];
+
+ uint32 nvisited = 0;
+ _navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY);
+ npolys = FixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited);
+
+ _navMeshQuery->getPolyHeight(polys[0], result, &result[1]);
+ result[1] += 0.5f;
+ dtVcopy(iterPos, result);
+
+ // Handle end of path and off-mesh links when close enough.
+ if (endOfPath && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
{
- float vec[3];
- dtVsub(vec, &straightPath[i * 3 - 3], &straightPath[i * 3]);
- // If distanceToWall is 0 means the point is in the edge, so we can't get the hitpos.
- if (distanceToWall == 0)
+ // Reached end of path.
+ dtVcopy(iterPos, targetPos);
+ if (nsmoothPath < maxSmoothPathSize)
{
- // Test the left side
- dtVcross(testPos, vec, up);
- dtVadd(testPos, testPos, curPoi);
- float ft = PathGenerator::MinWallDistance / dtVdist(testPos, curPoi);
- dtVlerp(testPos, curPoi, testPos, ft);
- distanceToWall = DistanceToWall(polyPickExt, testPos, hitPos, hitNormal);
- if (abs(PathGenerator::MinWallDistance - distanceToWall) > 0.1f)
- {
- // Test the right side
- dtVcross(testPos, up, vec);
- dtVadd(testPos, testPos, curPoi);
- ft = PathGenerator::MinWallDistance / dtVdist(testPos, curPoi);
- dtVlerp(testPos, curPoi, testPos, ft);
- distanceToWall = DistanceToWall(polyPickExt, testPos, hitPos, hitNormal);
- }
-
- // If the test point is better than the orig point, replace it.
- if (abs(distanceToWall - PathGenerator::MinWallDistance) < 0.1f)
- dtVcopy(curPoi, testPos);
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
+ nsmoothPath++;
}
- else
+ break;
+ }
+ else if (offMeshConnection && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
+ {
+ // Advance the path up to and over the off-mesh connection.
+ dtPolyRef prevRef = INVALID_POLYREF;
+ dtPolyRef polyRef = polys[0];
+ uint32 npos = 0;
+ while (npos < npolys && polyRef != steerPosRef)
{
- // We get the hitpos with a ray
- float ft = PathGenerator::MinWallDistance / distanceToWall;
- dtVlerp(testPos, hitPos, curPoi, ft);
- distanceToWall = DistanceToWall(polyPickExt, testPos, hitPos, hitNormal);
+ prevRef = polyRef;
+ polyRef = polys[npos];
+ npos++;
+ }
+
+ for (uint32 i = npos; i < npolys; ++i)
+ polys[i-npos] = polys[i];
- if (abs(distanceToWall - PathGenerator::MinWallDistance) < 0.1f)
- dtVcopy(curPoi, testPos);
+ npolys -= npos;
+
+ // Handle the connection.
+ float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE];
+ if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)))
+ {
+ if (nsmoothPath < maxSmoothPathSize)
+ {
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
+ nsmoothPath++;
+ }
+ // Move position at the other side of the off-mesh link.
+ dtVcopy(iterPos, endPos);
+ _navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
+ iterPos[1] += 0.5f;
}
}
+
+ // Store results.
+ if (nsmoothPath < maxSmoothPathSize)
+ {
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
+ nsmoothPath++;
+ }
}
+
+ *smoothPathSize = nsmoothPath;
+
+ // this is most likely a loop
+ return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE;
+}
+
+bool PathGenerator::InRangeYZX(const float* v1, const float* v2, float r, float h) const
+{
+ const float dx = v2[0] - v1[0];
+ const float dy = v2[1] - v1[1]; // elevation
+ const float dz = v2[2] - v1[2];
+ return (dx * dx + dz * dz) < r * r && fabsf(dy) < h;
+}
+
+bool PathGenerator::InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const
+{
+ G3D::Vector3 d = p1 - p2;
+ return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h;
+}
+
+float PathGenerator::Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const
+{
+ return (p1 - p2).squaredLength();
}
diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h
index 075d6dabc9f..ac66b7cec57 100644
--- a/src/server/game/Movement/PathGenerator.h
+++ b/src/server/game/Movement/PathGenerator.h
@@ -26,6 +26,18 @@
class Unit;
+// 74*4.0f=296y number_of_points*interval = max_path_len
+// this is way more than actual evade range
+// I think we can safely cut those down even more
+#define MAX_PATH_LENGTH 74
+#define MAX_POINT_PATH_LENGTH 74
+
+#define SMOOTH_PATH_STEP_SIZE 4.0f
+#define SMOOTH_PATH_SLOP 0.3f
+
+#define VERTEX_SIZE 3
+#define INVALID_POLYREF 0
+
enum PathType
{
PATHFIND_BLANK = 0x00, // path not built yet
@@ -37,12 +49,6 @@ enum PathType
PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length
};
-enum PolyFlag
-{
- POLY_FLAG_WALK = 1,
- POLY_FLAG_SWIM = 2
-};
-
class PathGenerator
{
public:
@@ -53,6 +59,10 @@ class PathGenerator
// return: true if new path was calculated, false otherwise (no change needed)
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false);
+ // option setters - use optional
+ void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; }
+ void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }
+
// result getters
G3D::Vector3 const& GetStartPosition() const { return _startPosition; }
G3D::Vector3 const& GetEndPosition() const { return _endPosition; }
@@ -61,13 +71,19 @@ class PathGenerator
Movement::PointsArray const& GetPath() const { return _pathPoints; }
PathType GetPathType() const { return _type; }
-
- static float MinWallDistance;
private:
+
+ dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references
+ uint32 _polyLength; // number of polygons in the path
+
Movement::PointsArray _pathPoints; // our actual (x,y,z) path to the target
PathType _type; // tells what kind of path this is
+ bool _useStraightPath; // type of path will be generated
+ bool _forceDestination; // when set, we will always arrive at given point
+ uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH)
+
G3D::Vector3 _startPosition; // {x, y, z} of current location
G3D::Vector3 _endPosition; // {x, y, z} of the destination
G3D::Vector3 _actualEndPosition; // {x, y, z} of the closest possible point to given destination
@@ -81,16 +97,37 @@ class PathGenerator
void SetStartPosition(G3D::Vector3 const& point) { _startPosition = point; }
void SetEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; _endPosition = point; }
void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; }
+ void NormalizePath();
+
+ void Clear()
+ {
+ _polyLength = 0;
+ _pathPoints.clear();
+ }
- // Path smoothing
- void SmoothPath(float* polyPickExt, int pathLength, float*& straightPath);
- float DistanceToWall(float* polyPickExt, float* pos, float* hitPos, float* hitNormal);
- // dtPointInPolygon will return false when the point is too close to the edge, so we rewrite the test function.
- static bool PointInPoly(float* pos, float* verts, int nv, float err);
- static float GetTriangleArea(float* verts, int nv);
+ bool InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const;
+ float Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const;
+ bool InRangeYZX(float const* v1, float const* v2, float r, float h) const;
+ dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = NULL) const;
+ dtPolyRef GetPolyByLocation(float const* Point, float* Distance) const;
+ bool HaveTile(G3D::Vector3 const& p) const;
+
+ void BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos);
+ void BuildPointPath(float const* startPoint, float const* endPoint);
+ void BuildShortcut();
+
+ NavTerrain GetNavTerrain(float x, float y, float z);
void CreateFilter();
void UpdateFilter();
+
+ // smooth path aux functions
+ uint32 FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited);
+ bool GetSteerTarget(float const* startPos, float const* endPos, float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos,
+ unsigned char& steerPosFlag, dtPolyRef& steerPosRef);
+ dtStatus FindSmoothPath(float const* startPos, float const* endPos,
+ dtPolyRef const* polyPath, uint32 polyPathSize,
+ float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize);
};
#endif
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 417d7be78ad..0d5ba60df65 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5234,6 +5234,7 @@ SpellCastResult Spell::CheckCast(bool strict)
target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster));
+ m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f);
bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize());
if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index e472e975777..ef6f2869ec5 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -152,7 +152,7 @@ World::~World()
delete command;
VMAP::VMapFactory::clear();
- MMAP::MMapFactory::Clear();
+ MMAP::MMapFactory::clear();
/// @todo free addSessQueue
}
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 81fc9f9b2b2..ba355d08d0c 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -186,7 +186,7 @@ public:
uint32 haveMap = Map::ExistMap(mapId, gridX, gridY) ? 1 : 0;
uint32 haveVMap = Map::ExistVMap(mapId, gridX, gridY) ? 1 : 0;
- uint32 haveMMap = (MMAP::MMapFactory::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0;
+ uint32 haveMMap = (MMAP::MMapFactory::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0;
if (haveVMap)
{
diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp
index f38717ba31e..37e7177cbc6 100644
--- a/src/server/scripts/Commands/cs_mmaps.cpp
+++ b/src/server/scripts/Commands/cs_mmaps.cpp
@@ -1,19 +1,19 @@
/*
- * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
/**
* @file cs_mmaps.cpp
@@ -30,13 +30,11 @@
#include "PointMovementGenerator.h"
#include "PathGenerator.h"
#include "MMapFactory.h"
-#include "DetourCommon.h"
#include "Map.h"
#include "TargetedMovementGenerator.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
-#include "MMapManager.h"
class mmaps_commandscript : public CommandScript
{
@@ -48,152 +46,24 @@ public:
static ChatCommand mmapCommandTable[] =
{
{ "loadedtiles", rbac::RBAC_PERM_COMMAND_MMAP_LOADEDTILES, false, &HandleMmapLoadedTilesCommand, "", NULL },
- { "loc", rbac::RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "", NULL },
- { "path", rbac::RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "", NULL },
- { "stats", rbac::RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "", NULL },
- { "testarea", rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "", NULL },
- { NULL, 0, false, NULL, "", NULL }
+ { "loc", rbac::RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "", NULL },
+ { "path", rbac::RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "", NULL },
+ { "stats", rbac::RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "", NULL },
+ { "testarea", rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
{
- { "mmap", rbac::RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable },
- { NULL, 0, false, NULL, "", NULL }
+ { "mmap", rbac::RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable },
+ { NULL, 0, false, NULL, "", NULL }
};
return commandTable;
}
- static float Fix_GetXZArea(float* verts, int nv)
- {
- float area = 0;
- for(int i=0; i<nv-1; i++)
- area+=(verts[i*3]*verts[i*3+5]-verts[i*3+3]*verts[i*3+2]);
- area += (verts[(nv-1)*3]*verts[2] - verts[0]*verts[(nv-1)*3+2]);
- return area*0.5f;
- }
-
-
- //dtPointInPolygon will return false when the point is too close to the edge,so we rewite the test function.
- static bool Fix_PointIsInPoly(float* pos,float* verts,int nv,float err)
- {
- //poly area
- float area = abs(Fix_GetXZArea(verts,nv));
-
- //calculate each area of triangles
- float TestTri[9];
- memcpy(TestTri,pos,sizeof(float)*3);
- float area1 = 0;
- for(int i=0;i<nv-1;++i)
- {
- memcpy(&TestTri[3],&verts[i*3],sizeof(float)*3);
- memcpy(&TestTri[6],&verts[i*3+3],sizeof(float)*3);
- area1+= abs(Fix_GetXZArea(TestTri,3));
- if(area1-err>area)
- return false;
- }
-
- //last one
- memcpy(&TestTri[3],verts,sizeof(float)*3);
- memcpy(&TestTri[6],&verts[nv*3-3],sizeof(float)*3);
- area1+= abs(Fix_GetXZArea(TestTri,3));
-
- return abs(area1-area)<err;
- }
-
-
- static float DistanceToWall(dtNavMeshQuery* navQuery, dtNavMesh* navMesh, float* polyPickExt, dtQueryFilter& filter, float* pos,float* hitPos,float* hitNormal)
- {
- float distanceToWall=0;
- dtPolyRef ref;
- if(dtStatusSucceed(navQuery->findNearestPoly(pos, polyPickExt, &filter, &ref, 0))==false || ref ==0)
- return -1;
-
- const dtMeshTile* tile = 0;
- const dtPoly* poly = 0;
- if (dtStatusFailed(navMesh->getTileAndPolyByRef(ref, &tile, &poly)))
- return -1;
-
- // Collect vertices.
- float verts[DT_VERTS_PER_POLYGON*3];
- int nv = 0;
- for (int i = 0; i < (int)poly->vertCount; ++i)
- {
- dtVcopy(&verts[nv*3], &tile->verts[poly->verts[i]*3]);
- nv++;
- }
-
- bool inside = Fix_PointIsInPoly(pos, verts, nv,0.05f);
- if(inside == false)
- return -1;
-
- if(dtStatusSucceed(navQuery->findDistanceToWall(ref, pos, 100.0f, &filter, &distanceToWall, hitPos, hitNormal))==false)
- return -1;
-
- return distanceToWall;
- }
-
- #define MIN_WALL_DISTANCE 1.5f //set this value bigger to make the path point far way from wall
-
- //Try to fix the path,
- static void FixPath(dtNavMesh* navMesh, dtNavMeshQuery* navQuery, float* polyPickExt, dtQueryFilter& filter, int pathLength, float*& straightPath)
- {
- float hitPos[3];
- float hitNormal[3];
- float TestPos[3];
- float distanceToWall=0;
- float up[3]={0,1,0};
- float origDis = 0;
-
- for(int i=1;i<pathLength-1;++i)
- {
- dtPolyRef pt;
- float* pCurPoi=&straightPath[i*3];
- distanceToWall = DistanceToWall(navQuery, navMesh, polyPickExt, filter, pCurPoi,hitPos,hitNormal);
-
- if(distanceToWall<MIN_WALL_DISTANCE && distanceToWall>=0)
- {
- float vec[3];
- dtVsub(vec,&straightPath[i*3-3],&straightPath[i*3]);
- //distanceToWall is 0 means the point is in the edge.so we can't get the hitpos.
- if(distanceToWall == 0)
- {
- //test left side
- dtVcross(TestPos,vec,up);
- dtVadd(TestPos,TestPos,pCurPoi);
- float ft = MIN_WALL_DISTANCE/dtVdist(TestPos,pCurPoi);
- dtVlerp(TestPos,pCurPoi,TestPos,ft);
- distanceToWall = DistanceToWall(navQuery, navMesh, polyPickExt, filter,TestPos,hitPos,hitNormal);
- if(abs(MIN_WALL_DISTANCE - distanceToWall)>0.1f)
- {
- //test right side
- dtVcross(TestPos,up,vec);
- dtVadd(TestPos,TestPos,pCurPoi);
- ft = MIN_WALL_DISTANCE/dtVdist(TestPos,pCurPoi);
- dtVlerp(TestPos,pCurPoi,TestPos,ft);
- distanceToWall = DistanceToWall(navQuery, navMesh, polyPickExt, filter,TestPos,hitPos,hitNormal);
- }
-
- //if test point is better than the orig point,replace it.
- if(abs(distanceToWall-MIN_WALL_DISTANCE)<0.1f)
- dtVcopy(pCurPoi,TestPos);
- }
- else
- {
- //ok,we get the hitpos,just make a ray
- float ft = MIN_WALL_DISTANCE/distanceToWall;
- dtVlerp(TestPos,hitPos,pCurPoi,ft);
- distanceToWall = DistanceToWall(navQuery, navMesh, polyPickExt, filter, TestPos,hitPos,hitNormal);
-
- if(abs(distanceToWall-MIN_WALL_DISTANCE)<0.1f)
- dtVcopy(pCurPoi,TestPos);
- }
- }
- }
- }
-
static bool HandleMmapPathCommand(ChatHandler* handler, char const* args)
{
- if (!MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()))
+ if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()))
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
return true;
@@ -221,10 +91,10 @@ public:
player->GetPosition(x, y, z);
// path
- /*PathGenerator path(target);
+ PathGenerator path(target);
path.SetUseStraightPath(useStraightPath);
bool result = path.CalculatePath(x, y, z);
-
+
Movement::PointsArray const& pointPath = path.GetPath();
handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str());
handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath");
@@ -237,64 +107,13 @@ public:
handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z);
handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z);
handler->PSendSysMessage("ActualEndPosition (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z);
- */
- float m_spos[3];
- m_spos[0] = -y;
- m_spos[1] = z;
- m_spos[2] = -x;
-
- //
- float m_epos[3];
- m_epos[0] = -target->GetPositionY();
- m_epos[1] = target->GetPositionZ();
- m_epos[2] = -target->GetPositionX();
-
- //
- dtQueryFilter m_filter;
- m_filter.setIncludeFlags(3);
- m_filter.setExcludeFlags(2);
-
- //
- float m_polyPickExt[3];
- m_polyPickExt[0] = 2.5f;
- m_polyPickExt[1] = 2.5f;
- m_polyPickExt[2] = 2.5f;
-
- //
- dtPolyRef m_startRef;
- dtPolyRef m_endRef;
-
- const dtNavMesh* navMesh = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(player->GetMapId());
- const dtNavMeshQuery* navMeshQuery = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), handler->GetSession()->GetPlayer()->GetInstanceId());
-
- float nearestPt[3];
-
- navMeshQuery->findNearestPoly(m_spos, m_polyPickExt, &m_filter, &m_startRef, nearestPt);
- navMeshQuery->findNearestPoly(m_epos, m_polyPickExt, &m_filter, &m_endRef, nearestPt);
-
- if ( !m_startRef || !m_endRef )
- {
- std::cerr << "Could not find any nearby poly's (" << m_startRef << "," << m_endRef << ")" << std::endl;
- return 0;
- }
-
- int hops;
- dtPolyRef* hopBuffer = new dtPolyRef[8192];
- dtStatus status = navMeshQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, &m_filter, hopBuffer, &hops, 8192);
-
- int resultHopCount;
- float* straightPath = new float[2048*3];
- unsigned char* pathFlags = new unsigned char[2048];
- dtPolyRef* pathRefs = new dtPolyRef[2048];
-
- status = navMeshQuery->findStraightPath(m_spos, m_epos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048);
- FixPath(const_cast<dtNavMesh*>(navMesh), const_cast<dtNavMeshQuery*>(navMeshQuery), m_polyPickExt, m_filter, resultHopCount, straightPath);
- for (uint32 i = 0; i < resultHopCount; ++i)
- player->SummonCreature(VISUAL_WAYPOINT, -straightPath[i * 3 + 2], -straightPath[i * 3 + 0], straightPath[i * 3 + 1], 0, TEMPSUMMON_TIMED_DESPAWN, 9000);
if (!player->IsGameMaster())
handler->PSendSysMessage("Enable GM mode to see the path points.");
+ for (uint32 i = 0; i < pointPath.size(); ++i)
+ player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000);
+
return true;
}
@@ -312,8 +131,8 @@ public:
handler->PSendSysMessage("gridloc [%i, %i]", gx, gy);
// calculate navmesh tile location
- dtNavMesh const* navmesh = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId());
- dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId());
+ dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId());
+ dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId());
if (!navmesh || !navmeshquery)
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
@@ -323,8 +142,8 @@ public:
float const* min = navmesh->getParams()->orig;
float x, y, z;
player->GetPosition(x, y, z);
- float location[] = {y, z, x};
- float extents[] = {3.0f, 5.0f, 3.0f};
+ float location[VERTEX_SIZE] = { y, z, x };
+ float extents[VERTEX_SIZE] = { 3.0f, 5.0f, 3.0f };
int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS);
int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS);
@@ -333,14 +152,14 @@ public:
// navmesh poly -> navmesh tile location
dtQueryFilter filter = dtQueryFilter();
- dtPolyRef polyRef = 0;
+ dtPolyRef polyRef = INVALID_POLYREF;
if (dtStatusFailed(navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL)))
{
handler->PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)");
return true;
}
- if (polyRef == 0)
+ if (polyRef == INVALID_POLYREF)
handler->PSendSysMessage("Dt [??, ??] (invalid poly, probably no tile loaded)");
else
{
@@ -364,8 +183,8 @@ public:
static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/)
{
uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId();
- dtNavMesh const* navmesh = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(mapid);
- dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId());
+ dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid);
+ dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId());
if (!navmesh || !navmeshquery)
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
@@ -392,8 +211,8 @@ public:
handler->PSendSysMessage("mmap stats:");
handler->PSendSysMessage(" global mmap pathfinding is %sabled", MMAP::MMapFactory::IsPathfindingEnabled(mapId) ? "en" : "dis");
- MMAP::MMapManager* manager = MMAP::MMapFactory::CreateOrGetMMapManager();
- handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->GetLoadedMapsCount(), manager->GetLoadedTilesCount());
+ MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager();
+ handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId());
if (!navmesh)
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 7c181e95104..0267f17fd6c 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -11,6 +11,7 @@
add_subdirectory(map_extractor)
add_subdirectory(vmap4_assembler)
add_subdirectory(vmap4_extractor)
+
#if (WITH_MESHEXTRACTOR)
# add_subdirectory(mesh_extractor)
#else()
diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp
index f1b06fb1c0b..a55bdd5e4bb 100644
--- a/src/tools/mesh_extractor/ADT.cpp
+++ b/src/tools/mesh_extractor/ADT.cpp
@@ -25,7 +25,7 @@ ADT::ADT( std::string file, int x, int y ) : ObjectData(NULL), Data(NULL), HasOb
{
Data = new ChunkedData(file);
ObjectData = new ChunkedData(file);
- if (ObjectData->_Stream)
+ if (ObjectData->Stream)
HasObjectData = true;
else
ObjectData = NULL;
@@ -33,11 +33,6 @@ ADT::ADT( std::string file, int x, int y ) : ObjectData(NULL), Data(NULL), HasOb
ADT::~ADT()
{
- // Temporarily delete the underlying streams, they are guaranteed to be different
- // @TODO: Remove this code once the ChunkedData destructor properly releases _Stream
- delete ObjectData->_Stream;
- delete Data->_Stream;
-
delete ObjectData;
delete Data;
diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h
index 37aeb9caf48..5d8c02252c9 100644
--- a/src/tools/mesh_extractor/Cache.h
+++ b/src/tools/mesh_extractor/Cache.h
@@ -31,18 +31,24 @@ class GenericCache
public:
GenericCache() {}
- T const* Get(K key)
+ static const uint32 FlushLimit = 300; // We can't get too close to filling up all the memory, and we have to be wary of the maximum number of open streams.
+
+ void Insert(K key, T* val)
+ {
+ ACE_GUARD(ACE_Thread_Mutex, g, mutex);
+
+ if (_items.size() > FlushLimit)
+ Clear();
+ _items[key] = val;
+ }
+
+ T* Get(K key)
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL);
typename std::map<K, T*>::iterator itr = _items.find(key);
if (itr != _items.end())
return itr->second;
- else
- {
- T* t = new T(key); // Create the object
- _items[key] = t;
- return t;
- }
+ return NULL;
}
void Clear()
diff --git a/src/tools/mesh_extractor/Chunk.cpp b/src/tools/mesh_extractor/Chunk.cpp
index b1b28494a66..e4b2f60ff99 100644
--- a/src/tools/mesh_extractor/Chunk.cpp
+++ b/src/tools/mesh_extractor/Chunk.cpp
@@ -25,24 +25,24 @@ int32 Chunk::FindSubChunkOffset(std::string name)
if (name.size() != 4)
return -1;
- Stream* stream = GetStream();
+ FILE* stream = GetStream();
uint32 matched = 0;
- while (stream->GetPos() < stream->GetSize())
+ while (uint32(ftell(stream)) < Utils::Size(stream))
{
- char b = stream->Read<char>();
- if (b != name[matched])
+ char b = 0;
+ if (fread(&b, sizeof(char), 1, stream) != 1 || b != name[matched])
matched = 0;
else
++matched;
if (matched == 4)
- return stream->GetPos() - 4;
+ return ftell(stream) - 4;
}
return -1;
}
-Stream* Chunk::GetStream()
+FILE* Chunk::GetStream()
{
- _Stream->Seek(Offset, SEEK_SET);
- return _Stream;
+ fseek(Stream, Offset, SEEK_SET);
+ return Stream;
}
diff --git a/src/tools/mesh_extractor/Chunk.h b/src/tools/mesh_extractor/Chunk.h
index 6cb6a10c8c2..87201928435 100644
--- a/src/tools/mesh_extractor/Chunk.h
+++ b/src/tools/mesh_extractor/Chunk.h
@@ -19,21 +19,19 @@
#define CHUNK_H
#include "Define.h"
#include <string>
-#include "Stream.h"
-
class ChunkedData;
class Chunk
{
public:
- Chunk(const char* name, uint32 length, uint32 offset, Stream* stream) : Name(name), Length(length), Offset(offset), _Stream(stream) {}
+ Chunk(const char* name, uint32 length, uint32 offset, FILE* stream) : Name(name), Length(length), Offset(offset), Stream(stream) {}
int32 FindSubChunkOffset(std::string name);
- Stream* GetStream();
+ FILE* GetStream();
std::string Name;
uint32 Length;
uint32 Offset;
- Stream* _Stream;
+ FILE* Stream;
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp
index 96af6f56a52..ae7827d98ea 100644
--- a/src/tools/mesh_extractor/ChunkedData.cpp
+++ b/src/tools/mesh_extractor/ChunkedData.cpp
@@ -21,18 +21,18 @@
#include <string>
-ChunkedData::ChunkedData(Stream* stream, uint32 maxLength, uint32 chunksHint /*= 300*/ ) :
-_Stream(stream)
+ChunkedData::ChunkedData( FILE* stream, uint32 maxLength, uint32 chunksHint /*= 300*/ ) :
+Stream(stream)
{
- if (!_Stream)
+ if (!Stream)
return;
Load(maxLength, chunksHint);
}
ChunkedData::ChunkedData( const std::string& file, uint32 chunksHint /*= 300*/ )
{
- _Stream = MPQHandler->GetFile(file);
- if (!_Stream)
+ Stream = MPQHandler->GetFile(file);
+ if (!Stream)
return;
Load(0, chunksHint);
}
@@ -40,30 +40,31 @@ ChunkedData::ChunkedData( const std::string& file, uint32 chunksHint /*= 300*/ )
void ChunkedData::Load( uint32 maxLength, uint32 chunksHint )
{
if (!maxLength)
- maxLength = _Stream->GetSize();
+ maxLength = Utils::Size(Stream);
Chunks.reserve(chunksHint);
- uint32 baseOffset = _Stream->GetPos();
+ uint32 baseOffset = ftell(Stream);
uint32 calcOffset = 0;
- while ((calcOffset + baseOffset) < _Stream->GetSize() && (calcOffset < maxLength))
+ while ((calcOffset + baseOffset) < Utils::Size(Stream) && (calcOffset < maxLength))
{
char nameBytes[5];
- _Stream->Read(nameBytes, sizeof(char) * 4);
- nameBytes[4] = '\0';
+ uint32 read = fread(&nameBytes, sizeof(char), 4, Stream);
+ nameBytes[read] = '\0';
std::string name = std::string(nameBytes);
+ // Utils::Reverse(nameBytes);
name = std::string(name.rbegin(), name.rend());
-
- uint32 length = _Stream->Read<uint32>();
+ uint32 length;
+ if (fread(&length, sizeof(uint32), 1, Stream) != 1)
+ continue;
calcOffset += 8;
-
- Chunks.push_back(new Chunk(name.c_str(), length, calcOffset + baseOffset, _Stream));
+ Chunks.push_back(new Chunk(name.c_str(), length, calcOffset + baseOffset, Stream));
calcOffset += length;
// save an extra seek at the end
- if ((calcOffset + baseOffset) < _Stream->GetSize() && calcOffset < maxLength)
- _Stream->Seek(length, SEEK_CUR);
+ if ((calcOffset + baseOffset) < Utils::Size(Stream) && calcOffset < maxLength)
+ fseek(Stream, length, SEEK_CUR);
}
}
-int ChunkedData::GetFirstIndex( const std::string& name ) const
+int ChunkedData::GetFirstIndex( const std::string& name )
{
for (uint32 i = 0; i < Chunks.size(); ++i)
if (Chunks[i]->Name == name)
@@ -85,7 +86,6 @@ ChunkedData::~ChunkedData()
delete *itr;
Chunks.clear();
- /* WorldModelGroup Data and SubData share the same _Stream so it's deleted twice and it crashes
- if (_Stream)
- delete _Stream;*/
+ if (Stream)
+ fclose(Stream);
}
diff --git a/src/tools/mesh_extractor/ChunkedData.h b/src/tools/mesh_extractor/ChunkedData.h
index cef6c111542..48bb61f6959 100644
--- a/src/tools/mesh_extractor/ChunkedData.h
+++ b/src/tools/mesh_extractor/ChunkedData.h
@@ -20,20 +20,19 @@
#include <vector>
#include "Chunk.h"
-#include "Stream.h"
class ChunkedData
{
public:
- ChunkedData(Stream* stream, uint32 maxLength, uint32 chunksHint = 300);
+ ChunkedData(FILE* stream, uint32 maxLength, uint32 chunksHint = 300);
ChunkedData(const std::string &file, uint32 chunksHint = 300);
~ChunkedData();
- int GetFirstIndex(const std::string& name) const;
+ int GetFirstIndex(const std::string& name);
Chunk* GetChunkByName(const std::string& name);
void Load(uint32 maxLength, uint32 chunksHint);
std::vector<Chunk*> Chunks;
- Stream* _Stream;
+ FILE* Stream;
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h
index 1961c2f386f..75e08bcf6fd 100644
--- a/src/tools/mesh_extractor/Constants.h
+++ b/src/tools/mesh_extractor/Constants.h
@@ -26,8 +26,6 @@ public:
TRIANGLE_TYPE_UNKNOWN,
TRIANGLE_TYPE_TERRAIN,
TRIANGLE_TYPE_WATER,
- TRIANGLE_TYPE_MAGMA,
- TRIANGLE_TYPE_SLIME,
TRIANGLE_TYPE_DOODAD,
TRIANGLE_TYPE_WMO
};
diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp
index aa1666fd0e3..8f6a918ef8d 100644
--- a/src/tools/mesh_extractor/ContinentBuilder.cpp
+++ b/src/tools/mesh_extractor/ContinentBuilder.cpp
@@ -16,21 +16,80 @@
*/
#include "ContinentBuilder.h"
+#include "TileBuilder.h"
#include "WDT.h"
#include "Utils.h"
#include "DetourNavMesh.h"
#include "Cache.h"
+#include "ace/Task.h"
#include "Recast.h"
#include "DetourCommon.h"
-void ContinentBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) const
+class BuilderThread : public ACE_Task_Base
+{
+private:
+ int X, Y, MapId;
+ std::string Continent;
+ dtNavMeshParams Params;
+ ContinentBuilder* cBuilder;
+public:
+ BuilderThread(ContinentBuilder* _cBuilder, dtNavMeshParams& params) : Params(params), cBuilder(_cBuilder), Free(true) {}
+
+ void SetData(int x, int y, int map, const std::string& cont)
+ {
+ X = x;
+ Y = y;
+ MapId = map;
+ Continent = cont;
+ }
+
+ int svc()
+ {
+ Free = false;
+ printf("[%02i,%02i] Building tile\n", X, Y);
+ TileBuilder builder(cBuilder, Continent, X, Y, MapId);
+ char buff[100];
+ sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X);
+ FILE* f = fopen(buff, "r");
+ if (f) // Check if file already exists.
+ {
+ printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
+ fclose(f);
+ Free = true;
+ return 0;
+ }
+ uint8* nav = builder.BuildTiled(Params);
+ if (nav)
+ {
+ f = fopen(buff, "wb");
+ if (!f)
+ {
+ printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
+ return 0;
+ }
+ MmapTileHeader header;
+ header.size = builder.DataSize;
+ fwrite(&header, sizeof(MmapTileHeader), 1, f);
+ fwrite(nav, sizeof(unsigned char), builder.DataSize, f);
+ fclose(f);
+ }
+ dtFree(nav);
+ printf("[%02i,%02i] Tile Built!\n", X, Y);
+ Free = true;
+ return 0;
+ }
+
+ bool Free;
+};
+
+void ContinentBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax)
{
// this is for elevation
if (verts && vertCount)
rcCalcBounds(verts, vertCount, bmin, bmax);
else
{
- bmin[1] = -FLT_MAX;
+ bmin[1] = FLT_MIN;
bmax[1] = FLT_MAX;
}
@@ -69,6 +128,8 @@ void ContinentBuilder::Build()
dtNavMeshParams params;
+ std::vector<BuilderThread*> Threads;
+
if (TileMap->IsGlobalModel)
{
printf("Map %s ( %u ) is a WMO. Building with 1 thread.\n", Continent.c_str(), MapId);
@@ -98,7 +159,6 @@ void ContinentBuilder::Build()
}
MmapTileHeader mheader;
- Utils::InitializeMmapTileHeader(mheader);
mheader.size = builder->DataSize;
fwrite(&mheader, sizeof(MmapTileHeader), 1, f);
fwrite(nav, sizeof(unsigned char), builder->DataSize, f);
@@ -110,70 +170,44 @@ void ContinentBuilder::Build()
}
else
{
- params.maxPolys = 1024;
- params.maxTiles = TileMap->TileTable.size();
+ params.maxPolys = 32768;
+ params.maxTiles = 4096;
rcVcopy(params.orig, Constants::Origin);
params.tileHeight = Constants::TileSize;
params.tileWidth = Constants::TileSize;
fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
- std::vector<BuilderThread*> _threads;
- BuilderThreadPool* pool = NumberOfThreads > 0 ? new BuilderThreadPool() : NULL;
-
+ for (uint32 i = 0; i < NumberOfThreads; ++i)
+ Threads.push_back(new BuilderThread(this, params));
printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads);
-
for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
- pool->Enqueue(new TileBuildRequest(this, Continent, itr->X, itr->Y, MapId, params));
-
- for (uint32 i = 0; i < NumberOfThreads; ++i)
- _threads.push_back(new BuilderThread(this, pool->Queue()));
-
- // Free memory
- for (std::vector<BuilderThread*>::iterator _th = _threads.begin(); _th != _threads.end(); ++_th)
{
- (*_th)->wait();
- delete *_th;
+ bool next = false;
+ while (!next)
+ {
+ for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
+ {
+ if ((*_th)->Free)
+ {
+ (*_th)->SetData(itr->X, itr->Y, MapId, Continent);
+ (*_th)->activate();
+ next = true;
+ break;
+ }
+ }
+ // Wait for 20 seconds
+ ACE_OS::sleep(ACE_Time_Value (0, 20000));
+ }
}
-
- delete pool;
}
Cache->Clear();
-}
-int TileBuildRequest::call()
-{
- printf("[%02i,%02i] Building tile\n", X, Y);
- // Build the tile and return negative on error
- TileBuilder tile(_builder, _continent, X, Y, _mapId);
- char buff[100];
- sprintf(buff, "mmaps/%03u%02i%02i.mmtile", _mapId, Y, X);
- FILE* f = fopen(buff, "r");
- if (f) // Check if file already exists.
+ // Free memory
+ for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
{
- printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
- fclose(f);
- return 0;
- }
- uint8* nav = tile.BuildTiled(_params);
- if (nav)
- {
- f = fopen(buff, "wb");
- if (!f)
- {
- printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
- dtFree(nav);
- return -1;
- }
- MmapTileHeader header;
- Utils::InitializeMmapTileHeader(header);
- header.size = tile.DataSize;
- fwrite(&header, sizeof(MmapTileHeader), 1, f);
- fwrite(nav, sizeof(unsigned char), tile.DataSize, f);
- fclose(f);
+ (*_th)->wait();
+ delete *_th;
}
- dtFree(nav);
- printf("[%02i,%02i] Tile Built!\n", X, Y);
- return 0;
}
diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h
index 3dccced09c3..075265f2627 100644
--- a/src/tools/mesh_extractor/ContinentBuilder.h
+++ b/src/tools/mesh_extractor/ContinentBuilder.h
@@ -17,15 +17,9 @@
#ifndef CONT_BUILDER_H
#define CONT_BUILDER_H
-
#include <string>
#include "WDT.h"
#include "Define.h"
-#include "TileBuilder.h"
-
-#include <ace/Task.h>
-#include <ace/Activation_Queue.h>
-#include <ace/Method_Request.h>
class ContinentBuilder
{
@@ -36,7 +30,7 @@ public:
{}
void Build();
- void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) const;
+ void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax);
void CalculateTileBounds();
float bmin[3];
float bmax[3];
@@ -51,60 +45,4 @@ private:
int tileYMax;
};
-class TileBuildRequest : public ACE_Method_Request
-{
-public:
- TileBuildRequest(ContinentBuilder* builder, std::string& continent, uint32 x, uint32 y, uint32 mapId, dtNavMeshParams& params) : _mapId(mapId), _builder(builder), _continent(continent), X(x), Y(y), _params(params) { }
-
- virtual int call();
-
-private:
- uint32 _mapId;
- ContinentBuilder* _builder;
- std::string& _continent;
- uint32 X;
- uint32 Y;
- dtNavMeshParams& _params;
-};
-
-class BuilderThreadPool
-{
-public:
- BuilderThreadPool() : _queue(new ACE_Activation_Queue()) {}
- ~BuilderThreadPool() { _queue->queue()->close(); delete _queue; }
-
- void Enqueue(TileBuildRequest* request)
- {
- _queue->enqueue(request);
- }
-
- ACE_Activation_Queue* Queue() { return _queue; }
-
-private:
- ACE_Activation_Queue* _queue;
-};
-
-class BuilderThread : public ACE_Task_Base
-{
-private:
- ContinentBuilder* _builder;
- ACE_Activation_Queue* _queue;
-public:
- BuilderThread(ContinentBuilder* builder, ACE_Activation_Queue* queue) : _builder(builder), _queue(queue) { activate(); }
-
- int svc()
- {
- /// @ Set a timeout for dequeue attempts (only used when the queue is empty) as it will never get populated after thread starts
- ACE_Time_Value timeout(5);
- ACE_Method_Request* request = NULL;
- while ((request = _queue->dequeue(&timeout)) != NULL)
- {
- request->call();
- delete request;
- request = NULL;
- }
- return 0;
- }
-};
-
#endif
diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp
index 49c136efc80..e38b9560533 100644
--- a/src/tools/mesh_extractor/DBC.cpp
+++ b/src/tools/mesh_extractor/DBC.cpp
@@ -19,15 +19,19 @@
#include "DBC.h"
#include "Define.h"
-DBC::DBC(Stream* stream) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true)
+DBC::DBC( FILE* stream ) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true)
{
- delete[] stream->Read(4); // Read the magic "WDBC"
-
- RecordCount = stream->Read<int>();
+ char magic[5];
+ uint32 count = 0;
+ count += fread(&magic, sizeof(char), 4, stream);
+ magic[4] = '\0';
+ count += fread(&RecordCount, sizeof(uint32), 1, stream);
Records.reserve(RecordCount);
- Fields = stream->Read<int>();
- RecordSize = stream->Read<int>();
- StringBlockSize = stream->Read<uint32>();
+ count += fread(&Fields, sizeof(uint32), 1, stream);
+ count += fread(&RecordSize, sizeof(uint32), 1, stream);
+ count += fread(&StringBlockSize, sizeof(uint32), 1, stream);
+ if (count != 8)
+ printf("DBC::DBC: Failed to read some data expected 8, read %u\n", count);
for (int i = 0; i < RecordCount; i++)
{
@@ -41,21 +45,21 @@ DBC::DBC(Stream* stream) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true)
IsFaulty = true;
break;
}
- rec->Values.push_back(stream->Read<uint32>());
+ uint32 tmp;
+ if (fread(&tmp, sizeof(uint32), 1, stream) != 1)
+ printf("DBC::DBC: Failed to read some data expected 1, read 0\n");
+ rec->Values.push_back(tmp);
size += 4;
}
}
- StringBlock = (uint8*)stream->Read(StringBlockSize);
-}
-DBC::~DBC()
-{
- delete[] StringBlock;
- for (std::vector<Record*>::iterator itr = Records.begin(); itr != Records.end(); ++itr)
- delete *itr;
+ StringBlock = new uint8[StringBlockSize];
+ count = fread(StringBlock, sizeof(uint8), StringBlockSize, stream);
+ if (count != StringBlockSize)
+ printf("DBC::DBC: Failed to read some data expected %u, read %u\n", StringBlockSize, count);
}
-std::string DBC::GetStringByOffset( int offset ) const
+std::string DBC::GetStringByOffset( int offset )
{
int len = 0;
for (uint32 i = offset; i < StringBlockSize; i++)
@@ -70,14 +74,14 @@ std::string DBC::GetStringByOffset( int offset ) const
strcpy(d, (const char*)(StringBlock + offset));
d[len] = '\0';
std::string val = std::string(d);
- delete[] d;
+ delete [] d;
return val;
}
-Record const* DBC::GetRecordById( int id ) const
+Record* DBC::GetRecordById( int id )
{
// we assume Id is index 0
- for (std::vector<Record*>::const_iterator itr = Records.begin(); itr != Records.end(); ++itr)
+ for (std::vector<Record*>::iterator itr = Records.begin(); itr != Records.end(); ++itr)
if ((*itr)->Values[0] == id)
return *itr;
return NULL;
diff --git a/src/tools/mesh_extractor/DBC.h b/src/tools/mesh_extractor/DBC.h
index 179c63ffcf2..d0951e36737 100644
--- a/src/tools/mesh_extractor/DBC.h
+++ b/src/tools/mesh_extractor/DBC.h
@@ -20,19 +20,17 @@
#include <vector>
#include <string>
#include "Define.h"
-#include "Stream.h"
class Record;
class DBC
{
public:
- DBC(Stream* stream);
- ~DBC();
+ DBC(FILE* stream);
- std::string GetStringByOffset(int offset) const;
+ std::string GetStringByOffset(int offset);
- Record const* GetRecordById(int id) const;
+ Record* GetRecordById(int id);
std::string Name;
std::vector<Record*> Records;
@@ -52,18 +50,18 @@ public:
DBC* Source;
std::vector<int> Values;
- int operator[](int index) const
+ int operator[](int index)
{
return Values[index];
}
template <typename T>
- T GetValue(int index) const
+ T GetValue(int index)
{
return *(T*)(&Values[index]);
}
- const std::string GetString(int index) const
+ std::string GetString(int index)
{
return Source->GetStringByOffset(Values[index]);
}
diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp
index 7e84eaa6044..d56ba4c3bdf 100644
--- a/src/tools/mesh_extractor/DoodadHandler.cpp
+++ b/src/tools/mesh_extractor/DoodadHandler.cpp
@@ -34,18 +34,20 @@ DoodadHandler::DoodadHandler( ADT* adt ) :
ReadDoodadPaths(mmid, mmdx);
}
-void DoodadHandler::ProcessInternal(MapChunk* mcnk)
+void DoodadHandler::ProcessInternal( MapChunk* mcnk )
{
if (!IsSane())
return;
uint32 refCount = mcnk->Header.DoodadRefs;
- Stream* stream = mcnk->Source->GetStream();
- stream->Seek(mcnk->Source->Offset + mcnk->Header.OffsetMCRF, SEEK_SET);
-
+ FILE* stream = mcnk->Source->GetStream();
+ fseek(stream, mcnk->Source->Offset + mcnk->Header.OffsetMCRF, SEEK_SET);
for (uint32 i = 0; i < refCount; i++)
{
- int32 index = stream->Read<int32>();
+ int32 index;
+ int32 count;
+ if ((count = fread(&index, sizeof(int32), 1, stream)) != 1)
+ printf("DoodadHandler::ProcessInternal: Failed to read some data expected 1, read %d\n", count);
if (index < 0 || uint32(index) >= _definitions->size())
continue;
DoodadDefinition doodad = (*_definitions)[index];
@@ -56,7 +58,12 @@ void DoodadHandler::ProcessInternal(MapChunk* mcnk)
continue;
std::string path = (*_paths)[doodad.MmidIndex];
- Model const* model = Cache->ModelCache.Get(path);
+ Model* model = Cache->ModelCache.Get(path);
+ if (!model)
+ {
+ model = new Model(path);
+ Cache->ModelCache.Insert(path, model);
+ }
if (!model->IsCollidable)
continue;
@@ -66,7 +73,7 @@ void DoodadHandler::ProcessInternal(MapChunk* mcnk)
InsertModelGeometry(doodad, model);
}
// Restore the stream position
- stream->Seek(mcnk->Source->Offset, SEEK_SET);
+ fseek(stream, mcnk->Source->Offset, SEEK_SET);
}
void DoodadHandler::ReadDoodadDefinitions( Chunk* chunk )
@@ -74,7 +81,7 @@ void DoodadHandler::ReadDoodadDefinitions( Chunk* chunk )
int32 count = chunk->Length / 36;
_definitions = new std::vector<DoodadDefinition>;
_definitions->reserve(count);
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
for (int i = 0; i < count; i++)
{
DoodadDefinition def;
@@ -90,24 +97,25 @@ void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data )
_paths->reserve(paths);
for (int i = 0; i < paths; i++)
{
- Stream* idStream = id->GetStream();
- idStream->Seek(i * 4, SEEK_CUR);
- uint32 offset = idStream->Read<uint32>();
-
- Stream* dataStream = data->GetStream();
- dataStream->Seek(offset + data->Offset, SEEK_SET);
- _paths->push_back(dataStream->ReadString());
+ FILE* idStream = id->GetStream();
+ fseek(idStream, i * 4, SEEK_CUR);
+ uint32 offset;
+ if (fread(&offset, sizeof(uint32), 1, idStream) != 1)
+ printf("DoodadHandler::ReadDoodadPaths: Failed to read some data expected 1, read 0\n");
+ FILE* dataStream = data->GetStream();
+ fseek(dataStream, offset + data->Offset, SEEK_SET);
+ _paths->push_back(Utils::ReadString(dataStream));
}
}
-void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model const* model)
+void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model* model)
{
uint32 vertOffset = Vertices.size();
- for (std::vector<Vector3>::const_iterator itr = model->Vertices.begin(); itr != model->Vertices.end(); ++itr)
+ for (std::vector<Vector3>::iterator itr = model->Vertices.begin(); itr != model->Vertices.end(); ++itr)
Vertices.push_back(Utils::TransformDoodadVertex(def, *itr)); // Vertices have to be converted based on the information from the DoodadDefinition struct
- for (std::vector<Triangle<uint16> >::const_iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr)
+ for (std::vector<Triangle<uint16> >::iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr)
Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset));
}
diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h
index 00bb3edb7b0..3e179f63539 100644
--- a/src/tools/mesh_extractor/DoodadHandler.h
+++ b/src/tools/mesh_extractor/DoodadHandler.h
@@ -21,7 +21,6 @@
#include "Utils.h"
#include "Chunk.h"
#include "Model.h"
-#include "Stream.h"
#include <set>
#include <vector>
@@ -40,14 +39,18 @@ public:
return Vector3(vec.z, vec.x, vec.y);
}
- void Read(Stream* stream)
+ void Read(FILE* stream)
{
- MmidIndex = stream->Read<uint32>();
- UniqueId = stream->Read<uint32>();
- Position = Vector3::Read(stream);
+ int count = 0;
+
+ count += fread(&MmidIndex, sizeof(uint32), 1, stream);
+ count += fread(&UniqueId, sizeof(uint32), 1, stream);
+ Position = (Vector3::Read(stream));
Rotation = Vector3::Read(stream);
- DecimalScale = stream->Read<uint16>();
- Flags = stream->Read<uint16>();
+ count += fread(&DecimalScale, sizeof(uint16), 1, stream);
+ count += fread(&Flags, sizeof(uint16), 1, stream);
+ if (count != 4)
+ printf("DoodadDefinition::Read: Failed to read some data expected 4, read %d\n", count);
}
};
@@ -59,7 +62,7 @@ public:
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
- bool IsSane() const { return _definitions && _paths; }
+ bool IsSane() { return _definitions && _paths; }
protected:
@@ -68,7 +71,7 @@ protected:
private:
void ReadDoodadDefinitions(Chunk* chunk);
void ReadDoodadPaths(Chunk* id, Chunk* data);
- void InsertModelGeometry(const DoodadDefinition& def, Model const* model);
+ void InsertModelGeometry(const DoodadDefinition& def, Model* model);
std::set<uint32> _drawn;
std::vector<DoodadDefinition>* _definitions;
std::vector<std::string>* _paths;
diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp
index d95c07bc89b..e81dd8a7660 100644
--- a/src/tools/mesh_extractor/Geometry.cpp
+++ b/src/tools/mesh_extractor/Geometry.cpp
@@ -20,7 +20,6 @@
#include "ADT.h"
#include "WorldModelHandler.h"
#include "DoodadHandler.h"
-#include "LiquidHandler.h"
#include <limits.h>
Geometry::Geometry() : Transform(false)
@@ -35,7 +34,7 @@ void Geometry::CalculateBoundingBox( float*& min, float*& max )
max = new float[3];
for (int i = 0; i < 3; ++i)
{
- max[i] = -FLT_MAX;
+ max[i] = std::numeric_limits<float>::lowest();
min[i] = std::numeric_limits<float>::max();
}
@@ -61,7 +60,7 @@ void Geometry::CalculateBoundingBox( float*& min, float*& max )
void Geometry::CalculateMinMaxHeight( float& min, float& max )
{
min = std::numeric_limits<float>::max();
- max = -FLT_MAX;
+ max = std::numeric_limits<float>::lowest();
for (std::vector<Vector3>::iterator itr = Vertices.begin(); itr != Vertices.end(); ++itr)
{
@@ -92,12 +91,12 @@ void Geometry::AddData( std::vector<Vector3>& verts, std::vector<Triangle<uint32
Triangles.push_back(Triangle<uint32>(itr->Type, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset));
}
-void Geometry::GetRawData( float*& verts, int*& tris, uint8*& areas ) const
+void Geometry::GetRawData( float*& verts, int*& tris, uint8*& areas )
{
verts = new float[Vertices.size() * 3];
for (uint32 i = 0; i < Vertices.size(); ++i)
{
- const Vector3& vert = Vertices[i];
+ Vector3& vert = Vertices[i];
verts[(i * 3) + 0] = vert.x;
verts[(i * 3) + 1] = vert.y;
verts[(i * 3) + 2] = vert.z;
@@ -106,7 +105,7 @@ void Geometry::GetRawData( float*& verts, int*& tris, uint8*& areas ) const
tris = new int[Triangles.size() * 3];
for (uint32 i = 0; i < Triangles.size(); ++i)
{
- const Triangle<uint32>& tri = Triangles[i];
+ Triangle<uint32>& tri = Triangles[i];
tris[(i * 3) + 0] = (int)tri.V0;
tris[(i * 3) + 1] = (int)tri.V1;
tris[(i * 3) + 2] = (int)tri.V2;
@@ -143,8 +142,5 @@ void Geometry::AddAdt( ADT* adt )
if (!adt->_WorldModelHandler->Triangles.empty())
AddData(adt->_WorldModelHandler->Vertices, adt->_WorldModelHandler->Triangles);
-
- if (!adt->_LiquidHandler->Triangles.empty())
- AddData(adt->_LiquidHandler->Vertices, adt->_LiquidHandler->Triangles);
}
diff --git a/src/tools/mesh_extractor/Geometry.h b/src/tools/mesh_extractor/Geometry.h
index d7a664068c6..d54cdbde5dd 100644
--- a/src/tools/mesh_extractor/Geometry.h
+++ b/src/tools/mesh_extractor/Geometry.h
@@ -31,7 +31,7 @@ public:
void CalculateMinMaxHeight(float& min, float& max);
void AddData(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris);
void AddAdt(ADT* adt);
- void GetRawData(float*& verts, int*& tris, uint8*& areas) const;
+ void GetRawData(float*& verts, int*& tris, uint8*& areas);
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp
index 177b94924d0..0a76dbfb54c 100644
--- a/src/tools/mesh_extractor/LiquidHandler.cpp
+++ b/src/tools/mesh_extractor/LiquidHandler.cpp
@@ -17,20 +17,10 @@
#include "LiquidHandler.h"
#include "Utils.h"
-#include "DBC.h"
-#include "MPQManager.h"
LiquidHandler::LiquidHandler( ADT* adt ) : Source(adt)
{
HandleNewLiquid();
- HandleOldLiquid();
-}
-
-LiquidHandler::~LiquidHandler()
-{
- for (std::vector<MCNKLiquidData*>::iterator itr = MCNKData.begin(); itr != MCNKData.end(); ++itr)
- delete *itr;
- MCNKData.clear();
}
void LiquidHandler::HandleNewLiquid()
@@ -42,7 +32,7 @@ void LiquidHandler::HandleNewLiquid()
Vertices.reserve(1000);
Triangles.reserve(1000);
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
H2OHeader header[256];
MCNKData.reserve(256);
for (int i = 0; i < 256; i++)
@@ -54,44 +44,40 @@ void LiquidHandler::HandleNewLiquid()
if (h.LayerCount == 0)
{
// Need to fill in missing data with dummies.
- MCNKData.push_back(new MCNKLiquidData(NULL, H2ORenderMask()));
+ MCNKData.push_back(MCNKLiquidData(NULL, H2ORenderMask()));
continue;
}
- stream->Seek(chunk->Offset + h.OffsetInformation, SEEK_SET);
+ fseek(stream, chunk->Offset + h.OffsetInformation, SEEK_SET);
H2OInformation information = H2OInformation::Read(stream);
- // Load the LiquidTypes DBC
- DBC const* liquidTypes = MPQHandler->GetDBC("LiquidTypes");
- Record const* liquid = liquidTypes->GetRecordById(information.LiquidType);
- ASSERT(liquid);
-
- // This pointer will be passed to the MCNKLiquidData constructor, from that point on, it is the job of MCNKLiquidData's destructor to release it.
float** heights = new float*[9];
for (int j = 0; j < 9; ++j)
{
heights[j] = new float[9];
memset(heights[j], 0, sizeof(float) * 9);
}
-
+
H2ORenderMask renderMask;
- if (liquid->GetValue<uint32>(3) != 1) // Read the liquid type and skip Ocean, Slow Ocean and Fast Ocean
+ if (information.LiquidType != 2)
{
- stream->Seek(chunk->Offset + h.OffsetRender, SEEK_SET);
+ fseek(stream, chunk->Offset + h.OffsetRender, SEEK_SET);
renderMask = H2ORenderMask::Read(stream);
if ((Utils::IsAllZero(renderMask.Mask, 8) || (information.Width == 8 && information.Height == 8)) && information.OffsetMask2)
{
- stream->Seek(chunk->Offset + information.OffsetMask2, SEEK_SET);
+ fseek(stream, chunk->Offset + information.OffsetMask2, SEEK_SET);
uint32 size = ceil(information.Width * information.Height / 8.0f);
- uint8* altMask = (uint8*)stream->Read(size);
- for (uint32 mi = 0; mi < size; mi++)
- renderMask.Mask[mi + information.OffsetY] |= altMask[mi];
+ uint8* altMask = new uint8[size];
+ if (fread(altMask, sizeof(uint8), size, stream) == size)
+ for (uint32 mi = 0; mi < size; mi++)
+ renderMask.Mask[mi + information.OffsetY] |= altMask[mi];
delete[] altMask;
}
- stream->Seek(chunk->Offset + information.OffsetHeightmap, SEEK_SET);
+ fseek(stream, chunk->Offset + information.OffsetHeightmap, SEEK_SET);
for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++)
for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++)
- heights[x][y] = stream->Read<float>();
+ if (fread(&heights[x][y], sizeof(float), 1, stream) != 1)
+ return;
}
else
{
@@ -104,7 +90,7 @@ void LiquidHandler::HandleNewLiquid()
heights[x][y] = information.HeightLevel1;
}
- MCNKData.push_back(new MCNKLiquidData(heights, renderMask));
+ MCNKData.push_back(MCNKLiquidData(heights, renderMask));
for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++)
{
@@ -124,37 +110,10 @@ void LiquidHandler::HandleNewLiquid()
Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y, location.z));
Vertices.push_back(Vector3(location.x, location.y - Constants::UnitSize, location.z));
Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y - Constants::UnitSize, location.z));
-
- // Define the liquid type
- Constants::TriangleType type = Constants::TRIANGLE_TYPE_UNKNOWN;
- switch (liquid->GetValue<uint32>(3))
- {
- case 0: // Water
- case 1: // Ocean
- type = Constants::TRIANGLE_TYPE_WATER;
- break;
- case 2: // Magma
- type = Constants::TRIANGLE_TYPE_MAGMA;
- break;
- case 3: // Slime
- type = Constants::TRIANGLE_TYPE_SLIME;
- break;
- }
- Triangles.push_back(Triangle<uint32>(type, vertOffset, vertOffset+2, vertOffset + 1));
- Triangles.push_back(Triangle<uint32>(type, vertOffset + 2, vertOffset + 3, vertOffset + 1));
+ Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset+2, vertOffset + 1));
+ Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1));
}
}
}
}
-
-void LiquidHandler::HandleOldLiquid()
-{
- for (uint32 i = 0; i < 256; ++i)
- {
- MapChunk* mapChunk = Source->MapChunks[i];
- if (!mapChunk->Header.OffsetMCLQ || mapChunk->Header.SizeMCLQ <= 8)
- continue;
- printf("Found old liquid");
- }
-}
diff --git a/src/tools/mesh_extractor/LiquidHandler.h b/src/tools/mesh_extractor/LiquidHandler.h
index 7001e849097..424dbde7e63 100644
--- a/src/tools/mesh_extractor/LiquidHandler.h
+++ b/src/tools/mesh_extractor/LiquidHandler.h
@@ -27,14 +27,12 @@ class LiquidHandler
{
public:
LiquidHandler(ADT* adt);
- ~LiquidHandler();
ADT* Source;
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
- std::vector<MCNKLiquidData*> MCNKData;
+ std::vector<MCNKLiquidData> MCNKData;
private:
void HandleNewLiquid();
- void HandleOldLiquid();
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/MPQ.cpp b/src/tools/mesh_extractor/MPQ.cpp
index 5551b0a9d47..b75a5bbdd85 100644
--- a/src/tools/mesh_extractor/MPQ.cpp
+++ b/src/tools/mesh_extractor/MPQ.cpp
@@ -17,7 +17,6 @@
#include "MPQ.h"
#include "MPQManager.h"
-#include "Stream.h"
#include <deque>
#include <cstdio>
@@ -126,8 +125,15 @@ void MPQFile::close()
eof = true;
}
-Stream* MPQFile::GetFileStream()
+FILE* MPQFile::GetFileStream()
{
- Stream* stream = new Stream(buffer, size);
- return stream;
+ FILE* file = tmpfile();
+ if (!file)
+ {
+ printf("Could not create temporary file. Please run as Administrator or root\n");
+ exit(1);
+ }
+ fwrite(buffer, sizeof(char), size, file);
+ fseek(file, 0, SEEK_SET);
+ return file;
}
diff --git a/src/tools/mesh_extractor/MPQ.h b/src/tools/mesh_extractor/MPQ.h
index 68c678df616..7eb048480b9 100644
--- a/src/tools/mesh_extractor/MPQ.h
+++ b/src/tools/mesh_extractor/MPQ.h
@@ -20,7 +20,6 @@
#include "libmpq/mpq.h"
#include "Define.h"
-#include "Stream.h"
#include <string>
#include <ctype.h>
#include <vector>
@@ -31,7 +30,7 @@ class MPQArchive
{
public:
- mpq_archive_s* mpq_a;
+ mpq_archive_s *mpq_a;
std::vector<std::string> Files;
@@ -71,8 +70,8 @@ class MPQFile
{
//MPQHANDLE handle;
bool eof;
- char* buffer;
- libmpq__off_t pointer, size;
+ char *buffer;
+ libmpq__off_t pointer,size;
// disable copying
MPQFile(const MPQFile& /*f*/) {}
@@ -82,18 +81,18 @@ public:
MPQFile(const char* filename); // filenames are not case sensitive
~MPQFile() { close(); }
size_t Read(void* dest, size_t bytes);
- Stream* GetFileStream();
- size_t getSize() const { return size; }
- size_t getPos() const { return pointer; }
+ FILE* GetFileStream();
+ size_t getSize() { return size; }
+ size_t getPos() { return pointer; }
char* getBuffer() { return buffer; }
char* getPointer() { return buffer + pointer; }
- bool isEof() const { return eof; }
+ bool isEof() { return eof; }
void seek(int offset);
void seekRelative(int offset);
void close();
};
-inline void flipcc(char* fcc)
+inline void flipcc(char *fcc)
{
char t;
t=fcc[0];
diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp
index 563b31d724e..5f6e4a331ac 100644
--- a/src/tools/mesh_extractor/MPQManager.cpp
+++ b/src/tools/mesh_extractor/MPQManager.cpp
@@ -19,7 +19,6 @@
#include "MPQ.h"
#include "DBC.h"
#include "Utils.h"
-#include "Stream.h"
#include <ace/Guard_T.h>
char const* MPQManager::Files[] = {
@@ -32,12 +31,6 @@ char const* MPQManager::Files[] = {
"patch-3.MPQ"
};
-char const* MPQManager::LocalePatchFiles[] = {
- "Data/%s/patch-%s.MPQ",
- "Data/%s/patch-%s-2.MPQ",
- "Data/%s/patch-%s-3.MPQ"
-};
-
char const* MPQManager::Languages[] = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
void MPQManager::Initialize()
@@ -55,7 +48,9 @@ void MPQManager::Initialize()
void MPQManager::InitializeDBC()
{
BaseLocale = -1;
+ std::string fileName;
uint32 size = sizeof(Languages) / sizeof(char*);
+ MPQArchive* _baseLocale = NULL;
for (uint32 i = 0; i < size; ++i)
{
std::string _fileName = "Data/" + std::string(Languages[i]) + "/locale-" + std::string(Languages[i]) + ".MPQ";
@@ -63,34 +58,20 @@ void MPQManager::InitializeDBC()
if (file)
{
if (BaseLocale == -1)
- BaseLocale = i;
-
- // Load the base locale file
- MPQArchive* arch = new MPQArchive(_fileName.c_str());
- LocaleFiles[i].push_front(arch);
-
- Archives.push_front(arch); // For lookup in GetFile
-
- // Load the locale patches
- for (uint32 j = 0; j < sizeof(LocalePatchFiles) / sizeof(char*); ++j)
{
- char patchName[100];
- sprintf(patchName, LocalePatchFiles[j], Languages[i], Languages[i]);
- FILE* patch = fopen(patchName, "rb");
- if (file)
- {
- MPQArchive* archP = new MPQArchive(patchName);
- LocaleFiles[i].push_front(archP);
- Archives.push_front(archP); // For lookup in GetFile
- fclose(patch);
- }
+ BaseLocale = i;
+ _baseLocale = new MPQArchive(_fileName.c_str());
+ fileName = _fileName;
+ LocaleFiles[i] = _baseLocale;
}
+ else
+ LocaleFiles[i] = new MPQArchive(_fileName.c_str());
AvailableLocales.insert(i);
printf("Detected locale: %s\n", Languages[i]);
}
}
-
+ Archives.push_front(_baseLocale);
if (BaseLocale == -1)
{
printf("No locale data detected. Please make sure that the executable is in the same folder as your WoW installation.\n");
@@ -100,7 +81,7 @@ void MPQManager::InitializeDBC()
printf("Using default locale: %s\n", Languages[BaseLocale]);
}
-Stream* MPQManager::GetFile(const std::string& path )
+FILE* MPQManager::GetFile(const std::string& path )
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL);
MPQFile file(path.c_str());
@@ -109,54 +90,13 @@ Stream* MPQManager::GetFile(const std::string& path )
return file.GetFileStream();
}
-DBC const* MPQManager::GetDBC(const std::string& name )
+DBC* MPQManager::GetDBC(const std::string& name )
{
- std::map<std::string, DBC*>::const_iterator itr = LoadedDBCs.find(name);
- if (itr != LoadedDBCs.end())
- return itr->second;
-
std::string path = "DBFilesClient\\" + name + ".dbc";
- DBC* dbc = new DBC(GetFile(path));
-
- LoadedDBCs[name] = dbc;
-
- return dbc;
+ return new DBC(GetFile(path));
}
-Stream* MPQManager::GetFileFromLocale( const std::string& path, uint32 locale )
-{
- ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL);
- std::deque<MPQArchive*> files = LocaleFiles[locale];
- Stream* ret = NULL;
- for (std::deque<MPQArchive*>::iterator itr = files.begin(); itr != files.end(); ++itr)
- {
- mpq_archive* mpq_a = (*itr)->mpq_a;
-
- uint32_t filenum;
- if(libmpq__file_number(mpq_a, path.c_str(), &filenum))
- continue;
- libmpq__off_t transferred;
- libmpq__off_t size = 0;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
-
- // HACK: in patch.mpq some files don't want to open and give 1 for filesize
- if (size <= 1)
- continue;
-
- char* buffer = new char[size];
-
- //libmpq_file_getdata
- libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
-
- ret = new Stream(buffer, size);
-
- delete[] buffer;
- break;
- }
- return ret;
-}
-
-Stream* MPQManager::GetFileFrom(const std::string& path, MPQArchive* file )
+FILE* MPQManager::GetFileFrom(const std::string& path, MPQArchive* file )
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL);
mpq_archive* mpq_a = file->mpq_a;
@@ -179,7 +119,14 @@ Stream* MPQManager::GetFileFrom(const std::string& path, MPQArchive* file )
libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
// Pack the return into a FILE stream
- Stream* ret = new Stream((char*)buffer, size);
+ FILE* ret = tmpfile();
+ if (!ret)
+ {
+ printf("Could not create temporary file. Please run as Administrator or root\n");
+ exit(1);
+ }
+ fwrite(buffer, sizeof(uint8), size, ret);
+ fseek(ret, 0, SEEK_SET);
delete[] buffer;
return ret;
}
diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h
index 43aba352dd3..588052bb844 100644
--- a/src/tools/mesh_extractor/MPQManager.h
+++ b/src/tools/mesh_extractor/MPQManager.h
@@ -19,7 +19,6 @@
#define MPQ_MANAGER_H
#include "MPQ.h"
-#include "Stream.h"
#include <ace/Synch.h>
#include <set>
#include <map>
@@ -32,26 +31,22 @@ public:
~MPQManager() {}
void Initialize();
- Stream* GetFile(const std::string& path);
- Stream* GetFileFrom(const std::string& path, MPQArchive* file);
- Stream* GetFileFromLocale(const std::string& path, uint32 locale);
-
- DBC const* GetDBC(const std::string& name);
+ FILE* GetFile(const std::string& path);
+ FILE* GetFileFrom(const std::string& path, MPQArchive* file);
+ DBC* GetDBC(const std::string& name);
std::vector<std::string> GetAllFiles(std::string extension);
std::deque<MPQArchive*> Archives;
int32 BaseLocale;
std::set<uint32> AvailableLocales;
- std::map<uint32, std::deque<MPQArchive*> > LocaleFiles;
+ std::map<uint32, MPQArchive*> LocaleFiles;
static char const* Files[];
- static char const* LocalePatchFiles[];
static char const* Languages[];
protected:
void InitializeDBC();
private:
ACE_Thread_Mutex mutex;
- std::map<std::string, DBC*> LoadedDBCs;
};
extern MPQManager* MPQHandler;
diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp
index 3a9738c92b1..76280dcc973 100644
--- a/src/tools/mesh_extractor/MapChunk.cpp
+++ b/src/tools/mesh_extractor/MapChunk.cpp
@@ -21,9 +21,9 @@
MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk)
{
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
Header.Read(stream);
- stream->Seek(chunk->Offset, SEEK_SET);
+ fseek(stream, chunk->Offset, SEEK_SET);
Index = Header.IndexX + Header.IndexY * 16;
GenerateVertices(stream);
}
@@ -47,12 +47,12 @@ void MapChunk::GenerateTriangles()
Constants::TriangleType triangleType = Constants::TRIANGLE_TYPE_TERRAIN;
if (Adt->_LiquidHandler && !Adt->_LiquidHandler->MCNKData.empty())
{
- MCNKLiquidData* data = Adt->_LiquidHandler->MCNKData[Index];
+ MCNKLiquidData& data = Adt->_LiquidHandler->MCNKData[Index];
float maxHeight = std::max(
std::max(
std::max(std::max(Vertices[topLeft].z, Vertices[topRight].z), Vertices[bottomLeft].z),
Vertices[bottomRight].z), Vertices[center].z);
- if (data->IsWater(x, y, maxHeight))
+ if (data.IsWater(x, y, maxHeight))
triangleType = Constants::TRIANGLE_TYPE_WATER;
}
@@ -64,9 +64,9 @@ void MapChunk::GenerateTriangles()
}
}
-void MapChunk::GenerateVertices(Stream* stream)
+void MapChunk::GenerateVertices( FILE* stream )
{
- stream->Seek(Header.OffsetMCVT, SEEK_CUR);
+ fseek(stream, Header.OffsetMCVT, SEEK_CUR);
Vertices.reserve(125);
for (int j = 0; j < 17; j++)
@@ -74,7 +74,9 @@ void MapChunk::GenerateVertices(Stream* stream)
int values = j % 2 ? 8 : 9;
for (int i = 0; i < values; i++)
{
- float tmp = stream->Read<float>();
+ float tmp;
+ if (fread(&tmp, sizeof(float), 1, stream) != 1)
+ printf("MapChunk::GenerateVertices: Failed to read some data expected 1, read 0\n");
Vector3 vert(Header.Position.x - (j * (Constants::UnitSize * 0.5f)), Header.Position.y - (i * Constants::UnitSize), Header.Position.z + tmp);
if (values == 8)
vert.y -= Constants::UnitSize * 0.5f;
@@ -82,7 +84,7 @@ void MapChunk::GenerateVertices(Stream* stream)
}
}
// Restore stream position.
- stream->Seek(Source->Offset, SEEK_SET);
+ fseek(stream, Source->Offset, SEEK_SET);
}
bool MapChunk::HasHole( uint32 map, int x, int y )
diff --git a/src/tools/mesh_extractor/MapChunk.h b/src/tools/mesh_extractor/MapChunk.h
index a32a6ce20a7..97adc790e94 100644
--- a/src/tools/mesh_extractor/MapChunk.h
+++ b/src/tools/mesh_extractor/MapChunk.h
@@ -29,7 +29,7 @@ public:
MapChunk(ADT* _adt, Chunk* chunk);
void GenerateTriangles();
- void GenerateVertices(Stream* stream);
+ void GenerateVertices(FILE* stream);
static bool HasHole(uint32 map, int x, int y);
ADT* Adt;
Chunk* Source;
diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp
index 00121509a8a..df1393f7e6b 100644
--- a/src/tools/mesh_extractor/MeshExtractor.cpp
+++ b/src/tools/mesh_extractor/MeshExtractor.cpp
@@ -34,41 +34,16 @@
MPQManager* MPQHandler;
CacheClass* Cache;
-bool IgnoreMap(uint32 id)
-{
- switch (id)
- {
- case 13: // test.wdt
- case 25: // ScottTest.wdt
- case 29: // Test.wdt
- case 42: // Colin.wdt
- case 169: // EmeraldDream.wdt (unused, and very large)
- case 451: // development.wdt
- case 573: // ExteriorTest.wdt
- case 597: // CraigTest.wdt
- case 605: // development_nonweighted.wdt
- case 606: // QA_DVD.wdt
- return true;
- default:
- break;
- }
-
- return false;
-}
-
void ExtractMMaps(std::set<uint32>& mapIds, uint32 threads)
{
- std::string basePath = "mmaps/";
- Utils::CreateDir(basePath);
-
- DBC const* dbc = MPQHandler->GetDBC("Map");
- printf("Map.dbc contains " SIZEFMTD " rows.\n", dbc->Records.size());
- for (std::vector<Record*>::const_iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr)
+ DBC* dbc = MPQHandler->GetDBC("Map");
+ printf("Map.dbc contains %u rows.\n", dbc->Records.size());
+ for (std::vector<Record*>::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr)
{
uint32 mapId = (*itr)->Values[0];
- // Skip this map if a list of specific maps was provided and this one is not contained in it, or if the map is in the ignore list.
- if ((!mapIds.empty() && mapIds.find(mapId) == mapIds.end()) || IgnoreMap(mapId))
+ // Skip this map if a list of specific maps was provided and this one is not contained in it.
+ if (!mapIds.empty() && mapIds.find(mapId) == mapIds.end())
{
if (Constants::Debug)
printf("Map %u will not be built.\n", mapId);
@@ -100,12 +75,9 @@ void ExtractDBCs()
// Populate list of DBC files
// We get the DBC names by going over the (guaranteed to exist) default locale files
// Then we look in other locale files in case that they are available.
- for (std::map<uint32, std::deque<MPQArchive*> >::iterator itr = MPQHandler->LocaleFiles.begin(); itr != MPQHandler->LocaleFiles.end(); ++itr)
- for (std::deque<MPQArchive*>::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
- for (std::vector<std::string>::iterator itr3 = (*itr2)->Files.begin(); itr3 != (*itr2)->Files.end(); ++itr3)
- if (itr3->rfind(".dbc") == itr3->length() - extLen) // Check if the extension is ".dbc"
- if (DBCFiles.find(*itr3) == DBCFiles.end())
- DBCFiles.insert(*itr3);
+ for (std::vector<std::string>::iterator itr = MPQHandler->LocaleFiles[MPQHandler->BaseLocale]->Files.begin(); itr != MPQHandler->LocaleFiles[MPQHandler->BaseLocale]->Files.end(); ++itr)
+ if (itr->rfind(".dbc") == itr->length() - extLen) // Check if the extension is ".dbc"
+ DBCFiles.insert(*itr);
const size_t folderLen = strlen("DBFilesClient\\");
// Iterate over all available locales
@@ -121,10 +93,10 @@ void ExtractDBCs()
std::string component = "component.wow-" + std::string(MPQManager::Languages[*itr]) + ".txt";
// Extract the component file
- Utils::SaveToDisk(MPQHandler->GetFileFromLocale(component, *itr), path + component);
+ Utils::SaveToDisk(MPQHandler->GetFileFrom(component, MPQHandler->LocaleFiles[*itr]), path + component);
// Extract the DBC files for the given locale
for (std::set<std::string>::iterator itr2 = DBCFiles.begin(); itr2 != DBCFiles.end(); ++itr2)
- Utils::SaveToDisk(MPQHandler->GetFileFromLocale(*itr2, *itr), path + (itr2->c_str() + folderLen));
+ Utils::SaveToDisk(MPQHandler->GetFileFrom(*itr2, MPQHandler->LocaleFiles[*itr]), path + (itr2->c_str() + folderLen));
}
printf("DBC extraction finished!\n");
}
@@ -146,8 +118,8 @@ void ExtractGameobjectModels()
return;
}
- DBC const* dbc = MPQHandler->GetDBC("GameObjectDisplayInfo");
- for (std::vector<Record*>::const_iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr)
+ DBC* dbc = MPQHandler->GetDBC("GameObjectDisplayInfo");
+ for (std::vector<Record*>::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr)
{
std::string path = (*itr)->GetString(1);
std::string fileName = Utils::GetPlainName(path.c_str());
@@ -253,9 +225,8 @@ void ExtractGameobjectModels()
fwrite(&model.Header.WmoId, sizeof(uint32), 1, output);
const char grp[] = { 'G' , 'R' , 'P', ' ' };
- for (std::vector<WorldModelGroup*>::iterator groupItr = model.Groups.begin(); groupItr != model.Groups.end(); ++groupItr)
+ for (std::vector<WorldModelGroup>::iterator itr2 = model.Groups.begin(); itr2 != model.Groups.end(); ++itr2)
{
- WorldModelGroup* itr2 = *groupItr;
const WMOGroupHeader& header = itr2->Header;
fwrite(&header.Flags, sizeof(uint32), 1, output);
fwrite(&header.WmoId, sizeof(uint32), 1, output);
@@ -392,6 +363,7 @@ void LoadTile(dtNavMesh*& navMesh, const char* tile)
int main(int argc, char* argv[])
{
+ _setmaxstdio(2048);
uint32 threads = 4, extractFlags = 0;
std::set<uint32> mapIds;
@@ -423,8 +395,13 @@ int main(int argc, char* argv[])
if (extractFlags & Constants::EXTRACT_FLAG_TEST)
{
+<<<<<<< .mine
float start[] = { -45.4745407f, -29.5000954f, -21.4456501f };
float end[] = { -107.686218f, -32.3544769f, -30.3459435f };
+=======
+ float start[] = { 16226.200195f, 16257.000000f, 13.202200f };
+ float end[] = { 16245.725586f, 16382.465820f, 47.384956f };
+>>>>>>> .theirs
//
float m_spos[3];
@@ -453,7 +430,7 @@ int main(int argc, char* argv[])
dtPolyRef m_startRef;
dtPolyRef m_endRef;
- FILE* mmap = fopen("mmaps/631.mmap", "rb");
+ FILE* mmap = fopen("mmaps/001.mmap", "rb");
dtNavMeshParams params;
int count = fread(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
@@ -472,7 +449,7 @@ int main(int argc, char* argv[])
for (int j = 0; j <= 32; ++j)
{
char buff[100];
- sprintf(buff, "mmaps/631%02i%02i.mmtile", i, j);
+ sprintf(buff, "mmaps/001%02i%02i.mmtile", i, j);
LoadTile(navMesh, buff);
}
}
@@ -490,6 +467,7 @@ int main(int argc, char* argv[])
return 0;
}
+<<<<<<< .mine
dtStatus status;
status = navMeshQuery->initSlicedFindPath(m_startRef, m_endRef, m_spos, m_epos, &m_filter);
while (status != DT_SUCCESS)
@@ -500,12 +478,46 @@ int main(int argc, char* argv[])
int resultHopCount = 0;
float* straightPath = new float[2048 * 3];
unsigned char* pathFlags = new unsigned char[2048];
+=======
+ int hops;
+
+
+
+
+
+
+
+
+
+>>>>>>> .theirs
dtPolyRef* hopBuffer = new dtPolyRef[8192];
+<<<<<<< .mine
navMeshQuery->finalizeSlicedFindPath(pathRefs, &pcount, 200);
+
+
+
+
+
+
+=======
+ dtStatus status = navMeshQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, &m_filter, hopBuffer, &hops, 8192);
+
+ int resultHopCount;
+ float* straightPath = new float[2048*3];
+ unsigned char* pathFlags = new unsigned char[2048];
+ dtPolyRef* pathRefs = new dtPolyRef[2048];
+
+ status = navMeshQuery->findStraightPath(m_spos, m_epos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048);
+>>>>>>> .theirs
std::vector<Vector3> FinalPath;
+<<<<<<< .mine
for (int i = 0; i < pcount; ++i)
+=======
+ FinalPath.reserve(resultHopCount);
+ for (uint32 i = 0; i < resultHopCount; ++i)
+>>>>>>> .theirs
{
navMeshQuery->findStraightPath(m_spos, m_epos, &pathRefs[i], 1,
straightPath, pathFlags,
@@ -514,14 +526,6 @@ int main(int argc, char* argv[])
FinalPath.push_back(finalV);
printf("Point %f %f %f\n", finalV.x, finalV.y, finalV.z);
}
- /*
- FinalPath.reserve(resultHopCount);
- for (int i = 0; i < resultHopCount; ++i)
- {
- Vector3 finalV = Utils::ToWoWCoords(Vector3(straightPath[i * 3 + 0], straightPath[i * 3 + 1], straightPath[i * 3 + 2]));
- FinalPath.push_back(finalV);
- printf("Point %f %f %f\n", finalV.x, finalV.y, finalV.z);
- }*/
}
return 0;
diff --git a/src/tools/mesh_extractor/Model.cpp b/src/tools/mesh_extractor/Model.cpp
index 6e735ec7440..48c60d9d644 100644
--- a/src/tools/mesh_extractor/Model.cpp
+++ b/src/tools/mesh_extractor/Model.cpp
@@ -19,15 +19,15 @@
#include "MPQManager.h"
#include "Utils.h"
-Model::Model(std::string path) : IsCollidable(false), IsBad(false)
+Model::Model( std::string path ) : IsCollidable(false), IsBad(false)
{
- _Stream = MPQHandler->GetFile(Utils::FixModelPath(path));
- if (!_Stream)
+ Stream = MPQHandler->GetFile(Utils::FixModelPath(path));
+ if (!Stream)
{
IsBad = true;
return;
}
- Header.Read(_Stream);
+ Header.Read(Stream);
if (Header.OffsetBoundingNormals > 0 && Header.OffsetBoundingVertices > 0 &&
Header.OffsetBoundingTriangles > 0 && Header.BoundingRadius > 0.0f)
{
@@ -40,17 +40,17 @@ Model::Model(std::string path) : IsCollidable(false), IsBad(false)
Model::~Model()
{
- if (_Stream)
- delete _Stream;
+ if (Stream)
+ fclose(Stream);
}
void Model::ReadVertices()
{
- _Stream->Seek(Header.OffsetBoundingVertices, SEEK_SET);
+ fseek(Stream, Header.OffsetBoundingVertices, SEEK_SET);
Vertices.reserve(Header.CountBoundingVertices);
for (uint32 i = 0; i < Header.CountBoundingVertices; ++i)
{
- Vertices.push_back(Vector3::Read(_Stream));
+ Vertices.push_back(Vector3::Read(Stream));
if (Constants::ToWoWCoords)
Vertices[i] = Utils::ToWoWCoords(Vertices[i]);
}
@@ -58,24 +58,27 @@ void Model::ReadVertices()
void Model::ReadBoundingTriangles()
{
- _Stream->Seek(Header.OffsetBoundingTriangles, SEEK_SET);
+ fseek(Stream, Header.OffsetBoundingTriangles, SEEK_SET);
Triangles.reserve(Header.CountBoundingTriangles / 3);
for (uint32 i = 0; i < Header.CountBoundingTriangles / 3; i++)
{
Triangle<uint16> tri;
tri.Type = Constants::TRIANGLE_TYPE_DOODAD;
- tri.V0 = _Stream->Read<uint16>();
- tri.V1 = _Stream->Read<uint16>();
- tri.V2 = _Stream->Read<uint16>();
+ int count = 0;
+ count += fread(&tri.V0, sizeof(uint16), 1, Stream);
+ count += fread(&tri.V1, sizeof(uint16), 1, Stream);
+ count += fread(&tri.V2, sizeof(uint16), 1, Stream);
+ if (count != 3)
+ printf("Model::ReadBoundingTriangles: Error reading data, expected 3, read %d\n", count);
Triangles.push_back(tri);
}
}
void Model::ReadBoundingNormals()
{
- _Stream->Seek(Header.OffsetBoundingNormals, SEEK_SET);
+ fseek(Stream, Header.OffsetBoundingNormals, SEEK_SET);
Normals.reserve(Header.CountBoundingNormals);
for (uint32 i = 0; i < Header.CountBoundingNormals; i++)
- Normals.push_back(Vector3::Read(_Stream));
+ Normals.push_back(Vector3::Read(Stream));
}
diff --git a/src/tools/mesh_extractor/Model.h b/src/tools/mesh_extractor/Model.h
index 1169421cdf1..8f43b2963ea 100644
--- a/src/tools/mesh_extractor/Model.h
+++ b/src/tools/mesh_extractor/Model.h
@@ -19,7 +19,6 @@
#define MODEL_H
#include <vector>
#include "Utils.h"
-#include "Stream.h"
class Model
{
@@ -35,7 +34,7 @@ public:
std::vector<Vector3> Normals;
std::vector<Triangle<uint16> > Triangles;
bool IsCollidable;
- Stream* _Stream;
+ FILE* Stream;
bool IsBad;
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/ObjectDataHandler.h b/src/tools/mesh_extractor/ObjectDataHandler.h
index 423d8704a00..dc57301563a 100644
--- a/src/tools/mesh_extractor/ObjectDataHandler.h
+++ b/src/tools/mesh_extractor/ObjectDataHandler.h
@@ -24,7 +24,6 @@ class ObjectDataHandler
{
public:
ObjectDataHandler(ADT* _adt) : Source(_adt) {}
- virtual ~ObjectDataHandler() {}
void ProcessMapChunk(MapChunk* chunk);
virtual void ProcessInternal(MapChunk* data) = 0;
diff --git a/src/tools/mesh_extractor/Stream.cpp b/src/tools/mesh_extractor/Stream.cpp
deleted file mode 100644
index f775d97d114..00000000000
--- a/src/tools/mesh_extractor/Stream.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "Stream.h"
-#include <iostream>
-
-Stream::Stream(char* buffer, uint32 size) : _size(size), _position(0)
-{
- _buffer = new char[size];
- memcpy(_buffer, buffer, size); // Initialize the buffer
-}
-
-Stream::~Stream()
-{
- delete[] _buffer;
-}
-
-char* Stream::Read(uint32 size)
-{
- char* buff = new char[size];
- memcpy(buff, &_buffer[_position], size);
- _position += size;
- return buff;
-}
-
-void Stream::Seek(uint32 position, uint32 type)
-{
- switch (type)
- {
- case SEEK_SET:
- _position = position;
- break;
- case SEEK_CUR:
- _position += position;
- break;
- }
-}
-
-std::string Stream::ReadString()
-{
- std::string str;
- while (true)
- {
- char b = Read<char>();
- if (b == 0)
- break;
- str.push_back(b);
- }
- return str;
-} \ No newline at end of file
diff --git a/src/tools/mesh_extractor/Stream.h b/src/tools/mesh_extractor/Stream.h
deleted file mode 100644
index 647ff9d5357..00000000000
--- a/src/tools/mesh_extractor/Stream.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef STREAM_H
-#define STREAM_H
-
-#include "Define.h"
-#include <iostream>
-
-class Stream
-{
-public:
- Stream(char* buffer, uint32 size);
- ~Stream();
-
- template<typename T>
- T Read()
- {
- T ret = *((T*)(&_buffer[_position]));
- _position += sizeof(T);
- return ret;
- }
-
- template<typename T>
- void Read(T* dest, uint32 size)
- {
- memcpy(dest, &_buffer[_position], size);
- _position += size;
- }
-
- template<typename T>
- void Skip()
- {
- _position += sizeof(T);
- }
-
- char* Read(uint32 size);
- std::string ReadString();
-
- void Reset()
- {
- _position = 0;
- }
-
- void Seek(uint32 position, uint32 type);
-
- uint32 GetSize() const
- {
- return _size;
- }
-
- uint32 GetPos() const
- {
- return _position;
- }
-
-private:
- char* _buffer;
- uint32 _size;
- uint32 _position;
-};
-#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp
index 0ec35c5a04f..a9774abe6ce 100644
--- a/src/tools/mesh_extractor/TileBuilder.cpp
+++ b/src/tools/mesh_extractor/TileBuilder.cpp
@@ -43,8 +43,8 @@ TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x,
Config.detailSampleDist = 3.0f;
Config.detailSampleMaxError = 1.25f;
Config.walkableClimb = 1.0f / Config.ch;
- Config.walkableHeight = 2.1;
- Config.walkableRadius = 0.6f;
+ Config.walkableHeight = 2.1 / Config.ch;
+ Config.walkableRadius = 0.6f / Config.cs;
Config.maxEdgeLen = Config.walkableRadius * 8;
Config.borderSize = Config.walkableRadius + 8;
Config.tileSize = 1800;
@@ -59,19 +59,19 @@ TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x,
InstanceConfig.mergeRegionArea = 100;
InstanceConfig.walkableSlopeAngle = 50.0f;
InstanceConfig.detailSampleDist = 3.0f;
- InstanceConfig.detailSampleMaxError = 1.25f;
+ InstanceConfig.detailSampleMaxError = 1.5f;
InstanceConfig.walkableClimb = 1.0f / InstanceConfig.ch;
- InstanceConfig.walkableHeight = 2.1f;
- InstanceConfig.walkableRadius = 0.6f;
+ InstanceConfig.walkableHeight = 2.1f / InstanceConfig.ch;
+ InstanceConfig.walkableRadius = 0.6f / InstanceConfig.cs;
InstanceConfig.maxEdgeLen = 8 * InstanceConfig.walkableRadius;
InstanceConfig.maxVertsPerPoly = 6;
- InstanceConfig.maxSimplificationError = 1.3f;
+ InstanceConfig.maxSimplificationError = 1.25f;
InstanceConfig.borderSize = 0;
Context = new rcContext;
}
-void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshParams& /*navMeshParams*/ ) const
+void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshParams& /*navMeshParams*/ )
{
bmin = new float[3];
bmax = new float[3];
@@ -81,7 +81,7 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshPara
bmax[2] = Constants::Origin[2] /*navMeshParams.orig[2]*/ + (Constants::TileSize * (Y + 1));
}
-void TileBuilder::AddGeometry(WorldModelRoot const* root, const WorldModelDefinition& def)
+void TileBuilder::AddGeometry(WorldModelRoot* root, const WorldModelDefinition& def)
{
_Geometry = new Geometry();
_Geometry->Transform = true;
@@ -91,7 +91,7 @@ void TileBuilder::AddGeometry(WorldModelRoot const* root, const WorldModelDefini
OutputDebugVertices();
}
-uint8* TileBuilder::BuildInstance( dtNavMeshParams& /*navMeshParams*/ )
+uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams )
{
float* bmin = NULL, *bmax = NULL;
@@ -183,11 +183,11 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& /*navMeshParams*/ )
rcFreeHeightField(hf);
rcFreeCompactHeightfield(chf);
rcFreeContourSet(contours);
- delete[] vertices;
- delete[] triangles;
- delete[] areas;
- delete[] bmin;
- delete[] bmax;
+ delete vertices;
+ delete triangles;
+ delete areas;
+ delete bmin;
+ delete bmax;
if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount)
{
@@ -226,7 +226,7 @@ uint8* TileBuilder::BuildTiled(dtNavMeshParams& navMeshParams)
adt->Read();
_Geometry->AddAdt(adt);
delete adt;
-
+
if (_Geometry->Vertices.empty() && _Geometry->Triangles.empty())
return NULL;
@@ -246,7 +246,7 @@ uint8* TileBuilder::BuildTiled(dtNavMeshParams& navMeshParams)
ADT* _adt = new ADT(Utils::GetAdtPath(World, tx, ty), tx, ty);
// If this condition is met, it means that this WDT does not contain the ADT
- if (!_adt->Data->_Stream)
+ if (!_adt->Data->Stream)
{
delete _adt;
continue;
@@ -352,11 +352,12 @@ uint8* TileBuilder::BuildTiled(dtNavMeshParams& navMeshParams)
rcFreeHeightField(hf);
rcFreeCompactHeightfield(chf);
rcFreeContourSet(contours);
- delete[] vertices;
- delete[] triangles;
- delete[] areas;
- delete[] bmin;
- delete[] bmax;
+
+ delete vertices;
+ delete triangles;
+ delete areas;
+ delete bmin;
+ delete bmax;
if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount)
{
@@ -387,7 +388,7 @@ uint8* TileBuilder::BuildTiled(dtNavMeshParams& navMeshParams)
return NULL;
}
-void TileBuilder::OutputDebugVertices() const
+void TileBuilder::OutputDebugVertices()
{
if (Constants::Debug)
{
diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h
index ba8b9539649..b88966190b0 100644
--- a/src/tools/mesh_extractor/TileBuilder.h
+++ b/src/tools/mesh_extractor/TileBuilder.h
@@ -32,11 +32,11 @@ public:
TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId);
~TileBuilder();
- void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams) const;
+ void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams);
uint8* BuildTiled(dtNavMeshParams& navMeshParams);
uint8* BuildInstance(dtNavMeshParams& navMeshParams);
- void AddGeometry(WorldModelRoot const* root, const WorldModelDefinition& def);
- void OutputDebugVertices() const;
+ void AddGeometry(WorldModelRoot* root, const WorldModelDefinition& def);
+ void OutputDebugVertices();
std::string World;
int X;
int Y;
diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp
index 42df1107bc0..704acf967ee 100644
--- a/src/tools/mesh_extractor/Utils.cpp
+++ b/src/tools/mesh_extractor/Utils.cpp
@@ -18,7 +18,6 @@
#include "Utils.h"
#include "WorldModelHandler.h"
#include "Constants.h"
-#include "Stream.h"
#include <cstring>
#include "G3D/Matrix4.h"
#include "G3D/Quat.h"
@@ -54,9 +53,40 @@ void Utils::CreateDir( const std::string& Path )
#endif
}
-void Utils::Reverse(std::string& str)
+void Utils::Reverse(char word[])
{
- std::reverse(str.begin(), str.end());
+ int len = strlen(word);
+ for (int i = 0;i < len / 2; i++)
+ {
+ word[i] ^= word[len-i-1];
+ word[len-i-1] ^= word[i];
+ word[i] ^= word[len-i-1];
+ }
+}
+
+std::string Utils::ReadString( FILE* file )
+{
+ std::string ret;
+ while (true)
+ {
+ char b;
+ if (fread(&b, sizeof(char), 1, file) != 1 || b == 0)
+ break;
+ ret.push_back(b);
+ }
+ return ret;
+}
+
+uint32 Utils::Size( FILE* file )
+{
+ // store the old position
+ uint32 offset = ftell(file);
+ // Get file size
+ fseek(file, 0, SEEK_END);
+ uint32 size = ftell(file);
+ // reset back to the old position
+ fseek(file, offset, SEEK_SET);
+ return size;
}
Vector3 Utils::ToRecast(const Vector3& val )
@@ -74,7 +104,7 @@ std::string Utils::FixModelPath(const std::string& path )
return Utils::GetPathBase(path) + ".M2";
}
-Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3 vec, bool translate)
+Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec, bool translate)
{
// Sources of information:
/// http://www.pxr.dk/wowdev/wiki/index.php?title=ADT/v18&oldid=3715
@@ -92,7 +122,7 @@ Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3 vec, bool t
return ret;
}
-Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& /*root*/, const Vector3& vec, bool translate)
+Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec, bool translate )
{
G3D::Quat quat = G3D::Quat(-inst.QuatY, inst.QuatZ, -inst.QuatX, inst.QuatW);
@@ -123,9 +153,12 @@ std::string Utils::GetPathBase(const std::string& path )
return path;
}
-Vector3 Vector3::Read(Stream* file)
+Vector3 Vector3::Read( FILE* file )
{
- return file->Read<Vector3>();
+ Vector3 ret;
+ if (fread(&ret, sizeof(Vector3), 1, file) != 1)
+ printf("Vector3::Read: Failed to read some data expected 1, read 0\n");
+ return ret;
}
Vector3 Utils::GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int x, int y, bool translate)
@@ -151,36 +184,41 @@ std::string Utils::Replace( std::string str, const std::string& oldStr, const st
return str;
}
-void Utils::SaveToDisk(Stream* stream, const std::string& path)
+void Utils::SaveToDisk( FILE* stream, const std::string& path )
{
FILE* disk = fopen(path.c_str(), "wb");
if (!disk)
{
printf("SaveToDisk: Could not save file %s to disk, please verify that you have write permissions on that directory\n", path.c_str());
- delete stream;
+ fclose(stream);
return;
}
- uint32 size = stream->GetSize();
- stream->Reset(); // Reset the stream just in case
-
+ uint32 size = Utils::Size(stream);
+ uint8* data = new uint8[size];
// Read the data to an array
- char* data = stream->Read(size);
-
+ size_t read = fread(data, size, 1, stream);
+ if (read != 1)
+ {
+ printf("SaveToDisk: Error reading from Stream while trying to save file %s to disk.\n", path.c_str());
+ fclose(disk);
+ fclose(stream);
+ return;
+ }
+
// And write it in the file
size_t wrote = fwrite(data, size, 1, disk);
if (wrote != 1)
{
printf("SaveToDisk: Error writing to the file while trying to save %s to disk.\n", path.c_str());
- delete[] data;
- delete stream;
+ fclose(stream);
fclose(disk);
return;
}
// Close the filestream
fclose(disk);
- delete stream;
+ fclose(stream);
// Free the used memory
delete[] data;
@@ -201,193 +239,249 @@ std::string Utils::GetExtension( std::string path )
return extension;
}
-void MapChunkHeader::Read(Stream* stream)
-{
- Flags = stream->Read<uint32>();
- IndexX = stream->Read<uint32>();
- IndexY = stream->Read<uint32>();
- Layers = stream->Read<uint32>();
- DoodadRefs = stream->Read<uint32>();
- OffsetMCVT = stream->Read<uint32>();
- OffsetMCNR = stream->Read<uint32>();
- OffsetMCLY = stream->Read<uint32>();
- OffsetMCRF = stream->Read<uint32>();
- OffsetMCAL = stream->Read<uint32>();
- SizeMCAL = stream->Read<uint32>();
- OffsetMCSH = stream->Read<uint32>();
- SizeMCSH = stream->Read<uint32>();
- AreaId = stream->Read<uint32>();
- MapObjectRefs = stream->Read<uint32>();
- Holes = stream->Read<uint32>();
- stream->Read(LowQualityTextureMap, sizeof(uint32) * 4);
- PredTex = stream->Read<uint32>();
- NumberEffectDoodad = stream->Read<uint32>();
- OffsetMCSE = stream->Read<uint32>();
- SoundEmitters = stream->Read<uint32>();
- OffsetMCLQ = stream->Read<uint32>();
- SizeMCLQ = stream->Read<uint32>();
+void MapChunkHeader::Read(FILE* stream)
+{
+ int count = 0;
+
+ count += fread(&Flags, sizeof(uint32), 1, stream);
+ count += fread(&IndexX, sizeof(uint32), 1, stream);
+ count += fread(&IndexY, sizeof(uint32), 1, stream);
+ count += fread(&Layers, sizeof(uint32), 1, stream);
+ count += fread(&DoodadRefs, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCVT, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCNR, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCLY, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCRF, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCAL, sizeof(uint32), 1, stream);
+ count += fread(&SizeMCAL, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCSH, sizeof(uint32), 1, stream);
+ count += fread(&SizeMCSH, sizeof(uint32), 1, stream);
+ count += fread(&AreaId, sizeof(uint32), 1, stream);
+ count += fread(&MapObjectRefs, sizeof(uint32), 1, stream);
+ count += fread(&Holes, sizeof(uint32), 1, stream);
+ LowQualityTextureMap = new uint32[4];
+ count += fread(LowQualityTextureMap, sizeof(uint32), 4, stream);
+ count += fread(&PredTex, sizeof(uint32), 1, stream);
+ count += fread(&NumberEffectDoodad, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCSE, sizeof(uint32), 1, stream);
+ count += fread(&SoundEmitters, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCLQ, sizeof(uint32), 1, stream);
+ count += fread(&SizeMCLQ, sizeof(uint32), 1, stream);
Position = Vector3::Read(stream);
- OffsetMCCV = stream->Read<uint32>();
+ count += fread(&OffsetMCCV, sizeof(uint32), 1, stream);
+
+ if (count != 27)
+ printf("MapChunkHeader::Read: Failed to read some data expected 27, read %d\n", count);
}
-void MHDR::Read(Stream* stream)
+void MHDR::Read(FILE* stream)
{
- Flags = stream->Read<uint32>();
- OffsetMCIN = stream->Read<uint32>();
- OffsetMTEX = stream->Read<uint32>();
- OffsetMMDX = stream->Read<uint32>();
- OffsetMMID = stream->Read<uint32>();
- OffsetMWMO = stream->Read<uint32>();
- OffsetMWID = stream->Read<uint32>();
- OffsetMDDF = stream->Read<uint32>();
- OffsetMODF = stream->Read<uint32>();
- OffsetMFBO = stream->Read<uint32>();
- OffsetMH2O = stream->Read<uint32>();
- OffsetMTFX = stream->Read<uint32>();
+ int count = 0;
+
+ count += fread(&Flags, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMCIN, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMTEX, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMMDX, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMMID, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMWMO, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMWID, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMDDF, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMODF, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMFBO, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMH2O, sizeof(uint32), 1, stream);
+ count += fread(&OffsetMTFX, sizeof(uint32), 1, stream);
+
+ if (count != 12)
+ printf("MHDR::Read: Failed to read some data expected 12, read %d\n", count);
}
-void ModelHeader::Read(Stream* stream)
+void ModelHeader::Read(FILE* stream)
{
- stream->Read(Magic, 4);
+ int count = 0;
+
+ count += fread(&Magic, sizeof(char), 4, stream);
Magic[4] = '\0'; // null-terminate it.
- Version = stream->Read<uint32>();
- LengthModelName = stream->Read<uint32>();
- OffsetName = stream->Read<uint32>();
- ModelFlags = stream->Read<uint32>();
- CountGlobalSequences = stream->Read<uint32>();
- OffsetGlobalSequences = stream->Read<uint32>();
- CountAnimations = stream->Read<uint32>();
- OffsetAnimations = stream->Read<uint32>();
- CountAnimationLookup = stream->Read<uint32>();
- OffsetAnimationLookup = stream->Read<uint32>();
- CountBones = stream->Read<uint32>();
- OffsetBones = stream->Read<uint32>();
- CountKeyBoneLookup = stream->Read<uint32>();
- OffsetKeyBoneLookup = stream->Read<uint32>();
- CountVertices = stream->Read<uint32>();
- OffsetVertices = stream->Read<uint32>();
- CountViews = stream->Read<uint32>();
- CountColors = stream->Read<uint32>();
- OffsetColors = stream->Read<uint32>();
- CountTextures = stream->Read<uint32>();
- OffsetTextures = stream->Read<uint32>();
- CountTransparency = stream->Read<uint32>();
- OffsetTransparency = stream->Read<uint32>();
- CountUvAnimation = stream->Read<uint32>();
- OffsetUvAnimation = stream->Read<uint32>();
- CountTexReplace = stream->Read<uint32>();
- OffsetTexReplace = stream->Read<uint32>();
- CountRenderFlags = stream->Read<uint32>();
- OffsetRenderFlags = stream->Read<uint32>();
- CountBoneLookup = stream->Read<uint32>();
- OffsetBoneLookup = stream->Read<uint32>();
- CountTexLookup = stream->Read<uint32>();
- OffsetTexLookup = stream->Read<uint32>();
- CountTexUnits = stream->Read<uint32>();
- OffsetTexUnits = stream->Read<uint32>();
- CountTransLookup = stream->Read<uint32>();
- OffsetTransLookup = stream->Read<uint32>();
- CountUvAnimLookup = stream->Read<uint32>();
- OffsetUvAnimLookup = stream->Read<uint32>();
+ count += fread(&Version, sizeof(uint32), 1, stream);
+ count += fread(&LengthModelName, sizeof(uint32), 1, stream);
+ count += fread(&OffsetName, sizeof(uint32), 1, stream);
+ count += fread(&ModelFlags, sizeof(uint32), 1, stream);
+ count += fread(&CountGlobalSequences, sizeof(uint32), 1, stream);
+ count += fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream);
+ count += fread(&CountAnimations, sizeof(uint32), 1, stream);
+ count += fread(&OffsetAnimations, sizeof(uint32), 1, stream);
+ count += fread(&CountAnimationLookup, sizeof(uint32), 1, stream);
+ count += fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream);
+ count += fread(&CountBones, sizeof(uint32), 1, stream);
+ count += fread(&OffsetBones, sizeof(uint32), 1, stream);
+ count += fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream);
+ count += fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream);
+ count += fread(&CountVertices, sizeof(uint32), 1, stream);
+ count += fread(&OffsetVertices, sizeof(uint32), 1, stream);
+ count += fread(&CountViews, sizeof(uint32), 1, stream);
+ count += fread(&CountColors, sizeof(uint32), 1, stream);
+ count += fread(&OffsetColors, sizeof(uint32), 1, stream);
+ count += fread(&CountTextures, sizeof(uint32), 1, stream);
+ count += fread(&OffsetTextures, sizeof(uint32), 1, stream);
+ count += fread(&CountTransparency, sizeof(uint32), 1, stream);
+ count += fread(&OffsetTransparency, sizeof(uint32), 1, stream);
+ count += fread(&CountUvAnimation, sizeof(uint32), 1, stream);
+ count += fread(&OffsetUvAnimation, sizeof(uint32), 1, stream);
+ count += fread(&CountTexReplace, sizeof(uint32), 1, stream);
+ count += fread(&OffsetTexReplace, sizeof(uint32), 1, stream);
+ count += fread(&CountRenderFlags, sizeof(uint32), 1, stream);
+ count += fread(&OffsetRenderFlags, sizeof(uint32), 1, stream);
+ count += fread(&CountBoneLookup, sizeof(uint32), 1, stream);
+ count += fread(&OffsetBoneLookup, sizeof(uint32), 1, stream);
+ count += fread(&CountTexLookup, sizeof(uint32), 1, stream);
+ count += fread(&OffsetTexLookup, sizeof(uint32), 1, stream);
+ count += fread(&CountTexUnits, sizeof(uint32), 1, stream);
+ count += fread(&OffsetTexUnits, sizeof(uint32), 1, stream);
+ count += fread(&CountTransLookup, sizeof(uint32), 1, stream);
+ count += fread(&OffsetTransLookup, sizeof(uint32), 1, stream);
+ count += fread(&CountUvAnimLookup, sizeof(uint32), 1, stream);
+ count += fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream);
VertexBox[0] = Vector3::Read(stream);
VertexBox[1] = Vector3::Read(stream);
- VertexRadius = stream->Read<float>();
+ count += fread(&VertexRadius, sizeof(float), 1, stream);
BoundingBox[0] = Vector3::Read(stream);
BoundingBox[1] = Vector3::Read(stream);
- BoundingRadius = stream->Read<float>();
- CountBoundingTriangles = stream->Read<uint32>();
- OffsetBoundingTriangles = stream->Read<uint32>();
- CountBoundingVertices = stream->Read<uint32>();
- OffsetBoundingVertices = stream->Read<uint32>();
- CountBoundingNormals = stream->Read<uint32>();
- OffsetBoundingNormals = stream->Read<uint32>();
-}
-
-void WorldModelHeader::Read(Stream* stream)
-{
- CountMaterials = stream->Read<uint32>();
- CountGroups = stream->Read<uint32>();
- CountPortals = stream->Read<uint32>();
- CountLights = stream->Read<uint32>();
- CountModels = stream->Read<uint32>();
- CountDoodads = stream->Read<uint32>();
- CountSets = stream->Read<uint32>();
- AmbientColorUnk = stream->Read<uint32>();
- WmoId = stream->Read<uint32>();
- BoundingBox[0] = Vector3::Read(stream);
- BoundingBox[1] = Vector3::Read(stream);
- LiquidTypeRelated = stream->Read<uint32>();
+ count += fread(&BoundingRadius, sizeof(float), 1, stream);
+ count += fread(&CountBoundingTriangles, sizeof(uint32), 1, stream);
+ count += fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream);
+ count += fread(&CountBoundingVertices, sizeof(uint32), 1, stream);
+ count += fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream);
+ count += fread(&CountBoundingNormals, sizeof(uint32), 1, stream);
+ count += fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream);
+
+ if (count != 51)
+ printf("ModelHeader::Read: Failed to read some data expected 51, read %d\n", count);
+
}
-DoodadInstance DoodadInstance::Read(Stream* stream)
+WorldModelHeader WorldModelHeader::Read(FILE* stream)
+{
+ WorldModelHeader ret;
+ int count = 0;
+
+ count += fread(&ret.CountMaterials, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountGroups, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountPortals, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountLights, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountModels, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountDoodads, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountSets, sizeof(uint32), 1, stream);
+ count += fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream);
+ count += fread(&ret.WmoId, sizeof(uint32), 1, stream);
+ ret.BoundingBox[0] = Vector3::Read(stream);
+ ret.BoundingBox[1] = Vector3::Read(stream);
+ count += fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream);
+
+ if (count != 10)
+ printf("WorldModelHeader::Read: Failed to read some data expected 10, read %d\n", count);
+
+ return ret;
+}
+
+DoodadInstance DoodadInstance::Read(FILE* stream)
{
DoodadInstance ret;
+ int count = 0;
- ret.FileOffset = stream->Read<uint32>();
+ count += fread(&ret.FileOffset, sizeof(uint32), 1, stream);
ret.Position = Vector3::Read(stream);
- ret.QuatW = stream->Read<float>();
- ret.QuatX = stream->Read<float>();
- ret.QuatY = stream->Read<float>();
- ret.QuatZ = stream->Read<float>();
- ret.Scale = stream->Read<float>();
- ret.LightColor = stream->Read<uint32>();
+ count += fread(&ret.QuatW, sizeof(float), 1, stream);
+ count += fread(&ret.QuatX, sizeof(float), 1, stream);
+ count += fread(&ret.QuatY, sizeof(float), 1, stream);
+ count += fread(&ret.QuatZ, sizeof(float), 1, stream);
+ count += fread(&ret.Scale, sizeof(float), 1, stream);
+ count += fread(&ret.LightColor, sizeof(uint32), 1, stream);
+
+ if (count != 7)
+ printf("DoodadInstance::Read: Failed to read some data expected 7, read %d\n", count);
+
return ret;
}
-DoodadSet DoodadSet::Read(Stream* stream)
+DoodadSet DoodadSet::Read(FILE* stream)
{
DoodadSet ret;
- char* name = stream->Read(20);
- ret.Name = std::string(name, 20);
- delete[] name;
- ret.FirstInstanceIndex = stream->Read<uint32>();
- ret.CountInstances = stream->Read<uint32>();
- ret.UnknownZero = stream->Read<uint32>();
-
+ char name[21];
+ int count = 0;
+
+ count += fread(&name, sizeof(char), 20, stream);
+ name[20] = '\0';
+ ret.Name = name;
+ count += fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountInstances, sizeof(uint32), 1, stream);
+ count += fread(&ret.UnknownZero, sizeof(uint32), 1, stream);
+
+ if (count != 23)
+ printf("DoodadSet::Read: Failed to read some data expected 23, read %d\n", count);
+
return ret;
}
-void LiquidHeader::Read(Stream* stream)
+LiquidHeader LiquidHeader::Read(FILE* stream)
{
- CountXVertices = stream->Read<uint32>();
- CountYVertices = stream->Read<uint32>();
- Width = stream->Read<uint32>();
- Height = stream->Read<uint32>();
- BaseLocation = Vector3::Read(stream);
- MaterialId = stream->Read<uint16>();
+ LiquidHeader ret;
+ int count = 0;
+ count += fread(&ret.CountXVertices, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountYVertices, sizeof(uint32), 1, stream);
+ count += fread(&ret.Width, sizeof(uint32), 1, stream);
+ count += fread(&ret.Height, sizeof(uint32), 1, stream);
+ ret.BaseLocation = Vector3::Read(stream);
+ count += fread(&ret.MaterialId, sizeof(uint16), 1, stream);
+
+ if (count != 5)
+ printf("LiquidHeader::Read: Failed to read some data expected 5, read %d\n", count);
+
+ return ret;
}
-void LiquidData::Read(Stream* stream, LiquidHeader& header)
+LiquidData LiquidData::Read(FILE* stream, LiquidHeader& header)
{
- CountXVertices = header.CountXVertices;
- Width = header.Width;
-
- HeightMap = new float*[header.CountXVertices];
+ LiquidData ret;
+ ret.HeightMap = new float*[header.CountXVertices];
for (uint32 i = 0; i < header.CountXVertices; ++i)
- HeightMap[i] = new float[header.CountYVertices];
+ ret.HeightMap[i] = new float[header.CountYVertices];
- RenderFlags = new uint8*[header.Width];
+ ret.RenderFlags = new uint8*[header.Width];
for (uint32 i = 0; i < header.Width; ++i)
- RenderFlags[i] = new uint8[header.Height];
+ ret.RenderFlags[i] = new uint8[header.Height];
for (uint32 y = 0; y < header.CountYVertices; y++)
{
for (uint32 x = 0; x < header.CountXVertices; x++)
{
- stream->Skip<uint32>();
- HeightMap[x][y] = stream->Read<float>();
+ uint32 discard;
+ float tmp;
+ if (fread(&discard, sizeof(uint32), 1, stream) == 1 &&
+ fread(&tmp, sizeof(float), 1, stream) == 1)
+ {
+ ret.HeightMap[x][y] = tmp;
+ }
}
}
for (uint32 y = 0; y < header.Height; y++)
+ {
for (uint32 x = 0; x < header.Width; x++)
- RenderFlags[x][y] = stream->Read<uint8>();
+ {
+ uint8 tmp = 0;
+ if (fread(&tmp, sizeof(uint8), 1, stream) == 1)
+ ret.RenderFlags[x][y] = tmp;
+ }
+ }
+
+ return ret;
}
-H2ORenderMask H2ORenderMask::Read(Stream* stream)
+H2ORenderMask H2ORenderMask::Read(FILE* stream)
{
H2ORenderMask ret;
- stream->Read(ret.Mask, sizeof(uint8) * 8);
+ int32 count;
+ if ((count = fread(&ret.Mask, sizeof(uint8), 8, stream)) != 8)
+ printf("H2OHeader::Read: Failed to read some data expected 8, read %d\n", count);
return ret;
}
@@ -403,42 +497,38 @@ bool MCNKLiquidData::IsWater(int x, int y, float height)
return false;
}
-MCNKLiquidData::~MCNKLiquidData()
+H2OHeader H2OHeader::Read(FILE* stream)
{
- if (!Heights)
- return;
+ H2OHeader ret;
+ int count = 0;
+ count += fread(&ret.OffsetInformation, sizeof(uint32), 1, stream);
+ count += fread(&ret.LayerCount, sizeof(uint32), 1, stream);
+ count += fread(&ret.OffsetRender, sizeof(uint32), 1, stream);
- for (uint32 i = 0; i < 9; ++i)
- delete[] Heights[i];
- delete[] Heights;
- Heights = NULL;
-}
+ if (count != 3)
+ printf("H2OHeader::Read: Failed to read some data expected 3, read %d\n", count);
-H2OHeader H2OHeader::Read(Stream* stream)
-{
- H2OHeader ret;
-
- ret.OffsetInformation = stream->Read<uint32>();
- ret.LayerCount = stream->Read<uint32>();
- ret.OffsetRender = stream->Read<uint32>();
-
return ret;
}
-H2OInformation H2OInformation::Read(Stream* stream)
+H2OInformation H2OInformation::Read(FILE* stream)
{
H2OInformation ret;
- ret.LiquidType = stream->Read<uint16>();
- ret.Flags = stream->Read<uint16>();
- ret.HeightLevel1 = stream->Read<float>();
- ret.HeightLevel2 = stream->Read<float>();
- ret.OffsetX = stream->Read<uint8>();
- ret.OffsetY = stream->Read<uint8>();
- ret.Width = stream->Read<uint8>();
- ret.Height = stream->Read<uint8>();
- ret.OffsetMask2 = stream->Read<uint32>();
- ret.OffsetHeightmap = stream->Read<uint32>();
-
+ int count = 0;
+ count += fread(&ret.LiquidType, sizeof(uint16), 1, stream);
+ count += fread(&ret.Flags, sizeof(uint16), 1, stream);
+ count += fread(&ret.HeightLevel1, sizeof(float), 1, stream);
+ count += fread(&ret.HeightLevel2, sizeof(float), 1, stream);
+ count += fread(&ret.OffsetX, sizeof(uint8), 1, stream);
+ count += fread(&ret.OffsetY, sizeof(uint8), 1, stream);
+ count += fread(&ret.Width, sizeof(uint8), 1, stream);
+ count += fread(&ret.Height, sizeof(uint8), 1, stream);
+ count += fread(&ret.OffsetMask2, sizeof(uint32), 1, stream);
+ count += fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream);
+
+ if (count != 10)
+ printf("H2OInformation::Read: Failed to read some data expected 10, read %d\n", count);
+
return ret;
}
@@ -451,30 +541,24 @@ char* Utils::GetPlainName(const char* FileName)
return (char*)FileName;
}
-WMOGroupHeader WMOGroupHeader::Read(Stream* stream)
+WMOGroupHeader WMOGroupHeader::Read( FILE* stream )
{
WMOGroupHeader ret;
- ret.OffsetGroupName = stream->Read<uint32>();
- ret.OffsetDescriptiveName = stream->Read<uint32>();
- ret.Flags = stream->Read<uint32>();
+ int count = 0;
+ count += fread(&ret.OffsetGroupName, sizeof(uint32), 1, stream);
+ count += fread(&ret.OffsetDescriptiveName, sizeof(uint32), 1, stream);
+ count += fread(&ret.Flags, sizeof(uint32), 1, stream);
ret.BoundingBox[0] = Vector3::Read(stream);
ret.BoundingBox[1] = Vector3::Read(stream);
- ret.OffsetPortals = stream->Read<uint32>();
- ret.CountPortals = stream->Read<uint32>();
- stream->Read(ret.CountBatches, sizeof(uint16) * 4);
- stream->Read(ret.Fogs, sizeof(uint8) * 4);
- ret.LiquidTypeRelated = stream->Read<uint32>();
- ret.WmoId = stream->Read<uint32>();
-
- return ret;
-}
+ count += fread(&ret.OffsetPortals, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountPortals, sizeof(uint32), 1, stream);
+ count += fread(&ret.CountBatches, sizeof(uint16), 4, stream);
+ count += fread(&ret.Fogs, sizeof(uint8), 4, stream);
+ count += fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream);
+ count += fread(&ret.WmoId, sizeof(uint32), 1, stream);
-void Utils::InitializeMmapTileHeader(MmapTileHeader& header)
-{
- memset(&header, 0, sizeof(MmapTileHeader));
- header.mmapMagic = MMAP_MAGIC;
- header.dtVersion = DT_NAVMESH_VERSION;
- header.mmapVersion = MMAP_VERSION;
- header.size = 0;
- header.usesLiquids = true;
+ if (count != 15)
+ printf("WMOGroupHeader::Read: Failed to read some data expected 15, read %d\n", count);
+
+ return ret;
}
diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h
index f93bc6e6be6..267a32c27cd 100644
--- a/src/tools/mesh_extractor/Utils.h
+++ b/src/tools/mesh_extractor/Utils.h
@@ -27,8 +27,6 @@
#include "Define.h"
#include "Constants.h"
-#include "Stream.h"
-
#include <ace/Stack_Trace.h>
struct WorldModelDefinition;
@@ -61,7 +59,7 @@ struct Vector3
return Vector3(x * s, y * s, z * s);
}
- static Vector3 Read(Stream* file);
+ static Vector3 Read(FILE* file);
};
struct TilePos
@@ -102,7 +100,7 @@ public:
uint32 AreaId;
uint32 MapObjectRefs;
uint32 Holes;
- uint32 LowQualityTextureMap[4];
+ uint32* LowQualityTextureMap;
uint32 PredTex;
uint32 NumberEffectDoodad;
uint32 OffsetMCSE;
@@ -112,7 +110,7 @@ public:
Vector3 Position;
uint32 OffsetMCCV;
- void Read(Stream* stream);
+ void Read(FILE* stream);
};
class MHDR
@@ -132,7 +130,7 @@ public:
uint32 OffsetMH2O;
uint32 OffsetMTFX;
- void Read(Stream* stream);
+ void Read(FILE* stream);
};
class ModelHeader
@@ -189,7 +187,7 @@ public:
uint32 CountBoundingNormals;
uint32 OffsetBoundingNormals;
- void Read(Stream* stream);
+ void Read(FILE* stream);
};
class WorldModelHeader
@@ -208,7 +206,7 @@ public:
Vector3 BoundingBox[2];
uint32 LiquidTypeRelated;
- void Read(Stream* stream);
+ static WorldModelHeader Read(FILE* stream);
};
class DoodadInstance
@@ -225,7 +223,7 @@ public:
float Scale;
uint32 LightColor;
- static DoodadInstance Read(Stream* stream);
+ static DoodadInstance Read(FILE* stream);
};
class DoodadSet
@@ -237,13 +235,13 @@ public:
uint32 CountInstances;
uint32 UnknownZero;
- static DoodadSet Read(Stream* stream);
+ static DoodadSet Read(FILE* stream);
};
class LiquidHeader
{
public:
- LiquidHeader() : CountXVertices(0), CountYVertices(0), Width(0), Height(0), BaseLocation(0,0,0), MaterialId(0) {}
+ LiquidHeader() {}
uint32 CountXVertices;
uint32 CountYVertices;
uint32 Width;
@@ -251,36 +249,22 @@ public:
Vector3 BaseLocation;
uint16 MaterialId;
- void Read(Stream* stream);
+ static LiquidHeader Read(FILE* stream);
};
class LiquidData
{
public:
- LiquidData() : HeightMap(NULL), RenderFlags(NULL), CountXVertices(0), Width(0) {}
-
- ~LiquidData()
- {
- for (uint32 i = 0; i < CountXVertices; ++i)
- delete[] HeightMap[i];
- delete[] HeightMap;
-
- for (uint32 i = 0; i < Width; ++i)
- delete[] RenderFlags[i];
- delete[] RenderFlags;
- }
-
+ LiquidData() {}
float** HeightMap;
uint8** RenderFlags;
- uint32 CountXVertices;
- uint32 Width;
- bool ShouldRender(int x, int y) const
+ bool ShouldRender(int x, int y)
{
return RenderFlags[x][y] != 0x0F;
}
- void Read(Stream* stream, LiquidHeader& header);
+ static LiquidData Read(FILE* stream, LiquidHeader& header);
};
class H2ORenderMask
@@ -294,15 +278,14 @@ public:
return (Mask[y] >> x & 1) != 0;
}
- static H2ORenderMask Read(Stream* stream);
+ static H2ORenderMask Read(FILE* stream);
};
class MCNKLiquidData
{
public:
- MCNKLiquidData() : Heights(NULL) {}
+ MCNKLiquidData() {}
MCNKLiquidData(float** heights, H2ORenderMask mask) : Heights(heights), Mask(mask) {}
- ~MCNKLiquidData();
float** Heights;
H2ORenderMask Mask;
@@ -318,7 +301,7 @@ public:
uint32 LayerCount;
uint32 OffsetRender;
- static H2OHeader Read(Stream* stream);
+ static H2OHeader Read(FILE* stream);
};
class H2OInformation
@@ -336,7 +319,7 @@ public:
uint32 OffsetMask2;
uint32 OffsetHeightmap;
- static H2OInformation Read(Stream* stream);
+ static H2OInformation Read(FILE* stream);
};
class WMOGroupHeader
@@ -355,7 +338,7 @@ public:
uint32 LiquidTypeRelated;
uint32 WmoId;
- static WMOGroupHeader Read(Stream* stream);
+ static WMOGroupHeader Read(FILE* stream);
};
// Dummy class to act as an interface.
@@ -368,7 +351,7 @@ public:
};
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 5
+#define MMAP_VERSION 3
struct MmapTileHeader
{
@@ -376,13 +359,18 @@ struct MmapTileHeader
uint32 dtVersion;
uint32 mmapVersion;
uint32 size;
- bool usesLiquids : 1;
+ bool usesLiquids;
+
+ MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
+ mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {}
};
class Utils
{
public:
- static void Reverse(std::string& str);
+ static void Reverse(char word[]);
+ static std::string ReadString(FILE* file);
+ static uint32 Size(FILE* file);
static Vector3 ToRecast(const Vector3& val );
static std::string GetAdtPath(const std::string& world, int x, int y);
static std::string FixModelPath(const std::string& path);
@@ -406,15 +394,14 @@ public:
return false;
return true;
}
- static std::string Replace(std::string str, const std::string& oldStr, const std::string& newStr);
- static void CreateDir(const std::string& Path);
- static void SaveToDisk(Stream* stream, const std::string& path);
- static Vector3 ToWoWCoords(const Vector3& vec);
- static std::string GetExtension( std::string path);
+ static std::string Replace( std::string str, const std::string& oldStr, const std::string& newStr );
+ static void CreateDir( const std::string& Path );
+ static void SaveToDisk(FILE* stream, const std::string& path);
+ static Vector3 ToWoWCoords(const Vector3& vec );
+ static std::string GetExtension( std::string path );
static char* GetPlainName(const char* FileName);
- static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3 vec, bool translate = true);
- static Vector3 VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix, bool normal = false);
- static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, const Vector3& vec, bool translate = true);
- static void InitializeMmapTileHeader(MmapTileHeader& header);
+ static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec, bool translate = true);
+ static Vector3 VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix, bool normal = false );
+ static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec, bool translate = true );
};
#endif
diff --git a/src/tools/mesh_extractor/WDT.cpp b/src/tools/mesh_extractor/WDT.cpp
index 42461f4f247..593127e0d34 100644
--- a/src/tools/mesh_extractor/WDT.cpp
+++ b/src/tools/mesh_extractor/WDT.cpp
@@ -20,7 +20,6 @@
#include "ChunkedData.h"
#include "Utils.h"
#include "WorldModelHandler.h"
-#include "Cache.h"
WDT::WDT(std::string file) : IsGlobalModel(false), IsValid(false), Model(NULL)
{
@@ -38,8 +37,8 @@ void WDT::ReadGlobalModel()
IsGlobalModel = true;
ModelDefinition = WorldModelDefinition::Read(defChunk->GetStream());
- ModelFile = fileChunk->GetStream()->ReadString();
- Model = Cache->WorldModelCache.Get(ModelFile);
+ ModelFile = Utils::ReadString(fileChunk->GetStream());
+ Model = new WorldModelRoot(ModelFile);
}
void WDT::ReadTileTable()
@@ -48,14 +47,20 @@ void WDT::ReadTileTable()
if (!chunk)
return;
IsValid = true;
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
for (int y = 0; y < 64; ++y)
{
for (int x = 0; x < 64; ++x)
{
const uint32 hasTileFlag = 0x1;
- uint32 flags = stream->Read<uint32>();
- stream->Skip<uint32>();
+ uint32 flags;
+ uint32 discard;
+ int count = 0;
+ count += fread(&flags, sizeof(uint32), 1, stream);
+ count += fread(&discard, sizeof(uint32), 1, stream);
+
+ if (count != 2)
+ printf("WDT::ReadTileTable: Failed to read some data expected 2, read %d\n", count);
if (flags & hasTileFlag)
TileTable.push_back(TilePos(x, y));
@@ -64,9 +69,9 @@ void WDT::ReadTileTable()
}
}
-bool WDT::HasTile( int x, int y ) const
+bool WDT::HasTile( int x, int y )
{
- for (std::vector<TilePos>::const_iterator itr = TileTable.begin(); itr != TileTable.end(); ++itr)
+ for (std::vector<TilePos>::iterator itr = TileTable.begin(); itr != TileTable.end(); ++itr)
if (itr->X == x && itr->Y == y)
return true;
return false;
diff --git a/src/tools/mesh_extractor/WDT.h b/src/tools/mesh_extractor/WDT.h
index 8943471ca86..55a1a9861ff 100644
--- a/src/tools/mesh_extractor/WDT.h
+++ b/src/tools/mesh_extractor/WDT.h
@@ -36,8 +36,8 @@ public:
bool IsValid;
std::string ModelFile;
WorldModelDefinition ModelDefinition;
- WorldModelRoot const* Model;
- bool HasTile(int x, int y) const;
+ WorldModelRoot* Model;
+ bool HasTile(int x, int y);
private:
void ReadGlobalModel();
void ReadTileTable();
diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp
index 530b78e2792..9d32a096592 100644
--- a/src/tools/mesh_extractor/WorldModelGroup.cpp
+++ b/src/tools/mesh_extractor/WorldModelGroup.cpp
@@ -20,37 +20,14 @@
#include "Chunk.h"
#include "Utils.h"
-WorldModelGroup::WorldModelGroup(std::string path, int groupIndex) : SubData(NULL), GroupIndex(groupIndex), MOBA(NULL), MOBALength(0), HasLiquidData(false), IsBad(false)
+WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), MOBA(NULL), IsBad(false), HasLiquidData(false)
{
Data = new ChunkedData(path);
- if (!Data->_Stream)
+ if (!Data->Stream)
{
IsBad = true;
return;
}
- Load(path);
-}
-
-WorldModelGroup::WorldModelGroup(Stream* stream, std::string path, int groupIndex) : SubData(NULL), GroupIndex(groupIndex), MOBA(NULL), MOBALength(0), HasLiquidData(false), IsBad(false)
-{
- Data = new ChunkedData(stream, stream->GetSize());
- Load(path);
-}
-
-WorldModelGroup::~WorldModelGroup()
-{
- // Temporarily delete the underlying stream, it is the same pointer for both Data and SubData.
- // @TODO: Remove this code once the ChunkedData destructor properly releases _Stream
- delete Data->_Stream;
-
- delete Data;
- delete SubData;
- delete[] MOBA;
-
-}
-
-void WorldModelGroup::Load(std::string& path)
-{
Chunk* mainChunk = Data->GetChunkByName("MOGP");
int32 firstSub = mainChunk->FindSubChunkOffset("MOPY");
if (firstSub == -1)
@@ -58,8 +35,8 @@ void WorldModelGroup::Load(std::string& path)
Name = Utils::GetPlainName(path.c_str());
- Stream* stream = mainChunk->GetStream();
- stream->Seek(firstSub, SEEK_SET);
+ FILE* stream = mainChunk->GetStream();
+ fseek(stream, firstSub, SEEK_SET);
SubData = new ChunkedData(stream, mainChunk->Length - firstSub);
ReadHeader();
@@ -80,7 +57,7 @@ void WorldModelGroup::ReadNormals()
uint32 normalCount = chunk->Length / 12;
ASSERT(normalCount == Vertices.size() && "normalCount is different than the Vertices count");
Normals.reserve(normalCount);
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
for (uint32 i = 0; i < normalCount; i++)
Normals.push_back(Vector3::Read(stream));
}
@@ -92,9 +69,9 @@ void WorldModelGroup::ReadLiquid()
return;
HasLiquidData = true;
- Stream* stream = chunk->GetStream();
- LiquidDataHeader.Read(stream);
- LiquidDataGeometry.Read(stream, LiquidDataHeader);
+ FILE* stream = chunk->GetStream();
+ LiquidDataHeader = LiquidHeader::Read(stream);
+ LiquidDataGeometry = LiquidData::Read(stream, LiquidDataHeader);
}
void WorldModelGroup::ReadVertices()
@@ -105,7 +82,7 @@ void WorldModelGroup::ReadVertices()
uint32 verticeCount = chunk->Length / 12;
Vertices.reserve(verticeCount);
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
for (uint32 i = 0; i < verticeCount; i++)
Vertices.push_back(Vector3::Read(stream));
}
@@ -118,13 +95,19 @@ void WorldModelGroup::ReadTriangles()
uint32 triangleCount = chunk->Length / 6;
ASSERT(triangleCount == TriangleFlags.size() && "triangleCount != TriangleFlags.size()");
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
Triangles.reserve(triangleCount);
for (uint32 i = 0; i < triangleCount; i++)
{
- uint16 v0 = stream->Read<uint16>();
- uint16 v1 = stream->Read<uint16>();
- uint16 v2 = stream->Read<uint16>();
+ uint16 v0;
+ uint16 v1;
+ uint16 v2;
+ int count = 0;
+ count += fread(&v0, sizeof(uint16), 1, stream);
+ count += fread(&v1, sizeof(uint16), 1, stream);
+ count += fread(&v2, sizeof(uint16), 1, stream);
+ if (count != 3)
+ printf("WorldModelGroup::ReadMaterials: Error reading data, expected 3, read %d\n", count);
Triangles.push_back(Triangle<uint16>(Constants::TRIANGLE_TYPE_WMO, v0, v1, v2));
}
@@ -136,15 +119,20 @@ void WorldModelGroup::ReadMaterials()
if (!chunk)
return;
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
uint32 triangleCount = chunk->Length / 2;
TriangleFlags.reserve(triangleCount);
TriangleMaterials.reserve(triangleCount);
for (uint32 i = 0; i < triangleCount; i++)
{
- TriangleFlags.push_back(stream->Read<uint8>());
+ uint8 tmp;
+ if (fread(&tmp, sizeof(uint8), 1, stream) != 1)
+ printf("WorldModelGroup::ReadMaterials: Error reading data, expected 1, read 0\n");
+ TriangleFlags.push_back(tmp);
// Read again for material.
- TriangleMaterials.push_back(stream->Read<uint8>());
+ if (fread(&tmp, sizeof(uint8), 1, stream) != 1)
+ printf("WorldModelGroup::ReadMaterials: Error reading data, expected 1, read 0\n");
+ TriangleMaterials.push_back(tmp);
}
}
@@ -154,7 +142,7 @@ void WorldModelGroup::ReadHeader()
if (!chunk)
return;
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
Header = WMOGroupHeader::Read(stream);
}
@@ -166,5 +154,7 @@ void WorldModelGroup::ReadBatches()
MOBALength = chunk->Length / 2;
MOBA = new uint16[MOBALength];
- chunk->GetStream()->Read(MOBA, sizeof(uint16) * MOBALength);
+ uint32 count = (uint32)fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream());
+ if (count != MOBALength)
+ printf("WorldModelGroup::ReadBatches: Error reading data, expected %u, read %u\n", MOBALength, count);
}
diff --git a/src/tools/mesh_extractor/WorldModelGroup.h b/src/tools/mesh_extractor/WorldModelGroup.h
index 54056f9d37e..cf98dc8768a 100644
--- a/src/tools/mesh_extractor/WorldModelGroup.h
+++ b/src/tools/mesh_extractor/WorldModelGroup.h
@@ -24,10 +24,6 @@ class WorldModelGroup
{
public:
WorldModelGroup(std::string path, int groupIndex);
- WorldModelGroup(Stream* stream, std::string path, int groupIndex);
- ~WorldModelGroup();
- void Load(std::string& path);
-
ChunkedData* Data;
ChunkedData* SubData;
int GroupIndex;
diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp
index a0de6ec1172..fa816627435 100644
--- a/src/tools/mesh_extractor/WorldModelHandler.cpp
+++ b/src/tools/mesh_extractor/WorldModelHandler.cpp
@@ -21,24 +21,27 @@
#include "Cache.h"
#include "Model.h"
#include "Define.h"
-#include "Stream.h"
#include "G3D/Matrix4.h"
#include "G3D/Quat.h"
#include <cstdio>
-WorldModelDefinition WorldModelDefinition::Read(Stream* file)
+WorldModelDefinition WorldModelDefinition::Read( FILE* file )
{
WorldModelDefinition ret;
- ret.MwidIndex = file->Read<uint32>();
- ret.UniqueId = file->Read<uint32>();
+ int count = 0;
+ count += fread(&ret.MwidIndex, sizeof(uint32), 1, file);
+ count += fread(&ret.UniqueId, sizeof(uint32), 1, file);
ret.Position = Vector3::Read(file);
ret.Rotation = Vector3::Read(file);
ret.UpperExtents = Vector3::Read(file);
ret.LowerExtents = Vector3::Read(file);
- ret.Flags = file->Read<uint16>();
- ret.DoodadSet = file->Read<uint16>();
- file->Read<uint32>(); // Discarded
-
+ count += fread(&ret.Flags, sizeof(uint16), 1, file);
+ count += fread(&ret.DoodadSet, sizeof(uint16), 1, file);
+ uint32 discard;
+ count += fread(&discard, sizeof(uint32), 1, file);
+
+ if (count != 5)
+ printf("WorldModelDefinition::Read: Error reading data, expected 5, read %d\n", count);
return ret;
}
@@ -55,12 +58,14 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk )
return;
uint32 refCount = mcnk->Header.MapObjectRefs;
- Stream* stream = mcnk->Source->GetStream();
- stream->Seek(mcnk->Source->Offset + mcnk->Header.OffsetMCRF, SEEK_SET);
+ FILE* stream = mcnk->Source->GetStream();
+ fseek(stream, mcnk->Source->Offset + mcnk->Header.OffsetMCRF, SEEK_SET);
// Start looping at the last Doodad Ref index
for (uint32 i = mcnk->Header.DoodadRefs; i < refCount; i++)
{
- int32 index = stream->Read<int32>();
+ int32 index;
+ if (fread(&index, sizeof(int32), 1, stream) != 1)
+ printf("WorldModelDefinition::Read: Error reading data, expected 1, read 0\n");
if (index < 0 || uint32(index) >= _definitions->size())
continue;
@@ -75,7 +80,12 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk )
continue;
std::string path = (*_paths)[wmo.MwidIndex];
- WorldModelRoot const* model = Cache->WorldModelCache.Get(path);
+ WorldModelRoot* model = Cache->WorldModelCache.Get(path);
+ if (!model)
+ {
+ model = new WorldModelRoot(path);
+ Cache->WorldModelCache.Insert(path, model);
+ }
Vertices.reserve(1000);
Triangles.reserve(1000);
@@ -83,16 +93,15 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk )
InsertModelGeometry(Vertices, Triangles, wmo, model);
}
// Restore the stream position
- stream->Seek(mcnk->Source->Offset, SEEK_SET);
+ fseek(stream, mcnk->Source->Offset, SEEK_SET);
}
-void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot const* root, bool translate )
+void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root, bool translate )
{
- for (std::vector<WorldModelGroup*>::const_iterator groupItr = root->Groups.begin(); groupItr != root->Groups.end(); ++groupItr)
+ for (std::vector<WorldModelGroup>::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group)
{
- WorldModelGroup const* group = *groupItr;
uint32 vertOffset = verts.size();
- for (std::vector<Vector3>::const_iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2)
+ for (std::vector<Vector3>::iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2)
{
Vector3 v = Utils::TransformDoodadVertex(def, *itr2, translate);
// If translate is false, then we were called directly from the TileBuilder to add data to it's _Geometry member, hence, we have to manually convert the vertices to Recast format.
@@ -104,7 +113,6 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
// only include colliding tris
if ((group->TriangleFlags[i] & 0x04) != 0 || group->TriangleMaterials[i] == 0xFF)
continue;
-
Triangle<uint16> tri = group->Triangles[i];
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WMO, tri.V0 + vertOffset, tri.V1 + vertOffset, tri.V2 + vertOffset));
}
@@ -124,33 +132,38 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
for (std::vector<DoodadInstance>::iterator instance = instances.begin(); instance != instances.end(); ++instance)
{
- Model const* model = Cache->ModelCache.Get(instance->File);
+ Model* model = Cache->ModelCache.Get(instance->File);
+ if (!model)
+ {
+ model = new Model(instance->File);
+ Cache->ModelCache.Insert(instance->File, model);
+ }
if (!model->IsCollidable)
continue;
int vertOffset = verts.size();
- for (std::vector<Vector3>::const_iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2)
+ for (std::vector<Vector3>::iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2)
{
Vector3 v = Utils::TransformDoodadVertex(def, Utils::TransformWmoDoodad(*instance, def, *itr2, false), translate);
verts.push_back(translate ? v : Utils::ToRecast(v));
}
- for (std::vector<Triangle<uint16> >::const_iterator itr2 = model->Triangles.begin(); itr2 != model->Triangles.end(); ++itr2)
+ for (std::vector<Triangle<uint16> >::iterator itr2 = model->Triangles.begin(); itr2 != model->Triangles.end(); ++itr2)
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WMO, itr2->V0 + vertOffset, itr2->V1 + vertOffset, itr2->V2 + vertOffset));
}
- for (std::vector<WorldModelGroup*>::const_iterator groupItr = root->Groups.begin(); groupItr != root->Groups.end(); ++groupItr)
+ for (std::vector<WorldModelGroup>::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group)
{
- WorldModelGroup const* group = *groupItr;
if (!group->HasLiquidData)
continue;
const LiquidHeader& liquidHeader = group->LiquidDataHeader;
- const LiquidData& liquidDataGeometry = group->LiquidDataGeometry;
+ LiquidData& liquidDataGeometry = group->LiquidDataGeometry;
for (uint32 y = 0; y < liquidHeader.Height; y++)
{
for (uint32 x = 0; x < liquidHeader.Width; x++)
{
+
if (!liquidDataGeometry.ShouldRender(x, y))
continue;
@@ -189,7 +202,7 @@ void WorldModelHandler::ReadDefinitions()
uint32 definitionCount = chunk->Length / definitionSize;
_definitions = new std::vector<WorldModelDefinition>;
_definitions->reserve(definitionCount);
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
for (uint32 i = 0; i < definitionCount; i++)
_definitions->push_back(WorldModelDefinition::Read(stream));
}
@@ -206,13 +219,14 @@ void WorldModelHandler::ReadModelPaths()
_paths->reserve(paths);
for (uint32 i = 0; i < paths; i++)
{
- Stream* stream = mwid->GetStream();
- stream->Seek(i * 4, SEEK_CUR);
- uint32 offset = stream->Read<uint32>();
-
- Stream* dataStream = mwmo->GetStream();
- dataStream->Seek(offset + mwmo->Offset, SEEK_SET);
- _paths->push_back(dataStream->ReadString());
+ FILE* stream = mwid->GetStream();
+ fseek(stream, i * 4, SEEK_CUR);
+ uint32 offset;
+ if (fread(&offset, sizeof(uint32), 1, stream) != 1)
+ printf("WorldModelDefinition::Read: Error reading data, expected 1, read 0\n");
+ FILE* dataStream = mwmo->GetStream();
+ fseek(dataStream, offset + mwmo->Offset, SEEK_SET);
+ _paths->push_back(Utils::ReadString(dataStream));
}
}
diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h
index ac7b7431c1e..972dda0f5d8 100644
--- a/src/tools/mesh_extractor/WorldModelHandler.h
+++ b/src/tools/mesh_extractor/WorldModelHandler.h
@@ -39,7 +39,7 @@ public:
uint16 Flags;
uint16 DoodadSet;
- static WorldModelDefinition Read(Stream* file);
+ static WorldModelDefinition Read(FILE* file);
};
class WorldModelHandler : public ObjectDataHandler
@@ -50,8 +50,8 @@ public:
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
- bool IsSane() const { return _definitions && _paths; }
- static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot const* root, bool translate = true);
+ bool IsSane() { return _definitions && _paths; }
+ static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root, bool translate = true);
protected:
void ProcessInternal(MapChunk* data);
private:
diff --git a/src/tools/mesh_extractor/WorldModelRoot.cpp b/src/tools/mesh_extractor/WorldModelRoot.cpp
index ffc7d7c8484..d9bc4e550b3 100644
--- a/src/tools/mesh_extractor/WorldModelRoot.cpp
+++ b/src/tools/mesh_extractor/WorldModelRoot.cpp
@@ -18,7 +18,6 @@
#include "WorldModelRoot.h"
#include "ChunkedData.h"
#include "Utils.h"
-#include "MPQManager.h"
WorldModelRoot::WorldModelRoot( std::string path )
{
@@ -33,10 +32,6 @@ WorldModelRoot::WorldModelRoot( std::string path )
WorldModelRoot::~WorldModelRoot()
{
delete Data;
- for (std::vector<WorldModelGroup*>::iterator group = Groups.begin(); group != Groups.end(); ++group)
- delete *group;
-
- Groups.clear();
}
void WorldModelRoot::ReadGroups()
@@ -47,10 +42,9 @@ void WorldModelRoot::ReadGroups()
{
char name[200];
sprintf(name, "%s_%03u.wmo", pathBase.c_str(), i);
- Stream* stream = MPQHandler->GetFile(name);
- if (!stream)
- continue;
- Groups.push_back(new WorldModelGroup(stream, name, i));
+ WorldModelGroup group(name, i);
+ if (!group.IsBad)
+ Groups.push_back(group);
}
}
@@ -60,7 +54,7 @@ void WorldModelRoot::ReadDoodadSets()
if (!chunk)
return;
- Stream* stream = chunk->GetStream();
+ FILE* stream = chunk->GetStream();
ASSERT(chunk->Length / 32 == Header.CountSets && "chunk.Length / 32 == Header.CountSets");
DoodadSets.reserve(Header.CountSets);
for (uint32 i = 0; i < Header.CountSets; i++)
@@ -79,14 +73,14 @@ void WorldModelRoot::ReadDoodadInstances()
DoodadInstances.reserve(countInstances);
for (uint32 i = 0; i < countInstances; i++)
{
- Stream* stream = chunk->GetStream();
- stream->Seek(instanceSize * i, SEEK_CUR);
+ FILE* stream = chunk->GetStream();
+ fseek(stream, instanceSize * i, SEEK_CUR);
DoodadInstance instance = DoodadInstance::Read(stream);
- Stream* nameStream = nameChunk->GetStream();
+ FILE* nameStream = nameChunk->GetStream();
if (instance.FileOffset >= nameChunk->Length)
continue;
- nameStream->Seek(instance.FileOffset, SEEK_CUR);
- instance.File = nameStream->ReadString();
+ fseek(nameStream, instance.FileOffset, SEEK_CUR);
+ instance.File = Utils::ReadString(nameStream);
DoodadInstances.push_back(instance);
}
}
@@ -97,6 +91,6 @@ void WorldModelRoot::ReadHeader()
if (!chunk)
return;
- Stream* stream = chunk->GetStream();
- Header.Read(stream);
+ FILE* stream = chunk->GetStream();
+ Header = WorldModelHeader::Read(stream);
}
diff --git a/src/tools/mesh_extractor/WorldModelRoot.h b/src/tools/mesh_extractor/WorldModelRoot.h
index 89ebb681f17..7fbc04d2b6d 100644
--- a/src/tools/mesh_extractor/WorldModelRoot.h
+++ b/src/tools/mesh_extractor/WorldModelRoot.h
@@ -34,7 +34,7 @@ public:
WorldModelHeader Header;
std::vector<DoodadInstance> DoodadInstances;
std::vector<DoodadSet> DoodadSets;
- std::vector<WorldModelGroup*> Groups;
+ std::vector<WorldModelGroup> Groups;
private:
void ReadGroups();
void ReadDoodadSets();