Tools/MeshExtractor: Fixed mmap extracting for instance maps and fixed a number of issues.

ToDo:
Cleanup the code a bit.
WILL NOT CURRENTLY WORK WITH TrinityCore, if you want to test it, use the --extract 32 flag of MeshExtractor.
This commit is contained in:
Sebastian Valle
2013-09-30 17:27:03 -05:00
parent 1010e140bf
commit 271a57b80d
8 changed files with 163 additions and 74 deletions

View File

@@ -6,6 +6,7 @@
#include "Cache.h"
#include "ace/Task.h"
#include "Recast.h"
#include "DetourCommon.h"
class BuilderThread : public ACE_Task_Base
{
@@ -52,7 +53,7 @@ public:
return 0;
}
uint8* nav = builder.BuildInstance(Params, Model, *Definition);
uint8* nav = builder.BuildInstance(Params);
if (nav)
{
f = fopen(buff, "wb");
@@ -155,26 +156,58 @@ void ContinentBuilder::Build()
CalculateTileBounds();
dtNavMeshParams params;
params.maxPolys = 1 << STATIC_POLY_BITS;
params.maxTiles = TileMap->TileTable.size();
rcVcopy(params.orig, bmin);
params.tileHeight = Constants::TileSize;
params.tileWidth = Constants::TileSize;
fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
std::vector<BuilderThread*> Threads;
if (TileMap->IsGlobalModel)
{
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();
TileBuilder* builder = new TileBuilder(this, Continent, 0, 0, MapId);
builder->AddGeometry(TileMap->Model, TileMap->ModelDefinition);
builder->SetCoords(0, 0);
uint8* nav = builder->BuildInstance(params);
if (nav)
{
// Set some params for the navmesh
dtMeshHeader* header = (dtMeshHeader*)nav;
dtVcopy(params.orig, header->bmin);
params.tileWidth = header->bmax[0] - header->bmin[0];
params.tileHeight = header->bmax[2] - header->bmin[2];
params.maxTiles = 1;
params.maxPolys = header->polyCount;
fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
char buff[100];
sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, 0, 0);
FILE* 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;
}
MmapTileHeader mheader;
mheader.size = builder->DataSize;
fwrite(&mheader, sizeof(MmapTileHeader), 1, f);
fwrite(nav, sizeof(unsigned char), builder->DataSize, f);
fclose(f);
}
dtFree(nav);
delete builder;
}
else
{
params.maxPolys = 1 << STATIC_POLY_BITS;
params.maxTiles = TileMap->TileTable.size();
rcVcopy(params.orig, bmin);
params.tileHeight = Constants::TileSize;
params.tileWidth = Constants::TileSize;
fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
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);

View File

@@ -328,6 +328,8 @@ void PrintUsage()
void LoadTile(dtNavMesh*& navMesh, const char* tile)
{
FILE* f = fopen(tile, "rb");
if (!f)
return;
MmapTileHeader header;
if (fread(&header, sizeof(MmapTileHeader), 1, f) != 1)
@@ -376,37 +378,37 @@ int main(int argc, char* argv[])
if (extractFlags & Constants::EXTRACT_FLAG_TEST)
{
float start[] = { 0.0f, 0.0f, 0.0f };
float end[] = { 0.0f, 0.0f, 0.0f };
float start[] = { -230.133f, 191.085f, -24.9191f };
float end[] = { -396.309f, 150.828f, 7.82184f };
//
float m_spos[3];
m_spos[0] = -1.0f * start[1];
m_spos[0] = -start[1];
m_spos[1] = start[2];
m_spos[2] = -1.0f * start[0];
m_spos[2] = -start[0];
//
float m_epos[3];
m_epos[0] = -1.0f * end[1];
m_epos[0] = -end[1];
m_epos[1] = end[2];
m_epos[2] = -1.0f * end[0];
m_epos[2] = -end[0];
//
dtQueryFilter m_filter;
m_filter.setIncludeFlags(0xffff);
m_filter.setExcludeFlags(0);
m_filter.setIncludeFlags(Constants::POLY_AREA_ROAD | Constants::POLY_AREA_TERRAIN);
m_filter.setExcludeFlags(Constants::POLY_AREA_WATER);
//
float m_polyPickExt[3];
m_polyPickExt[0] = 2;
m_polyPickExt[1] = 4;
m_polyPickExt[2] = 2;
m_polyPickExt[0] = 2.5f;
m_polyPickExt[1] = 2.5f;
m_polyPickExt[2] = 2.5f;
//
dtPolyRef m_startRef;
dtPolyRef m_endRef;
FILE* mmap = fopen(".mmap", "rb");
FILE* mmap = fopen("mmaps/389.mmap", "rb");
dtNavMeshParams params;
int count = fread(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
@@ -420,13 +422,16 @@ int main(int argc, char* argv[])
dtNavMeshQuery* navMeshQuery = new dtNavMeshQuery();
navMesh->init(&params);
LoadTile(navMesh, ".mmtile");
LoadTile(navMesh, ".mmtile");
LoadTile(navMesh, ".mmtile");
LoadTile(navMesh, ".mmtile");
LoadTile(navMesh, ".mmtile");
LoadTile(navMesh, ".mmtile");
for (int i = 0; i <= 32; ++i)
{
for (int j = 0; j <= 32; ++j)
{
char buff[100];
sprintf(buff, "mmaps/389%02i%02i.mmtile", i, j);
LoadTile(navMesh, buff);
}
}
navMeshQuery->init(navMesh, 2048);
float nearestPt[3];
@@ -440,7 +445,24 @@ int main(int argc, char* argv[])
return 0;
}
printf("Found!");
int hops;
dtPolyRef* hopBuffer = new dtPolyRef[8192];
dtStatus status = navMeshQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, &m_filter, hopBuffer, &hops, 8192);
int resultHopCount;
float* straightPath = new float[2048*3];
unsigned char* pathFlags = new unsigned char[2048];
dtPolyRef* pathRefs = new dtPolyRef[2048];
status = navMeshQuery->findStraightPath(m_spos, m_epos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048);
std::vector<Vector3> FinalPath;
FinalPath.reserve(resultHopCount);
for (uint32 i = 0; i < resultHopCount; ++i)
{
Vector3 finalV = Utils::ToWoWCoords(Vector3(straightPath[i * 3 + 0], straightPath[i * 3 + 1], straightPath[i * 3 + 2]));
FinalPath.push_back(finalV);
printf("Point %f %f %f\n", finalV.x, finalV.y, finalV.z);
}
}
return 0;

View File

