refactor(Core/Misc): add braces and impove codestyle (#6402)

This commit is contained in:
Kargatum
2021-06-25 00:50:18 +07:00
committed by GitHub
parent 33c271cc7c
commit 3c24b511f2
72 changed files with 1486 additions and 401 deletions

View File

@@ -47,7 +47,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
// perform quick consistency checks
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++)
{
if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i])
@@ -76,7 +78,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
// stay left
i++;
if (clipL < maxb)
{
clipL = maxb;
}
}
else
{
@@ -86,7 +90,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
dat.indices[right] = t;
right--;
if (clipR > minb)
{
clipR = minb;
}
}
nodeL = std::min(nodeL, minb);
nodeR = std::max(nodeR, maxb);
@@ -212,7 +218,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
tempTree.push_back(0);
}
else
{
nextIndex -= 3;
}
// allocate right node
if (nr > 0)
{
@@ -233,13 +241,21 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
nodeBoxR.lo[axis] = clipR;
// recurse
if (nl > 0)
{
subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
}
else
{
stats.updateLeaf(depth + 1, 0);
}
if (nr > 0)
{
subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats);
}
else
{
stats.updateLeaf(depth + 1, 0);
}
}
bool BIH::writeToFile(FILE* wf) const

View File

@@ -90,11 +90,15 @@ public:
BuildStats stats;
buildHierarchy(tempTree, dat, stats);
if (printStats)
{
stats.printStats();
}
objects.resize(dat.numPrims);
for (uint32 i = 0; i < dat.numPrims; ++i)
{
objects[i] = dat.indices[i];
}
//nObjects = dat.numPrims;
tree = tempTree;
delete[] dat.primBound;
@@ -118,20 +122,30 @@ public:
float t1 = (bounds.low()[i] - org[i]) * invDir[i];
float t2 = (bounds.high()[i] - org[i]) * invDir[i];
if (t1 > t2)
{
std::swap(t1, t2);
}
if (t1 > intervalMin)
{
intervalMin = t1;
}
if (t2 < intervalMax || intervalMax < 0.f)
{
intervalMax = t2;
}
// intervalMax can only become smaller for other axis,
// and intervalMin only larger respectively, so stop early
if (intervalMax <= 0 || intervalMin >= maxDist)
{
return;
}
}
}
if (intervalMin > intervalMax)
{
return;
}
intervalMin = std::max(intervalMin, 0.f);
intervalMax = std::min(intervalMax, maxDist);
@@ -174,7 +188,9 @@ public:
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
// ray passes between clip zones
if (tf < intervalMin && tb > intervalMax)
{
break;
}
int back = offset + offsetBack3[axis];
node = back;
// ray passes through far node only
@@ -207,7 +223,7 @@ public:
while (n > 0)
{
bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit);
if (stopAtFirstHit && hit) return;
if (stopAtFirstHit && hit) { return; }
--n;
++offset;
}
@@ -217,14 +233,18 @@ public:
else
{
if (axis > 2)
return; // should not happen
{
return; // should not happen
}
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
node = offset;
intervalMin = (tf >= intervalMin) ? tf : intervalMin;
intervalMax = (tb <= intervalMax) ? tb : intervalMax;
if (intervalMin > intervalMax)
{
break;
}
continue;
}
} // traversal loop
@@ -232,12 +252,16 @@ public:
{
// stack is empty?
if (stackPos == 0)
{
return;
}
// move back up the stack
stackPos--;
intervalMin = stack[stackPos].tnear;
if (maxDist < intervalMin)
{
continue;
}
node = stack[stackPos].node;
intervalMax = stack[stackPos].tfar;
break;
@@ -249,7 +273,9 @@ public:
void intersectPoint(const G3D::Vector3& p, IsectCallback& intersectCallback) const
{
if (!bounds.contains(p))
{
return;
}
StackNode stack[MAX_STACK_SIZE];
int stackPos = 0;
@@ -272,7 +298,9 @@ public:
float tr = intBitsToFloat(tree[node + 2]);
// point is between clip zones
if (tl < p[axis] && tr > p[axis])
{
break;
}
int right = offset + 3;
node = right;
// point is in right node only
@@ -308,19 +336,25 @@ public:
else // BVH2 node (empty space cut off left and right)
{
if (axis > 2)
return; // should not happen
{
return; // should not happen
}
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
node = offset;
if (tl > p[axis] || tr < p[axis])
{
break;
}
continue;
}
} // traversal loop
// stack is empty?
if (stackPos == 0)
{
return;
}
// move back up the stack
stackPos--;
node = stack[stackPos].node;
@@ -366,7 +400,7 @@ protected:
public:
BuildStats()
{
for (int & i : numLeavesN) i = 0;
for (int& i : numLeavesN) { i = 0; }
}
void updateInner() { numNodes++; }

View File

@@ -28,9 +28,13 @@ class BIHWrap
bool operator() (const G3D::Ray& ray, uint32 idx, float& maxDist, bool stopAtFirstHit)
{
if (idx >= objects_size)
{
return false;
}
if (const T* obj = objects[idx])
{
return _callback(ray, *obj, maxDist, stopAtFirstHit);
}
return false;
}
@@ -38,9 +42,13 @@ class BIHWrap
void operator() (const G3D::Vector3& p, uint32 idx)
{
if (idx >= objects_size)
{
return;
}
if (const T* obj = objects[idx])
{
_callback(p, *obj);
}
}
};
@@ -67,15 +75,21 @@ public:
uint32 Idx = 0;
const T* temp;
if (m_obj2Idx.getRemove(&obj, temp, Idx))
{
m_objects[Idx] = nullptr;
}
else
{
m_objects_to_push.remove(&obj);
}
}
void balance()
{
if (unbalanced_times == 0)
{
return;
}
unbalanced_times = 0;
m_objects.fastClear();

View File

@@ -72,14 +72,18 @@ struct DynTreeImpl : public ParentTree
void update(uint32 difftime)
{
if (!size())
{
return;
}
rebalance_timer.Update(difftime);
if (rebalance_timer.Passed())
{
rebalance_timer.Reset(CHECK_TREE_PERIOD);
if (unbalanced_times > 0)
{
balance();
}
}
}
@@ -133,7 +137,9 @@ struct DynamicTreeIntersectionCallback
{
bool result = obj.intersectRay(r, distance, stopAtFirstHit, phase_mask);
if (result)
{
did_hit = result;
}
return result;
}
bool didHit() const { return did_hit;}
@@ -146,7 +152,9 @@ bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray&
DynamicTreeIntersectionCallback callback(phasemask);
impl->intersectRay(ray, callback, distance, endPos, false);
if (callback.didHit())
{
maxDist = distance;
}
return callback.didHit();
}
@@ -173,12 +181,18 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3&
if (modifyDist < 0)
{
if ((resultHit - startPos).magnitude() > -modifyDist)
{
resultHit = resultHit + dir * modifyDist;
}
else
{
resultHit = startPos;
}
}
else
{
resultHit = resultHit + dir * modifyDist;
}
result = true;
}
@@ -197,7 +211,9 @@ bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, flo
float maxDist = (v2 - v1).magnitude();
if (!G3D::fuzzyGt(maxDist, 0) )
{
return true;
}
G3D::Ray r(v1, (v2 - v1) / maxDist);
DynamicTreeIntersectionCallback callback(phasemask);
@@ -214,7 +230,11 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist,
impl->intersectZAllignedRay(r, callback, maxSearchDist);
if (callback.didHit())
{
return v.z - maxSearchDist;
}
else
{
return -G3D::finf();
}
}

View File

@@ -27,7 +27,7 @@ public:
~DynamicMapTree();
[[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2,
float z2, uint32 phasemask) const;
float z2, uint32 phasemask) const;
bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray,
const G3D::Vector3& endPos, float& maxDist) const;

View File

@@ -18,7 +18,9 @@ namespace MMAP
MMapManager* MMapFactory::createOrGetMMapManager()
{
if (g_MMapManager == nullptr)
{
g_MMapManager = new MMapManager();
}
return g_MMapManager;
}
@@ -29,7 +31,9 @@ namespace MMAP
int32 f[] = {616 /*EoE*/, 649 /*ToC25*/, 650 /*ToC5*/, -1};
uint32 i = 0;
while (f[i] >= 0)
{
forbiddenMaps[f[i++]] = true;
}
}
void MMapFactory::clear()

View File

@@ -20,7 +20,9 @@ namespace MMAP
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!
@@ -30,7 +32,9 @@ namespace MMAP
{
// the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
for (const uint32& mapId : mapIds)
{
loadedMMaps.emplace(mapId, nullptr);
}
thread_safe_environment = false;
}
@@ -40,7 +44,9 @@ namespace MMAP
// return the iterator if found or end() if not found/NULL
MMapDataSet::const_iterator itr = loadedMMaps.find(mapId);
if (itr != loadedMMaps.cend() && !itr->second)
{
itr = loadedMMaps.cend();
}
return itr;
}
@@ -52,14 +58,20 @@ namespace MMAP
if (itr != loadedMMaps.end())
{
if (itr->second)
{
return true;
}
}
else
{
if (thread_safe_environment)
{
itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first;
}
else
{
ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId);
}
}
// load and init dtNavMesh - read parameters from file
@@ -107,7 +119,9 @@ namespace MMAP
{
// make sure the mmap is loaded and ready to load tiles
if (!loadMapData(mapId))
{
return false;
}
// get this mmap data
MMapData* mmap = loadedMMaps[mapId];
@@ -243,7 +257,9 @@ namespace MMAP
uint32 y = (i.first & 0x0000FFFF);
if (dtStatusFailed(mmap->navMesh->removeTile(i.second, nullptr, nullptr)))
{
LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
}
else
{
--loadedTiles;
@@ -289,7 +305,9 @@ namespace MMAP
{
MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end())
{
return nullptr;
}
return itr->second->navMesh;
}
@@ -298,7 +316,9 @@ namespace MMAP
{
MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end())
{
return nullptr;
}
MMapData* mmap = itr->second;
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())

View File

@@ -40,10 +40,14 @@ namespace MMAP
~MMapData()
{
for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
{
dtFreeNavMeshQuery(i->second);
}
if (navMesh)
{
dtFreeNavMesh(navMesh);
}
}
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe

View File

@@ -16,7 +16,9 @@ namespace VMAP
VMapManager2* VMapFactory::createOrGetVMapManager()
{
if (!gVMapManager)
{
gVMapManager = new VMapManager2();
}
return gVMapManager;
}

View File

@@ -57,7 +57,9 @@ namespace VMAP
{
// the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
for (const uint32& mapId : mapIds)
{
iInstanceMapTrees.emplace(mapId, nullptr);
}
thread_safe_environment = false;
}
@@ -78,7 +80,9 @@ namespace VMAP
// return the iterator if found or end() if not found/NULL
InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId);
if (itr != iInstanceMapTrees.cend() && !itr->second)
{
itr = iInstanceMapTrees.cend();
}
return itr;
}
@@ -99,9 +103,13 @@ namespace VMAP
if (isMapLoadingEnabled())
{
if (_loadMap(mapId, basePath, x, y))
{
result = VMAP_LOAD_RESULT_OK;
}
else
{
result = VMAP_LOAD_RESULT_ERROR;
}
}
return result;
@@ -114,10 +122,12 @@ namespace VMAP
if (instanceTree == iInstanceMapTrees.end())
{
if (thread_safe_environment)
{
instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
}
else
ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment",
mapId, tileX, tileY);
mapId, tileX, tileY);
}
if (!instanceTree->second)
@@ -167,7 +177,9 @@ namespace VMAP
{
#if defined(ENABLE_VMAP_CHECKS)
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
{
return true;
}
#endif
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
@@ -232,7 +244,9 @@ namespace VMAP
Vector3 pos = convertPositionToInternalRep(x, y, z);
float height = instanceTree->second->getHeight(pos, maxSearchDist);
if (!(height < G3D::finf()))
return height = VMAP_INVALID_HEIGHT_VALUE; // No height
{
return height = VMAP_INVALID_HEIGHT_VALUE; // No height
}
return height;
}
@@ -278,9 +292,13 @@ namespace VMAP
ASSERT(floor < std::numeric_limits<float>::max());
type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType))
{
return false;
}
if (info.hitInstance->GetLiquidLevel(pos, info, level))
{
return true;
}
}
}
}

View File

@@ -22,7 +22,7 @@ struct MmapTileHeader
uint32 mmapVersion{MMAP_VERSION};
uint32 size{0};
char usesLiquids{true};
char padding[3]{};
char padding[3] {};
MmapTileHeader() : dtVersion(DT_NAVMESH_VERSION) { }
};

View File

@@ -27,7 +27,9 @@ namespace VMAP
{
bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit);
if (result)
{
hit = true;
}
return result;
}
bool didHit() { return hit; }
@@ -62,7 +64,9 @@ namespace VMAP
LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
#endif
if (prims[entry].GetLocationInfo(point, locInfo))
{
result = true;
}
}
ModelInstance* prims;
@@ -133,7 +137,9 @@ namespace VMAP
MapRayCallback intersectionCallBack(iTreeValues);
iTree.intersectRay(pRay, intersectionCallBack, distance, StopAtFirstHit);
if (intersectionCallBack.didHit())
{
pMaxDist = distance;
}
return intersectionCallBack.didHit();
}
//=========================================================
@@ -143,17 +149,23 @@ namespace VMAP
float maxDist = (pos2 - pos1).magnitude();
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist))
{
return false;
}
// 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);
if (getIntersectionTime(ray, maxDist, true))
{
return false;
}
return true;
}
@@ -227,12 +239,16 @@ namespace VMAP
{
std::string basePath = vmapPath;
if (basePath.length() > 0 && basePath[basePath.length() - 1] != '/' && basePath[basePath.length() - 1] != '\\')
{
basePath.push_back('/');
}
std::string fullname = basePath + VMapManager2::getMapFileName(mapID);
bool success = true;
FILE* rf = fopen(fullname.c_str(), "rb");
if (!rf)
{
return false;
}
// TODO: check magic number when implemented...
char tiled;
char chunk[8];
@@ -246,11 +262,15 @@ namespace VMAP
std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY);
FILE* tf = fopen(tilefile.c_str(), "rb");
if (!tf)
{
success = false;
}
else
{
if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
{
success = false;
}
fclose(tf);
}
}
@@ -267,7 +287,9 @@ namespace VMAP
std::string fullname = iBasePath + fname;
FILE* rf = fopen(fullname.c_str(), "rb");
if (!rf)
{
return false;
}
char chunk[8];
char tiled = '\0';
@@ -317,7 +339,9 @@ namespace VMAP
{
iTreeValues[i->first].setUnloaded();
for (uint32 refCount = 0; refCount < i->second; ++refCount)
{
vm->releaseModelInstance(iTreeValues[i->first].name);
}
}
iLoadedSpawns.clear();
iLoadedTiles.clear();
@@ -348,10 +372,14 @@ namespace VMAP
char chunk[8];
if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
{
result = false;
}
uint32 numSpawns = 0;
if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
{
result = false;
}
for (uint32 i = 0; i < numSpawns && result; ++i)
{
// read model spawns
@@ -362,7 +390,9 @@ namespace VMAP
// acquire model instance
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
if (!model)
{
LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);
}
// update tree
uint32 referencedVal;
@@ -386,21 +416,29 @@ namespace VMAP
++iLoadedSpawns[referencedVal];
#if defined(VMAP_DEBUG)
if (iTreeValues[referencedVal].ID != spawn.ID)
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node");
}
else if (iTreeValues[referencedVal].name != spawn.name)
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID);
}
#endif
}
}
else
{
result = false;
}
}
}
iLoadedTiles[packTileID(tileX, tileY)] = true;
fclose(tf);
}
else
{
iLoadedTiles[packTileID(tileX, tileY)] = false;
}
return result;
}
@@ -424,10 +462,14 @@ namespace VMAP
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;
}
for (uint32 i = 0; i < numSpawns && result; ++i)
{
// read model spawns
@@ -442,11 +484,15 @@ namespace VMAP
uint32 referencedNode;
if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1)
{
result = false;
}
else
{
if (!iLoadedSpawns.count(referencedNode))
{
LOG_ERROR("maps", "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();

View File

@@ -27,7 +27,7 @@ namespace VMAP
{
bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len)
{
if (fread(dest, sizeof(char), len, rf) != len) return false;
if (fread(dest, sizeof(char), len, rf) != len) { return false; }
return memcmp(dest, compare, len) == 0;
}
@@ -56,7 +56,9 @@ namespace VMAP
{
bool success = readMapSpawns();
if (!success)
{
return false;
}
// export Map data
for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter)
@@ -71,7 +73,9 @@ namespace VMAP
if (entry->second.flags & MOD_M2)
{
if (!calculateTransformedBound(entry->second))
{
break;
}
}
else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/
{
@@ -99,7 +103,9 @@ namespace VMAP
// ===> possibly move this code to StaticMapTree class
std::map<uint32, uint32> modelNodeIdx;
for (uint32 i = 0; i < mapSpawns.size(); ++i)
{
modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i));
}
// write map tree file
std::stringstream mapfilename;
@@ -113,16 +119,16 @@ namespace VMAP
}
//general info
if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false;
if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) { success = false; }
uint32 globalTileID = StaticMapTree::packTileID(65, 65);
pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID);
char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO
if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false;
if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) { success = false; }
// Nodes
if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false;
if (success) success = pTree.writeToFile(mapfile);
if (success && fwrite("NODE", 4, 1, mapfile) != 1) { success = false; }
if (success) { success = pTree.writeToFile(mapfile); }
// global map spawns (WDT), if any (most instances)
if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false;
if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) { success = false; }
for (TileMap::iterator glob = globalRange.first; glob != globalRange.second && success; ++glob)
{
@@ -140,7 +146,9 @@ namespace VMAP
{
const ModelSpawn& spawn = map_iter->second->UniqueEntries[tile->second];
if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently...
{
continue;
}
uint32 nSpawns = tileEntries.count(tile->first);
std::stringstream tilefilename;
tilefilename.fill('0');
@@ -151,19 +159,21 @@ namespace VMAP
if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb"))
{
// file header
if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false;
if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) { success = false; }
// write number of tile spawns
if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false;
if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) { success = false; }
// write tile spawns
for (uint32 s = 0; s < nSpawns; ++s)
{
if (s)
{
++tile;
}
const ModelSpawn& spawn2 = map_iter->second->UniqueEntries[tile->second];
success = success && ModelSpawn::writeToFile(tilefile, spawn2);
// MapTree nodes to update when loading tile:
std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID);
if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false;
if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) { success = false; }
}
fclose(tilefile);
}
@@ -212,11 +222,15 @@ namespace VMAP
// read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
check = fread(&mapID, sizeof(uint32), 1, dirf);
if (check == 0) // EoF...
{
break;
}
check += fread(&tileX, sizeof(uint32), 1, dirf);
check += fread(&tileY, sizeof(uint32), 1, dirf);
if (!ModelSpawn::readFromFile(dirf, spawn))
{
break;
}
MapSpawns* current;
MapData::iterator map_iter = mapData.find(mapID);
@@ -226,7 +240,9 @@ namespace VMAP
mapData[mapID] = current = new MapSpawns();
}
else
{
current = map_iter->second;
}
current->UniqueEntries.emplace(spawn.ID, spawn);
current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID));
@@ -249,11 +265,15 @@ namespace VMAP
WorldModel_Raw raw_model;
if (!raw_model.Read(modelFilename.c_str()))
{
return false;
}
uint32 groups = raw_model.groupsArray.size();
if (groups != 1)
{
printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str());
}
AABox modelBound;
bool boundEmpty = true;
@@ -274,9 +294,13 @@ namespace VMAP
Vector3 v = modelPosition.transform(vertices[i]);
if (boundEmpty)
{
modelBound = AABox(v, v), boundEmpty = false;
}
else
{
modelBound.merge(v);
}
}
}
spawn.iBound = modelBound + spawn.iPos;
@@ -300,12 +324,16 @@ namespace VMAP
bool success = true;
std::string filename = iSrcDir;
if (filename.length() > 0)
{
filename.push_back('/');
}
filename.append(pModelFilename);
WorldModel_Raw raw_model;
if (!raw_model.Read(filename.c_str()))
{
return false;
}
// write WorldModel
WorldModel model;
@@ -335,11 +363,15 @@ namespace VMAP
{
FILE* model_list = fopen((iSrcDir + "/" + "temp_gameobject_models").c_str(), "rb");
if (!model_list)
{
return;
}
char ident[8];
if (fread(ident, 1, 8, model_list) != 8 || memcmp(ident, VMAP::RAW_VMAP_MAGIC, 8) != 0)
{
return;
}
FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb");
if (!model_list_copy)
@@ -357,12 +389,14 @@ namespace VMAP
{
if (fread(&displayId, sizeof(uint32), 1, model_list) != 1)
if (feof(model_list)) // EOF flag is only set after failed reading attempt
{
break;
}
if (fread(&isWmo, sizeof(uint8), 1, model_list) != 1
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1
|| name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1
|| name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
{
std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl;
break;
@@ -372,7 +406,9 @@ namespace VMAP
WorldModel_Raw raw_model;
if ( !raw_model.Read((iSrcDir + "/" + model_name).c_str()) )
{
continue;
}
spawnedModelFiles.insert(model_name);
AABox bounds;
@@ -386,9 +422,13 @@ namespace VMAP
{
Vector3& v = vertices[i];
if (boundEmpty)
{
bounds = AABox(v, v), boundEmpty = false;
}
else
{
bounds.merge(v);
}
}
}
@@ -454,7 +494,9 @@ namespace VMAP
READ_OR_RETURN_WITH_DELETE(indexarray, nindexes * sizeof(uint16));
triangles.reserve(nindexes / 3);
for (uint32 i = 0; i < nindexes; i += 3)
{
triangles.push_back(MeshTriangle(indexarray[i], indexarray[i + 1], indexarray[i + 2]));
}
delete[] indexarray;
}
@@ -471,7 +513,9 @@ namespace VMAP
float* vectorarray = new float[nvectors * 3];
READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors * sizeof(float) * 3);
for (uint32 i = 0; i < nvectors; ++i)
{
vertexArray.push_back( Vector3(vectorarray + 3 * i) );
}
delete[] vectorarray;
}
@@ -526,10 +570,14 @@ namespace VMAP
groupsArray.resize(groups);
bool succeed = true;
for (uint32 g = 0; g < groups && succeed; ++g)
{
succeed = groupsArray[g].Read(rf);
}
if (succeed) /// rf will be freed inside Read if the function had any errors.
{
fclose(rf);
}
return succeed;
}

View File

@@ -80,23 +80,23 @@ namespace VMAP
class TileAssembler
{
private:
std::string iDestDir;
std::string iSrcDir;
G3D::Table<std::string, unsigned int > iUniqueNameIds;
MapData mapData;
std::set<std::string> spawnedModelFiles;
private:
std::string iDestDir;
std::string iSrcDir;
G3D::Table<std::string, unsigned int > iUniqueNameIds;
MapData mapData;
std::set<std::string> spawnedModelFiles;
public:
TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName);
virtual ~TileAssembler();
public:
TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName);
virtual ~TileAssembler();
bool convertWorld2();
bool readMapSpawns();
bool calculateTransformedBound(ModelSpawn &spawn);
void exportGameobjectModels();
bool convertWorld2();
bool readMapSpawns();
bool calculateTransformedBound(ModelSpawn& spawn);
void exportGameobjectModels();
bool convertRawFile(const std::string& pModelFilename);
bool convertRawFile(const std::string& pModelFilename);
};
} // VMAP

View File

@@ -55,14 +55,16 @@ void LoadGameObjectModelList(std::string const& dataPath)
Vector3 v1, v2;
if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1)
if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
{
break;
}
if (fread(&isWmo, sizeof(uint8), 1, model_list_file) != 1
|| fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|| name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
|| fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|| name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
{
LOG_ERROR("maps", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
fclose(model_list_file);
@@ -72,7 +74,7 @@ void LoadGameObjectModelList(std::string const& dataPath)
if (v1.isNaN() || v2.isNaN())
{
LOG_ERROR("maps", "File '%s' Model '%s' has invalid v1%s v2%s values!",
VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str());
VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str());
continue;
}
@@ -88,14 +90,18 @@ void LoadGameObjectModelList(std::string const& dataPath)
GameObjectModel::~GameObjectModel()
{
if (iModel)
{
VMAP::VMapFactory::createOrGetVMapManager()->releaseModelInstance(name);
}
}
bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath)
{
ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId());
if (it == model_list.end())
{
return false;
}
G3D::AABox mdl_box(it->second.bound);
// ignore models with no bounds
@@ -108,7 +114,9 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
iModel = VMAP::VMapFactory::createOrGetVMapManager()->acquireModelInstance(dataPath + "vmaps/", it->second.name);
if (!iModel)
{
return false;
}
name = it->second.name;
iPos = modelOwner->GetPosition();
@@ -122,7 +130,9 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
AABox rotated_bounds;
for (int i = 0; i < 8; ++i)
{
rotated_bounds.merge(iRotation * mdl_box.corner(i));
}
iBound = rotated_bounds + iPos;
@@ -154,11 +164,15 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
{
if (!(phasemask & ph_mask) || !owner->IsSpawned())
{
return false;
}
float time = ray.intersectionTime(iBound);
if (time == G3D::inf())
{
return false;
}
// child bounds are defined in object space:
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
@@ -176,11 +190,15 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
bool GameObjectModel::UpdatePosition()
{
if (!iModel)
{
return false;
}
ModelList::const_iterator it = model_list.find(owner->GetDisplayId());
if (it == model_list.end())
{
return false;
}
G3D::AABox mdl_box(it->second.bound);
@@ -200,7 +218,9 @@ bool GameObjectModel::UpdatePosition()
AABox rotated_bounds;
for (int i = 0; i < 8; ++i)
{
rotated_bounds.merge(iRotation * mdl_box.corner(i));
}
iBound = rotated_bounds + iPos;
#ifdef SPAWN_CORNERS

View File

@@ -65,9 +65,13 @@ namespace VMAP
// M2 files don't contain area info, only WMO files
if (flags & MOD_M2)
{
return;
}
if (!iBound.contains(p))
{
return;
}
// child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
@@ -99,9 +103,13 @@ namespace VMAP
// M2 files don't contain area info, only WMO files
if (flags & MOD_M2)
{
return false;
}
if (!iBound.contains(p))
{
return false;
}
// child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
@@ -147,7 +155,9 @@ namespace VMAP
if (!check)
{
if (ferror(rf))
{
std::cout << "Error reading ModelSpawn!\n";
}
return false;
}
check += fread(&spawn.adtId, sizeof(uint16), 1, rf);
@@ -202,9 +212,9 @@ namespace VMAP
}
uint32 nameLen = spawn.name.length();
check += fwrite(&nameLen, sizeof(uint32), 1, wf);
if (check != uint32(has_bound ? 17 : 11)) return false;
if (check != uint32(has_bound ? 17 : 11)) { return false; }
check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf);
if (check != nameLen) return false;
if (check != nameLen) { return false; }
return true;
}

