aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/mesh_extractor/Chunk.cpp2
-rw-r--r--src/tools/mesh_extractor/Constants.h2
-rw-r--r--src/tools/mesh_extractor/DBC.cpp2
-rw-r--r--src/tools/mesh_extractor/DBC.h5
-rw-r--r--src/tools/mesh_extractor/MeshExtractor.cpp123
-rw-r--r--src/tools/mesh_extractor/Model.cpp29
-rw-r--r--src/tools/mesh_extractor/Model.h2
-rw-r--r--src/tools/mesh_extractor/ObjectDataHandler.cpp2
-rw-r--r--src/tools/mesh_extractor/TileBuilder.cpp4
-rw-r--r--src/tools/mesh_extractor/Utils.cpp36
-rw-r--r--src/tools/mesh_extractor/Utils.h3
-rw-r--r--src/tools/mesh_extractor/WorldModelGroup.cpp2
12 files changed, 183 insertions, 29 deletions
diff --git a/src/tools/mesh_extractor/Chunk.cpp b/src/tools/mesh_extractor/Chunk.cpp
index b41fa7d07d4..2f521f1badd 100644
--- a/src/tools/mesh_extractor/Chunk.cpp
+++ b/src/tools/mesh_extractor/Chunk.cpp
@@ -10,7 +10,7 @@ int32 Chunk::FindSubChunkOffset(std::string name)
FILE* stream = GetStream();
uint32 matched = 0;
- while (ftell(stream) < Utils::Size(stream))
+ while (uint32(ftell(stream)) < Utils::Size(stream))
{
char b;
fread(&b, sizeof(char), 1, stream);
diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h
index f3b71812155..89cd6da20a2 100644
--- a/src/tools/mesh_extractor/Constants.h
+++ b/src/tools/mesh_extractor/Constants.h
@@ -47,6 +47,8 @@ public:
static const float Origin[];
static const float PI;
static const float MaxStandableHeight;
+ static bool ToWoWCoords;
+ static const char* VMAPMagic;
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp
index be04ce070ee..c50e02014da 100644
--- a/src/tools/mesh_extractor/DBC.cpp
+++ b/src/tools/mesh_extractor/DBC.cpp
@@ -38,7 +38,7 @@ DBC::DBC( FILE* stream ) : StringBlock(NULL), IsFaulty(true), StringBlockSize(0)
std::string DBC::GetStringByOffset( int offset )
{
int len = 0;
- for (int i = offset; i < StringBlockSize; i++)
+ for (uint32 i = offset; i < StringBlockSize; i++)
{
if (!StringBlock[i])
{
diff --git a/src/tools/mesh_extractor/DBC.h b/src/tools/mesh_extractor/DBC.h
index 6c86c1391dd..0c857bd40ed 100644
--- a/src/tools/mesh_extractor/DBC.h
+++ b/src/tools/mesh_extractor/DBC.h
@@ -37,9 +37,10 @@ public:
return Values[index];
}
- float GetFloat(int index)
+ template <typename T>
+ T GetValue(int index)
{
- return *(float*)(&Values[index]);
+ return *(T*)(&Values[index]);
}
std::string GetString(int index)
diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp
index d6b701607ba..8eb6ba5cb6e 100644
--- a/src/tools/mesh_extractor/MeshExtractor.cpp
+++ b/src/tools/mesh_extractor/MeshExtractor.cpp
@@ -4,6 +4,7 @@
#include "Cache.h"
#include "DBC.h"
#include "Constants.h"
+#include "Model.h"
#include <set>
@@ -70,6 +71,116 @@ void ExtractDBCs()
printf("DBC extraction finished!\n");
}
+void ExtractGameobjectModels()
+{
+ Constants::ToWoWCoords = true;
+ printf("Extracting GameObject models\n");
+
+ std::string baseBuildingsPath = "Buildings/";
+ std::string baseVmapsPath = "vmaps/";
+ Utils::CreateDir(baseVmapsPath);
+ Utils::CreateDir(baseBuildingsPath);
+
+ FILE* modelList = fopen((baseVmapsPath + "GameObjectModels.list").c_str(), "wb");
+ if (!modelList)
+ {
+ printf("Could not create file vmaps/GameObjectModels.list, please make sure that you have the write permissions in the folder\n");
+ return;
+ }
+
+ DBC* dbc = MPQHandler->GetDBC("GameObjectDisplayInfo");
+ for (std::vector<Record*>::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr)
+ {
+ std::string path = (*itr)->GetString(1);
+ std::string fileName = Utils::GetPlainName(path.c_str());
+ std::string extension = Utils::GetExtension(fileName);
+ // Convert the extension to lowercase
+ std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+ if (extension == "mdx" || extension == "m2")
+ {
+ fileName = Utils::FixModelPath(fileName);
+ Model model(path);
+
+ if (model.IsBad)
+ continue;
+
+ FILE* output = fopen((baseBuildingsPath + fileName).c_str(), "wb");
+ if (!output)
+ {
+ printf("Could not create file %s, please check that you have write permissions\n", (baseBuildingsPath + fileName).c_str());
+ continue;
+ }
+ // Placeholder for 0 values
+ int Nop[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ fwrite(Constants::VMAPMagic, 8, 1, output);
+ uint32 numVerts = model.Header.CountBoundingVertices;
+ fwrite(&numVerts, sizeof(uint32), 1, output);
+ uint32 numGroups = 1;
+ fwrite(&numGroups, sizeof(uint32), 1, output);
+ fwrite(Nop, 4 * 3 , 1, output); // rootwmoid, flags, groupid
+ fwrite(Nop, sizeof(float), 3 * 2, output);//bbox, only needed for WMO currently
+ fwrite(Nop, 4, 1, output);// liquidflags
+ fwrite("GRP ", 4, 1, output);
+
+ uint32 branches = 1;
+ uint32 wsize = sizeof(branches) + sizeof(uint32) * branches;
+ fwrite(&wsize, sizeof(uint32), 1, output);
+ fwrite(&branches, sizeof(branches), 1, output);
+ uint32 numTris = model.Header.CountBoundingTriangles;
+ fwrite(&numTris, sizeof(uint32), 1, output);
+ fwrite("INDX", 4, 1, output);
+ wsize = sizeof(uint32) + sizeof(unsigned short) * numTris;
+ fwrite(&wsize, sizeof(int), 1, output);
+ fwrite(&numTris, sizeof(uint32), 1, output);
+ uint16* indices = new uint16[numTris];
+
+ if (numTris > 0)
+ {
+ uint32 i = 0;
+ for (std::vector<Triangle<uint16> >::iterator itr2 = model.Triangles.begin(); itr2 != model.Triangles.end(); ++itr2, ++i)
+ {
+ indices[i * 3 + 0] = itr2->V0;
+ indices[i * 3 + 1] = itr2->V1;
+ indices[i * 3 + 2] = itr2->V2;
+ }
+ fwrite(indices, sizeof(uint16), numTris, output);
+ }
+
+
+ fwrite("VERT", 4, 1, output);
+ wsize = sizeof(int) + sizeof(float) * 3 * numVerts;
+ fwrite(&wsize, sizeof(int), 1, output);
+ fwrite(&numVerts, sizeof(int), 1, output);
+ float* vertices = new float[numVerts*3];
+
+ if (numVerts > 0)
+ {
+ uint32 i = 0;
+ for (std::vector<Vector3>::iterator itr2 = model.Vertices.begin(); itr2 != model.Vertices.end(); ++itr2, ++i)
+ {
+ vertices[i * 3 + 0] = itr2->x;
+ vertices[i * 3 + 1] = itr2->y;
+ vertices[i * 3 + 2] = itr2->z;
+ }
+
+ fwrite(vertices, sizeof(float), numVerts * 3, output);
+ }
+
+ fclose(output);
+ delete[] indices;
+ delete[] vertices;
+ }
+ else if (extension == "wmo")
+ {
+ //WorldModelRoot model(path);
+ }
+ }
+
+ printf("GameObject models extraction finished!");
+ Constants::ToWoWCoords = false;
+}
+
bool HandleArgs(int argc, char** argv, uint32& threads, std::set<uint32>& mapList, bool& debugOutput, uint32& extractFlags)
{
char* param = NULL;
@@ -141,7 +252,7 @@ void PrintUsage()
printf("- %u to extract DBCs\n", Constants::EXTRACT_FLAG_DBC);
printf("- %u to extract Maps (Not yet implemented)\n", Constants::EXTRACT_FLAG_MAPS);
printf("- %u to extract VMaps (Not yet implemented)\n", Constants::EXTRACT_FLAG_VMAPS);
- printf("- %u to extract GameObject models (Not yet implemented)\n", Constants::EXTRACT_FLAG_GOB_MODELS);
+ printf("- %u to extract GameObject models (Not yet finished)\n", Constants::EXTRACT_FLAG_GOB_MODELS);
printf("- %u to extract MMaps (Not yet finished)\n", Constants::EXTRACT_FLAG_MMAPS);
}
}
@@ -149,9 +260,6 @@ void PrintUsage()
int main(int argc, char* argv[])
{
system("pause");
- Cache = new CacheClass();
- MPQHandler = new MPQManager();
- MPQHandler->Initialize();
uint32 threads = 4, extractFlags = 0;
std::set<uint32> mapIds;
bool debug = false;
@@ -162,11 +270,18 @@ int main(int argc, char* argv[])
return -1;
}
+ Cache = new CacheClass();
+ MPQHandler = new MPQManager();
+ MPQHandler->Initialize();
+
if (extractFlags & Constants::EXTRACT_FLAG_DBC)
ExtractDBCs();
if (extractFlags & Constants::EXTRACT_FLAG_MMAPS)
ExtractMMaps(mapIds, threads, debug);
+
+ if (extractFlags & Constants::EXTRACT_FLAG_GOB_MODELS)
+ ExtractGameobjectModels();
return 0;
} \ No newline at end of file
diff --git a/src/tools/mesh_extractor/Model.cpp b/src/tools/mesh_extractor/Model.cpp
index a1c67d23f28..10fde0ebc2d 100644
--- a/src/tools/mesh_extractor/Model.cpp
+++ b/src/tools/mesh_extractor/Model.cpp
@@ -2,9 +2,14 @@
#include "MPQManager.h"
#include "Utils.h"
-Model::Model( std::string path )
+Model::Model( std::string path ) : IsCollidable(false), IsBad(false)
{
Stream = MPQHandler->GetFile(Utils::FixModelPath(path));
+ if (!Stream)
+ {
+ IsBad = true;
+ return;
+ }
Header.Read(Stream);
if (Header.OffsetBoundingNormals > 0 && Header.OffsetBoundingVertices > 0 &&
Header.OffsetBoundingTriangles > 0 && Header.BoundingRadius > 0.0f)
@@ -16,26 +21,36 @@ Model::Model( std::string path )
}
}
+Model::~Model()
+{
+ if (Stream)
+ fclose(Stream);
+}
+
void Model::ReadVertices( FILE* stream )
{
fseek(stream, Header.OffsetBoundingVertices, SEEK_SET);
Vertices.reserve(Header.CountBoundingVertices);
- for (int i = 0; i < Header.CountBoundingVertices; ++i)
- Vertices[i] = Vector3::Read(stream);
+ for (uint32 i = 0; i < Header.CountBoundingVertices; ++i)
+ {
+ Vertices.push_back(Vector3::Read(stream));
+ if (Constants::ToWoWCoords)
+ Vertices[i] = Utils::ToWoWCoords(Vertices[i]);
+ }
}
void Model::ReadBoundingTriangles( FILE* stream )
{
fseek(stream, Header.OffsetBoundingTriangles, SEEK_SET);
Triangles.reserve(Header.CountBoundingTriangles / 3);
- for (int i = 0; i < Header.CountBoundingTriangles / 3; i++)
+ for (uint32 i = 0; i < Header.CountBoundingTriangles / 3; i++)
{
Triangle<uint16> tri;
tri.Type = Constants::TRIANGLE_TYPE_DOODAD;
fread(&tri.V0, sizeof(uint16), 1, stream);
fread(&tri.V1, sizeof(uint16), 1, stream);
fread(&tri.V2, sizeof(uint16), 1, stream);
- Triangles[i] = tri;
+ Triangles.push_back(tri);
}
}
@@ -43,7 +58,7 @@ void Model::ReadBoundingNormals( FILE* stream )
{
fseek(stream, Header.OffsetBoundingNormals, SEEK_SET);
Normals.reserve(Header.CountBoundingNormals);
- for (int i = 0; i < Header.CountBoundingNormals; i++)
- Normals[i] = Vector3::Read(stream);
+ for (uint32 i = 0; i < Header.CountBoundingNormals; i++)
+ Normals.push_back(Vector3::Read(stream));
}
diff --git a/src/tools/mesh_extractor/Model.h b/src/tools/mesh_extractor/Model.h
index a5b8338461d..ea9331e7c30 100644
--- a/src/tools/mesh_extractor/Model.h
+++ b/src/tools/mesh_extractor/Model.h
@@ -7,6 +7,7 @@ class Model
{
public:
Model(std::string path);
+ ~Model();
void ReadVertices(FILE* stream);
void ReadBoundingTriangles(FILE* stream);
@@ -17,5 +18,6 @@ public:
std::vector<Triangle<uint16> > Triangles;
bool IsCollidable;
FILE* Stream;
+ bool IsBad;
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/ObjectDataHandler.cpp b/src/tools/mesh_extractor/ObjectDataHandler.cpp
index 3ed2ee49604..789efc6d62c 100644
--- a/src/tools/mesh_extractor/ObjectDataHandler.cpp
+++ b/src/tools/mesh_extractor/ObjectDataHandler.cpp
@@ -11,7 +11,7 @@ void ObjectDataHandler::ProcessMapChunk( MapChunk* chunk )
int32 firstIndex = Source->ObjectData->GetFirstIndex("MCNK");
if (firstIndex == -1)
return;
- if (firstIndex + chunk->Index > Source->ObjectData->Chunks.size())
+ if (uint32(firstIndex + chunk->Index) > Source->ObjectData->Chunks.size())
return;
Chunk* ourChunk = Source->ObjectData->Chunks[firstIndex + chunk->Index];
if (ourChunk->Length == 0)
diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp
index 5b3e181713e..12213b16373 100644
--- a/src/tools/mesh_extractor/TileBuilder.cpp
+++ b/src/tools/mesh_extractor/TileBuilder.cpp
@@ -88,9 +88,9 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams)
char buff[100];
sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X);
FILE* debug = fopen(buff, "wb");
- for (int i = 0; i < _Geometry->Vertices.size(); ++i)
+ for (uint32 i = 0; i < _Geometry->Vertices.size(); ++i)
fprintf(debug, "v %f %f %f\n", _Geometry->Vertices[i].x, _Geometry->Vertices[i].y, _Geometry->Vertices[i].z);
- for (int i = 0; i < _Geometry->Triangles.size(); ++i)
+ for (uint32 i = 0; i < _Geometry->Triangles.size(); ++i)
fprintf(debug, "f %i %i %i\n", _Geometry->Triangles[i].V0 + 1, _Geometry->Triangles[i].V1 + 1, _Geometry->Triangles[i].V2 + 1);
fclose(debug);
}
diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp
index 5b752885d17..5fccd319554 100644
--- a/src/tools/mesh_extractor/Utils.cpp
+++ b/src/tools/mesh_extractor/Utils.cpp
@@ -19,6 +19,8 @@ const float Constants::UnitSize = Constants::ChunkSize / 8.0f;
const float Constants::Origin[] = { -Constants::MaxXY, 0.0f, -Constants::MaxXY };
const float Constants::PI = 3.1415926f;
const float Constants::MaxStandableHeight = 1.5f;
+const char* Constants::VMAPMagic = "VMAP042";
+bool Constants::ToWoWCoords = false;
void Utils::CreateDir( const std::string& Path )
{
@@ -219,6 +221,21 @@ void Utils::SaveToDisk( FILE* stream, std::string path )
delete data;
}
+Vector3 Utils::ToWoWCoords( Vector3 vec )
+{
+ return Vector3(vec.x, -vec.z, vec.y);
+}
+
+std::string Utils::GetExtension( std::string path )
+{
+ std::string::size_type idx = path.rfind('.');
+ std::string extension = "";
+
+ if(idx != std::string::npos)
+ extension = path.substr(idx+1);
+ return extension;
+}
+
void MapChunkHeader::Read(FILE* stream)
{
fread(&Flags, sizeof(uint32), 1, stream);
@@ -308,16 +325,6 @@ void ModelHeader::Read(FILE* stream)
fread(&OffsetTransLookup, sizeof(uint32), 1, stream);
fread(&CountUvAnimLookup, sizeof(uint32), 1, stream);
fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream);
- fread(&CountColors, sizeof(uint32), 1, stream);
- fread(&OffsetColors, sizeof(uint32), 1, stream);
- fread(&CountTextures, sizeof(uint32), 1, stream);
- fread(&OffsetTextures, sizeof(uint32), 1, stream);
- fread(&CountTransparency, sizeof(uint32), 1, stream);
- fread(&OffsetTransparency, sizeof(uint32), 1, stream);
- fread(&CountUvAnimation, sizeof(uint32), 1, stream);
- fread(&OffsetUvAnimation, sizeof(uint32), 1, stream);
- fread(&CountTexReplace, sizeof(uint32), 1, stream);
- fread(&OffsetTexReplace, sizeof(uint32), 1, stream);
VertexBox[0] = Vector3::Read(stream);
VertexBox[1] = Vector3::Read(stream);
fread(&VertexRadius, sizeof(float), 1, stream);
@@ -468,3 +475,12 @@ H2OInformation H2OInformation::Read(FILE* stream)
fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream);
return ret;
}
+
+char* Utils::GetPlainName(const char* FileName)
+{
+ char* temp;
+
+ if((temp = (char*)strrchr(FileName, '\\')) != NULL)
+ FileName = temp + 1;
+ return (char*)FileName;
+} \ No newline at end of file
diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h
index c19bc1bb29c..47a6354d3b2 100644
--- a/src/tools/mesh_extractor/Utils.h
+++ b/src/tools/mesh_extractor/Utils.h
@@ -351,5 +351,8 @@ public:
static G3D::Matrix4 GetWmoDoodadTransformation( DoodadInstance inst, WorldModelDefinition root );
static void CreateDir( const std::string& Path );
static void SaveToDisk(FILE* stream, std::string path);
+ static Vector3 ToWoWCoords( Vector3 vec );
+ static std::string GetExtension( std::string path );
+ static char* GetPlainName(const char* FileName);
};
#endif \ No newline at end of file
diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp
index bd0d106dabb..c7e6f0c525e 100644
--- a/src/tools/mesh_extractor/WorldModelGroup.cpp
+++ b/src/tools/mesh_extractor/WorldModelGroup.cpp
@@ -37,7 +37,7 @@ void WorldModelGroup::ReadNormals()
Normals.reserve(normalCount);
FILE* stream = chunk->GetStream();
for (uint32 i = 0; i < normalCount; i++)
- Normals[i] = Vector3::Read(stream);
+ Normals.push_back(Vector3::Read(stream));
}
void WorldModelGroup::ReadLiquid()