mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-30 00:53:46 +00:00
feat(Tools/Vmapextractor): Improved vmap detail level by extracting w… (#4922)
This commit is contained in:
@@ -17,6 +17,7 @@ add_executable(vmap4extractor ${PRIVATE_SOURCES})
|
||||
|
||||
target_link_libraries(vmap4extractor
|
||||
PUBLIC
|
||||
g3dlib
|
||||
mpq)
|
||||
|
||||
# Group sources
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "vmapexport.h"
|
||||
#include "adtfile.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -34,6 +33,9 @@ char* GetPlainName(char* FileName)
|
||||
|
||||
void fixnamen(char* name, size_t len)
|
||||
{
|
||||
if (len < 3)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < len - 3; i++)
|
||||
{
|
||||
if (i > 0 && name[i] >= 'A' && name[i] <= 'Z' && isalpha(name[i - 1]))
|
||||
@@ -41,6 +43,7 @@ void fixnamen(char* name, size_t len)
|
||||
else if ((i == 0 || !isalpha(name[i - 1])) && name[i] >= 'a' && name[i] <= 'z')
|
||||
name[i] &= ~0x20;
|
||||
}
|
||||
|
||||
//extension in lowercase
|
||||
for (size_t i = len - 3; i < len; i++)
|
||||
name[i] |= 0x20;
|
||||
@@ -48,11 +51,12 @@ void fixnamen(char* name, size_t len)
|
||||
|
||||
void fixname2(char* name, size_t len)
|
||||
{
|
||||
if (len < 3)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < len - 3; i++)
|
||||
{
|
||||
if (name[i] == ' ')
|
||||
name[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
char* GetExtension(char* FileName)
|
||||
@@ -62,33 +66,17 @@ char* GetExtension(char* FileName)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ADTFile::ADTFile(char* filename): ADT(filename), nWMO(0), nMDX(0), WmoInstansName(nullptr), ModelInstansName(nullptr)
|
||||
ADTFile::ADTFile(char* filename): _file(filename)
|
||||
{
|
||||
Adtfilename.append(filename);
|
||||
}
|
||||
|
||||
bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
|
||||
{
|
||||
if (ADT.isEof ())
|
||||
if (_file.isEof())
|
||||
return false;
|
||||
|
||||
uint32 size;
|
||||
|
||||
string xMap;
|
||||
string yMap;
|
||||
|
||||
Adtfilename.erase(Adtfilename.find(".adt"), 4);
|
||||
string TempMapNumber;
|
||||
TempMapNumber = Adtfilename.substr(Adtfilename.length() - 6, 6);
|
||||
xMap = TempMapNumber.substr(TempMapNumber.find("_") + 1, (TempMapNumber.find_last_of("_") - 1) - (TempMapNumber.find("_")));
|
||||
yMap = TempMapNumber.substr(TempMapNumber.find_last_of("_") + 1, (TempMapNumber.length()) - (TempMapNumber.find_last_of("_")));
|
||||
Adtfilename.erase((Adtfilename.length() - xMap.length() - yMap.length() - 2), (xMap.length() + yMap.length() + 2));
|
||||
//string AdtMapNumber = xMap + ' ' + yMap + ' ' + GetPlainName((char*)Adtfilename.c_str());
|
||||
//printf("Processing map %s...\n", AdtMapNumber.c_str());
|
||||
//printf("MapNumber = %s\n", TempMapNumber.c_str());
|
||||
//printf("xMap = %s\n", xMap.c_str());
|
||||
//printf("yMap = %s\n", yMap.c_str());
|
||||
|
||||
std::string dirname = std::string(szWorkDirWmo) + "/dir_bin";
|
||||
FILE* dirfile;
|
||||
dirfile = fopen(dirname.c_str(), "ab");
|
||||
@@ -98,15 +86,15 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!ADT.isEof())
|
||||
while (!_file.isEof())
|
||||
{
|
||||
char fourcc[5];
|
||||
ADT.read(&fourcc, 4);
|
||||
ADT.read(&size, 4);
|
||||
_file.read(&fourcc, 4);
|
||||
_file.read(&size, 4);
|
||||
flipcc(fourcc);
|
||||
fourcc[4] = 0;
|
||||
|
||||
size_t nextpos = ADT.getPos() + size;
|
||||
size_t nextpos = _file.getPos() + size;
|
||||
|
||||
if (!strcmp(fourcc, "MCIN"))
|
||||
{
|
||||
@@ -119,17 +107,15 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
|
||||
if (size)
|
||||
{
|
||||
char* buf = new char[size];
|
||||
ADT.read(buf, size);
|
||||
_file.read(buf, size);
|
||||
char* p = buf;
|
||||
int t = 0;
|
||||
ModelInstansName = new string[size];
|
||||
while (p < buf + size)
|
||||
{
|
||||
fixnamen(p, strlen(p));
|
||||
char* s = GetPlainName(p);
|
||||
fixname2(s, strlen(s));
|
||||
|
||||
ModelInstansName[t++] = s;
|
||||
ModelInstanceNames.emplace_back(s);
|
||||
|
||||
string path(p);
|
||||
ExtractSingleModel(path);
|
||||
@@ -144,17 +130,20 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
|
||||
if (size)
|
||||
{
|
||||
char* buf = new char[size];
|
||||
ADT.read(buf, size);
|
||||
_file.read(buf, size);
|
||||
char* p = buf;
|
||||
int q = 0;
|
||||
WmoInstansName = new string[size];
|
||||
while (p < buf + size)
|
||||
{
|
||||
std::string path(p);
|
||||
|
||||
char* s = GetPlainName(p);
|
||||
fixnamen(s, strlen(s));
|
||||
fixname2(s, strlen(s));
|
||||
WmoInstanceNames.emplace_back(s);
|
||||
|
||||
ExtractSingleWmo(path);
|
||||
|
||||
p += strlen(p) + 1;
|
||||
WmoInstansName[q++] = s;
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
@@ -164,39 +153,38 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
nMDX = (int)size / 36;
|
||||
for (int i = 0; i < nMDX; ++i)
|
||||
uint32 doodadCount = size / sizeof(ADT::MDDF);
|
||||
for (uint32 i = 0; i < doodadCount; ++i)
|
||||
{
|
||||
uint32 id;
|
||||
ADT.read(&id, 4);
|
||||
ModelInstance inst(ADT, ModelInstansName[id].c_str(), map_num, tileX, tileY, dirfile);
|
||||
ADT::MDDF doodadDef;
|
||||
_file.read(&doodadDef, sizeof(ADT::MDDF));
|
||||
Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, tileX, tileY, dirfile);
|
||||
}
|
||||
delete[] ModelInstansName;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(fourcc, "MODF"))
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
nWMO = (int)size / 64;
|
||||
for (int i = 0; i < nWMO; ++i)
|
||||
uint32 mapObjectCount = size / sizeof(ADT::MODF);
|
||||
for (uint32 i = 0; i < mapObjectCount; ++i)
|
||||
{
|
||||
uint32 id;
|
||||
ADT.read(&id, 4);
|
||||
WMOInstance inst(ADT, WmoInstansName[id].c_str(), map_num, tileX, tileY, dirfile);
|
||||
ADT::MODF mapObjDef;
|
||||
_file.read(&mapObjDef, sizeof(ADT::MODF));
|
||||
MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), map_num, tileX, tileY, dirfile);
|
||||
Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, map_num, tileX, tileY, dirfile);
|
||||
}
|
||||
delete[] WmoInstansName;
|
||||
}
|
||||
}
|
||||
//======================
|
||||
ADT.seek(nextpos);
|
||||
_file.seek(nextpos);
|
||||
}
|
||||
ADT.close();
|
||||
_file.close();
|
||||
fclose(dirfile);
|
||||
return true;
|
||||
}
|
||||
|
||||
ADTFile::~ADTFile()
|
||||
{
|
||||
ADT.close();
|
||||
_file.close();
|
||||
}
|
||||
|
||||
@@ -94,20 +94,45 @@ struct MapChunkHeader
|
||||
uint32 effectId;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
namespace ADT
|
||||
{
|
||||
struct MDDF
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 UniqueId;
|
||||
Vec3D Position;
|
||||
Vec3D Rotation;
|
||||
uint16 Scale;
|
||||
uint16 Flags;
|
||||
};
|
||||
|
||||
struct MODF
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 UniqueId;
|
||||
Vec3D Position;
|
||||
Vec3D Rotation;
|
||||
AaBox3D Bounds;
|
||||
uint16 Flags;
|
||||
uint16 DoodadSet; // can be larger than number of doodad sets in WMO
|
||||
uint16 NameSet;
|
||||
uint16 Scale;
|
||||
};
|
||||
}
|
||||
#pragma pack(pop)
|
||||
|
||||
class ADTFile
|
||||
{
|
||||
private:
|
||||
//size_t mcnk_offsets[256], mcnk_sizes[256];
|
||||
MPQFile ADT;
|
||||
//mcell Mcell;
|
||||
string Adtfilename;
|
||||
MPQFile _file;
|
||||
std::string Adtfilename;
|
||||
public:
|
||||
ADTFile(char* filename);
|
||||
~ADTFile();
|
||||
int nWMO;
|
||||
int nMDX;
|
||||
string* WmoInstansName;
|
||||
string* ModelInstansName;
|
||||
std::vector<std::string> WmoInstanceNames;
|
||||
std::vector<std::string> ModelInstanceNames;
|
||||
bool init(uint32 map_num, uint32 tileX, uint32 tileY);
|
||||
//void LoadMapChunks();
|
||||
|
||||
|
||||
@@ -8,17 +8,16 @@
|
||||
#include "dbcfile.h"
|
||||
#include "adtfile.h"
|
||||
#include "vmapexport.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
bool ExtractSingleModel(std::string& fname)
|
||||
{
|
||||
char* name = GetPlainName((char*)fname.c_str());
|
||||
char* ext = GetExtension(name);
|
||||
if (fname.length() < 4)
|
||||
return false;
|
||||
|
||||
// < 3.1.0 ADT MMDX section store filename.mdx filenames for corresponded .m2 file
|
||||
if (!strcmp(ext, ".mdx"))
|
||||
std::string extension = fname.substr(fname.length() - 4, 4);
|
||||
if (extension == ".mdx" || extension == ".MDX" || extension == ".mdl" || extension == ".MDL")
|
||||
{
|
||||
// replace .mdx -> .m2
|
||||
fname.erase(fname.length() - 2, 2);
|
||||
@@ -27,6 +26,12 @@ bool ExtractSingleModel(std::string& fname)
|
||||
// >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file
|
||||
// nothing do
|
||||
|
||||
std::string originalName = fname;
|
||||
|
||||
char* name = GetPlainName((char*)fname.c_str());
|
||||
fixnamen(name, strlen(name));
|
||||
fixname2(name, strlen(name));
|
||||
|
||||
std::string output(szWorkDirWmo);
|
||||
output += "/";
|
||||
output += name;
|
||||
@@ -34,7 +39,7 @@ bool ExtractSingleModel(std::string& fname)
|
||||
if (FileExists(output.c_str()))
|
||||
return true;
|
||||
|
||||
Model mdl(fname);
|
||||
Model mdl(originalName);
|
||||
if (!mdl.open())
|
||||
return false;
|
||||
|
||||
@@ -63,6 +68,8 @@ void ExtractGameobjectModels()
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, model_list);
|
||||
|
||||
for (const auto & it : dbc)
|
||||
{
|
||||
path = it.getString(1);
|
||||
@@ -81,8 +88,10 @@ void ExtractGameobjectModels()
|
||||
strToLower(ch_ext);
|
||||
|
||||
bool result = false;
|
||||
uint8 isWmo = 0;
|
||||
if (!strcmp(ch_ext, ".wmo"))
|
||||
{
|
||||
isWmo = 1;
|
||||
result = ExtractSingleWmo(path);
|
||||
}
|
||||
else if (!strcmp(ch_ext, ".mdl"))
|
||||
@@ -100,6 +109,7 @@ void ExtractGameobjectModels()
|
||||
uint32 displayId = it.getUInt(0);
|
||||
uint32 path_length = strlen(name);
|
||||
fwrite(&displayId, sizeof(uint32), 1, model_list);
|
||||
fwrite(&isWmo, sizeof(uint8), 1, model_list);
|
||||
fwrite(&path_length, sizeof(uint32), 1, model_list);
|
||||
fwrite(name, sizeof(char), path_length, model_list);
|
||||
}
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
#include "vmapexport.h"
|
||||
#include "model.h"
|
||||
#include "wmo.h"
|
||||
#include "mpq_libmpq04.h"
|
||||
#include "adtfile.h"
|
||||
#include <cassert>
|
||||
#include "mpq_libmpq04.h"
|
||||
#include <G3D/Quat.h>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
Model::Model(std::string& filename) : filename(filename), vertices(nullptr), indices(nullptr)
|
||||
Model::Model(std::string& filename) : filename(filename), header(), vertices(nullptr), indices(nullptr)
|
||||
{
|
||||
memset(&header, 0, sizeof(header));
|
||||
}
|
||||
|
||||
bool Model::open()
|
||||
@@ -64,7 +66,7 @@ bool Model::ConvertToVMAPModel(const char* outfilename)
|
||||
printf("Can't create the output file '%s'\n", outfilename);
|
||||
return false;
|
||||
}
|
||||
fwrite(szRawVMAPMagic, 8, 1, output);
|
||||
fwrite(VMAP::RAW_VMAP_MAGIC, 8, 1, output);
|
||||
uint32 nVertices = header.nBoundingVertices;
|
||||
fwrite(&nVertices, sizeof(int), 1, output);
|
||||
uint32 nofgroups = 1;
|
||||
@@ -118,38 +120,20 @@ bool Model::ConvertToVMAPModel(const char* outfilename)
|
||||
return true;
|
||||
}
|
||||
|
||||
Vec3D fixCoordSystem(Vec3D v)
|
||||
|
||||
Vec3D fixCoordSystem(Vec3D const& v)
|
||||
{
|
||||
return Vec3D(v.x, v.z, -v.y);
|
||||
}
|
||||
|
||||
Vec3D fixCoordSystem2(Vec3D v)
|
||||
void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
|
||||
{
|
||||
return Vec3D(v.x, v.z, v.y);
|
||||
}
|
||||
|
||||
ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
|
||||
{
|
||||
float ff[3];
|
||||
f.read(&id, 4);
|
||||
f.read(ff, 12);
|
||||
pos = fixCoords(Vec3D(ff[0], ff[1], ff[2]));
|
||||
f.read(ff, 12);
|
||||
rot = Vec3D(ff[0], ff[1], ff[2]);
|
||||
f.read(&scale, 2);
|
||||
f.read(&flags, 2);
|
||||
// scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float?
|
||||
sc = scale / 1024.0f;
|
||||
|
||||
char tempname[512];
|
||||
char tempname[1036];
|
||||
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName);
|
||||
FILE* input = fopen(tempname, "r+b");
|
||||
|
||||
if (!input)
|
||||
{
|
||||
//printf("ModelInstance::ModelInstance couldn't open %s\n", tempname);
|
||||
return;
|
||||
}
|
||||
|
||||
fseek(input, 8, SEEK_SET); // get the correct no of vertices
|
||||
int nVertices;
|
||||
@@ -159,37 +143,111 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID
|
||||
if (count != 1 || nVertices == 0)
|
||||
return;
|
||||
|
||||
uint16 adtId = 0;// not used for models
|
||||
uint32 flags = MOD_M2;
|
||||
if (tileX == 65 && tileY == 65)
|
||||
flags |= MOD_WORLDSPAWN;
|
||||
// scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float?
|
||||
float sc = doodadDef.Scale / 1024.0f;
|
||||
|
||||
//write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, name
|
||||
Vec3D position = fixCoords(doodadDef.Position);
|
||||
|
||||
uint16 nameSet = 0;// not used for models
|
||||
uint32 uniqueId = GenerateUniqueObjectId(doodadDef.UniqueId, 0);
|
||||
uint32 tcflags = MOD_M2;
|
||||
if (tileX == 65 && tileY == 65)
|
||||
tcflags |= MOD_WORLDSPAWN;
|
||||
|
||||
//write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name
|
||||
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&id, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&pos, sizeof(float), 3, pDirfile);
|
||||
fwrite(&rot, sizeof(float), 3, pDirfile);
|
||||
fwrite(&tcflags, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&nameSet, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&doodadDef.Rotation, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&sc, sizeof(float), 1, pDirfile);
|
||||
uint32 nlen = strlen(ModelInstName);
|
||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(ModelInstName, sizeof(char), nlen, pDirfile);
|
||||
|
||||
/* int realx1 = (int) ((float) pos.x / 533.333333f);
|
||||
int realy1 = (int) ((float) pos.z / 533.333333f);
|
||||
int realx2 = (int) ((float) pos.x / 533.333333f);
|
||||
int realy2 = (int) ((float) pos.z / 533.333333f);
|
||||
fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n",
|
||||
MapName,
|
||||
ModelInstName,
|
||||
(float) pos.x, (float) pos.y, (float) pos.z,
|
||||
(float) rot.x, (float) rot.y, (float) rot.z,
|
||||
sc,
|
||||
nVertices,
|
||||
realx1, realy1,
|
||||
realx2, realy2
|
||||
); */
|
||||
}
|
||||
|
||||
void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
|
||||
{
|
||||
if (wmo.DoodadSet >= doodadData.Sets.size())
|
||||
return;
|
||||
|
||||
G3D::Vector3 wmoPosition(wmo.Position.z, wmo.Position.x, wmo.Position.y);
|
||||
G3D::Matrix3 wmoRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::toRadians(wmo.Rotation.y), G3D::toRadians(wmo.Rotation.x), G3D::toRadians(wmo.Rotation.z));
|
||||
|
||||
uint16 doodadId = 0;
|
||||
WMO::MODS const& doodadSetData = doodadData.Sets[wmo.DoodadSet];
|
||||
for (uint16 doodadIndex : doodadData.References)
|
||||
{
|
||||
if (doodadIndex < doodadSetData.StartIndex ||
|
||||
doodadIndex >= doodadSetData.StartIndex + doodadSetData.Count)
|
||||
continue;
|
||||
|
||||
WMO::MODD const& doodad = doodadData.Spawns[doodadIndex];
|
||||
|
||||
char ModelInstName[1024];
|
||||
sprintf(ModelInstName, "%s", GetPlainName(&doodadData.Paths[doodad.NameIndex]));
|
||||
uint32 nlen = strlen(ModelInstName);
|
||||
fixnamen(ModelInstName, nlen);
|
||||
fixname2(ModelInstName, nlen);
|
||||
if (nlen > 3)
|
||||
{
|
||||
char const* extension = &ModelInstName[nlen - 4];
|
||||
if (!strcmp(extension, ".mdx") || !strcmp(extension, ".mdl"))
|
||||
{
|
||||
ModelInstName[nlen - 2] = '2';
|
||||
ModelInstName[nlen - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
char tempname[1036];
|
||||
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName);
|
||||
FILE* input = fopen(tempname, "r+b");
|
||||
if (!input)
|
||||
continue;
|
||||
|
||||
fseek(input, 8, SEEK_SET); // get the correct no of vertices
|
||||
int nVertices;
|
||||
int count = fread(&nVertices, sizeof(int), 1, input);
|
||||
fclose(input);
|
||||
|
||||
if (count != 1 || nVertices == 0)
|
||||
continue;
|
||||
|
||||
assert(doodadId < std::numeric_limits<uint16>::max());
|
||||
++doodadId;
|
||||
|
||||
G3D::Vector3 position = wmoPosition + (wmoRotation * G3D::Vector3(doodad.Position.x, doodad.Position.y, doodad.Position.z));
|
||||
|
||||
Vec3D rotation;
|
||||
(G3D::Quat(doodad.Rotation.X, doodad.Rotation.Y, doodad.Rotation.Z, doodad.Rotation.W)
|
||||
.toRotationMatrix() * wmoRotation)
|
||||
.toEulerAnglesXYZ(rotation.z, rotation.x, rotation.y);
|
||||
|
||||
rotation.z = G3D::toDegrees(rotation.z);
|
||||
rotation.x = G3D::toDegrees(rotation.x);
|
||||
rotation.y = G3D::toDegrees(rotation.y);
|
||||
|
||||
uint16 nameSet = 0; // not used for models
|
||||
uint32 uniqueId = GenerateUniqueObjectId(wmo.UniqueId, doodadId);
|
||||
uint32 tcflags = MOD_M2;
|
||||
if (tileX == 65 && tileY == 65)
|
||||
tcflags |= MOD_WORLDSPAWN;
|
||||
|
||||
//write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name
|
||||
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tcflags, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&nameSet, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&rotation, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&doodad.Scale, sizeof(float), 1, pDirfile);
|
||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(ModelInstName, sizeof(char), nlen, pDirfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
#include <vector>
|
||||
|
||||
class MPQFile;
|
||||
struct WMODoodadData;
|
||||
namespace ADT { struct MDDF; struct MODF; }
|
||||
|
||||
Vec3D fixCoordSystem(Vec3D v);
|
||||
Vec3D fixCoordSystem(Vec3D const& v);
|
||||
|
||||
class Model
|
||||
{
|
||||
@@ -39,16 +41,11 @@ public:
|
||||
~Model() { _unload(); }
|
||||
};
|
||||
|
||||
class ModelInstance
|
||||
namespace Doodad
|
||||
{
|
||||
public:
|
||||
uint32 id{0};
|
||||
Vec3D pos, rot;
|
||||
uint16 scale{0}, flags{0};
|
||||
float sc{0.0f};
|
||||
void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
|
||||
|
||||
ModelInstance() {}
|
||||
ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
|
||||
};
|
||||
void ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -126,6 +126,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AaBox3D
|
||||
{
|
||||
public:
|
||||
Vec3D min;
|
||||
Vec3D max;
|
||||
};
|
||||
|
||||
class Vec2D
|
||||
{
|
||||
public:
|
||||
@@ -233,4 +240,9 @@ inline void rotate(float x0, float y0, float* x, float* y, float angle)
|
||||
*y = xa * sinf(angle) + ya * cosf(angle) + y0;
|
||||
}
|
||||
|
||||
struct Quaternion
|
||||
{
|
||||
float X, Y, Z, W;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -51,19 +52,24 @@ typedef struct
|
||||
unsigned int id;
|
||||
} map_id;
|
||||
|
||||
map_id* map_ids;
|
||||
uint16* LiqType = nullptr;
|
||||
std::vector<map_id> map_ids;
|
||||
uint32 map_count;
|
||||
char output_path[128] = ".";
|
||||
char input_path[1024] = ".";
|
||||
bool hasInputPathParam = false;
|
||||
bool preciseVectorData = false;
|
||||
std::unordered_map<std::string, WMODoodadData> WmoDoodads;
|
||||
|
||||
// Constants
|
||||
|
||||
//static const char * szWorkDirMaps = ".\\Maps";
|
||||
const char* szWorkDirWmo = "./Buildings";
|
||||
const char* szRawVMAPMagic = "VMAP044";
|
||||
char const* szWorkDirWmo = "./Buildings";
|
||||
|
||||
std::map<std::pair<uint32, uint16>, uint32> uniqueObjectIds;
|
||||
|
||||
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId)
|
||||
{
|
||||
return uniqueObjectIds.emplace(std::make_pair(clientId, clientDoodadId), uint32(uniqueObjectIds.size() + 1)).first->second;
|
||||
}
|
||||
|
||||
// Local testing functions
|
||||
|
||||
@@ -86,60 +92,16 @@ void strToLower(char* str)
|
||||
}
|
||||
}
|
||||
|
||||
// copied from contrib/extractor/System.cpp
|
||||
void ReadLiquidTypeTableDBC()
|
||||
{
|
||||
printf("Read LiquidType.dbc file...");
|
||||
DBCFile dbc("DBFilesClient\\LiquidType.dbc");
|
||||
if (!dbc.open())
|
||||
{
|
||||
printf("Fatal error: Invalid LiquidType.dbc file format!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t LiqType_count = dbc.getRecordCount();
|
||||
size_t LiqType_maxid = dbc.getRecord(LiqType_count - 1).getUInt(0);
|
||||
LiqType = new uint16[LiqType_maxid + 1];
|
||||
memset(LiqType, 0xff, (LiqType_maxid + 1) * sizeof(uint16));
|
||||
|
||||
for (uint32 x = 0; x < LiqType_count; ++x)
|
||||
LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
|
||||
|
||||
printf("Done! (%u LiqTypes loaded)\n", (unsigned int)LiqType_count);
|
||||
}
|
||||
|
||||
bool ExtractWmo()
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
//const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};
|
||||
|
||||
for (ArchiveSet::const_iterator ar_itr = gOpenArchives.begin(); ar_itr != gOpenArchives.end() && success; ++ar_itr)
|
||||
{
|
||||
vector<string> filelist;
|
||||
|
||||
(*ar_itr)->GetFileListTo(filelist);
|
||||
for (vector<string>::iterator fname = filelist.begin(); fname != filelist.end() && success; ++fname)
|
||||
{
|
||||
if (fname->find(".wmo") != string::npos)
|
||||
success = ExtractSingleWmo(*fname);
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
printf("\nExtract wmo complete (No (fatal) errors)\n");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ExtractSingleWmo(std::string& fname)
|
||||
{
|
||||
// Copy files from archive
|
||||
std::string originalName = fname;
|
||||
|
||||
char szLocalFile[1024];
|
||||
const char* plain_name = GetPlainName(fname.c_str());
|
||||
char* plain_name = GetPlainName(&fname[0]);
|
||||
fixnamen(plain_name, strlen(plain_name));
|
||||
fixname2(plain_name, strlen(plain_name));
|
||||
sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name);
|
||||
fixnamen(szLocalFile, strlen(szLocalFile));
|
||||
|
||||
if (FileExists(szLocalFile))
|
||||
return true;
|
||||
@@ -162,12 +124,12 @@ bool ExtractSingleWmo(std::string& fname)
|
||||
return true;
|
||||
|
||||
bool file_ok = true;
|
||||
std::cout << "Extracting " << fname << std::endl;
|
||||
WMORoot froot(fname);
|
||||
printf("Extracting %s\n", originalName.c_str());
|
||||
WMORoot froot(originalName);
|
||||
if (!froot.open())
|
||||
{
|
||||
printf("Couldn't open RootWmo!!!\n");
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
FILE* output = fopen(szLocalFile, "wb");
|
||||
if (!output)
|
||||
@@ -176,6 +138,8 @@ bool ExtractSingleWmo(std::string& fname)
|
||||
return false;
|
||||
}
|
||||
froot.ConvertToVMAPRootWmo(output);
|
||||
WMODoodadData& doodads = WmoDoodads[plain_name];
|
||||
std::swap(doodads, froot.DoodadData);
|
||||
int Wmo_nVertices = 0;
|
||||
//printf("root has %d groups\n", froot->nGroups);
|
||||
if (froot.nGroups != 0)
|
||||
@@ -204,6 +168,17 @@ bool ExtractSingleWmo(std::string& fname)
|
||||
}
|
||||
|
||||
Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData);
|
||||
for (uint16 groupReference : fgroup.DoodadReferences)
|
||||
{
|
||||
if (groupReference >= doodads.Spawns.size())
|
||||
continue;
|
||||
|
||||
uint32 doodadNameIndex = doodads.Spawns[groupReference].NameIndex;
|
||||
if (froot.ValidDoodadNames.find(doodadNameIndex) == froot.ValidDoodadNames.end())
|
||||
continue;
|
||||
|
||||
doodads.References.insert(groupReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,13 +196,11 @@ void ParsMapFiles()
|
||||
{
|
||||
char fn[512];
|
||||
//char id_filename[64];
|
||||
char id[10];
|
||||
for (unsigned int i = 0; i < map_count; ++i)
|
||||
{
|
||||
sprintf(id, "%03u", map_ids[i].id);
|
||||
snprintf(fn, sizeof(fn), R"(World\Maps\%s\%s.wdt)", map_ids[i].name, map_ids[i].name);
|
||||
WDTFile WDT(fn, map_ids[i].name);
|
||||
if (WDT.init(id, map_ids[i].id))
|
||||
sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
|
||||
WDTFile WDT(fn,map_ids[i].name);
|
||||
if (WDT.init(map_ids[i].id))
|
||||
{
|
||||
printf("Processing Map %u\n[", map_ids[i].id);
|
||||
for (int x = 0; x < 64; ++x)
|
||||
@@ -490,11 +463,6 @@ int main(int argc, char** argv)
|
||||
printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n", input_path);
|
||||
return 1;
|
||||
}
|
||||
ReadLiquidTypeTableDBC();
|
||||
|
||||
// extract data
|
||||
if (success)
|
||||
success = ExtractWmo();
|
||||
|
||||
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
//map.dbc
|
||||
@@ -507,18 +475,28 @@ int main(int argc, char** argv)
|
||||
printf("FATAL ERROR: Map.dbc not found in data file.\n");
|
||||
return 1;
|
||||
}
|
||||
map_count = dbc->getRecordCount ();
|
||||
map_ids = new map_id[map_count];
|
||||
map_count = dbc->getRecordCount();
|
||||
map_ids.resize(map_count);
|
||||
for (unsigned int x = 0; x < map_count; ++x)
|
||||
{
|
||||
map_ids[x].id = dbc->getRecord (x).getUInt(0);
|
||||
strcpy(map_ids[x].name, dbc->getRecord(x).getString(1));
|
||||
map_ids[x].id = dbc->getRecord(x).getUInt(0);
|
||||
|
||||
char const* map_name = dbc->getRecord(x).getString(1);
|
||||
size_t max_map_name_length = sizeof(map_ids[x].name);
|
||||
if (strlen(map_name) >= max_map_name_length)
|
||||
{
|
||||
delete dbc;
|
||||
printf("FATAL ERROR: Map name too long.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpy(map_ids[x].name, map_name, max_map_name_length);
|
||||
map_ids[x].name[max_map_name_length - 1] = '\0';
|
||||
printf("Map - %s\n", map_ids[x].name);
|
||||
}
|
||||
|
||||
delete dbc;
|
||||
ParsMapFiles();
|
||||
delete [] map_ids;
|
||||
//nError = ERROR_SUCCESS;
|
||||
// Extract models, listed in DameObjectDisplayInfo.dbc
|
||||
ExtractGameobjectModels();
|
||||
@@ -532,6 +510,5 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
printf("Extract %s. Work complete. No errors.\n", versionString);
|
||||
delete [] LiqType;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,15 @@
|
||||
#ifndef VMAPEXPORT_H
|
||||
#define VMAPEXPORT_H
|
||||
|
||||
#include "loadlib/loadlib.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
const char VMAP_MAGIC[] = "VMAP_4.5";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP045"; // used in extracted vmap files with raw data
|
||||
}
|
||||
|
||||
enum ModelFlags
|
||||
{
|
||||
@@ -16,8 +24,12 @@ enum ModelFlags
|
||||
MOD_HAS_BOUND = 1 << 2
|
||||
};
|
||||
|
||||
extern const char* szWorkDirWmo;
|
||||
extern const char* szRawVMAPMagic; // vmap magic string for extracted raw vmap data
|
||||
struct WMODoodadData;
|
||||
|
||||
extern const char * szWorkDirWmo;
|
||||
extern std::unordered_map<std::string, WMODoodadData> WmoDoodads;
|
||||
|
||||
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId);
|
||||
|
||||
bool FileExists(const char* file);
|
||||
void strToLower(char* str);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "vmapexport.h"
|
||||
#include "wdtfile.h"
|
||||
#include "adtfile.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
char* wdtGetPlainName(char* FileName)
|
||||
@@ -18,14 +19,14 @@ char* wdtGetPlainName(char* FileName)
|
||||
return FileName;
|
||||
}
|
||||
|
||||
WDTFile::WDTFile(char* file_name, char* file_name1) : WDT(file_name), gWmoInstansName(nullptr), gnWMO(0)
|
||||
WDTFile::WDTFile(char* file_name, char* file_name1) : _file(file_name)
|
||||
{
|
||||
filename.append(file_name1, strlen(file_name1));
|
||||
}
|
||||
|
||||
bool WDTFile::init(char* /*map_id*/, unsigned int mapID)
|
||||
bool WDTFile::init(uint32 mapId)
|
||||
{
|
||||
if (WDT.isEof())
|
||||
if (_file.isEof())
|
||||
{
|
||||
//printf("Can't find WDT file.\n");
|
||||
return false;
|
||||
@@ -43,15 +44,15 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID)
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!WDT.isEof())
|
||||
while (!_file.isEof())
|
||||
{
|
||||
WDT.read(fourcc, 4);
|
||||
WDT.read(&size, 4);
|
||||
_file.read(fourcc, 4);
|
||||
_file.read(&size, 4);
|
||||
|
||||
flipcc(fourcc);
|
||||
fourcc[4] = 0;
|
||||
|
||||
size_t nextpos = WDT.getPos() + size;
|
||||
size_t nextpos = _file.getPos() + size;
|
||||
|
||||
if (!strcmp(fourcc, "MAIN"))
|
||||
{
|
||||
@@ -62,16 +63,19 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID)
|
||||
if (size)
|
||||
{
|
||||
char* buf = new char[size];
|
||||
WDT.read(buf, size);
|
||||
_file.read(buf, size);
|
||||
char* p = buf;
|
||||
int q = 0;
|
||||
gWmoInstansName = new string[size];
|
||||
while (p < buf + size)
|
||||
{
|
||||
std::string path(p);
|
||||
|
||||
char* s = wdtGetPlainName(p);
|
||||
fixnamen(s, strlen(s));
|
||||
fixname2(s, strlen(s));
|
||||
p = p + strlen(p) + 1;
|
||||
gWmoInstansName[q++] = s;
|
||||
_wmoNames.push_back(s);
|
||||
|
||||
ExtractSingleWmo(path);
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
@@ -81,29 +85,27 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID)
|
||||
// global wmo instance data
|
||||
if (size)
|
||||
{
|
||||
gnWMO = (int)size / 64;
|
||||
|
||||
for (int i = 0; i < gnWMO; ++i)
|
||||
uint32 mapObjectCount = size / sizeof(ADT::MODF);
|
||||
for (uint32 i = 0; i < mapObjectCount; ++i)
|
||||
{
|
||||
int id;
|
||||
WDT.read(&id, 4);
|
||||
WMOInstance inst(WDT, gWmoInstansName[id].c_str(), mapID, 65, 65, dirfile);
|
||||
ADT::MODF mapObjDef;
|
||||
_file.read(&mapObjDef, sizeof(ADT::MODF));
|
||||
MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), mapId, 65, 65, dirfile);
|
||||
Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, mapId, 65, 65, dirfile);
|
||||
}
|
||||
|
||||
delete[] gWmoInstansName;
|
||||
}
|
||||
}
|
||||
WDT.seek((int)nextpos);
|
||||
_file.seek((int)nextpos);
|
||||
}
|
||||
|
||||
WDT.close();
|
||||
_file.close();
|
||||
fclose(dirfile);
|
||||
return true;
|
||||
}
|
||||
|
||||
WDTFile::~WDTFile()
|
||||
{
|
||||
WDT.close();
|
||||
_file.close();
|
||||
}
|
||||
|
||||
ADTFile* WDTFile::GetMap(int x, int z)
|
||||
|
||||
@@ -16,18 +16,18 @@ class ADTFile;
|
||||
|
||||
class WDTFile
|
||||
{
|
||||
private:
|
||||
MPQFile WDT;
|
||||
string filename;
|
||||
public:
|
||||
WDTFile(char* file_name, char* file_name1);
|
||||
~WDTFile();
|
||||
bool init(char* map_id, unsigned int mapID);
|
||||
|
||||
string* gWmoInstansName;
|
||||
int gnWMO;
|
||||
~WDTFile(void);
|
||||
|
||||
bool init(uint32 mapId);
|
||||
ADTFile* GetMap(int x, int z);
|
||||
|
||||
std::vector<std::string> _wmoNames;
|
||||
|
||||
private:
|
||||
MPQFile _file;
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*/
|
||||
|
||||
#include "adtfile.h"
|
||||
#include "wmo.h"
|
||||
#include "vec3d.h"
|
||||
#include "vmapexport.h"
|
||||
@@ -17,12 +18,9 @@
|
||||
#undef max
|
||||
#include "mpq_libmpq04.h"
|
||||
|
||||
using namespace std;
|
||||
extern uint16* LiqType;
|
||||
|
||||
WMORoot::WMORoot(std::string& filename)
|
||||
: filename(filename), col(0), nTextures(0), nGroups(0), nP(0), nLights(0),
|
||||
nModels(0), nDoodads(0), nDoodadSets(0), RootWMOID(0), liquidType(0)
|
||||
WMORoot::WMORoot(std::string const& filename)
|
||||
: filename(filename), color(0), nTextures(0), nGroups(0), nPortals(0), nLights(0),
|
||||
nDoodadNames(0), nDoodadDefs(0), nDoodadSets(0), RootWMOID(0), liquidType(0)
|
||||
{
|
||||
memset(bbcorn1, 0, sizeof(bbcorn1));
|
||||
memset(bbcorn2, 0, sizeof(bbcorn2));
|
||||
@@ -54,17 +52,47 @@ bool WMORoot::open()
|
||||
{
|
||||
f.read(&nTextures, 4);
|
||||
f.read(&nGroups, 4);
|
||||
f.read(&nP, 4);
|
||||
f.read(&nPortals, 4);
|
||||
f.read(&nLights, 4);
|
||||
f.read(&nModels, 4);
|
||||
f.read(&nDoodads, 4);
|
||||
f.read(&nDoodadNames, 4);
|
||||
f.read(&nDoodadDefs, 4);
|
||||
f.read(&nDoodadSets, 4);
|
||||
f.read(&col, 4);
|
||||
f.read(&color, 4);
|
||||
f.read(&RootWMOID, 4);
|
||||
f.read(bbcorn1, 12);
|
||||
f.read(bbcorn2, 12);
|
||||
f.read(&liquidType, 4);
|
||||
break;
|
||||
}
|
||||
else if (!strcmp(fourcc, "MODS"))
|
||||
{
|
||||
DoodadData.Sets.resize(size / sizeof(WMO::MODS));
|
||||
f.read(DoodadData.Sets.data(), size);
|
||||
}
|
||||
else if (!strcmp(fourcc,"MODN"))
|
||||
{
|
||||
char* ptr = f.getPointer();
|
||||
char* end = ptr + size;
|
||||
DoodadData.Paths = std::make_unique<char[]>(size);
|
||||
memcpy(DoodadData.Paths.get(), ptr, size);
|
||||
while (ptr < end)
|
||||
{
|
||||
std::string path = ptr;
|
||||
|
||||
char* s = GetPlainName(ptr);
|
||||
fixnamen(s, strlen(s));
|
||||
fixname2(s, strlen(s));
|
||||
|
||||
uint32 doodadNameIndex = ptr - f.getPointer();
|
||||
ptr += path.length() + 1;
|
||||
|
||||
if (ExtractSingleModel(path))
|
||||
ValidDoodadNames.insert(doodadNameIndex);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(fourcc,"MODD"))
|
||||
{
|
||||
DoodadData.Spawns.resize(size / sizeof(WMO::MODD));
|
||||
f.read(DoodadData.Spawns.data(), size);
|
||||
}
|
||||
/*
|
||||
else if (!strcmp(fourcc,"MOTX"))
|
||||
@@ -82,15 +110,6 @@ bool WMORoot::open()
|
||||
else if (!strcmp(fourcc,"MOLT"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp(fourcc,"MODN"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp(fourcc,"MODS"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp(fourcc,"MODD"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp(fourcc,"MOSB"))
|
||||
{
|
||||
}
|
||||
@@ -117,7 +136,7 @@ bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile)
|
||||
{
|
||||
//printf("Convert RootWmo...\n");
|
||||
|
||||
fwrite(szRawVMAPMagic, 1, 8, pOutfile);
|
||||
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, pOutfile);
|
||||
unsigned int nVectors = 0;
|
||||
fwrite(&nVectors, sizeof(nVectors), 1, pOutfile); // will be filled later
|
||||
fwrite(&nGroups, 4, 1, pOutfile);
|
||||
@@ -125,7 +144,7 @@ bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile)
|
||||
return true;
|
||||
}
|
||||
|
||||
WMOGroup::WMOGroup(std::string filename) :
|
||||
WMOGroup::WMOGroup(std::string const& filename) :
|
||||
filename(std::move(filename)), MOPY(nullptr), MOVI(nullptr), MoviEx(nullptr), MOVT(nullptr), MOBA(nullptr), MobaEx(nullptr),
|
||||
hlq(nullptr), LiquEx(nullptr), LiquBytes(nullptr), groupName(0), descGroupName(0), mogpFlags(0),
|
||||
moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
|
||||
@@ -206,11 +225,16 @@ bool WMOGroup::open()
|
||||
moba_size = size / 2;
|
||||
f.read(MOBA, size);
|
||||
}
|
||||
else if (!strcmp(fourcc, "MLIQ"))
|
||||
else if (!strcmp(fourcc,"MODR"))
|
||||
{
|
||||
DoodadReferences.resize(size / sizeof(uint16));
|
||||
f.read(DoodadReferences.data(), size);
|
||||
}
|
||||
else if (!strcmp(fourcc,"MLIQ"))
|
||||
{
|
||||
liquflags |= 1;
|
||||
hlq = new WMOLiquidHeader();
|
||||
f.read(hlq, 0x1E);
|
||||
f.read(hlq, sizeof(WMOLiquidHeader));
|
||||
LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts;
|
||||
LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts];
|
||||
f.read(LiquEx, LiquEx_size);
|
||||
@@ -391,7 +415,7 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool precise
|
||||
//------LIQU------------------------
|
||||
if (LiquEx_size != 0)
|
||||
{
|
||||
int LIQU_h[] = {0x5551494C, static_cast<int>(sizeof(WMOLiquidHeader) + LiquEx_size) + hlq->xtiles* hlq->ytiles}; // "LIQU"
|
||||
int LIQU_h[] = { 0x5551494C, static_cast<int>(sizeof(WMOLiquidHeader) + LiquEx_size) + hlq->xtiles * hlq->ytiles }; // "LIQU"
|
||||
fwrite(LIQU_h, 4, 2, output);
|
||||
|
||||
// according to WoW.Dev Wiki:
|
||||
@@ -472,28 +496,16 @@ WMOGroup::~WMOGroup()
|
||||
delete [] LiquBytes;
|
||||
}
|
||||
|
||||
WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
|
||||
: currx(0), curry(0), wmo(nullptr), doodadset(0), pos(), indx(0), id(0), d2(0), d3(0)
|
||||
void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
|
||||
{
|
||||
float ff[3];
|
||||
f.read(&id, 4);
|
||||
f.read(ff, 12);
|
||||
pos = Vec3D(ff[0], ff[1], ff[2]);
|
||||
f.read(ff, 12);
|
||||
rot = Vec3D(ff[0], ff[1], ff[2]);
|
||||
f.read(ff, 12);
|
||||
pos2 = Vec3D(ff[0], ff[1], ff[2]);
|
||||
f.read(ff, 12);
|
||||
pos3 = Vec3D(ff[0], ff[1], ff[2]);
|
||||
f.read(&d2, 4);
|
||||
|
||||
uint16 trash, adtId;
|
||||
f.read(&adtId, 2);
|
||||
f.read(&trash, 2);
|
||||
// destructible wmo, do not dump. we can handle the vmap for these
|
||||
// in dynamic tree (gameobject vmaps)
|
||||
if ((mapObjDef.Flags & 0x1) != 0)
|
||||
return;
|
||||
|
||||
//-----------add_in _dir_file----------------
|
||||
|
||||
char tempname[512];
|
||||
char tempname[1036];
|
||||
sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName);
|
||||
FILE* input;
|
||||
input = fopen(tempname, "r+b");
|
||||
@@ -512,46 +524,39 @@ WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint
|
||||
if (count != 1 || nVertices == 0)
|
||||
return;
|
||||
|
||||
Vec3D position = mapObjDef.Position;
|
||||
|
||||
float x, z;
|
||||
x = pos.x;
|
||||
z = pos.z;
|
||||
x = position.x;
|
||||
z = position.z;
|
||||
if (x == 0 && z == 0)
|
||||
{
|
||||
pos.x = 533.33333f * 32;
|
||||
pos.z = 533.33333f * 32;
|
||||
position.x = 533.33333f * 32;
|
||||
position.z = 533.33333f * 32;
|
||||
}
|
||||
pos = fixCoords(pos);
|
||||
pos2 = fixCoords(pos2);
|
||||
pos3 = fixCoords(pos3);
|
||||
position = fixCoords(position);
|
||||
AaBox3D bounds;
|
||||
bounds.min = fixCoords(mapObjDef.Bounds.min);
|
||||
bounds.max = fixCoords(mapObjDef.Bounds.max);
|
||||
|
||||
float scale = 1.0f;
|
||||
uint32 uniqueId = GenerateUniqueObjectId(mapObjDef.UniqueId, 0);
|
||||
uint32 flags = MOD_HAS_BOUND;
|
||||
if (tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN;
|
||||
//write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||
//write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&id, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&pos, sizeof(float), 3, pDirfile);
|
||||
fwrite(&rot, sizeof(float), 3, pDirfile);
|
||||
fwrite(&mapObjDef.NameSet, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&mapObjDef.Rotation, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&scale, sizeof(float), 1, pDirfile);
|
||||
fwrite(&pos2, sizeof(float), 3, pDirfile);
|
||||
fwrite(&pos3, sizeof(float), 3, pDirfile);
|
||||
fwrite(&bounds, sizeof(AaBox3D), 1, pDirfile);
|
||||
uint32 nlen = strlen(WmoInstName);
|
||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
|
||||
|
||||
/* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n",
|
||||
MapName,
|
||||
WmoInstName,
|
||||
(float) x, (float) pos.y, (float) z,
|
||||
(float) rot.x, (float) rot.y, (float) rot.z,
|
||||
nVertices,
|
||||
realx1, realy1,
|
||||
realx2, realy2
|
||||
); */
|
||||
|
||||
// fclose(dirfile);
|
||||
}
|
||||
|
||||
@@ -6,14 +6,18 @@
|
||||
|
||||
#ifndef WMO_H
|
||||
#define WMO_H
|
||||
#define TILESIZE (533.33333f)
|
||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "vec3d.h"
|
||||
#include "loadlib/loadlib.h"
|
||||
|
||||
#define TILESIZE (533.33333f)
|
||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
||||
|
||||
// MOPY flags
|
||||
enum MopyFlags
|
||||
{
|
||||
@@ -30,26 +34,60 @@ enum MopyFlags
|
||||
class WMOInstance;
|
||||
class WMOManager;
|
||||
class MPQFile;
|
||||
namespace ADT { struct MODF; }
|
||||
|
||||
namespace WMO
|
||||
{
|
||||
struct MODS
|
||||
{
|
||||
char Name[20];
|
||||
uint32 StartIndex; // index of first doodad instance in this set
|
||||
uint32 Count; // number of doodad instances in this set
|
||||
char _pad[4];
|
||||
};
|
||||
|
||||
struct MODD
|
||||
{
|
||||
uint32 NameIndex : 24;
|
||||
Vec3D Position;
|
||||
Quaternion Rotation;
|
||||
float Scale;
|
||||
uint32 Color;
|
||||
};
|
||||
}
|
||||
|
||||
/* for whatever reason a certain company just can't stick to one coordinate system... */
|
||||
static inline Vec3D fixCoords(const Vec3D& v) { return Vec3D(v.z, v.x, v.y); }
|
||||
|
||||
struct WMODoodadData
|
||||
{
|
||||
std::vector<WMO::MODS> Sets;
|
||||
std::unique_ptr<char[]> Paths;
|
||||
std::vector<WMO::MODD> Spawns;
|
||||
std::unordered_set<uint16> References;
|
||||
};
|
||||
|
||||
class WMORoot
|
||||
{
|
||||
private:
|
||||
std::string filename;
|
||||
public:
|
||||
unsigned int col;
|
||||
uint32 nTextures, nGroups, nP, nLights, nModels, nDoodads, nDoodadSets, RootWMOID, liquidType;
|
||||
unsigned int color;
|
||||
uint32 nTextures, nGroups, nPortals, nLights, nDoodadNames, nDoodadDefs, nDoodadSets, RootWMOID, liquidType;
|
||||
float bbcorn1[3];
|
||||
float bbcorn2[3];
|
||||
|
||||
WMORoot(std::string& filename);
|
||||
WMODoodadData DoodadData;
|
||||
std::unordered_set<uint32> ValidDoodadNames;
|
||||
|
||||
WMORoot(std::string const& filename);
|
||||
|
||||
bool open();
|
||||
bool ConvertToVMAPRootWmo(FILE* output);
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct WMOLiquidHeader
|
||||
{
|
||||
int xverts, yverts, xtiles, ytiles;
|
||||
@@ -66,6 +104,8 @@ struct WMOLiquidVert
|
||||
float height;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
class WMOGroup
|
||||
{
|
||||
private:
|
||||
@@ -98,29 +138,18 @@ public:
|
||||
int nTriangles; // number when loaded
|
||||
uint32 liquflags;
|
||||
|
||||
WMOGroup(std::string filename);
|
||||
std::vector<uint16> DoodadReferences;
|
||||
|
||||
WMOGroup(std::string const& filename);
|
||||
~WMOGroup();
|
||||
|
||||
bool open();
|
||||
int ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData);
|
||||
};
|
||||
|
||||
class WMOInstance
|
||||
namespace MapObject
|
||||
{
|
||||
static std::set<int> ids;
|
||||
public:
|
||||
std::string MapName;
|
||||
int currx;
|
||||
int curry;
|
||||
WMOGroup* wmo;
|
||||
int doodadset;
|
||||
Vec3D pos;
|
||||
Vec3D pos2, pos3, rot;
|
||||
uint32 indx, id, d2, d3;
|
||||
|
||||
WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
|
||||
|
||||
static void reset();
|
||||
};
|
||||
void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user