View File

@@ -113,7 +113,9 @@ namespace VMAP
WmoLiquid& WmoLiquid::operator=(const WmoLiquid& other)
{
if (this == &other)
{
return *this;
}
iTilesX = other.iTilesX;
iTilesY = other.iTilesY;
iCorner = other.iCorner;
@@ -126,14 +128,18 @@ namespace VMAP
memcpy(iHeight, other.iHeight, (iTilesX + 1) * (iTilesY + 1)*sizeof(float));
}
else
{
iHeight = 0;
}
if (other.iFlags)
{
iFlags = new uint8[iTilesX * iTilesY];
memcpy(iFlags, other.iFlags, iTilesX * iTilesY);
}
else
{
iFlags = 0;
}
return *this;
}
@@ -142,16 +148,22 @@ namespace VMAP
float tx_f = (pos.x - iCorner.x) / LIQUID_TILE_SIZE;
uint32 tx = uint32(tx_f);
if (tx_f < 0.0f || tx >= iTilesX)
{
return false;
}
float ty_f = (pos.y - iCorner.y) / LIQUID_TILE_SIZE;
uint32 ty = uint32(ty_f);
if (ty_f < 0.0f || ty >= iTilesY)
{
return false;
}
// check if tile shall be used for liquid level
// checking for 0x08 *might* be enough, but disabled tiles always are 0x?F:
if ((iFlags[tx + ty * iTilesX] & 0x0F) == 0x0F)
{
return false;
}
// (dx, dy) coordinates inside tile, in [0, 1]^2
float dx = tx_f - (float)tx;
@@ -234,9 +246,13 @@ namespace VMAP
}
if (!result)
{
delete liquid;
}
else
{
out = liquid;
}
return result;
}
@@ -255,7 +271,9 @@ namespace VMAP
vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0)
{
if (other.iLiquid)
{
iLiquid = new WmoLiquid(*other.iLiquid);
}
}
void GroupModel::setMeshData(std::vector<Vector3>& vert, std::vector<MeshTriangle>& tri)
@@ -271,43 +289,45 @@ namespace VMAP
bool result = true;
uint32 chunkSize, count;
if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false;
if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) { result = false; }
if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) { result = false; }
// write vertices
if (result && fwrite("VERT", 1, 4, wf) != 4) result = false;
if (result && fwrite("VERT", 1, 4, wf) != 4) { result = false; }
count = vertices.size();
chunkSize = sizeof(uint32) + sizeof(Vector3) * count;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) { result = false; }
if (!count) // models without (collision) geometry end here, unsure if they are useful
{
return result;
if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false;
}
if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) { result = false; }
// write triangle mesh
if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false;
if (result && fwrite("TRIM", 1, 4, wf) != 4) { result = false; }
count = triangles.size();
chunkSize = sizeof(uint32) + sizeof(MeshTriangle) * count;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) { result = false; }
// write mesh BIH
if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false;
if (result) result = meshTree.writeToFile(wf);
if (result && fwrite("MBIH", 1, 4, wf) != 4) { result = false; }
if (result) { result = meshTree.writeToFile(wf); }
// write liquid data
if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false;
if (result && fwrite("LIQU", 1, 4, wf) != 4) { result = false; }
if (!iLiquid)
{
chunkSize = 0;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
return result;
}
chunkSize = iLiquid->GetFileSize();
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result) result = iLiquid->writeToFile(wf);
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result) { result = iLiquid->writeToFile(wf); }
return result;
}
@@ -323,35 +343,39 @@ namespace VMAP
delete iLiquid;
iLiquid = nullptr;
if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false;
if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) { result = false; }
if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) { result = false; }
// read vertices
if (result && !readChunk(rf, chunk, "VERT", 4)) result = false;
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
if (result && !readChunk(rf, chunk, "VERT", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) { result = false; }
if (!count) // models without (collision) geometry end here, unsure if they are useful
{
return result;
if (result) vertices.resize(count);
if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false;
}
if (result) { vertices.resize(count); }
if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) { result = false; }
// read triangle mesh
if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false;
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
if (result) triangles.resize(count);
if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false;
if (result && !readChunk(rf, chunk, "TRIM", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result) { triangles.resize(count); }
if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) { result = false; }
// read mesh BIH
if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false;
if (result) result = meshTree.readFromFile(rf);
if (result && !readChunk(rf, chunk, "MBIH", 4)) { result = false; }
if (result) { result = meshTree.readFromFile(rf); }
// write liquid data
if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false;
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
if (result && !readChunk(rf, chunk, "LIQU", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && chunkSize > 0)
{
result = WmoLiquid::readFromFile(rf, iLiquid);
}
return result;
}
@@ -362,7 +386,7 @@ namespace VMAP
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*StopAtFirstHit*/)
{
bool result = IntersectTriangle(triangles[entry], vertices, ray, distance);
if (result) hit = true;
if (result) { hit = true; }
return hit;
}
std::vector<Vector3>::const_iterator vertices;
@@ -373,7 +397,9 @@ namespace VMAP
bool GroupModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const
{
if (triangles.empty())
{
return false;
}
GModelRayCallback callback(triangles, vertices);
meshTree.intersectRay(ray, callback, distance, stopAtFirstHit);
@@ -383,28 +409,36 @@ namespace VMAP
bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const
{
if (triangles.empty() || !iBound.contains(pos))
{
return false;
}
GModelRayCallback callback(triangles, vertices);
Vector3 rPos = pos - 0.1f * down;
float dist = G3D::inf();
G3D::Ray ray(rPos, down);
bool hit = IntersectRay(ray, dist, false);
if (hit)
{
z_dist = dist - 0.1f;
}
return hit;
}
bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const
{
if (iLiquid)
{
return iLiquid->GetLiquidHeight(pos, liqHeight);
}
return false;
}
uint32 GroupModel::GetLiquidType() const
{
if (iLiquid)
{
return iLiquid->GetType();
}
return 0;
}
@@ -429,7 +463,7 @@ namespace VMAP
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
{
bool result = models[entry].IntersectRay(ray, distance, StopAtFirstHit);
if (result) hit = true;
if (result) { hit = true; }
return hit;
}
std::vector<GroupModel>::const_iterator models;
@@ -441,7 +475,9 @@ namespace VMAP
// small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1)
{
return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
}
WModelRayCallBack isc(groupModels);
groupTree.intersectRay(ray, isc, distance, stopAtFirstHit);
@@ -489,7 +525,9 @@ namespace VMAP
bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const
{
if (groupModels.empty())
{
return false;
}
WModelAreaCallback callback(groupModels, down);
groupTree.intersectPoint(p, callback);
@@ -508,7 +546,9 @@ namespace VMAP
bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const
{
if (groupModels.empty())
{
return false;
}
WModelAreaCallback callback(groupModels, down);
groupTree.intersectPoint(p, callback);
@@ -525,29 +565,33 @@ namespace VMAP
{
FILE* wf = fopen(filename.c_str(), "wb");
if (!wf)
{
return false;
}
uint32 chunkSize, count;
bool result = fwrite(VMAP_MAGIC, 1, 8, wf) == 8;
if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false;
if (result && fwrite("WMOD", 1, 4, wf) != 4) { result = false; }
chunkSize = sizeof(uint32) + sizeof(uint32);
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) { result = false; }
// write group models
count = groupModels.size();
if (count)
{
if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false;
if (result && fwrite("GMOD", 1, 4, wf) != 4) { result = false; }
//chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count;
//if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) { result = false; }
for (uint32 i = 0; i < groupModels.size() && result; ++i)
{
result = groupModels[i].writeToFile(wf);
}
// write group BIH
if (result && fwrite("GBIH", 1, 4, wf) != 4) result = false;
if (result) result = groupTree.writeToFile(wf);
if (result && fwrite("GBIH", 1, 4, wf) != 4) { result = false; }
if (result) { result = groupTree.writeToFile(wf); }
}
fclose(wf);
@@ -558,32 +602,36 @@ namespace VMAP
{
FILE* rf = fopen(filename.c_str(), "rb");
if (!rf)
{
return false;
}
bool result = true;
uint32 chunkSize = 0;
uint32 count = 0;
char chunk[8]; // Ignore the added magic header
if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) result = false;
if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) { result = false; }
if (result && !readChunk(rf, chunk, "WMOD", 4)) result = false;
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) result = false;
if (result && !readChunk(rf, chunk, "WMOD", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) { result = false; }
// read group models
if (result && readChunk(rf, chunk, "GMOD", 4))
{
//if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
if (result) groupModels.resize(count);
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result) { groupModels.resize(count); }
//if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false;
for (uint32 i = 0; i < count && result; ++i)
{
result = groupModels[i].readFromFile(rf);
}
// read group BIH
if (result && !readChunk(rf, chunk, "GBIH", 4)) result = false;
if (result) result = groupTree.readFromFile(rf);
if (result && !readChunk(rf, chunk, "GBIH", 4)) { result = false; }
if (result) { result = groupTree.readFromFile(rf); }
}
fclose(rf);

View File

@@ -22,7 +22,9 @@ public:
return;
}
else if (_nodes[i] == n)
{
return;
}
}
Node* _nodes[9];
};
@@ -64,7 +66,9 @@ public:
{
for (int x = 0; x < CELL_NUMBER; ++x)
for (int y = 0; y < CELL_NUMBER; ++y)
{
delete nodes[x][y];
}
}
void insert(const T& value)
@@ -85,7 +89,9 @@ public:
{
Cell c = Cell::ComputeCell(pos[i].x, pos[i].y);
if (!c.isValid())
{
continue;
}
Node& node = getGridFor(pos[i].x, pos[i].y);
na.AddNode(&node);
}
@@ -93,9 +99,13 @@ public:
for (uint8 i = 0; i < 9; ++i)
{
if (na._nodes[i])
{
na._nodes[i]->insert(value);
}
else
{
break;
}
}
memberTable.set(&value, na);
@@ -107,9 +117,13 @@ public:
for (uint8 i = 0; i < 9; ++i)
{
if (na._nodes[i])
{
na._nodes[i]->remove(value);
}
else
{
break;
}
}
// Remove the member
@@ -121,7 +135,9 @@ public:
for (int x = 0; x < CELL_NUMBER; ++x)
for (int y = 0; y < CELL_NUMBER; ++y)
if (Node* n = nodes[x][y])
{
n->balance();
}
}
bool contains(const T& value) const { return memberTable.containsKey(&value); }
@@ -151,7 +167,9 @@ public:
{
ASSERT(x < CELL_NUMBER && y < CELL_NUMBER);
if (!nodes[x][y])
{
nodes[x][y] = NodeCreatorFunc::makeNode(x, y);
}
return *nodes[x][y];
}
@@ -166,14 +184,18 @@ public:
{
Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y);
if (!cell.isValid())
{
return;
}
Cell last_cell = Cell::ComputeCell(end.x, end.y);
if (cell == last_cell)
{
if (Node* node = nodes[cell.x][cell.y])
{
node->intersectRay(ray, intersectCallback, max_dist, stopAtFirstHit);
}
return;
}
@@ -222,7 +244,9 @@ public:
node->intersectRay(ray, intersectCallback, max_dist, stopAtFirstHit);
}
if (cell == last_cell)
{
break;
}
if (tMaxX < tMaxY)
{
tMaxX += tDeltaX;
@@ -242,9 +266,13 @@ public:
{
Cell cell = Cell::ComputeCell(point.x, point.y);
if (!cell.isValid())
{
return;
}
if (Node* node = nodes[cell.x][cell.y])
{
node->intersectPoint(point, intersectCallback);
}
}
// Optimized verson of intersectRay function for rays with vertical directions
@@ -253,9 +281,13 @@ public:
{
Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y);
if (!cell.isValid())
{
return;
}
if (Node* node = nodes[cell.x][cell.y])
{
node->intersectRay(ray, intersectCallback, max_dist, false);
}
}
};