diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/mesh_extractor/ContinentBuilder.cpp | 143 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/Geometry.cpp | 6 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/MeshExtractor.cpp | 6 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/TileBuilder.cpp | 160 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/TileBuilder.h | 4 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/WDT.cpp | 3 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/WDT.h | 2 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/WorldModelHandler.cpp | 2 | ||||
| -rw-r--r-- | src/tools/mesh_extractor/WorldModelHandler.h | 2 |
9 files changed, 284 insertions, 44 deletions
diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index fd0202e36f9..7708aa36617 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -11,46 +11,99 @@ class BuilderThread : public ACE_Task_Base { private: int X, Y, MapId; + bool Instance; std::string Continent; dtNavMeshParams Params; ContinentBuilder* cBuilder; + WorldModelRoot* Model; + const WorldModelDefinition* Definition; public: BuilderThread(ContinentBuilder* _cBuilder, dtNavMeshParams& params) : Params(params), cBuilder(_cBuilder), Free(true) {} - void SetData(int x, int y, int map, const std::string& cont) { X = x; Y = y; MapId = map; Continent = cont; } + void SetData(int x, int y, int map, const std::string& cont, bool instance, WorldModelRoot* model, const WorldModelDefinition* def) + { + X = x; + Y = y; + MapId = map; + Continent = cont; + Instance = instance; + if (Instance) + { + Model = model; + Definition = def; + } + else + Model = NULL; + } int svc() { - Free = false; - printf("[%02i,%02i] Building tile\n", X, Y); - TileBuilder builder(cBuilder, Continent, X, Y, MapId); - char buff[100]; - sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X); - FILE* f = fopen(buff, "r"); - if (f) // Check if file already exists. + if (Instance) { - printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y); - fclose(f); - Free = true; + // Build a WMO + printf("Building WMO %s ( %u )", Continent.c_str(), MapId); + TileBuilder builder(cBuilder, Continent, X, Y, MapId); + char buff[100]; + sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X); + FILE* f = fopen(buff, "r"); + if (f) // Check if file already exists. + { + printf("Instance %s ( %u ) skipped, file already exists\n", Continent.c_str(), MapId); + fclose(f); + return 0; + } + + uint8* nav = builder.BuildInstance(Params, Model, *Definition); + if (nav) + { + f = fopen(buff, "wb"); + if (!f) + { + printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); + return 0; + } + MmapTileHeader header; + header.size = builder.DataSize; + fwrite(&header, sizeof(MmapTileHeader), 1, f); + fwrite(nav, sizeof(unsigned char), builder.DataSize, f); + fclose(f); + } + dtFree(nav); return 0; } - uint8* nav = builder.Build(Params); - if (nav) + else { - f = fopen(buff, "wb"); - if (!f) + Free = false; + printf("[%02i,%02i] Building tile\n", X, Y); + TileBuilder builder(cBuilder, Continent, X, Y, MapId); + char buff[100]; + sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X); + FILE* f = fopen(buff, "r"); + if (f) // Check if file already exists. { - printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); + printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y); + fclose(f); + Free = true; return 0; } - MmapTileHeader header; - header.size = builder.DataSize; - fwrite(&header, sizeof(MmapTileHeader), 1, f); - fwrite(nav, sizeof(unsigned char), builder.DataSize, f); - fclose(f); + uint8* nav = builder.Build(Params); + if (nav) + { + f = fopen(buff, "wb"); + if (!f) + { + printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); + return 0; + } + MmapTileHeader header; + header.size = builder.DataSize; + fwrite(&header, sizeof(MmapTileHeader), 1, f); + fwrite(nav, sizeof(unsigned char), builder.DataSize, f); + fclose(f); + } + dtFree(nav); + printf("[%02i,%02i] Tile Built!\n", X, Y); + Free = true; } - dtFree(nav); - printf("[%02i,%02i] Tile Built!\n", X, Y); - Free = true; return 0; } @@ -110,28 +163,42 @@ void ContinentBuilder::Build() fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); fclose(mmap); std::vector<BuilderThread*> Threads; - for (uint32 i = 0; i < NumberOfThreads; ++i) - Threads.push_back(new BuilderThread(this, params)); - printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads); - for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) + + if (TileMap->IsGlobalModel) { - bool next = false; - while (!next) + printf("Map %s ( %u ) is a WMO. Building with 1 thread.\n", Continent.c_str(), MapId); + BuilderThread* thread = new BuilderThread(this, params); + Threads.push_back(thread); + thread->SetData(65, 65, MapId, Continent, true, TileMap->Model, &TileMap->ModelDefinition); + thread->activate(); + thread->wait(); + } + else + { + for (uint32 i = 0; i < NumberOfThreads; ++i) + Threads.push_back(new BuilderThread(this, params)); + printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads); + for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { - for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th) + bool next = false; + while (!next) { - if ((*_th)->Free) + for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th) { - (*_th)->SetData(itr->X, itr->Y, MapId, Continent); - (*_th)->activate(); - next = true; - break; + if ((*_th)->Free) + { + (*_th)->SetData(itr->X, itr->Y, MapId, Continent, false, NULL, NULL); + (*_th)->activate(); + next = true; + break; + } } + // Wait for 20 seconds + ACE_OS::sleep(ACE_Time_Value (0, 20000)); } - // Wait for 20 seconds - ACE_OS::sleep(ACE_Time_Value (0, 20000)); } } + Cache->Clear(); // Free memory diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp index 2fc470e8e9f..37f5c68bb6d 100644 --- a/src/tools/mesh_extractor/Geometry.cpp +++ b/src/tools/mesh_extractor/Geometry.cpp @@ -3,6 +3,7 @@ #include "ADT.h" #include "WorldModelHandler.h" #include "DoodadHandler.h" +#include <limits.h> Geometry::Geometry() : Transform(false) { @@ -14,6 +15,11 @@ void Geometry::CalculateBoundingBox( float*& min, float*& max ) { min = new float[3]; max = new float[3]; + for (int i = 0; i < 3; ++i) + { + max[i] = std::numeric_limits<float>::min(); + min[i] = std::numeric_limits<float>::max(); + } for (std::vector<Vector3>::iterator itr = Vertices.begin(); itr != Vertices.end(); ++itr) { diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 3d56bab5c23..4a312640395 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -35,7 +35,7 @@ void ExtractMMaps(std::set<uint32>& mapIds, uint32 threads) std::string name = (*itr)->GetString(1); WDT wdt("World\\maps\\" + name + "\\" + name + ".wdt"); - if (!wdt.IsValid || wdt.IsGlobalModel) + if (!wdt.IsValid) { printf("Could not find WDT data for map %u (%s)\n", mapId, name.c_str()); continue; @@ -273,6 +273,8 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set<uint32>& mapLis mapList.insert(atoi(token)); token = strtok(NULL, ","); } + + free(copy); printf("Extracting only provided list of maps (%u).\n", uint32(mapList.size())); } @@ -391,7 +393,7 @@ int main(int argc, char* argv[]) // dtQueryFilter m_filter; - m_filter.setIncludeFlags(0xffff) ; + m_filter.setIncludeFlags(0xffff); m_filter.setExcludeFlags(0); // diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 5de41c9eb84..857cf7f16d8 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -1,6 +1,7 @@ #include "ContinentBuilder.h" #include "TileBuilder.h" #include "Geometry.h" +#include "WorldModelRoot.h" #include "Constants.h" #include "Utils.h" #include "Cache.h" @@ -60,6 +61,22 @@ TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, Config.detailSampleDist = Config.cs * 64; Config.detailSampleMaxError = Config.ch * 2; + memset(&InstanceConfig, 0, sizeof(rcConfig)); + InstanceConfig.cs = 0.2f; + InstanceConfig.ch = 0.3f; + InstanceConfig.minRegionArea = 25; + InstanceConfig.mergeRegionArea = 100; + InstanceConfig.walkableSlopeAngle = 50.0f; + InstanceConfig.detailSampleDist = 3.0f; + InstanceConfig.detailSampleMaxError = 1.5f; + InstanceConfig.walkableClimb = 1.0f / InstanceConfig.ch; + InstanceConfig.walkableHeight = 2.1f / InstanceConfig.ch; + InstanceConfig.walkableRadius = 0.6f / InstanceConfig.cs; + InstanceConfig.maxEdgeLen = 8 * InstanceConfig.walkableRadius; + InstanceConfig.maxVertsPerPoly = 6; + InstanceConfig.maxSimplificationError = 1.25f; + InstanceConfig.borderSize = 0; + Context = new rcContext; } @@ -73,6 +90,149 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshPara bmax[2] = Constants::Origin[2] /*navMeshParams.orig[2]*/ + (Constants::TileSize * (Y + 1)); } +uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoot* root, const WorldModelDefinition& def ) +{ + _Geometry = new Geometry(); + _Geometry->Transform = true; + + WorldModelHandler::InsertModelGeometry(_Geometry->Vertices, _Geometry->Triangles, def, root); + + if (Constants::Debug) + { + char buff[100]; + sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X); + FILE* debug = fopen(buff, "wb"); + for (uint32 i = 0; i < _Geometry->Vertices.size(); ++i) + { + const Vector3& vector = _Geometry->Vertices[i]; + fprintf(debug, "v %f %f %f\n", vector.x, vector.y, vector.z); + } + for (uint32 i = 0; i < _Geometry->Triangles.size(); ++i) + { + const Triangle<uint32>& triangle = _Geometry->Triangles[i]; + fprintf(debug, "f %u %u %u\n", triangle.V0 + 1, triangle.V1 + 1, triangle.V2 + 1); + } + fclose(debug); + } + + float* bmin, *bmax; + _Geometry->CalculateBoundingBox(bmin, bmax); + rcVcopy(InstanceConfig.bmax, bmax); + rcVcopy(InstanceConfig.bmin, bmin); + + uint32 numVerts = _Geometry->Vertices.size(); + uint32 numTris = _Geometry->Triangles.size(); + float* vertices; + int* triangles; + uint8* areas; + _Geometry->GetRawData(vertices, triangles, areas); + _Geometry->Vertices.clear(); + _Geometry->Triangles.clear(); + + // this sets the dimensions of the heightfield - should maybe happen before border padding + rcCalcGridSize(InstanceConfig.bmin, InstanceConfig.bmax, InstanceConfig.cs, &InstanceConfig.width, &InstanceConfig.height); + rcHeightfield* hf = rcAllocHeightfield(); + rcCreateHeightfield(Context, *hf, InstanceConfig.width, InstanceConfig.height, InstanceConfig.bmin, InstanceConfig.bmax, InstanceConfig.cs, InstanceConfig.ch); + + rcClearUnwalkableTriangles(Context, InstanceConfig.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); + rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, InstanceConfig.walkableClimb); + + rcFilterLowHangingWalkableObstacles(Context, InstanceConfig.walkableClimb, *hf); + rcFilterLedgeSpans(Context, InstanceConfig.walkableHeight, InstanceConfig.walkableClimb, *hf); + rcFilterWalkableLowHeightSpans(Context, InstanceConfig.walkableHeight, *hf); + + rcCompactHeightfield* chf = rcAllocCompactHeightfield(); + rcBuildCompactHeightfield(Context, InstanceConfig.walkableHeight, InstanceConfig.walkableClimb, *hf, *chf); + + rcErodeWalkableArea(Context, InstanceConfig.walkableRadius, *chf); + rcBuildDistanceField(Context, *chf); + rcBuildRegions(Context, *chf, InstanceConfig.borderSize, InstanceConfig.minRegionArea, InstanceConfig.minRegionArea); + + rcContourSet* contours = rcAllocContourSet(); + rcBuildContours(Context, *chf, InstanceConfig.maxSimplificationError, InstanceConfig.maxEdgeLen, *contours); + + rcPolyMesh* pmesh = rcAllocPolyMesh(); + rcBuildPolyMesh(Context, *contours, InstanceConfig.maxVertsPerPoly, *pmesh); + + rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail(); + rcBuildPolyMeshDetail(Context, *pmesh, *chf, InstanceConfig.detailSampleDist, InstanceConfig.detailSampleMaxError, *dmesh); + + // Set flags according to area types (e.g. Swim for Water) + for (int i = 0; i < pmesh->npolys; i++) + { + if (pmesh->areas[i] == Constants::POLY_AREA_ROAD || pmesh->areas[i] == Constants::POLY_AREA_TERRAIN) + pmesh->flags[i] = Constants::POLY_FLAG_WALK; + else if (pmesh->areas[i] == Constants::POLY_AREA_WATER) + pmesh->flags[i] = Constants::POLY_FLAG_SWIM; + } + + dtNavMeshCreateParams params; + memset(¶ms, 0, sizeof(params)); + // PolyMesh data + params.verts = pmesh->verts; + params.vertCount = pmesh->nverts; + params.polys = pmesh->polys; + params.polyAreas = pmesh->areas; + params.polyFlags = pmesh->flags; + params.polyCount = pmesh->npolys; + params.nvp = pmesh->nvp; + // PolyMeshDetail data + params.detailMeshes = dmesh->meshes; + params.detailVerts = dmesh->verts; + params.detailVertsCount = dmesh->nverts; + params.detailTris = dmesh->tris; + params.detailTriCount = dmesh->ntris; + rcVcopy(params.bmin, pmesh->bmin); + rcVcopy(params.bmax, pmesh->bmax); + // General settings + params.ch = InstanceConfig.ch; + params.cs = InstanceConfig.cs; + params.walkableClimb = InstanceConfig.walkableClimb * InstanceConfig.ch; + params.walkableHeight = InstanceConfig.walkableHeight * InstanceConfig.ch; + params.walkableRadius = InstanceConfig.walkableRadius * InstanceConfig.cs; + params.tileX = 0; + params.tileY = 0; + params.tileLayer = 0; + + rcVcopy(params.bmax, bmax); + rcVcopy(params.bmin, bmin); + + // Offmesh-connection settings + params.offMeshConCount = 0; // none for now + + //params.tileSize = Constants::VertexPerMap; + + if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount) + { + // 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 + // drop tiles with only exact count - some tiles may have geometry while having less tiles + printf("No polygons to build on tile, skipping.\n"); + delete areas; + delete triangles; + delete vertices; + return NULL; + } + + int navDataSize; + uint8* navData; + printf("Creating the navmesh with %i vertices, %i polys, %i triangles!\n", pmesh->nverts, pmesh->npolys, dmesh->ntris); + bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); + + delete areas; + delete triangles; + delete vertices; + + if (result) + { + printf("NavMesh created, size %i!\n", navDataSize); + DataSize = navDataSize; + return navData; + } + + return NULL; +} + uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams) { _Geometry = new Geometry(); diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index e0ff02cc599..814f989486e 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -4,6 +4,7 @@ #include "Recast.h" #include "Geometry.h" +#include "WorldModelRoot.h" class ContinentBuilder; class WDT; @@ -16,12 +17,13 @@ public: void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams); uint8* Build(dtNavMeshParams& navMeshParams); - + uint8* BuildInstance(dtNavMeshParams& navMeshParams, WorldModelRoot* root, const WorldModelDefinition& def); std::string World; int X; int Y; int MapId; rcConfig Config; + rcConfig InstanceConfig; rcContext* Context; Geometry* _Geometry; uint32 DataSize; diff --git a/src/tools/mesh_extractor/WDT.cpp b/src/tools/mesh_extractor/WDT.cpp index 70d140e79ed..2a5a18c9848 100644 --- a/src/tools/mesh_extractor/WDT.cpp +++ b/src/tools/mesh_extractor/WDT.cpp @@ -4,7 +4,7 @@ #include "Utils.h" #include "WorldModelHandler.h" -WDT::WDT(std::string file) : IsGlobalModel(false), IsValid(false) +WDT::WDT(std::string file) : IsGlobalModel(false), IsValid(false), Model(NULL) { Data = new ChunkedData(file, 2); ReadTileTable(); @@ -21,6 +21,7 @@ void WDT::ReadGlobalModel() IsGlobalModel = true; ModelDefinition = WorldModelDefinition::Read(defChunk->GetStream()); ModelFile = Utils::ReadString(fileChunk->GetStream()); + Model = new WorldModelRoot(ModelFile); } void WDT::ReadTileTable() diff --git a/src/tools/mesh_extractor/WDT.h b/src/tools/mesh_extractor/WDT.h index a12aa65218b..ce8a97fff00 100644 --- a/src/tools/mesh_extractor/WDT.h +++ b/src/tools/mesh_extractor/WDT.h @@ -5,6 +5,7 @@ #include "ChunkedData.h" #include "WorldModelHandler.h" +#include "WorldModelRoot.h" #include "Utils.h" class WDT @@ -18,6 +19,7 @@ public: bool IsValid; std::string ModelFile; WorldModelDefinition ModelDefinition; + WorldModelRoot* Model; bool HasTile(int x, int y); private: void ReadGlobalModel(); diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index 86ad8fc9984..24f63dc1e33 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -79,7 +79,7 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk ) fseek(stream, mcnk->Source->Offset, SEEK_SET); } -void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, WorldModelDefinition& def, WorldModelRoot* root ) +void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root ) { for (std::vector<WorldModelGroup>::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group) { diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h index d9da828da48..0611a02f764 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.h +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -34,7 +34,7 @@ public: std::vector<Vector3> Vertices; std::vector<Triangle<uint32> > Triangles; bool IsSane() { return _definitions && _paths; } - void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, WorldModelDefinition& def, WorldModelRoot* root); + static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root); protected: void ProcessInternal(MapChunk* data); private: |