@@ -14,7 +14,7 @@
#include <ace/Synch.h>
TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId) :
World(world), X(x), Y(y), MapId(mapId), _Geometry(NULL), DataSize(0), cBuilder(_cBuilder)
World(world), X(x), Y(y), MapId(mapId), _Geometry(NULL), DataSize(0), cBuilder(_cBuilder), pmesh(NULL), dmesh(NULL)
{
/*
Test, non-working values
@@ -90,12 +90,12 @@ 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 )
void TileBuilder::AddGeometry(WorldModelRoot* root, const WorldModelDefinition& def)
{
_Geometry = new Geometry();
_Geometry->Transform = true;
WorldModelHandler::InsertModelGeometry(_Geometry->Vertices, _Geometry->Triangles, def, root);
WorldModelHandler::InsertModelGeometry(_Geometry->Vertices, _Geometry->Triangles, def, root, false);
if (Constants::Debug)
{
@@ -114,26 +114,35 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
}
fclose(debug);
}
}
float* bmin, *bmax;
void TileBuilder::SetCoords(int x, int y)
{
X = x;
Y = y;
}
void TileBuilder::PrepareInstanceMesh(float*& bmin, float*& bmax)
{
_Geometry->CalculateBoundingBox(bmin, bmax);
rcVcopy(InstanceConfig.bmax, bmax);
rcVcopy(InstanceConfig.bmin, bmin);
if (pmesh && dmesh)
return;
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);
@@ -151,10 +160,10 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
rcContourSet* contours = rcAllocContourSet();
rcBuildContours(Context, *chf, InstanceConfig.maxSimplificationError, InstanceConfig.maxEdgeLen, *contours);
rcPolyMesh* pmesh = rcAllocPolyMesh();
pmesh = rcAllocPolyMesh();
rcBuildPolyMesh(Context, *contours, InstanceConfig.maxVertsPerPoly, *pmesh);
rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail();
dmesh = rcAllocPolyMeshDetail();
rcBuildPolyMeshDetail(Context, *pmesh, *chf, InstanceConfig.detailSampleDist, InstanceConfig.detailSampleMaxError, *dmesh);
// Set flags according to area types (e.g. Swim for Water)
@@ -165,6 +174,13 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
else if (pmesh->areas[i] == Constants::POLY_AREA_WATER)
pmesh->flags[i] = Constants::POLY_FLAG_SWIM;
}
}
uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams )
{
float* bmin = NULL, *bmax = NULL;
PrepareInstanceMesh(bmin, bmax);
dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params));
@@ -190,9 +206,10 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
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.tileX = X;
params.tileY = Y;
params.tileLayer = 0;
params.buildBvTree = true;
rcVcopy(params.bmax, bmax);
rcVcopy(params.bmin, bmin);
@@ -208,9 +225,6 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
// 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;
}
@@ -219,10 +233,6 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
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);

View File

@@ -17,7 +17,10 @@ public:
void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams);
uint8* Build(dtNavMeshParams& navMeshParams);
uint8* BuildInstance(dtNavMeshParams& navMeshParams, WorldModelRoot* root, const WorldModelDefinition& def);
uint8* BuildInstance(dtNavMeshParams& navMeshParams);
void AddGeometry(WorldModelRoot* root, const WorldModelDefinition& def);
void SetCoords(int x, int y);
void PrepareInstanceMesh(float*& bmin, float*& bmax);
std::string World;
int X;
int Y;
@@ -28,5 +31,7 @@ public:
Geometry* _Geometry;
uint32 DataSize;
ContinentBuilder* cBuilder;
rcPolyMesh* pmesh;
rcPolyMeshDetail* dmesh;
};
#endif

View File

@@ -87,7 +87,7 @@ std::string Utils::FixModelPath(const std::string& path )
return Utils::GetPathBase(path) + ".M2";
}
Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec)
Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec, bool translate)
{
// Sources of information:
/// http://www.pxr.dk/wowdev/wiki/index.php?title=ADT/v18&oldid=3715
@@ -99,15 +99,21 @@ Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec)
Vector3 ret = Utils::VectorTransform(vec, rot);
// And finally scale and translate it to our origin
return (ret * def.Scale()) + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
ret = ret * def.Scale();
if (translate)
ret = ret + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
return ret;
}
Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec )
Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec, bool translate )
{
G3D::Quat quat = G3D::Quat(-inst.QuatY, inst.QuatZ, -inst.QuatX, inst.QuatW);
Vector3 ret = Utils::VectorTransform(vec, G3D::Matrix4(quat.toRotationMatrix()));
return (ret * (inst.Scale / 1024.0f)) + Vector3(Constants::MaxXY - inst.Position.z, Constants::MaxXY - inst.Position.x, inst.Position.y);
ret = ret * (inst.Scale / 1024.0f);
if (translate)
ret = ret + Vector3(Constants::MaxXY - inst.Position.z, Constants::MaxXY - inst.Position.x, inst.Position.y);
return ret;
}
float Utils::ToRadians( float degrees )
@@ -138,11 +144,11 @@ Vector3 Vector3::Read( FILE* file )
return ret;
}
Vector3 Utils::GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/)
Vector3 Utils::GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int x, int y, bool translate)
{
if (Utils::Distance(height, 0.0f) > 0.5f)
basePosition.z = 0.0f;
return Utils::TransformDoodadVertex(def, basePosition + Vector3(basePosition.x * Constants::UnitSize, basePosition.y * Constants::UnitSize, height));
return Utils::TransformDoodadVertex(def, basePosition + Vector3(x * Constants::UnitSize, y * Constants::UnitSize, height), translate);
}
float Utils::Distance( float x, float y )
@@ -189,7 +195,7 @@ void Utils::SaveToDisk( FILE* stream, const std::string& path )
Vector3 Utils::ToWoWCoords(const Vector3& vec )
{
return Vector3(-vec.z, vec.x, vec.y);
return Vector3(-vec.z, -vec.x, vec.y);
}
std::string Utils::GetExtension( std::string path )

View File

@@ -367,7 +367,7 @@ public:
}
static float ToRadians(float degrees);
static std::string GetPathBase(const std::string& path);
static Vector3 GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/);
static Vector3 GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/, bool translate = true);
static float Distance(float x, float y);
template<typename T>
static bool IsAllZero(T* arr, uint32 size)
@@ -383,8 +383,8 @@ public:
static Vector3 ToWoWCoords(const Vector3& vec );
static std::string GetExtension( std::string path );
static char* GetPlainName(const char* FileName);
static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec);
static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec, bool translate = true);
static Vector3 VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix, bool normal = false );
static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec );
static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec, bool translate = true );
};
#endif

View File

@@ -79,13 +79,17 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk )
fseek(stream, mcnk->Source->Offset, SEEK_SET);
}
void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root )
void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root, bool translate )
{
for (std::vector<WorldModelGroup>::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group)
{
uint32 vertOffset = verts.size();
for (std::vector<Vector3>::iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2)
verts.push_back(Utils::TransformDoodadVertex(def, *itr2)); // Transform the vertex to world space
{
Vector3 v = Utils::TransformDoodadVertex(def, *itr2, translate);
// If translate is false, then we were called directly from the TileBuilder to add data to it's _Geometry member, hence, we have to manually convert the vertices to Recast format.
verts.push_back(translate ? v : Utils::ToRecast(v)); // Transform the vertex to world space
}
for (uint32 i = 0; i < group->Triangles.size(); ++i)
{
@@ -122,7 +126,10 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
continue;
int vertOffset = verts.size();
for (std::vector<Vector3>::iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2)
verts.push_back(Utils::TransformDoodadVertex(def, Utils::TransformWmoDoodad(*instance, def, *itr2)));
{
Vector3 v = Utils::TransformDoodadVertex(def, Utils::TransformWmoDoodad(*instance, def, *itr2, false), translate);
verts.push_back(translate ? v : Utils::ToRecast(v));
}
for (std::vector<Triangle<uint16> >::iterator itr2 = model->Triangles.begin(); itr2 != model->Triangles.end(); ++itr2)
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WMO, itr2->V0 + vertOffset, itr2->V1 + vertOffset, itr2->V2 + vertOffset));
}
@@ -144,14 +151,20 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
continue;
uint32 vertOffset = verts.size();
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x][y], x, y));
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x + 1][y], x + 1, y));
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x][y + 1], x, y + 1));
verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1));
Vector3 v1 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x][y], x, y, translate);
Vector3 v2 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x + 1][y], x + 1, y, translate);
Vector3 v3 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x][y + 1], x, y + 1, translate);
Vector3 v4 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
liquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1, translate);
verts.push_back(translate ? v1 : Utils::ToRecast(v1));
verts.push_back(translate ? v2 : Utils::ToRecast(v2));
verts.push_back(translate ? v3 : Utils::ToRecast(v3));
verts.push_back(translate ? v4 : Utils::ToRecast(v4));
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset + 2, vertOffset + 1));
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1));

View File

@@ -34,7 +34,7 @@ public:
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
bool IsSane() { return _definitions && _paths; }
static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root);
static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root, bool translate = true);
protected:
void ProcessInternal(MapChunk* data);
private: