diff options
Diffstat (limited to 'src/server/collision')
21 files changed, 650 insertions, 141 deletions
diff --git a/src/server/collision/BoundingIntervalHierarchy.cpp b/src/server/collision/BoundingIntervalHierarchy.cpp index ad3753ea3c9..340d66ddaf0 100644 --- a/src/server/collision/BoundingIntervalHierarchy.cpp +++ b/src/server/collision/BoundingIntervalHierarchy.cpp @@ -18,6 +18,12 @@ #include "BoundingIntervalHierarchy.h" +#ifdef _MSC_VER + #define isnan _isnan +#else + #define isnan std::isnan +#endif + void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats) { // create space for the first node @@ -51,7 +57,7 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat prevAxis = axis; prevSplit = split; // perform quick consistency checks - Vector3 d( gridBox.hi - gridBox.lo ); + G3D::Vector3 d( gridBox.hi - gridBox.lo ); if (d.x < 0 || d.y < 0 || d.z < 0) throw std::logic_error("negative node extents"); for (int i = 0; i < 3; i++) @@ -255,11 +261,11 @@ bool BIH::writeToFile(FILE* wf) const bool BIH::readFromFile(FILE* rf) { uint32 treeSize; - Vector3 lo, hi; + G3D::Vector3 lo, hi; uint32 check=0, count=0; check += fread(&lo, sizeof(float), 3, rf); check += fread(&hi, sizeof(float), 3, rf); - bounds = AABox(lo, hi); + bounds = G3D::AABox(lo, hi); check += fread(&treeSize, sizeof(uint32), 1, rf); tree.resize(treeSize); check += fread(&tree[0], sizeof(uint32), treeSize, rf); diff --git a/src/server/collision/BoundingIntervalHierarchy.h b/src/server/collision/BoundingIntervalHierarchy.h index 7cbaedbfba6..997f9c99e5f 100644 --- a/src/server/collision/BoundingIntervalHierarchy.h +++ b/src/server/collision/BoundingIntervalHierarchy.h @@ -31,20 +31,8 @@ #include <limits> #include <cmath> -#ifdef __APPLE__ - #define isnan(x) ( std::isnan(x) ) -#endif - #define MAX_STACK_SIZE 64 -#ifdef _MSC_VER - #define isnan(x) _isnan(x) -#endif - -using G3D::Vector3; -using G3D::AABox; -using G3D::Ray; - static inline uint32 floatToRawIntBits(float f) { union @@ -69,7 +57,7 @@ static inline float intBitsToFloat(uint32 i) struct AABound { - Vector3 lo, hi; + G3D::Vector3 lo, hi; }; /** Bounding Interval Hierarchy Class. @@ -105,12 +93,11 @@ class BIH dat.maxPrims = leafSize; dat.numPrims = primitives.size(); dat.indices = new uint32[dat.numPrims]; - dat.primBound = new AABox[dat.numPrims]; + dat.primBound = new G3D::AABox[dat.numPrims]; getBounds(primitives[0], bounds); for (uint32 i=0; i<dat.numPrims; ++i) { dat.indices[i] = i; - AABox tb; getBounds(primitives[i], dat.primBound[i]); bounds.merge(dat.primBound[i]); } @@ -131,13 +118,13 @@ class BIH uint32 primCount() const { return objects.size(); } template<typename RayCallback> - void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const + void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const { float intervalMin = -1.f; float intervalMax = -1.f; - Vector3 org = r.origin(); - Vector3 dir = r.direction(); - Vector3 invDir; + G3D::Vector3 org = r.origin(); + G3D::Vector3 dir = r.direction(); + G3D::Vector3 invDir; for (int i=0; i<3; ++i) { invDir[i] = 1.f / dir[i]; @@ -270,7 +257,7 @@ class BIH } template<typename IsectCallback> - void intersectPoint(const Vector3 &p, IsectCallback& intersectCallback) const + void intersectPoint(const G3D::Vector3 &p, IsectCallback& intersectCallback) const { if (!bounds.contains(p)) return; @@ -353,12 +340,12 @@ class BIH protected: std::vector<uint32> tree; std::vector<uint32> objects; - AABox bounds; + G3D::AABox bounds; struct buildData { uint32 *indices; - AABox *primBound; + G3D::AABox *primBound; uint32 numPrims; int maxPrims; }; @@ -410,4 +397,4 @@ class BIH void subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); }; -#endif // _BIH_H
\ No newline at end of file +#endif // _BIH_H diff --git a/src/server/collision/BoundingIntervalHierarchyWrapper.h b/src/server/collision/BoundingIntervalHierarchyWrapper.h index 8a99078caab..305d57b0075 100644 --- a/src/server/collision/BoundingIntervalHierarchyWrapper.h +++ b/src/server/collision/BoundingIntervalHierarchyWrapper.h @@ -33,18 +33,23 @@ class BIHWrap { const T* const* objects; RayCallback& _callback; + uint32 objects_size; - MDLCallback(RayCallback& callback, const T* const* objects_array ) : objects(objects_array), _callback(callback) {} + MDLCallback(RayCallback& callback, const T* const* objects_array, uint32 objects_size ) : objects(objects_array), _callback(callback), objects_size(objects_size) {} - bool operator() (const Ray& ray, uint32 Idx, float& MaxDist, bool /*stopAtFirst*/) + bool operator() (const G3D::Ray& ray, uint32 Idx, float& MaxDist, bool /*stopAtFirst*/) { + if (Idx >= objects_size) + return false; if (const T* obj = objects[Idx]) return _callback(ray, *obj, MaxDist/*, stopAtFirst*/); return false; } - void operator() (const Vector3& p, uint32 Idx) + void operator() (const G3D::Vector3& p, uint32 Idx) { + if (Idx >= objects_size) + return false; if (const T* obj = objects[Idx]) _callback(p, *obj); } @@ -87,21 +92,24 @@ public: m_objects.fastClear(); m_obj2Idx.getKeys(m_objects); m_objects_to_push.getMembers(m_objects); + //assert that m_obj2Idx has all the keys m_tree.build(m_objects, BoundsFunc::getBounds2); } template<typename RayCallback> - void intersectRay(const Ray& ray, RayCallback& intersectCallback, float& maxDist) const + void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& maxDist) { - MDLCallback<RayCallback> temp_cb(intersectCallback, m_objects.getCArray()); + balance(); + MDLCallback<RayCallback> temp_cb(intersectCallback, m_objects.getCArray(), m_objects.size()); m_tree.intersectRay(ray, temp_cb, maxDist, true); } template<typename IsectCallback> - void intersectPoint(const Vector3& point, IsectCallback& intersectCallback) const + void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback) { - MDLCallback<IsectCallback> callback(intersectCallback, m_objects.getCArray()); + balance(); + MDLCallback<IsectCallback> callback(intersectCallback, m_objects.getCArray(), m_objects.size()); m_tree.intersectPoint(point, callback); } }; diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt index 62af7dd081e..b4012b63812 100644 --- a/src/server/collision/CMakeLists.txt +++ b/src/server/collision/CMakeLists.txt @@ -33,7 +33,9 @@ set(collision_STAT_SRCS include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging diff --git a/src/server/collision/DynamicTree.cpp b/src/server/collision/DynamicTree.cpp index 1a2f721a69f..c70a4b78a03 100644 --- a/src/server/collision/DynamicTree.cpp +++ b/src/server/collision/DynamicTree.cpp @@ -27,15 +27,24 @@ #include "GameObjectModel.h" #include "ModelInstance.h" +#include <G3D/AABox.h> +#include <G3D/Ray.h> +#include <G3D/Vector3.h> + using VMAP::ModelInstance; -using G3D::Ray; + +namespace { + +int CHECK_TREE_PERIOD = 200; + +} // namespace template<> struct HashTrait< GameObjectModel>{ static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; } }; template<> struct PositionTrait< GameObjectModel> { - static void getPosition(const GameObjectModel& g, Vector3& p) { p = g.getPosition(); } + static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); } }; template<> struct BoundsTrait< GameObjectModel> { @@ -49,11 +58,6 @@ static bool operator == (const GameObjectModel& mdl, const GameObjectModel& mdl2 } */ -int valuesPerNode = 5, numMeanSplits = 3; - -int UNBALANCED_TIMES_LIMIT = 5; -int CHECK_TREE_PERIOD = 200; - typedef RegularGrid2D<GameObjectModel, BIHWrap<GameObjectModel> > ParentTree; struct DynTreeImpl : public ParentTree/*, public Intersectable*/ @@ -103,43 +107,43 @@ struct DynTreeImpl : public ParentTree/*, public Intersectable*/ int unbalanced_times; }; -DynamicMapTree::DynamicMapTree() : impl(*new DynTreeImpl()) +DynamicMapTree::DynamicMapTree() : impl(new DynTreeImpl()) { } DynamicMapTree::~DynamicMapTree() { - delete &impl; + delete impl; } void DynamicMapTree::insert(const GameObjectModel& mdl) { - impl.insert(mdl); + impl->insert(mdl); } void DynamicMapTree::remove(const GameObjectModel& mdl) { - impl.remove(mdl); + impl->remove(mdl); } bool DynamicMapTree::contains(const GameObjectModel& mdl) const { - return impl.contains(mdl); + return impl->contains(mdl); } void DynamicMapTree::balance() { - impl.balance(); + impl->balance(); } int DynamicMapTree::size() const { - return impl.size(); + return impl->size(); } void DynamicMapTree::update(uint32 t_diff) { - impl.update(t_diff); + impl->update(t_diff); } struct DynamicTreeIntersectionCallback @@ -147,7 +151,7 @@ struct DynamicTreeIntersectionCallback bool did_hit; uint32 phase_mask; DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) {} - bool operator()(const Ray& r, const GameObjectModel& obj, float& distance) + bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) { did_hit = obj.intersectRay(r, distance, true, phase_mask); return did_hit; @@ -163,7 +167,7 @@ struct DynamicTreeIntersectionCallback_WithLogger { sLog->outDebug(LOG_FILTER_MAPS, "Dynamic Intersection log"); } - bool operator()(const Ray& r, const GameObjectModel& obj, float& distance) + bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) { sLog->outDebug(LOG_FILTER_MAPS, "testing intersection with %s", obj.name.c_str()); bool hit = obj.intersectRay(r, distance, true, phase_mask); @@ -177,17 +181,20 @@ struct DynamicTreeIntersectionCallback_WithLogger bool didHit() const { return did_hit;} }; -bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, const Vector3& endPos, float& maxDist) const +bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, + const G3D::Vector3& endPos, float& maxDist) const { float distance = maxDist; DynamicTreeIntersectionCallback callback(phasemask); - impl.intersectRay(ray, callback, distance, endPos); + impl->intersectRay(ray, callback, distance, endPos); if (callback.didHit()) maxDist = distance; return callback.didHit(); } -bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const Vector3& startPos, const Vector3& endPos, Vector3& resultHit, float modifyDist) const +bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3& startPos, + const G3D::Vector3& endPos, G3D::Vector3& resultHit, + float modifyDist) const { bool result = false; float maxDist = (endPos - startPos).magnitude(); @@ -199,7 +206,7 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const Vector3& star resultHit = endPos; return false; } - Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1 + G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1 G3D::Ray ray(startPos, dir); float dist = maxDist; if (getIntersectionTime(phasemask, ray, endPos, dist)) @@ -227,26 +234,26 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const Vector3& star bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const { - Vector3 v1(x1,y1,z1), v2(x2,y2,z2); + G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2); float maxDist = (v2 - v1).magnitude(); if (!G3D::fuzzyGt(maxDist, 0) ) return true; - Ray r(v1, (v2-v1) / maxDist); + G3D::Ray r(v1, (v2-v1) / maxDist); DynamicTreeIntersectionCallback callback(phasemask); - impl.intersectRay(r, callback, maxDist, v2); + impl->intersectRay(r, callback, maxDist, v2); return !callback.did_hit; } float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const { - Vector3 v(x,y,z); - Ray r(v, Vector3(0,0,-1)); + G3D::Vector3 v(x, y, z); + G3D::Ray r(v, G3D::Vector3(0, 0, -1)); DynamicTreeIntersectionCallback callback(phasemask); - impl.intersectZAllignedRay(r, callback, maxSearchDist); + impl->intersectZAllignedRay(r, callback, maxSearchDist); if (callback.didHit()) return v.z - maxSearchDist; diff --git a/src/server/collision/DynamicTree.h b/src/server/collision/DynamicTree.h index ca199a9cd70..8e541fd453a 100644 --- a/src/server/collision/DynamicTree.h +++ b/src/server/collision/DynamicTree.h @@ -20,34 +20,36 @@ #ifndef _DYNTREE_H #define _DYNTREE_H -#include <G3D/Matrix3.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> - -//#include "ModelInstance.h" #include "Define.h" -//#include "GameObjectModel.h" namespace G3D { + class Ray; class Vector3; } -using G3D::Vector3; class GameObjectModel; +struct DynTreeImpl; class DynamicMapTree { - struct DynTreeImpl& impl; + DynTreeImpl *impl; + public: DynamicMapTree(); ~DynamicMapTree(); - bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const; - bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const Vector3& endPos, float& maxDist) const; - bool getObjectHitPos(uint32 phasemask, const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const; + bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, + float z2, uint32 phasemask) const; + + bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, + const G3D::Vector3& endPos, float& maxDist) const; + + bool getObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, + const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, + float pModifyDist) const; + float getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const; void insert(const GameObjectModel&); diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp new file mode 100644 index 00000000000..7adf7fbfa66 --- /dev/null +++ b/src/server/collision/Management/MMapFactory.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +#include "MMapFactory.h" +#include "World.h" +#include "Config.h" +#include "DisableMgr.h" + +namespace MMAP +{ + // ######################## MMapFactory ######################## + // our global singleton copy + MMapManager *g_MMapManager = NULL; + + MMapManager* MMapFactory::createOrGetMMapManager() + { + if (g_MMapManager == NULL) + g_MMapManager = new MMapManager(); + + return g_MMapManager; + } + + bool MMapFactory::IsPathfindingEnabled(uint32 mapId) + { + return sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) + && !DisableMgr::IsDisabledFor(DISABLE_TYPE_MMAP, mapId, NULL, MMAP_DISABLE_PATHFINDING); + } + + void MMapFactory::clear() + { + if (g_MMapManager) + { + 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 new file mode 100644 index 00000000000..038d44a941c --- /dev/null +++ b/src/server/collision/Management/MMapFactory.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +#ifndef _MMAP_FACTORY_H +#define _MMAP_FACTORY_H + +#include "MMapManager.h" +#include "UnorderedMap.h" +#include "DetourAlloc.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" + +namespace MMAP +{ + enum MMAP_LOAD_RESULT + { + MMAP_LOAD_RESULT_ERROR, + MMAP_LOAD_RESULT_OK, + MMAP_LOAD_RESULT_IGNORED + }; + + // static class + // holds all mmap global data + // access point to MMapManager singleton + class MMapFactory + { + public: + static MMapManager* createOrGetMMapManager(); + static void clear(); + static bool IsPathfindingEnabled(uint32 mapId); + }; +} + +#endif + diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp new file mode 100644 index 00000000000..e3ed8f3310a --- /dev/null +++ b/src/server/collision/Management/MMapManager.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +#include "MMapManager.h" +#include "Log.h" +#include "World.h" + +namespace MMAP +{ + // ######################## MMapManager ######################## + MMapManager::~MMapManager() + { + 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::loadMapData(uint32 mapId) + { + // we already have this map loaded? + if (loadedMMaps.find(mapId) != loadedMMaps.end()) + return true; + + // load and init dtNavMesh - read parameters from file + 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) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName); + delete [] fileName; + return false; + } + + dtNavMeshParams params; + int count = fread(¶ms, sizeof(dtNavMeshParams), 1, file); + fclose(file); + if (count != 1) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName); + delete [] fileName; + return false; + } + + dtNavMesh* mesh = dtAllocNavMesh(); + ASSERT(mesh); + if (DT_SUCCESS != mesh->init(¶ms)) + { + dtFreeNavMesh(mesh); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); + delete [] fileName; + return false; + } + + delete [] fileName; + + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:loadMapData: Loaded %03i.mmap", mapId); + + // store inside our map list + MMapData* mmap_data = new MMapData(mesh); + mmap_data->mmapLoadedTiles.clear(); + + loadedMMaps.insert(std::pair<uint32, MMapData*>(mapId, mmap_data)); + return true; + } + + 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 (!loadMapData(mapId)) + return false; + + // get this mmap data + MMapData* mmap = loadedMMaps[mapId]; + ASSERT(mmap->navMesh); + + // check if we already have this tile loaded + uint32 packedGridPos = packTileID(x, y); + if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end()) + return false; + + // 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, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); + + FILE *file = fopen(fileName, "rb"); + if (!file) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMap: Could not open mmtile file '%s'", fileName); + delete [] fileName; + return false; + } + delete [] fileName; + + // read header + MmapTileHeader fileHeader; + if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) + { + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); + return false; + } + + if (fileHeader.mmapVersion != MMAP_VERSION) + { + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); + return false; + } + + unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM); + ASSERT(data); + + size_t result = fread(data, fileHeader.size, 1, file); + if (!result) + { + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); + fclose(file); + return false; + } + + fclose(file); + + dtMeshHeader* header = (dtMeshHeader*)data; + dtTileRef tileRef = 0; + + // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed + if (DT_SUCCESS == mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)) + { + mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef)); + ++loadedTiles; + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y); + return true; + } + else + { + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); + dtFree(data); + return false; + } + + return false; + } + + bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) + { + // check if we have this map loaded + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); + return false; + } + + MMapData* mmap = loadedMMaps[mapId]; + + // check if we have this tile loaded + uint32 packedGridPos = packTileID(x, y); + if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); + return false; + } + + dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos]; + + // unload, and mark as non loaded + if (DT_SUCCESS != mmap->navMesh->removeTile(tileRef, NULL, NULL)) + { + // 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 + sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); + ASSERT(false); + } + else + { + mmap->mmapLoadedTiles.erase(packedGridPos); + --loadedTiles; + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId); + return true; + } + + return false; + } + + bool MMapManager::unloadMap(uint32 mapId) + { + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId); + return false; + } + + // unload all tiles from given map + 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 (DT_SUCCESS != mmap->navMesh->removeTile(i->second, NULL, NULL)) + sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); + else + { + --loadedTiles; + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId); + } + } + + delete mmap; + loadedMMaps.erase(mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded %03i.mmap", mapId); + + return true; + } + + bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) + { + // check if we have this map loaded + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); + return false; + } + + MMapData* mmap = loadedMMaps[mapId]; + if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); + return false; + } + + dtNavMeshQuery* query = mmap->navMeshQueries[instanceId]; + + dtFreeNavMeshQuery(query); + mmap->navMeshQueries.erase(instanceId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); + + return true; + } + + dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId) + { + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + return NULL; + + return loadedMMaps[mapId]->navMesh; + } + + dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) + { + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + return NULL; + + MMapData* mmap = loadedMMaps[mapId]; + if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + { + // allocate mesh query + dtNavMeshQuery* query = dtAllocNavMeshQuery(); + ASSERT(query); + if (DT_SUCCESS != query->init(mmap->navMesh, 1024)) + { + dtFreeNavMeshQuery(query); + sLog->outError(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + return NULL; + } + + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); + } + + return mmap->navMeshQueries[instanceId]; + } +} diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h new file mode 100644 index 00000000000..56b1b856d65 --- /dev/null +++ b/src/server/collision/Management/MMapManager.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> + * + * 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/>. + */ + +#ifndef _MMAP_MANAGER_H +#define _MMAP_MANAGER_H + +#include "UnorderedMap.h" +#include "DetourAlloc.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" + +// move map related classes +namespace MMAP +{ + typedef UNORDERED_MAP<uint32, dtTileRef> MMapTileSet; + typedef UNORDERED_MAP<uint32, dtNavMeshQuery*> NavMeshQuerySet; + + // dummy struct to hold map's mmap data + struct MMapData + { + MMapData(dtNavMesh* mesh) : navMesh(mesh) {} + ~MMapData() + { + for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i) + dtFreeNavMeshQuery(i->second); + + if (navMesh) + dtFreeNavMesh(navMesh); + } + + dtNavMesh* navMesh; + + // we have to use single dtNavMeshQuery for every instance, since those are not thread safe + NavMeshQuerySet navMeshQueries; // instanceId to query + MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile] + }; + + + typedef UNORDERED_MAP<uint32, MMapData*> MMapDataSet; + + // singleton class + // holds all all access to mmap loading unloading and meshes + class MMapManager + { + public: + MMapManager() : loadedTiles(0) {} + ~MMapManager(); + + 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 loadedMMaps.size(); } + private: + bool loadMapData(uint32 mapId); + uint32 packTileID(int32 x, int32 y); + + MMapDataSet loadedMMaps; + uint32 loadedTiles; + }; +} + +#endif
\ No newline at end of file diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 5e3741ca753..8a1bd346957 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -24,13 +24,13 @@ #include "MapTree.h" #include "ModelInstance.h" #include "WorldModel.h" -#include "VMapDefinitions.h" -#include "Log.h" #include <G3D/Vector3.h> #include <ace/Null_Mutex.h> #include <ace/Singleton.h> #include "DisableMgr.h" #include "DBCStores.h" +#include "Log.h" +#include "VMapDefinitions.h" using G3D::Vector3; @@ -257,11 +257,11 @@ namespace VMAP WorldModel* worldmodel = new WorldModel(); if (!worldmodel->readFile(basepath + filename + ".vmo")) { - sLog->outError(LOG_FILTER_GENERAL, "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); delete worldmodel; return NULL; } - sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first; model->second.setModel(worldmodel); } @@ -277,12 +277,12 @@ namespace VMAP ModelFileMap::iterator model = iLoadedModelFiles.find(filename); if (model == iLoadedModelFiles.end()) { - sLog->outError(LOG_FILTER_GENERAL, "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); return; } if (model->second.decRefCount() == 0) { - sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: unloading file '%s'", filename.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "VMapManager2: unloading file '%s'", filename.c_str()); delete model->second.getModel(); iLoadedModelFiles.erase(model); } diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h index e2e9965dbfc..51f15f0fda4 100644 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/server/collision/Management/VMapManager2.h @@ -112,6 +112,8 @@ namespace VMAP return getMapFileName(mapId); } virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y); + public: + void getInstanceMapTree(InstanceTreeMap &instanceMapTree); }; } diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index 5f4e2b6aa8b..bd925d5a0c4 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -21,18 +21,13 @@ #include "VMapManager2.h" #include "VMapDefinitions.h" #include "Log.h" +#include "Errors.h" #include <string> #include <sstream> #include <iomanip> #include <limits> -#ifndef NO_CORE_FUNCS - #include "Errors.h" -#else - #define ASSERT(x) -#endif - using G3D::Vector3; namespace VMAP @@ -248,7 +243,7 @@ namespace VMAP FILE* rf = fopen(fullname.c_str(), "rb"); if (!rf) return false; - // TODO: check magic number when implemented... + /// @todo check magic number when implemented... char tiled; char chunk[8]; if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1) @@ -277,7 +272,7 @@ namespace VMAP bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm) { - sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); bool success = true; std::string fullname = iBasePath + fname; FILE* rf = fopen(fullname.c_str(), "rb"); @@ -310,7 +305,7 @@ namespace VMAP if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) { WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); if (model) { // assume that global model always is the first and only tree value (could be improved...) @@ -320,7 +315,7 @@ namespace VMAP else { success = false; - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); } } @@ -356,7 +351,7 @@ namespace VMAP } if (!iTreeValues) { - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); return false; } bool result = true; @@ -382,7 +377,7 @@ namespace VMAP // acquire model instance WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); if (!model) - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); // update tree uint32 referencedVal; @@ -432,7 +427,7 @@ namespace VMAP loadedTileMap::iterator tile = iLoadedTiles.find(tileID); if (tile == iLoadedTiles.end()) { - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); return; } if (tile->second) // file associated with tile @@ -466,7 +461,7 @@ namespace VMAP else { if (!iLoadedSpawns.count(referencedNode)) - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); else if (--iLoadedSpawns[referencedNode] == 0) { iTreeValues[referencedNode].setUnloaded(); @@ -480,5 +475,4 @@ namespace VMAP } iLoadedTiles.erase(tile); } - } diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h index bd928d85c5a..e97c44d089e 100644 --- a/src/server/collision/Maps/MapTree.h +++ b/src/server/collision/Maps/MapTree.h @@ -31,7 +31,7 @@ namespace VMAP struct LocationInfo { - LocationInfo(): hitInstance(0), hitModel(0), ground_Z(-G3D::inf()) {}; + LocationInfo(): hitInstance(0), hitModel(0), ground_Z(-G3D::inf()) {} const ModelInstance* hitInstance; const GroupModel* hitModel; float ground_Z; @@ -72,7 +72,7 @@ namespace VMAP bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const; bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; - bool GetLocationInfo(const Vector3 &pos, LocationInfo &info) const; + bool GetLocationInfo(const G3D::Vector3 &pos, LocationInfo &info) const; bool InitMap(const std::string &fname, VMapManager2* vm); void UnloadMap(VMapManager2* vm); @@ -80,11 +80,12 @@ namespace VMAP void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); bool isTiled() const { return iIsTiled; } uint32 numLoadedTiles() const { return iLoadedTiles.size(); } + void getModelInstances(ModelInstance* &models, uint32 &count); }; struct AreaInfo { - AreaInfo(): result(false), ground_Z(-G3D::inf()) {}; + AreaInfo(): result(false), ground_Z(-G3D::inf()) {} bool result; float ground_Z; uint32 flags; diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index 380d6b5df21..ba1ae275c9a 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -88,7 +88,7 @@ namespace VMAP } else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ { - // TODO: remove extractor hack and uncomment below line: + /// @todo remove extractor hack and uncomment below line: //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); } @@ -380,11 +380,11 @@ namespace VMAP } } - fwrite(&displayId,sizeof(uint32),1,model_list_copy); - fwrite(&name_length,sizeof(uint32),1,model_list_copy); - fwrite(&buff,sizeof(char),name_length,model_list_copy); - fwrite(&bounds.low(),sizeof(Vector3),1,model_list_copy); - fwrite(&bounds.high(),sizeof(Vector3),1,model_list_copy); + fwrite(&displayId, sizeof(uint32), 1, model_list_copy); + fwrite(&name_length, sizeof(uint32), 1, model_list_copy); + fwrite(&buff, sizeof(char), name_length, model_list_copy); + fwrite(&bounds.low(), sizeof(Vector3), 1, model_list_copy); + fwrite(&bounds.high(), sizeof(Vector3), 1, model_list_copy); } fclose(model_list); diff --git a/src/server/collision/Maps/TileAssembler.h b/src/server/collision/Maps/TileAssembler.h index 087c2021b50..a11ce272d62 100644 --- a/src/server/collision/Maps/TileAssembler.h +++ b/src/server/collision/Maps/TileAssembler.h @@ -72,12 +72,12 @@ namespace VMAP uint32 liquidflags; std::vector<MeshTriangle> triangles; std::vector<G3D::Vector3> vertexArray; - class WmoLiquid *liquid; + class WmoLiquid* liquid; GroupModel_Raw() : liquid(0) {} ~GroupModel_Raw(); - bool Read(FILE * f); + bool Read(FILE* f); }; struct WorldModel_Raw diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp index 237a5b33621..e166a860cd2 100644 --- a/src/server/collision/Models/GameObjectModel.cpp +++ b/src/server/collision/Models/GameObjectModel.cpp @@ -34,8 +34,6 @@ using G3D::Vector3; using G3D::Ray; using G3D::AABox; -#ifndef NO_CORE_FUNCS - struct GameobjectModelData { GameobjectModelData(const std::string& name_, const AABox& box) : @@ -50,11 +48,14 @@ ModelList model_list; void LoadGameObjectModelList() { +#ifndef NO_CORE_FUNCS uint32 oldMSTime = getMSTime(); +#endif + FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb"); if (!model_list_file) { - sLog->outError(LOG_FILTER_GENERAL, "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS); return; } @@ -73,19 +74,18 @@ void LoadGameObjectModelList() || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1 || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1) { - sLog->outError(LOG_FILTER_GENERAL, "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); break; } model_list.insert ( - ModelList::value_type( displayId, GameobjectModelData(std::string(buff,name_length),AABox(v1,v2)) ) + ModelList::value_type( displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2)) ) ); } fclose(model_list_file); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime)); - + VMAP_INFO_LOG(LOG_FILTER_SERVER_LOADING, ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime)); } GameObjectModel::~GameObjectModel() @@ -104,7 +104,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn // ignore models with no bounds if (mdl_box == G3D::AABox::zero()) { - sLog->outError(LOG_FILTER_GENERAL, "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); return false; } @@ -184,5 +184,3 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto } return hit; } - -#endif diff --git a/src/server/collision/Models/ModelInstance.h b/src/server/collision/Models/ModelInstance.h index 5af02a1d1b1..f26089bb46c 100644 --- a/src/server/collision/Models/ModelInstance.h +++ b/src/server/collision/Models/ModelInstance.h @@ -74,6 +74,8 @@ namespace VMAP G3D::Matrix3 iInvRot; float iInvScale; WorldModel* iModel; + public: + WorldModel* getWorldModel(); }; } // namespace VMAP diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h index 8e046e561f7..9d588316cce 100644 --- a/src/server/collision/Models/WorldModel.h +++ b/src/server/collision/Models/WorldModel.h @@ -36,8 +36,8 @@ namespace VMAP class MeshTriangle { public: - MeshTriangle(){}; - MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) {}; + MeshTriangle(){} + MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) {} uint32 idx0; uint32 idx1; @@ -47,11 +47,11 @@ namespace VMAP class WmoLiquid { public: - WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type); + WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type); WmoLiquid(const WmoLiquid &other); ~WmoLiquid(); WmoLiquid& operator=(const WmoLiquid &other); - bool GetLiquidHeight(const Vector3 &pos, float &liqHeight) const; + bool GetLiquidHeight(const G3D::Vector3 &pos, float &liqHeight) const; uint32 GetType() const { return iType; } float *GetHeightStorage() { return iHeight; } uint8 *GetFlagsStorage() { return iFlags; } @@ -59,13 +59,15 @@ namespace VMAP bool writeToFile(FILE* wf); static bool readFromFile(FILE* rf, WmoLiquid* &liquid); private: - WmoLiquid(): iHeight(0), iFlags(0) {}; - uint32 iTilesX; //!< number of tiles in x direction, each + WmoLiquid(): iHeight(0), iFlags(0) {} + uint32 iTilesX; //!< number of tiles in x direction, each uint32 iTilesY; - Vector3 iCorner; //!< the lower corner - uint32 iType; //!< liquid type - float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values - uint8 *iFlags; //!< info if liquid tile is used + G3D::Vector3 iCorner; //!< the lower corner + uint32 iType; //!< liquid type + float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values + uint8 *iFlags; //!< info if liquid tile is used + public: + void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const; }; /*! holding additional info for WMO group files */ @@ -74,16 +76,16 @@ namespace VMAP public: GroupModel(): iLiquid(0) {} GroupModel(const GroupModel &other); - GroupModel(uint32 mogpFlags, uint32 groupWMOID, const AABox &bound): + GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound): iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) {} ~GroupModel() { delete iLiquid; } //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! - void setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri); + void setMeshData(std::vector<G3D::Vector3> &vert, std::vector<MeshTriangle> &tri); void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; } bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; - bool IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const; - bool GetLiquidLevel(const Vector3 &pos, float &liqHeight) const; + bool IsInsideObject(const G3D::Vector3 &pos, const G3D::Vector3 &down, float &z_dist) const; + bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const; uint32 GetLiquidType() const; bool writeToFile(FILE* wf); bool readFromFile(FILE* rf); @@ -94,10 +96,12 @@ namespace VMAP G3D::AABox iBound; uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor uint32 iGroupWMOID; - std::vector<Vector3> vertices; + std::vector<G3D::Vector3> vertices; std::vector<MeshTriangle> triangles; BIH meshTree; WmoLiquid* iLiquid; + public: + void getMeshData(std::vector<G3D::Vector3> &vertices, std::vector<MeshTriangle> &triangles, WmoLiquid* &liquid); }; /*! Holds a model (converted M2 or WMO) in its original coordinate space */ class WorldModel @@ -117,6 +121,8 @@ namespace VMAP uint32 RootWMOID; std::vector<GroupModel> groupModels; BIH groupTree; + public: + void getGroupModels(std::vector<GroupModel> &groupModels); }; } // namespace VMAP diff --git a/src/server/collision/RegularGrid.h b/src/server/collision/RegularGrid.h index 5b7d1d74987..d1832c1ea06 100644 --- a/src/server/collision/RegularGrid.h +++ b/src/server/collision/RegularGrid.h @@ -3,18 +3,12 @@ #include <G3D/Ray.h> -#include <G3D/AABox.h> #include <G3D/Table.h> #include <G3D/BoundsTrait.h> #include <G3D/PositionTrait.h> #include "Errors.h" -using G3D::Vector2; -using G3D::Vector3; -using G3D::AABox; -using G3D::Ray; - template<class Node> struct NodeCreator{ static Node * makeNode(int /*x*/, int /*y*/) { return new Node();} @@ -54,7 +48,7 @@ public: void insert(const T& value) { - Vector3 pos; + G3D::Vector3 pos; PositionFunc::getPosition(value, pos); Node& node = getGridFor(pos.x, pos.y); node.insert(value); @@ -104,18 +98,18 @@ public: { ASSERT(x < CELL_NUMBER && y < CELL_NUMBER); if (!nodes[x][y]) - nodes[x][y] = NodeCreatorFunc::makeNode(x,y); + nodes[x][y] = NodeCreatorFunc::makeNode(x, y); return *nodes[x][y]; } template<typename RayCallback> - void intersectRay(const Ray& ray, RayCallback& intersectCallback, float max_dist) + void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float max_dist) { intersectRay(ray, intersectCallback, max_dist, ray.origin() + ray.direction() * max_dist); } template<typename RayCallback> - void intersectRay(const Ray& ray, RayCallback& intersectCallback, float& max_dist, const Vector3& end) + void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist, const G3D::Vector3& end) { Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); if (!cell.isValid()) @@ -191,7 +185,7 @@ public: } template<typename IsectCallback> - void intersectPoint(const Vector3& point, IsectCallback& intersectCallback) + void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback) { Cell cell = Cell::ComputeCell(point.x, point.y); if (!cell.isValid()) @@ -202,7 +196,7 @@ public: // Optimized verson of intersectRay function for rays with vertical directions template<typename RayCallback> - void intersectZAllignedRay(const Ray& ray, RayCallback& intersectCallback, float& max_dist) + void intersectZAllignedRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist) { Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); if (!cell.isValid()) diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h index 609d00cd00f..bb0766dc8ff 100644 --- a/src/server/collision/VMapDefinitions.h +++ b/src/server/collision/VMapDefinitions.h @@ -31,4 +31,16 @@ namespace VMAP // defined in TileAssembler.cpp currently... bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len); } + +// Set of helper macros for extractors (VMAP and MMAP) +#ifndef NO_CORE_FUNCS +#define VMAP_ERROR_LOG(FILTER, ...) sLog->outError(FILTER, __VA_ARGS__) +#define VMAP_DEBUG_LOG(FILTER, ...) sLog->outDebug(FILTER, __VA_ARGS__) +#define VMAP_INFO_LOG(FILTER, ...) sLog->outInfo(FILTER, __VA_ARGS__) +#else +#define VMAP_ERROR_LOG(FILTER, ...) (void)sizeof(FILTER) +#define VMAP_DEBUG_LOG(FILTER, ...) (void)sizeof(FILTER) +#define VMAP_INFO_LOG(FILTER, ...) (void)sizeof(FILTER) +#endif + #endif |
