diff options
| author | Shauren <shauren.trinity@gmail.com> | 2025-10-25 11:30:07 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2025-10-25 11:30:07 +0200 |
| commit | f02112d52f943a495f4c0930ad091cb7dd8fbc6e (patch) | |
| tree | ea8238dece6d41d114570a5c2aec0d3589b73969 | |
| parent | 82e8c268314b6f21f3244878f86a99994744bb77 (diff) | |
Tools/mmaps_generator: Replace do while (false) loops with unique_ptr using custom deleter
| -rw-r--r-- | src/tools/mmaps_generator/IntermediateValues.cpp | 2 | ||||
| -rw-r--r-- | src/tools/mmaps_generator/IntermediateValues.h | 2 | ||||
| -rw-r--r-- | src/tools/mmaps_generator/TerrainBuilder.cpp | 205 | ||||
| -rw-r--r-- | src/tools/mmaps_generator/TileBuilder.cpp | 156 |
4 files changed, 183 insertions, 182 deletions
diff --git a/src/tools/mmaps_generator/IntermediateValues.cpp b/src/tools/mmaps_generator/IntermediateValues.cpp index 5906cd866bc..f71e36fec0c 100644 --- a/src/tools/mmaps_generator/IntermediateValues.cpp +++ b/src/tools/mmaps_generator/IntermediateValues.cpp @@ -188,7 +188,7 @@ namespace MMAP fwrite(mesh->meshes, sizeof(int), mesh->nmeshes*4, file); } - void IntermediateValues::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + void IntermediateValues::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData const& meshData) { std::string objFileName; objFileName = Trinity::StringFormat("meshes/map{:04}{:02}{:02}.obj", mapID, tileY, tileX); diff --git a/src/tools/mmaps_generator/IntermediateValues.h b/src/tools/mmaps_generator/IntermediateValues.h index c9bbd1d7d73..5620152c15f 100644 --- a/src/tools/mmaps_generator/IntermediateValues.h +++ b/src/tools/mmaps_generator/IntermediateValues.h @@ -44,7 +44,7 @@ namespace MMAP void debugWrite(FILE* file, rcPolyMesh const* mesh); void debugWrite(FILE* file, rcPolyMeshDetail const* mesh); - void generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + void generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData const& meshData); }; } #endif diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index f13a662ec31..ede0c32441d 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -571,136 +571,135 @@ namespace MMAP bool TerrainBuilder::loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData, VMAP::VMapManager* vmapManager) { VMAP::LoadResult result = vmapManager->loadMap("vmaps", mapID, tileX, tileY); - bool retval = false; + if (result != VMAP::LoadResult::Success) + return false; - do + auto vmapTile = Trinity::make_unique_ptr_with_deleter(vmapManager, [=](VMAP::VMapManager* mgr) { - if (result != VMAP::LoadResult::Success) - break; + mgr->unloadMap(mapID, tileX, tileY); + }); - std::span<VMAP::ModelInstance const> models = vmapManager->getModelsOnMap(mapID); - if (models.empty()) - break; + std::span<VMAP::ModelInstance const> models = vmapManager->getModelsOnMap(mapID); + if (models.empty()) + return false; - for (VMAP::ModelInstance const& instance : models) - { - // model instances exist in tree even though there are instances of that model in this tile - VMAP::WorldModel const* worldModel = instance.getWorldModel(); - if (!worldModel) - continue; + bool retval = false; - // now we have a model to add to the meshdata - retval = true; + for (VMAP::ModelInstance const& instance : models) + { + // model instances exist in tree even though there are instances of that model in this tile + VMAP::WorldModel const* worldModel = instance.getWorldModel(); + if (!worldModel) + continue; - std::vector<VMAP::GroupModel> const& groupModels = worldModel->getGroupModels(); + // now we have a model to add to the meshdata + retval = true; - // all M2s need to have triangle indices reversed - bool isM2 = worldModel->IsM2(); + std::vector<VMAP::GroupModel> const& groupModels = worldModel->getGroupModels(); - // transform data - float scale = instance.iScale; - G3D::Matrix3 rotation = instance.GetInvRot(); - G3D::Vector3 position = instance.iPos; - position.x -= 32 * GRID_SIZE; - position.y -= 32 * GRID_SIZE; + // all M2s need to have triangle indices reversed + bool isM2 = worldModel->IsM2(); - for (std::vector<VMAP::GroupModel>::const_iterator it = groupModels.begin(); it != groupModels.end(); ++it) - { - std::vector<G3D::Vector3> const& tempVertices = it->GetVertices(); - std::vector<G3D::Vector3> transformedVertices; - std::vector<VMAP::MeshTriangle> const& tempTriangles = it->GetTriangles(); - VMAP::WmoLiquid const* liquid = it->GetLiquid(); + // transform data + float scale = instance.iScale; + G3D::Matrix3 rotation = instance.GetInvRot(); + G3D::Vector3 position = instance.iPos; + position.x -= 32 * GRID_SIZE; + position.y -= 32 * GRID_SIZE; + + for (std::vector<VMAP::GroupModel>::const_iterator it = groupModels.begin(); it != groupModels.end(); ++it) + { + std::vector<G3D::Vector3> const& tempVertices = it->GetVertices(); + std::vector<G3D::Vector3> transformedVertices; + std::vector<VMAP::MeshTriangle> const& tempTriangles = it->GetTriangles(); + VMAP::WmoLiquid const* liquid = it->GetLiquid(); - // first handle collision mesh - transform(tempVertices, transformedVertices, scale, rotation, position); + // first handle collision mesh + transform(tempVertices, transformedVertices, scale, rotation, position); - int offset = meshData.solidVerts.size() / 3; + int offset = meshData.solidVerts.size() / 3; - copyVertices(transformedVertices, meshData.solidVerts); - copyIndices(tempTriangles, meshData.solidTris, offset, isM2); + copyVertices(transformedVertices, meshData.solidVerts); + copyIndices(tempTriangles, meshData.solidTris, offset, isM2); - // now handle liquid data - if (liquid && liquid->GetFlagsStorage()) + // now handle liquid data + if (liquid && liquid->GetFlagsStorage()) + { + std::vector<G3D::Vector3> liqVerts; + std::vector<int> liqTris; + uint32 tilesX, tilesY, vertsX, vertsY; + G3D::Vector3 corner; + liquid->getPosInfo(tilesX, tilesY, corner); + vertsX = tilesX + 1; + vertsY = tilesY + 1; + uint8 const* flags = liquid->GetFlagsStorage(); + float const* data = liquid->GetHeightStorage(); + uint8 type = NAV_AREA_EMPTY; + + // convert liquid type to NavTerrain + EnumFlag<map_liquidHeaderTypeFlags> liquidFlags = map_liquidHeaderTypeFlags(vmapManager->GetLiquidFlagsPtr(liquid->GetType())); + if (liquidFlags.HasFlag(map_liquidHeaderTypeFlags::Water | map_liquidHeaderTypeFlags::Ocean)) + type = NAV_AREA_WATER; + else if (liquidFlags.HasFlag(map_liquidHeaderTypeFlags::Magma | map_liquidHeaderTypeFlags::Slime)) + type = NAV_AREA_MAGMA_SLIME; + + // indexing is weird... + // after a lot of trial and error, this is what works: + // vertex = y*vertsX+x + // tile = x*tilesY+y + // flag = y*tilesY+x + + G3D::Vector3 vert; + for (uint32 x = 0; x < vertsX; ++x) { - std::vector<G3D::Vector3> liqVerts; - std::vector<int> liqTris; - uint32 tilesX, tilesY, vertsX, vertsY; - G3D::Vector3 corner; - liquid->getPosInfo(tilesX, tilesY, corner); - vertsX = tilesX + 1; - vertsY = tilesY + 1; - uint8 const* flags = liquid->GetFlagsStorage(); - float const* data = liquid->GetHeightStorage(); - uint8 type = NAV_AREA_EMPTY; - - // convert liquid type to NavTerrain - EnumFlag<map_liquidHeaderTypeFlags> liquidFlags = map_liquidHeaderTypeFlags(vmapManager->GetLiquidFlagsPtr(liquid->GetType())); - if (liquidFlags.HasFlag(map_liquidHeaderTypeFlags::Water | map_liquidHeaderTypeFlags::Ocean)) - type = NAV_AREA_WATER; - else if (liquidFlags.HasFlag(map_liquidHeaderTypeFlags::Magma | map_liquidHeaderTypeFlags::Slime)) - type = NAV_AREA_MAGMA_SLIME; - - // indexing is weird... - // after a lot of trial and error, this is what works: - // vertex = y*vertsX+x - // tile = x*tilesY+y - // flag = y*tilesY+x - - G3D::Vector3 vert; - for (uint32 x = 0; x < vertsX; ++x) + for (uint32 y = 0; y < vertsY; ++y) { - for (uint32 y = 0; y < vertsY; ++y) - { - vert = G3D::Vector3(corner.x + x * GRID_PART_SIZE, corner.y + y * GRID_PART_SIZE, data[y * vertsX + x]); - vert = vert * rotation * scale + position; - vert.x *= -1.f; - vert.y *= -1.f; - liqVerts.push_back(vert); - } + vert = G3D::Vector3(corner.x + x * GRID_PART_SIZE, corner.y + y * GRID_PART_SIZE, data[y * vertsX + x]); + vert = vert * rotation * scale + position; + vert.x *= -1.f; + vert.y *= -1.f; + liqVerts.push_back(vert); } + } - int idx1, idx2, idx3, idx4; - uint32 square; - for (uint32 x = 0; x < tilesX; ++x) + int idx1, idx2, idx3, idx4; + uint32 square; + for (uint32 x = 0; x < tilesX; ++x) + { + for (uint32 y = 0; y < tilesY; ++y) { - for (uint32 y = 0; y < tilesY; ++y) + if ((flags[x + y * tilesX] & 0x0f) != 0x0f) { - if ((flags[x + y * tilesX] & 0x0f) != 0x0f) - { - square = x * tilesY + y; - idx1 = square + x; - idx2 = square + 1 + x; - idx3 = square + tilesY + 1 + 1 + x; - idx4 = square + tilesY + 1 + x; - - // top triangle - liqTris.push_back(idx3); - liqTris.push_back(idx2); - liqTris.push_back(idx1); - // bottom triangle - liqTris.push_back(idx4); - liqTris.push_back(idx3); - liqTris.push_back(idx1); - } + square = x * tilesY + y; + idx1 = square + x; + idx2 = square + 1 + x; + idx3 = square + tilesY + 1 + 1 + x; + idx4 = square + tilesY + 1 + x; + + // top triangle + liqTris.push_back(idx3); + liqTris.push_back(idx2); + liqTris.push_back(idx1); + // bottom triangle + liqTris.push_back(idx4); + liqTris.push_back(idx3); + liqTris.push_back(idx1); } } + } - uint32 liqOffset = meshData.liquidVerts.size() / 3; - for (uint32 i = 0; i < liqVerts.size(); ++i) - meshData.liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x); + uint32 liqOffset = meshData.liquidVerts.size() / 3; + for (uint32 i = 0; i < liqVerts.size(); ++i) + meshData.liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x); - for (uint32 i = 0; i < liqTris.size() / 3; ++i) - { - meshData.liquidTris.append(liqTris[i * 3 + 1] + liqOffset, liqTris[i * 3 + 2] + liqOffset, liqTris[i * 3] + liqOffset); - meshData.liquidType.append(type); - } + for (uint32 i = 0; i < liqTris.size() / 3; ++i) + { + meshData.liquidTris.append(liqTris[i * 3 + 1] + liqOffset, liqTris[i * 3 + 2] + liqOffset, liqTris[i * 3] + liqOffset); + meshData.liquidType.append(type); } } } } - while (false); - - vmapManager->unloadMap(mapID, tileX, tileY); return retval; } diff --git a/src/tools/mmaps_generator/TileBuilder.cpp b/src/tools/mmaps_generator/TileBuilder.cpp index ffd7787f2cd..6cbf3eef99a 100644 --- a/src/tools/mmaps_generator/TileBuilder.cpp +++ b/src/tools/mmaps_generator/TileBuilder.cpp @@ -371,98 +371,100 @@ namespace MMAP unsigned char* navData = nullptr; int navDataSize = 0; - do + auto debugOutputWriter = Trinity::make_unique_ptr_with_deleter(m_debugOutput ? &iv : nullptr, [=, borderSize = static_cast<unsigned short>(config.borderSize), &meshData](IntermediateValues* intermediate) { - // these values are checked within dtCreateNavMeshData - handle them here - // so we have a clear error message - if (params.nvp > DT_VERTS_PER_POLYGON) + // restore padding so that the debug visualization is correct + for (std::ptrdiff_t i = 0; i < intermediate->polyMesh->nverts; ++i) { - TC_LOG_ERROR("maps.mmapgen", "{} Invalid verts-per-polygon value!", tileString); - break; + unsigned short* v = &intermediate->polyMesh->verts[i * 3]; + v[0] += borderSize; + v[2] += borderSize; } - if (params.vertCount >= 0xffff) - { - TC_LOG_ERROR("maps.mmapgen", "{} Too many vertices!", tileString); - break; - } - if (!params.vertCount || !params.verts) - { - // occurs mostly when adjacent tiles have models - // loaded but those models don't span into this tile - // message is an annoyance - //TC_LOG_ERROR("maps.mmapgen", "{} No vertices to build tile!", tileString); - break; - } - if (!params.polyCount || !params.polys) - { - // we have flat tiles with no actual geometry - don't build those, its useless - // keep in mind that we do output those into debug info - TC_LOG_ERROR("maps.mmapgen", "{} No polygons to build on tile!", tileString); - break; - } - if (!params.detailMeshes || !params.detailVerts || !params.detailTris) - { - TC_LOG_ERROR("maps.mmapgen", "{} No detail mesh to build tile!", tileString); - break; - } + intermediate->generateObjFile(mapID, tileX, tileY, meshData); + intermediate->writeIV(mapID, tileX, tileY); + }); - TC_LOG_DEBUG("maps.mmapgen", "{} Building navmesh tile...", tileString); - if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) - { - TC_LOG_ERROR("maps.mmapgen", "{} Failed building navmesh tile!", tileString); - break; - } + // these values are checked within dtCreateNavMeshData - handle them here + // so we have a clear error message + if (params.nvp > DT_VERTS_PER_POLYGON) + { + TC_LOG_ERROR("maps.mmapgen", "{} Invalid verts-per-polygon value!", tileString); + return; + } - dtTileRef tileRef = 0; - TC_LOG_DEBUG("maps.mmapgen", "{} Adding tile to navmesh...", tileString); - // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile - // is removed via removeTile() - dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); - if (!tileRef || !dtStatusSucceed(dtResult)) - { - TC_LOG_ERROR("maps.mmapgen", "{} Failed adding tile to navmesh!", tileString); - break; - } + if (params.vertCount >= 0xffff) + { + TC_LOG_ERROR("maps.mmapgen", "{} Too many vertices!", tileString); + return; + } - // file output - std::string fileName = Trinity::StringFormat("mmaps/{:04}{:02}{:02}.mmtile", mapID, tileY, tileX); - auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "wb")); - if (!file) - { - TC_LOG_ERROR("maps.mmapgen", "{}: [Map {:04}] Failed to open {} for writing!", strerror(errno), mapID, fileName); - navMesh->removeTile(tileRef, nullptr, nullptr); - break; - } + if (!params.vertCount || !params.verts) + { + // occurs mostly when adjacent tiles have models + // loaded but those models don't span into this tile - TC_LOG_DEBUG("maps.mmapgen", "{} Writing to file...", tileString); + // message is an annoyance + //TC_LOG_ERROR("maps.mmapgen", "{} No vertices to build tile!", tileString); + return; + } - // write header - MmapTileHeader header; - header.usesLiquids = m_terrainBuilder.usesLiquids(); - header.size = uint32(navDataSize); - fwrite(&header, sizeof(MmapTileHeader), 1, file.get()); + if (!params.polyCount || !params.polys) + { + // we have flat tiles with no actual geometry - don't build those, its useless + // keep in mind that we do output those into debug info + TC_LOG_ERROR("maps.mmapgen", "{} No polygons to build on tile!", tileString); + return; + } - // write data - fwrite(navData, sizeof(unsigned char), navDataSize, file.get()); + if (!params.detailMeshes || !params.detailVerts || !params.detailTris) + { + TC_LOG_ERROR("maps.mmapgen", "{} No detail mesh to build tile!", tileString); + return; + } - // now that tile is written to disk, we can unload it - navMesh->removeTile(tileRef, nullptr, nullptr); - } while (false); + TC_LOG_DEBUG("maps.mmapgen", "{} Building navmesh tile...", tileString); + if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) + { + TC_LOG_ERROR("maps.mmapgen", "{} Failed building navmesh tile!", tileString); + return; + } - if (m_debugOutput) + dtTileRef tileRef = 0; + TC_LOG_DEBUG("maps.mmapgen", "{} Adding tile to navmesh...", tileString); + // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile + // is removed via removeTile() + dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); + if (!tileRef || !dtStatusSucceed(dtResult)) { - // restore padding so that the debug visualization is correct - for (int i = 0; i < iv.polyMesh->nverts; ++i) - { - unsigned short* v = &iv.polyMesh->verts[i * 3]; - v[0] += (unsigned short)config.borderSize; - v[2] += (unsigned short)config.borderSize; - } + TC_LOG_ERROR("maps.mmapgen", "{} Failed adding tile to navmesh!", tileString); + return; + } - iv.generateObjFile(mapID, tileX, tileY, meshData); - iv.writeIV(mapID, tileX, tileY); + auto navMeshTile = Trinity::make_unique_ptr_with_deleter(&tileRef, [navMesh](dtTileRef const* ref) + { + navMesh->removeTile(*ref, nullptr, nullptr); + }); + + // file output + std::string fileName = Trinity::StringFormat("mmaps/{:04}{:02}{:02}.mmtile", mapID, tileY, tileX); + auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "wb")); + if (!file) + { + TC_LOG_ERROR("maps.mmapgen", "{}: [Map {:04}] Failed to open {} for writing!", strerror(errno), mapID, fileName); + return; } + + TC_LOG_DEBUG("maps.mmapgen", "{} Writing to file...", tileString); + + // write header + MmapTileHeader header; + header.usesLiquids = m_terrainBuilder.usesLiquids(); + header.size = uint32(navDataSize); + fwrite(&header, sizeof(MmapTileHeader), 1, file.get()); + + // write data + fwrite(navData, sizeof(unsigned char), navDataSize, file.get()); } /**************************************************************************/ |
