aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/mesh_extractor/ContinentBuilder.cpp143
-rw-r--r--src/tools/mesh_extractor/Geometry.cpp6
-rw-r--r--src/tools/mesh_extractor/MeshExtractor.cpp6
-rw-r--r--src/tools/mesh_extractor/TileBuilder.cpp160
-rw-r--r--src/tools/mesh_extractor/TileBuilder.h4
-rw-r--r--src/tools/mesh_extractor/WDT.cpp3
-rw-r--r--src/tools/mesh_extractor/WDT.h2
-rw-r--r--src/tools/mesh_extractor/WorldModelHandler.cpp2
-rw-r--r--src/tools/mesh_extractor/WorldModelHandler.h2
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(&params, 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(&params, 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(&params, &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: