diff options
Diffstat (limited to 'src/server/collision/Maps/MapTree.cpp')
-rw-r--r-- | src/server/collision/Maps/MapTree.cpp | 121 |
1 files changed, 75 insertions, 46 deletions
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index 8c77ee109f3..b47e34b2b72 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -1,29 +1,37 @@ /* + * Copyright (C) 2008-2010 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 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. + * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * 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 "MapTree.h" #include "ModelInstance.h" #include "VMapManager2.h" #include "VMapDefinitions.h" +#include "Log.h" #include <string> #include <sstream> #include <iomanip> +#include <limits> + +#ifndef NO_CORE_FUNCS + #include "Errors.h" +#else + #define ASSERT(x) +#endif using G3D::Vector3; @@ -33,13 +41,18 @@ namespace VMAP class MapRayCallback { public: - MapRayCallback(ModelInstance *val): prims(val) {} - ModelInstance *prims; + MapRayCallback(ModelInstance *val): prims(val), hit(false) {} bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) { - return prims[entry].intersectRay(ray, distance, pStopAtFirstHit); - //std::cout << "trying to intersect '" << entity->name << "'\n"; + bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit); + if (result) + hit = true; + return result; } + bool didHit() { return hit; } + protected: + ModelInstance *prims; + bool hit; }; class AreaInfoCallback @@ -49,7 +62,7 @@ namespace VMAP void operator()(const Vector3& point, uint32 entry) { #ifdef VMAP_DEBUG - std::cout << "trying to intersect '" << prims[entry].name << "'\n"; + sLog.outDebug("AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); #endif prims[entry].intersectPoint(point, aInfo); } @@ -65,7 +78,7 @@ namespace VMAP void operator()(const Vector3& point, uint32 entry) { #ifdef VMAP_DEBUG - std::cout << "trying to intersect '" << prims[entry].name << "'\n"; + sLog.outDebug("LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); #endif if (prims[entry].GetLocationInfo(point, locInfo)) result = true; @@ -113,7 +126,7 @@ namespace VMAP } StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath): - iMapID(mapID), /* iTree(0), */ iTreeValues(0), iBasePath(basePath) + iMapID(mapID), iTreeValues(0), iBasePath(basePath) { if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\')) { @@ -130,33 +143,35 @@ namespace VMAP //========================================================= /** - return dist to hit or inf() if no hit + If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true. + Else, pMaxDist is not modified and returns false; */ - float StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const + bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const { float distance = pMaxDist; MapRayCallback intersectionCallBack(iTreeValues); iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit); - return distance; + if (intersectionCallBack.didHit()) + pMaxDist = distance; + return intersectionCallBack.didHit(); } //========================================================= bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const { - bool result = true; float maxDist = (pos2 - pos1).magnitude(); + // valid map coords should *never ever* produce float overflow, but this would produce NaNs too + ASSERT(maxDist < std::numeric_limits<float>::max()); // prevent NaN values which can cause BIH intersection to enter infinite loop if (maxDist < 1e-10f) return true; // direction with length of 1 G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist); - float resultDist = getIntersectionTime(ray, maxDist, true); - if (resultDist < maxDist) - { - result = false; - } - return result; + if (getIntersectionTime(ray, maxDist, true)) + return false; + + return true; } //========================================================= /** @@ -168,6 +183,8 @@ namespace VMAP { bool result=false; float maxDist = (pPos2 - pPos1).magnitude(); + // valid map coords should *never ever* produce float overflow, but this would produce NaNs too + ASSERT(maxDist < std::numeric_limits<float>::max()); // prevent NaN values which can cause BIH intersection to enter infinite loop if (maxDist < 1e-10f) { @@ -176,8 +193,8 @@ namespace VMAP } Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 G3D::Ray ray(pPos1, dir); - float dist = getIntersectionTime(ray, maxDist, false); - if (dist < maxDist) + float dist = maxDist; + if (getIntersectionTime(ray, dist, false)) { pResultHitPos = pPos1 + dir * dist; if (pModifyDist < 0) @@ -213,10 +230,9 @@ namespace VMAP Vector3 dir = Vector3(0,0,-1); G3D::Ray ray(pPos, dir); // direction with length of 1 float maxDist = VMapDefinitions::getMaxCanFallDistance(); - float dist = getIntersectionTime(ray, maxDist, false); - if (dist < maxDist) + if (getIntersectionTime(ray, maxDist, false)) { - height = pPos.z - dist; + height = pPos.z - maxDist; } return(height); } @@ -248,7 +264,11 @@ namespace VMAP if (!tf) success = false; else + { + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + success = false; fclose(tf); + } } fclose(rf); return success; @@ -258,7 +278,7 @@ namespace VMAP bool StaticMapTree::InitMap(const std::string &fname, VMapManager2 *vm) { - std::cout << "Initializing StaticMapTree '" << fname << "'\n"; + sLog.outDebug("StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); bool success = true; std::string fullname = iBasePath + fname; FILE *rf = fopen(fullname.c_str(), "rb"); @@ -286,12 +306,12 @@ namespace VMAP // only non-tiled maps have them, and if so exactly one (so far at least...) ModelSpawn spawn; #ifdef VMAP_DEBUG - std::cout << "Map isTiled:" << bool(iIsTiled) << std::endl; + sLog.outDebug("StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled)); #endif if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) { WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name); - std::cout << "StaticMapTree::InitMap(): loading " << spawn.name << std::endl; + sLog.outDebug("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...) @@ -301,7 +321,7 @@ namespace VMAP else { success = false; - std::cout << "error: could not acquire WorldModel pointer!\n"; + sLog.outError("StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); } } @@ -337,7 +357,7 @@ namespace VMAP } if (!iTreeValues) { - std::cout << "Tree has not been initialized!\n"; + sLog.outError("StaticMapTree::LoadMapTile() : tree has not been initialized [%u,%u]", tileX, tileY); return false; } bool result = true; @@ -346,8 +366,12 @@ namespace VMAP FILE* tf = fopen(tilefile.c_str(), "rb"); if (tf) { + char chunk[8]; + + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + result = false; uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) + if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1) result = false; for (uint32 i=0; i<numSpawns && result; ++i) { @@ -358,7 +382,8 @@ namespace VMAP { // acquire model instance WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name); - if (!model) std::cout << "error: could not acquire WorldModel pointer!\n"; + if (!model) + sLog.outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u,%u]", tileX, tileY); // update tree uint32 referencedVal; @@ -369,7 +394,7 @@ namespace VMAP #ifdef VMAP_DEBUG if (referencedVal > iNTreeValues) { - std::cout << "invalid tree element! (" << referencedVal << "/" << iNTreeValues << ")\n"; + sLog.outDebug("StaticMapTree::LoadMapTile() : invalid tree element (%u/%u)", referencedVal, iNTreeValues); continue; } #endif @@ -380,8 +405,10 @@ namespace VMAP { ++iLoadedSpawns[referencedVal]; #ifdef VMAP_DEBUG - if (iTreeValues[referencedVal].ID != spawn.ID) std::cout << "error: trying to load wrong spawn in node!\n"; - else if (iTreeValues[referencedVal].name != spawn.name) std::cout << "error: name collision on GUID="<< spawn.ID << "\n"; + if (iTreeValues[referencedVal].ID != spawn.ID) + sLog.outDebug("StaticMapTree::LoadMapTile() : trying to load wrong spawn in node"); + else if (iTreeValues[referencedVal].name != spawn.name) + sLog.outDebug("StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID); #endif } } @@ -402,7 +429,7 @@ namespace VMAP loadedTileMap::iterator tile = iLoadedTiles.find(tileID); if (tile == iLoadedTiles.end()) { - std::cout << "WARNING: trying to unload non-loaded tile. Map:" << iMapID << " X:" << tileX << " Y:" << tileY << std::endl; + sLog.outError("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 @@ -412,6 +439,9 @@ namespace VMAP if (tf) { bool result=true; + char chunk[8]; + if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + result = false; uint32 numSpawns; if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) result = false; @@ -431,11 +461,10 @@ namespace VMAP fread(&referencedNode, sizeof(uint32), 1, tf); if (!iLoadedSpawns.count(referencedNode)) { - std::cout << "error! trying to unload non-referenced model '" << spawn.name << "' (ID:" << spawn.ID << ")\n"; + sLog.outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); } else if (--iLoadedSpawns[referencedNode] == 0) { - //std::cout << "MapTree: removing '" << spawn.name << "' from tree\n"; iTreeValues[referencedNode].setUnloaded(); iLoadedSpawns.erase(referencedNode); } |