Tools: merged Master tools updates
This commit is contained in:
1 parent
9ade5b77ff
commit
fbcb423f60
27 files changed
+723
-571
No files matched your search
@@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
#include "ostream.h"
|
#include "ostream.h"
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|
||||||
namespace fmt {
|
namespace fmt {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "DetourNavMesh.h"
|
#include "DetourNavMesh.h"
|
||||||
|
|
||||||
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
|
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
|
||||||
#define MMAP_VERSION 7
|
#define MMAP_VERSION 8
|
||||||
|
|
||||||
struct MmapTileHeader
|
struct MmapTileHeader
|
||||||
{
|
{
|
||||||
@@ -29,18 +29,22 @@ static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
|
|||||||
sizeof(MmapTileHeader::usesLiquids) +
|
sizeof(MmapTileHeader::usesLiquids) +
|
||||||
sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
|
sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
|
||||||
|
|
||||||
enum NavTerrain
|
enum NavArea
|
||||||
{
|
{
|
||||||
NAV_EMPTY = 0x00,
|
NAV_AREA_EMPTY = 0,
|
||||||
NAV_GROUND = 0x01,
|
// areas 1-60 will be used for destructible areas (currently skipped in vmaps, WMO with flag 1)
|
||||||
NAV_MAGMA = 0x02,
|
// ground is the highest value to make recast choose ground over water when merging surfaces very close to each other (shallow water would be walkable)
|
||||||
NAV_SLIME = 0x04,
|
NAV_AREA_GROUND = 63,
|
||||||
NAV_WATER = 0x08,
|
NAV_AREA_WATER = 62,
|
||||||
NAV_UNUSED1 = 0x10,
|
NAV_AREA_MAGMA_SLIME = 61 // don't need to differentiate between them
|
||||||
NAV_UNUSED2 = 0x20,
|
};
|
||||||
NAV_UNUSED3 = 0x40,
|
|
||||||
NAV_UNUSED4 = 0x80
|
enum NavTerrainFlag
|
||||||
// we only have 8 bits
|
{
|
||||||
|
NAV_EMPTY = 0x00,
|
||||||
|
NAV_GROUND = 1 << (63 - NAV_AREA_GROUND),
|
||||||
|
NAV_WATER = 1 << (63 - NAV_AREA_WATER),
|
||||||
|
NAV_MAGMA_SLIME = 1 << (63 - NAV_AREA_MAGMA_SLIME)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _MAPDEFINES_H */
|
#endif /* _MAPDEFINES_H */
|
||||||
@@ -54,7 +54,7 @@ namespace VMAP
|
|||||||
//=================================================================
|
//=================================================================
|
||||||
|
|
||||||
TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
|
TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
|
||||||
: iDestDir(pDestDirName), iSrcDir(pSrcDirName), iFilterMethod(nullptr), iCurrentUniqueNameId(0)
|
: iDestDir(pDestDirName), iSrcDir(pSrcDirName)
|
||||||
{
|
{
|
||||||
boost::filesystem::create_directory(iDestDir);
|
boost::filesystem::create_directory(iDestDir);
|
||||||
//init();
|
//init();
|
||||||
@@ -225,7 +225,7 @@ namespace VMAP
|
|||||||
ModelSpawn spawn;
|
ModelSpawn spawn;
|
||||||
while (!feof(dirf))
|
while (!feof(dirf))
|
||||||
{
|
{
|
||||||
// read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
// read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||||
check = fread(&mapID, sizeof(uint32), 1, dirf);
|
check = fread(&mapID, sizeof(uint32), 1, dirf);
|
||||||
if (check == 0) // EoF...
|
if (check == 0) // EoF...
|
||||||
break;
|
break;
|
||||||
@@ -241,8 +241,10 @@ namespace VMAP
|
|||||||
printf("spawning Map %u\n", mapID);
|
printf("spawning Map %u\n", mapID);
|
||||||
mapData[mapID] = current = new MapSpawns();
|
mapData[mapID] = current = new MapSpawns();
|
||||||
}
|
}
|
||||||
else current = map_iter->second;
|
else
|
||||||
current->UniqueEntries.insert(pair<uint32, ModelSpawn>(spawn.ID, spawn));
|
current = map_iter->second;
|
||||||
|
|
||||||
|
current->UniqueEntries.emplace(spawn.ID, spawn);
|
||||||
current->TileEntries.insert(pair<uint32, TileSpawn>(StaticMapTree::packTileID(tileX, tileY), TileSpawn{ spawn.ID, spawn.flags }));
|
current->TileEntries.insert(pair<uint32, TileSpawn>(StaticMapTree::packTileID(tileX, tileY), TileSpawn{ spawn.ID, spawn.flags }));
|
||||||
}
|
}
|
||||||
bool success = (ferror(dirf) == 0);
|
bool success = (ferror(dirf) == 0);
|
||||||
@@ -298,14 +300,16 @@ namespace VMAP
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
struct WMOLiquidHeader
|
struct WMOLiquidHeader
|
||||||
{
|
{
|
||||||
int xverts, yverts, xtiles, ytiles;
|
int xverts, yverts, xtiles, ytiles;
|
||||||
float pos_x;
|
float pos_x;
|
||||||
float pos_y;
|
float pos_y;
|
||||||
float pos_z;
|
float pos_z;
|
||||||
short type;
|
short material;
|
||||||
};
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
//=================================================================
|
//=================================================================
|
||||||
bool TileAssembler::convertRawFile(const std::string& pModelFilename)
|
bool TileAssembler::convertRawFile(const std::string& pModelFilename)
|
||||||
{
|
{
|
||||||
@@ -349,6 +353,13 @@ namespace VMAP
|
|||||||
if (!model_list)
|
if (!model_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
char ident[8];
|
||||||
|
if (fread(ident, 1, 8, model_list) != 8 || memcmp(ident, VMAP::RAW_VMAP_MAGIC, 8) != 0)
|
||||||
|
{
|
||||||
|
fclose(model_list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb");
|
FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb");
|
||||||
if (!model_list_copy)
|
if (!model_list_copy)
|
||||||
{
|
{
|
||||||
@@ -356,7 +367,10 @@ namespace VMAP
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fwrite(VMAP::VMAP_MAGIC, 1, 8, model_list_copy);
|
||||||
|
|
||||||
uint32 name_length, displayId;
|
uint32 name_length, displayId;
|
||||||
|
uint8 isWmo;
|
||||||
char buff[500];
|
char buff[500];
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -364,7 +378,8 @@ namespace VMAP
|
|||||||
if (feof(model_list)) // EOF flag is only set after failed reading attempt
|
if (feof(model_list)) // EOF flag is only set after failed reading attempt
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (fread(&name_length, sizeof(uint32), 1, model_list) != 1
|
if (fread(&isWmo, sizeof(uint8), 1, model_list) != 1
|
||||||
|
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1
|
||||||
|| name_length >= sizeof(buff)
|
|| name_length >= sizeof(buff)
|
||||||
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
|
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
|
||||||
{
|
{
|
||||||
@@ -409,6 +424,7 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
|
|
||||||
fwrite(&displayId, sizeof(uint32), 1, model_list_copy);
|
fwrite(&displayId, sizeof(uint32), 1, model_list_copy);
|
||||||
|
fwrite(&isWmo, sizeof(uint8), 1, model_list_copy);
|
||||||
fwrite(&name_length, sizeof(uint32), 1, model_list_copy);
|
fwrite(&name_length, sizeof(uint32), 1, model_list_copy);
|
||||||
fwrite(&buff, sizeof(char), name_length, model_list_copy);
|
fwrite(&buff, sizeof(char), name_length, model_list_copy);
|
||||||
fwrite(&bounds.low(), sizeof(Vector3), 1, model_list_copy);
|
fwrite(&bounds.low(), sizeof(Vector3), 1, model_list_copy);
|
||||||
@@ -493,25 +509,34 @@ namespace VMAP
|
|||||||
delete[] vectorarray;
|
delete[] vectorarray;
|
||||||
}
|
}
|
||||||
// ----- liquid
|
// ----- liquid
|
||||||
liquid = 0;
|
liquid = nullptr;
|
||||||
if (liquidflags& 1)
|
if (liquidflags & 3)
|
||||||
{
|
{
|
||||||
WMOLiquidHeader hlq;
|
|
||||||
READ_OR_RETURN(&blockId, 4);
|
READ_OR_RETURN(&blockId, 4);
|
||||||
CMP_OR_RETURN(blockId, "LIQU");
|
CMP_OR_RETURN(blockId, "LIQU");
|
||||||
READ_OR_RETURN(&blocksize, sizeof(int));
|
READ_OR_RETURN(&blocksize, sizeof(int));
|
||||||
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
|
uint32 liquidType;
|
||||||
liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type);
|
READ_OR_RETURN(&liquidType, sizeof(uint32));
|
||||||
uint32 size = hlq.xverts*hlq.yverts;
|
if (liquidflags & 1)
|
||||||
READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float));
|
{
|
||||||
size = hlq.xtiles*hlq.ytiles;
|
WMOLiquidHeader hlq;
|
||||||
READ_OR_RETURN(liquid->GetFlagsStorage(), size);
|
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
|
||||||
|
liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), liquidType);
|
||||||
|
uint32 size = hlq.xverts * hlq.yverts;
|
||||||
|
READ_OR_RETURN(liquid->GetHeightStorage(), size * sizeof(float));
|
||||||
|
size = hlq.xtiles * hlq.ytiles;
|
||||||
|
READ_OR_RETURN(liquid->GetFlagsStorage(), size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
liquid = new WmoLiquid(0, 0, Vector3::zero(), liquidType);
|
||||||
|
liquid->GetHeightStorage()[0] = bounds.high().z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GroupModel_Raw::~GroupModel_Raw()
|
GroupModel_Raw::~GroupModel_Raw()
|
||||||
{
|
{
|
||||||
delete liquid;
|
delete liquid;
|
||||||
|
|||||||
@@ -101,9 +101,7 @@ namespace VMAP
|
|||||||
private:
|
private:
|
||||||
std::string iDestDir;
|
std::string iDestDir;
|
||||||
std::string iSrcDir;
|
std::string iSrcDir;
|
||||||
bool (*iFilterMethod)(char *pName);
|
|
||||||
G3D::Table<std::string, unsigned int > iUniqueNameIds;
|
G3D::Table<std::string, unsigned int > iUniqueNameIds;
|
||||||
unsigned int iCurrentUniqueNameId;
|
|
||||||
MapData mapData;
|
MapData mapData;
|
||||||
std::set<std::string> spawnedModelFiles;
|
std::set<std::string> spawnedModelFiles;
|
||||||
|
|
||||||
@@ -117,8 +115,6 @@ namespace VMAP
|
|||||||
void exportGameobjectModels();
|
void exportGameobjectModels();
|
||||||
|
|
||||||
bool convertRawFile(const std::string& pModelFilename);
|
bool convertRawFile(const std::string& pModelFilename);
|
||||||
void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; }
|
|
||||||
std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // VMAP
|
} // VMAP
|
||||||
|
|||||||
@@ -30,11 +30,12 @@ using G3D::AABox;
|
|||||||
|
|
||||||
struct GameobjectModelData
|
struct GameobjectModelData
|
||||||
{
|
{
|
||||||
GameobjectModelData(const std::string& name_, const AABox& box) :
|
GameobjectModelData(char const* name_, uint32 nameLength, Vector3 const& lowBound, Vector3 const& highBound, bool isWmo_) :
|
||||||
bound(box), name(name_) { }
|
bound(lowBound, highBound), name(name_, nameLength), isWmo(isWmo_) { }
|
||||||
|
|
||||||
AABox bound;
|
AABox bound;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
bool isWmo;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<uint32, GameobjectModelData> ModelList;
|
typedef std::unordered_map<uint32, GameobjectModelData> ModelList;
|
||||||
@@ -53,7 +54,17 @@ void LoadGameObjectModelList(std::string const& dataPath)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char magic[8];
|
||||||
|
if (fread(magic, 1, 8, model_list_file) != 8
|
||||||
|
|| memcmp(magic, VMAP::VMAP_MAGIC, 8) != 0)
|
||||||
|
{
|
||||||
|
TC_LOG_ERROR("misc", "File '%s' has wrong header, expected %s.", VMAP::GAMEOBJECT_MODELS, VMAP::VMAP_MAGIC);
|
||||||
|
fclose(model_list_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 name_length, displayId;
|
uint32 name_length, displayId;
|
||||||
|
uint8 isWmo;
|
||||||
char buff[500];
|
char buff[500];
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -62,7 +73,8 @@ void LoadGameObjectModelList(std::string const& dataPath)
|
|||||||
if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
|
if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|
if (fread(&isWmo, sizeof(uint8), 1, model_list_file) != 1
|
||||||
|
|| fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|
||||||
|| name_length >= sizeof(buff)
|
|| name_length >= sizeof(buff)
|
||||||
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|
||||||
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|
||||||
@@ -78,10 +90,7 @@ void LoadGameObjectModelList(std::string const& dataPath)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
model_list.insert
|
model_list.emplace(std::piecewise_construct, std::forward_as_tuple(displayId), std::forward_as_tuple(&buff[0], name_length, v1, v2, isWmo != 0));
|
||||||
(
|
|
||||||
ModelList::value_type(displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(model_list_file);
|
fclose(model_list_file);
|
||||||
|
|||||||
@@ -40,14 +40,15 @@ struct GameObjectDisplayInfoEntry;
|
|||||||
class TC_COMMON_API GameObjectModelOwnerBase
|
class TC_COMMON_API GameObjectModelOwnerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool IsSpawned() const { return false; }
|
virtual ~GameObjectModelOwnerBase() = default;
|
||||||
virtual uint32 GetDisplayId() const { return 0; }
|
|
||||||
virtual bool IsInPhase(PhaseShift const& /*phaseShift*/) const { return false; }
|
virtual bool IsSpawned() const = 0;
|
||||||
virtual G3D::Vector3 GetPosition() const { return G3D::Vector3::zero(); }
|
virtual uint32 GetDisplayId() const = 0;
|
||||||
virtual float GetOrientation() const { return 0.0f; }
|
virtual bool IsInPhase(PhaseShift const& /*phaseShift*/) const = 0;
|
||||||
virtual float GetScale() const { return 1.0f; }
|
virtual G3D::Vector3 GetPosition() const = 0;
|
||||||
virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const { }
|
virtual float GetOrientation() const = 0;
|
||||||
virtual ~GameObjectModelOwnerBase() { }
|
virtual float GetScale() const = 0;
|
||||||
|
virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TC_COMMON_API GameObjectModel /*, public Intersectable*/
|
class TC_COMMON_API GameObjectModel /*, public Intersectable*/
|
||||||
|
|||||||
@@ -105,8 +105,16 @@ namespace VMAP
|
|||||||
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type):
|
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type):
|
||||||
iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
|
iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
|
||||||
{
|
{
|
||||||
iHeight = new float[(width+1)*(height+1)];
|
if (width && height)
|
||||||
iFlags = new uint8[width*height];
|
{
|
||||||
|
iHeight = new float[(width + 1) * (height + 1)];
|
||||||
|
iFlags = new uint8[width * height];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iHeight = new float[1];
|
||||||
|
iFlags = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr)
|
WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr)
|
||||||
@@ -149,6 +157,13 @@ namespace VMAP
|
|||||||
|
|
||||||
bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const
|
bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const
|
||||||
{
|
{
|
||||||
|
// simple case
|
||||||
|
if (!iFlags)
|
||||||
|
{
|
||||||
|
liqHeight = iHeight[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE;
|
float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE;
|
||||||
uint32 tx = uint32(tx_f);
|
uint32 tx = uint32(tx_f);
|
||||||
if (tx_f < 0.0f || tx >= iTilesX)
|
if (tx_f < 0.0f || tx >= iTilesX)
|
||||||
@@ -200,8 +215,8 @@ namespace VMAP
|
|||||||
{
|
{
|
||||||
return 2 * sizeof(uint32) +
|
return 2 * sizeof(uint32) +
|
||||||
sizeof(Vector3) +
|
sizeof(Vector3) +
|
||||||
(iTilesX + 1)*(iTilesY + 1) * sizeof(float) +
|
sizeof(uint32) +
|
||||||
iTilesX * iTilesY;
|
(iFlags ? ((iTilesX + 1) * (iTilesY + 1) * sizeof(float) + iTilesX * iTilesY) : sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmoLiquid::writeToFile(FILE* wf)
|
bool WmoLiquid::writeToFile(FILE* wf)
|
||||||
@@ -212,12 +227,17 @@ namespace VMAP
|
|||||||
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
|
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
|
||||||
fwrite(&iType, sizeof(uint32), 1, wf) == 1)
|
fwrite(&iType, sizeof(uint32), 1, wf) == 1)
|
||||||
{
|
{
|
||||||
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
if (iTilesX && iTilesY)
|
||||||
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
|
||||||
{
|
{
|
||||||
size = iTilesX*iTilesY;
|
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
||||||
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
||||||
|
{
|
||||||
|
size = iTilesX * iTilesY;
|
||||||
|
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
result = fwrite(iHeight, sizeof(float), 1, wf) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -233,13 +253,21 @@ namespace VMAP
|
|||||||
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
|
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
|
||||||
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
|
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
|
||||||
{
|
{
|
||||||
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
if (liquid->iTilesX && liquid->iTilesY)
|
||||||
liquid->iHeight = new float[size];
|
|
||||||
if (fread(liquid->iHeight, sizeof(float), size, rf) == size)
|
|
||||||
{
|
{
|
||||||
size = liquid->iTilesX * liquid->iTilesY;
|
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
||||||
liquid->iFlags = new uint8[size];
|
liquid->iHeight = new float[size];
|
||||||
result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size;
|
if (fread(liquid->iHeight, sizeof(float), size, rf) == size)
|
||||||
|
{
|
||||||
|
size = liquid->iTilesX * liquid->iTilesY;
|
||||||
|
liquid->iFlags = new uint8[size];
|
||||||
|
result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
liquid->iHeight = new float[1];
|
||||||
|
result = fread(liquid->iHeight, sizeof(float), 1, rf) == 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
namespace VMAP
|
namespace VMAP
|
||||||
{
|
{
|
||||||
const char VMAP_MAGIC[] = "VMAP_4.5";
|
const char VMAP_MAGIC[] = "VMAP_4.6";
|
||||||
const char RAW_VMAP_MAGIC[] = "VMAP045"; // used in extracted vmap files with raw data
|
const char RAW_VMAP_MAGIC[] = "VMAP046"; // used in extracted vmap files with raw data
|
||||||
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
|
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
|
||||||
|
|
||||||
// defined in TileAssembler.cpp currently...
|
// defined in TileAssembler.cpp currently...
|
||||||
|
|||||||
@@ -1741,7 +1741,8 @@ GridMap::GridMap()
|
|||||||
m_V9 = nullptr;
|
m_V9 = nullptr;
|
||||||
m_V8 = nullptr;
|
m_V8 = nullptr;
|
||||||
// Liquid data
|
// Liquid data
|
||||||
_liquidType = 0;
|
_liquidGlobalEntry = 0;
|
||||||
|
_liquidGlobalFlags = 0;
|
||||||
_liquidOffX = 0;
|
_liquidOffX = 0;
|
||||||
_liquidOffY = 0;
|
_liquidOffY = 0;
|
||||||
_liquidWidth = 0;
|
_liquidWidth = 0;
|
||||||
@@ -1901,7 +1902,8 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
|
|||||||
if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt)
|
if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_liquidType = header.liquidType;
|
_liquidGlobalEntry = header.liquidType;
|
||||||
|
_liquidGlobalFlags = header.liquidFlags;
|
||||||
_liquidOffX = header.offsetX;
|
_liquidOffX = header.offsetX;
|
||||||
_liquidOffY = header.offsetY;
|
_liquidOffY = header.offsetY;
|
||||||
_liquidWidth = header.width;
|
_liquidWidth = header.width;
|
||||||
@@ -2196,7 +2198,7 @@ uint8 GridMap::getTerrainType(float x, float y) const
|
|||||||
inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
|
inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
|
||||||
{
|
{
|
||||||
// Check water type (if no water return)
|
// Check water type (if no water return)
|
||||||
if (!_liquidType && !_liquidFlags)
|
if (!_liquidGlobalFlags && !_liquidFlags)
|
||||||
return LIQUID_MAP_NO_WATER;
|
return LIQUID_MAP_NO_WATER;
|
||||||
|
|
||||||
// Get cell
|
// Get cell
|
||||||
@@ -2208,37 +2210,33 @@ inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 R
|
|||||||
|
|
||||||
// Check water type in cell
|
// Check water type in cell
|
||||||
int idx=(x_int>>3)*16 + (y_int>>3);
|
int idx=(x_int>>3)*16 + (y_int>>3);
|
||||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidType;
|
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidGlobalFlags;
|
||||||
uint32 entry = 0;
|
uint32 entry = _liquidEntry ? _liquidEntry[idx] : _liquidGlobalEntry;
|
||||||
if (_liquidEntry)
|
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry))
|
||||||
{
|
{
|
||||||
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(_liquidEntry[idx]))
|
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
||||||
|
uint32 liqTypeIdx = liquidEntry->Type;
|
||||||
|
if (entry < 21)
|
||||||
{
|
{
|
||||||
entry = liquidEntry->Id;
|
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
||||||
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
|
||||||
uint32 liqTypeIdx = liquidEntry->Type;
|
|
||||||
if (entry < 21)
|
|
||||||
{
|
{
|
||||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
||||||
|
if (!overrideLiquid && area->zone)
|
||||||
{
|
{
|
||||||
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
area = sAreaTableStore.LookupEntry(area->zone);
|
||||||
if (!overrideLiquid && area->zone)
|
if (area)
|
||||||
{
|
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
||||||
area = sAreaTableStore.LookupEntry(area->zone);
|
}
|
||||||
if (area)
|
|
||||||
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
||||||
{
|
{
|
||||||
entry = overrideLiquid;
|
entry = overrideLiquid;
|
||||||
liqTypeIdx = liq->Type;
|
liqTypeIdx = liq->Type;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type |= 1 << liqTypeIdx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type |= 1 << liqTypeIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 0)
|
if (type == 0)
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ struct map_heightHeader
|
|||||||
struct map_liquidHeader
|
struct map_liquidHeader
|
||||||
{
|
{
|
||||||
uint32 fourcc;
|
uint32 fourcc;
|
||||||
uint16 flags;
|
uint8 flags;
|
||||||
|
uint8 liquidFlags;
|
||||||
uint16 liquidType;
|
uint16 liquidType;
|
||||||
uint8 offsetX;
|
uint8 offsetX;
|
||||||
uint8 offsetY;
|
uint8 offsetY;
|
||||||
@@ -150,7 +151,6 @@ enum ZLiquidStatus : uint32
|
|||||||
#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
|
#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
|
||||||
|
|
||||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
|
||||||
|
|
||||||
struct LiquidData
|
struct LiquidData
|
||||||
{
|
{
|
||||||
@@ -186,7 +186,8 @@ class TC_GAME_API GridMap
|
|||||||
uint8* _liquidFlags;
|
uint8* _liquidFlags;
|
||||||
float* _liquidMap;
|
float* _liquidMap;
|
||||||
uint16 _gridArea;
|
uint16 _gridArea;
|
||||||
uint16 _liquidType;
|
uint16 _liquidGlobalEntry;
|
||||||
|
uint8 _liquidGlobalFlags;
|
||||||
uint8 _liquidOffX;
|
uint8 _liquidOffX;
|
||||||
uint8 _liquidOffY;
|
uint8 _liquidOffY;
|
||||||
uint8 _liquidWidth;
|
uint8 _liquidWidth;
|
||||||
|
|||||||
@@ -617,12 +617,12 @@ void PathGenerator::CreateFilter()
|
|||||||
|
|
||||||
// creatures don't take environmental damage
|
// creatures don't take environmental damage
|
||||||
if (creature->CanSwim())
|
if (creature->CanSwim())
|
||||||
includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim
|
includeFlags |= (NAV_WATER | NAV_MAGMA_SLIME); // swim
|
||||||
}
|
}
|
||||||
else // assume Player
|
else // assume Player
|
||||||
{
|
{
|
||||||
// perfect support not possible, just stay 'safe'
|
// perfect support not possible, just stay 'safe'
|
||||||
includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME);
|
includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA_SLIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
_filter.setIncludeFlags(includeFlags);
|
_filter.setIncludeFlags(includeFlags);
|
||||||
@@ -646,7 +646,7 @@ void PathGenerator::UpdateFilter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z)
|
NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z)
|
||||||
{
|
{
|
||||||
LiquidData data;
|
LiquidData data;
|
||||||
ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data);
|
ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data);
|
||||||
@@ -660,9 +660,8 @@ NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z)
|
|||||||
case MAP_LIQUID_TYPE_OCEAN:
|
case MAP_LIQUID_TYPE_OCEAN:
|
||||||
return NAV_WATER;
|
return NAV_WATER;
|
||||||
case MAP_LIQUID_TYPE_MAGMA:
|
case MAP_LIQUID_TYPE_MAGMA:
|
||||||
return NAV_MAGMA;
|
|
||||||
case MAP_LIQUID_TYPE_SLIME:
|
case MAP_LIQUID_TYPE_SLIME:
|
||||||
return NAV_SLIME;
|
return NAV_MAGMA_SLIME;;
|
||||||
default:
|
default:
|
||||||
return NAV_GROUND;
|
return NAV_GROUND;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class TC_GAME_API PathGenerator
|
|||||||
void BuildPointPath(float const* startPoint, float const* endPoint);
|
void BuildPointPath(float const* startPoint, float const* endPoint);
|
||||||
void BuildShortcut();
|
void BuildShortcut();
|
||||||
|
|
||||||
NavTerrain GetNavTerrain(float x, float y, float z);
|
NavTerrainFlag GetNavTerrain(float x, float y, float z);
|
||||||
void CreateFilter();
|
void CreateFilter();
|
||||||
void UpdateFilter();
|
void UpdateFilter();
|
||||||
|
|
||||||
|
|||||||
@@ -16,42 +16,19 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PathCommon.h"
|
|
||||||
#include "MapBuilder.h"
|
#include "MapBuilder.h"
|
||||||
|
#include "MapDefines.h"
|
||||||
#include "MapTree.h"
|
#include "MapTree.h"
|
||||||
#include "DetourNavMeshBuilder.h"
|
#include "ModelInstance.h"
|
||||||
#include "DetourNavMesh.h"
|
#include "PathCommon.h"
|
||||||
#include "IntermediateValues.h"
|
#include "IntermediateValues.h"
|
||||||
#include "StringFormat.h"
|
#include "StringFormat.h"
|
||||||
#include "VMapFactory.h"
|
#include "VMapFactory.h"
|
||||||
#include "VMapManager2.h"
|
#include "VMapManager2.h"
|
||||||
|
#include <DetourCommon.h>
|
||||||
#include <limits.h>
|
#include <DetourNavMesh.h>
|
||||||
|
#include <DetourNavMeshBuilder.h>
|
||||||
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
|
#include <climits>
|
||||||
#define MMAP_VERSION 7
|
|
||||||
|
|
||||||
struct MmapTileHeader
|
|
||||||
{
|
|
||||||
uint32 mmapMagic;
|
|
||||||
uint32 dtVersion;
|
|
||||||
uint32 mmapVersion;
|
|
||||||
uint32 size;
|
|
||||||
char usesLiquids;
|
|
||||||
char padding[3];
|
|
||||||
|
|
||||||
MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
|
|
||||||
mmapVersion(MMAP_VERSION), size(0), usesLiquids(true), padding() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
|
|
||||||
static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size");
|
|
||||||
static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
|
|
||||||
sizeof(MmapTileHeader::dtVersion) +
|
|
||||||
sizeof(MmapTileHeader::mmapVersion) +
|
|
||||||
sizeof(MmapTileHeader::size) +
|
|
||||||
sizeof(MmapTileHeader::usesLiquids) +
|
|
||||||
sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
|
|
||||||
|
|
||||||
namespace MMAP
|
namespace MMAP
|
||||||
{
|
{
|
||||||
@@ -645,7 +622,7 @@ namespace MMAP
|
|||||||
|
|
||||||
// mark all walkable tiles, both liquids and solids
|
// mark all walkable tiles, both liquids and solids
|
||||||
unsigned char* triFlags = new unsigned char[tTriCount];
|
unsigned char* triFlags = new unsigned char[tTriCount];
|
||||||
memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char));
|
memset(triFlags, NAV_AREA_GROUND, tTriCount*sizeof(unsigned char));
|
||||||
rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
|
rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
|
||||||
rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
|
rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
|
||||||
delete[] triFlags;
|
delete[] triFlags;
|
||||||
@@ -751,8 +728,15 @@ namespace MMAP
|
|||||||
// set polygons as walkable
|
// set polygons as walkable
|
||||||
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
|
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
|
||||||
for (int i = 0; i < iv.polyMesh->npolys; ++i)
|
for (int i = 0; i < iv.polyMesh->npolys; ++i)
|
||||||
if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
|
{
|
||||||
iv.polyMesh->flags[i] = iv.polyMesh->areas[i];
|
if (uint8 area = iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
|
||||||
|
{
|
||||||
|
if (area >= NAV_AREA_MAGMA_SLIME)
|
||||||
|
iv.polyMesh->flags[i] = 1 << (63 - area);
|
||||||
|
else
|
||||||
|
iv.polyMesh->flags[i] = NAV_GROUND; // TODO: these will be dynamic in future
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setup mesh parameters
|
// setup mesh parameters
|
||||||
dtNavMeshCreateParams params;
|
dtNavMeshCreateParams params;
|
||||||
|
|||||||
@@ -32,20 +32,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum NavTerrain
|
|
||||||
{
|
|
||||||
NAV_EMPTY = 0x00,
|
|
||||||
NAV_GROUND = 0x01,
|
|
||||||
NAV_MAGMA = 0x02,
|
|
||||||
NAV_SLIME = 0x04,
|
|
||||||
NAV_WATER = 0x08,
|
|
||||||
NAV_UNUSED1 = 0x10,
|
|
||||||
NAV_UNUSED2 = 0x20,
|
|
||||||
NAV_UNUSED3 = 0x40,
|
|
||||||
NAV_UNUSED4 = 0x80
|
|
||||||
// we only have 8 bits
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace MMAP
|
namespace MMAP
|
||||||
{
|
{
|
||||||
inline bool matchWildcardFilter(char const* filter, char const* str)
|
inline bool matchWildcardFilter(char const* filter, char const* str)
|
||||||
|
|||||||
@@ -28,6 +28,11 @@
|
|||||||
|
|
||||||
using namespace MMAP;
|
using namespace MMAP;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unordered_map<uint32, uint8> _liquidTypes;
|
||||||
|
}
|
||||||
|
|
||||||
bool checkDirectories(bool debugOutput)
|
bool checkDirectories(bool debugOutput)
|
||||||
{
|
{
|
||||||
std::vector<std::string> dirFiles;
|
std::vector<std::string> dirFiles;
|
||||||
@@ -258,6 +263,49 @@ int finish(char const* message, int returnValue)
|
|||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint32, uint8> LoadLiquid()
|
||||||
|
{
|
||||||
|
bool silent = false;
|
||||||
|
|
||||||
|
DBCFileLoader* liquidDbc = new DBCFileLoader();
|
||||||
|
std::unordered_map<uint32, uint8> liquidData;
|
||||||
|
std::string liquidTypeSource = (boost::filesystem::path("dbc") / "LiquidType.dbc").string();
|
||||||
|
char const* liquidTypeFmt = "nxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||||
|
|
||||||
|
if (liquidDbc->Load(liquidTypeSource.c_str(), liquidTypeFmt))
|
||||||
|
{
|
||||||
|
for (uint32 x = 0; x < liquidDbc->GetNumRows(); ++x)
|
||||||
|
{
|
||||||
|
DBCFileLoader::Record record = liquidDbc->getRecord(x);
|
||||||
|
liquidData[record.getUInt(0)] = record.getUInt(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return liquidData;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint32, std::vector<uint32>> LoadMap()
|
||||||
|
{
|
||||||
|
DBCFileLoader* mapDbc = new DBCFileLoader;
|
||||||
|
std::unordered_map<uint32, std::vector<uint32>> mapData;
|
||||||
|
std::string mapSource = (boost::filesystem::path("dbc") / "Map.dbc").string();
|
||||||
|
char const* mapFmt = "nxxxxxxxxxxxxxxxxxxi";
|
||||||
|
|
||||||
|
if (mapDbc->Load(mapSource.c_str(), mapFmt))
|
||||||
|
{
|
||||||
|
for (uint32 x = 0; x < mapDbc->GetNumRows(); ++x)
|
||||||
|
{
|
||||||
|
DBCFileLoader::Record record = mapDbc->getRecord(x);
|
||||||
|
mapData.emplace(std::piecewise_construct, std::forward_as_tuple(record.getUInt(0)), std::forward_as_tuple());
|
||||||
|
int16 parentMapId = int16(record.getUInt(19));
|
||||||
|
if (parentMapId != -1)
|
||||||
|
mapData[parentMapId].push_back(record.getUInt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapData;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
Trinity::Banner::Show("MMAP generator", [](char const* text) { printf("%s\n", text); }, nullptr);
|
Trinity::Banner::Show("MMAP generator", [](char const* text) { printf("%s\n", text); }, nullptr);
|
||||||
@@ -300,28 +348,6 @@ int main(int argc, char** argv)
|
|||||||
if (!checkDirectories(debugOutput))
|
if (!checkDirectories(debugOutput))
|
||||||
return silent ? -3 : finish("Press ENTER to close...", -3);
|
return silent ? -3 : finish("Press ENTER to close...", -3);
|
||||||
|
|
||||||
std::string mapPath = (boost::filesystem::path("dbc") / "Map.dbc").string();
|
|
||||||
|
|
||||||
std::unordered_map<uint32, std::vector<uint32>> mapData;
|
|
||||||
{
|
|
||||||
DBCFileLoader* loader = new DBCFileLoader();
|
|
||||||
char const* mapFmt = "nxxxxxxxxxxxxxxxxxxi";
|
|
||||||
if (!loader->Load(mapPath.c_str(), mapFmt))
|
|
||||||
{
|
|
||||||
delete loader;
|
|
||||||
return silent ? -4 : finish("Failed to load Map.dbc", -4);
|
|
||||||
}
|
|
||||||
for (uint32 x = 0; x < loader->GetNumRows(); ++x)
|
|
||||||
{
|
|
||||||
mapData.emplace(std::piecewise_construct, std::forward_as_tuple(loader->getRecord(x).getUInt(0)), std::forward_as_tuple());
|
|
||||||
int16 parentMapId = int16(loader->getRecord(x).getUInt(19));
|
|
||||||
if (parentMapId != -1)
|
|
||||||
mapData[parentMapId].push_back(loader->getRecord(x).getUInt(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
static_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->InitializeThreadUnsafe(mapData);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps,
|
MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps,
|
||||||
skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath);
|
skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "TerrainBuilder.h"
|
#include "TerrainBuilder.h"
|
||||||
#include "MapBuilder.h"
|
#include "MapBuilder.h"
|
||||||
|
#include "MapDefines.h"
|
||||||
#include "MapTree.h"
|
#include "MapTree.h"
|
||||||
#include "ModelInstance.h"
|
#include "ModelInstance.h"
|
||||||
#include "VMapFactory.h"
|
#include "VMapFactory.h"
|
||||||
@@ -426,11 +427,9 @@ namespace MMAP
|
|||||||
useLiquid = false;
|
useLiquid = false;
|
||||||
}
|
}
|
||||||
else if ((liquidType & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0)
|
else if ((liquidType & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0)
|
||||||
liquidType = NAV_WATER;
|
liquidType = NAV_AREA_WATER;
|
||||||
else if (liquidType & MAP_LIQUID_TYPE_MAGMA)
|
else if ((liquidType & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0)
|
||||||
liquidType = NAV_MAGMA;
|
liquidType = NAV_AREA_MAGMA_SLIME;
|
||||||
else if (liquidType & MAP_LIQUID_TYPE_SLIME)
|
|
||||||
liquidType = NAV_SLIME;
|
|
||||||
else
|
else
|
||||||
useLiquid = false;
|
useLiquid = false;
|
||||||
}
|
}
|
||||||
@@ -721,22 +720,14 @@ namespace MMAP
|
|||||||
vertsY = tilesY + 1;
|
vertsY = tilesY + 1;
|
||||||
uint8* flags = liquid->GetFlagsStorage();
|
uint8* flags = liquid->GetFlagsStorage();
|
||||||
float* data = liquid->GetHeightStorage();
|
float* data = liquid->GetHeightStorage();
|
||||||
uint8 type = NAV_EMPTY;
|
uint8 type = NAV_AREA_EMPTY;
|
||||||
|
|
||||||
// convert liquid type to NavTerrain
|
// convert liquid type to NavTerrain
|
||||||
switch (liquid->GetType() & 3)
|
uint32 liquidFlags = vmapManager->GetLiquidFlagsPtr(liquid->GetType());
|
||||||
{
|
if ((liquidFlags & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0)
|
||||||
case 0:
|
type = NAV_AREA_WATER;
|
||||||
case 1:
|
else if ((liquidFlags & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0)
|
||||||
type = NAV_WATER;
|
type = NAV_AREA_MAGMA_SLIME;
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
type = NAV_MAGMA;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
type = NAV_SLIME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// indexing is weird...
|
// indexing is weird...
|
||||||
// after a lot of trial and error, this is what works:
|
// after a lot of trial and error, this is what works:
|
||||||
|
|||||||
@@ -18,13 +18,10 @@
|
|||||||
|
|
||||||
#include "vmapexport.h"
|
#include "vmapexport.h"
|
||||||
#include "adtfile.h"
|
#include "adtfile.h"
|
||||||
|
#include "StringFormat.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include "Errors.h"
|
||||||
#ifdef WIN32
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char const* GetPlainName(char const* FileName)
|
char const* GetPlainName(char const* FileName)
|
||||||
{
|
{
|
||||||
@@ -63,11 +60,12 @@ void FixNameCase(char* name, size_t len)
|
|||||||
|
|
||||||
void FixNameSpaces(char* name, size_t len)
|
void FixNameSpaces(char* name, size_t len)
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<len-3; i++)
|
if (len < 3)
|
||||||
{
|
return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len - 3; i++)
|
||||||
if (name[i] == ' ')
|
if (name[i] == ' ')
|
||||||
name[i] = '_';
|
name[i] = '_';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* GetExtension(char* FileName)
|
char* GetExtension(char* FileName)
|
||||||
@@ -79,7 +77,7 @@ char* GetExtension(char* FileName)
|
|||||||
|
|
||||||
extern HANDLE WorldMpq;
|
extern HANDLE WorldMpq;
|
||||||
|
|
||||||
ADTFile::ADTFile(char* filename, bool cache) : ADT(WorldMpq, filename, false)
|
ADTFile::ADTFile(char* filename, bool cache) : _file(WorldMpq, filename, false)
|
||||||
{
|
{
|
||||||
Adtfilename.append(filename);
|
Adtfilename.append(filename);
|
||||||
cacheable = cache;
|
cacheable = cache;
|
||||||
@@ -91,7 +89,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
if (dirfileCache)
|
if (dirfileCache)
|
||||||
return initFromCache(map_num, tileX, tileY, originalMapId);
|
return initFromCache(map_num, tileX, tileY, originalMapId);
|
||||||
|
|
||||||
if (ADT.isEof ())
|
if (_file.isEof ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint32 size;
|
uint32 size;
|
||||||
@@ -122,15 +120,15 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
if (cacheable)
|
if (cacheable)
|
||||||
dirfileCache = new std::vector<ADTOutputCache>();
|
dirfileCache = new std::vector<ADTOutputCache>();
|
||||||
|
|
||||||
while (!ADT.isEof())
|
while (!_file.isEof())
|
||||||
{
|
{
|
||||||
char fourcc[5];
|
char fourcc[5];
|
||||||
ADT.read(&fourcc,4);
|
_file.read(&fourcc,4);
|
||||||
ADT.read(&size, 4);
|
_file.read(&size, 4);
|
||||||
flipcc(fourcc);
|
flipcc(fourcc);
|
||||||
fourcc[4] = 0;
|
fourcc[4] = 0;
|
||||||
|
|
||||||
size_t nextpos = ADT.getPos() + size;
|
size_t nextpos = _file.getPos() + size;
|
||||||
|
|
||||||
if (!strcmp(fourcc,"MCIN"))
|
if (!strcmp(fourcc,"MCIN"))
|
||||||
{
|
{
|
||||||
@@ -143,7 +141,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
char* buf = new char[size];
|
char* buf = new char[size];
|
||||||
ADT.read(buf, size);
|
_file.read(buf, size);
|
||||||
char* p = buf;
|
char* p = buf;
|
||||||
int t = 0;
|
int t = 0;
|
||||||
ModelInstanceNames = new std::string[size];
|
ModelInstanceNames = new std::string[size];
|
||||||
@@ -169,7 +167,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
char* buf = new char[size];
|
char* buf = new char[size];
|
||||||
ADT.read(buf, size);
|
_file.read(buf, size);
|
||||||
char* p = buf;
|
char* p = buf;
|
||||||
int q = 0;
|
int q = 0;
|
||||||
WmoInstanceNames = new std::string[size];
|
WmoInstanceNames = new std::string[size];
|
||||||
@@ -187,17 +185,27 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//======================
|
//======================
|
||||||
else if (!strcmp(fourcc,"MDDF"))
|
else if (!strcmp(fourcc, "MDDF"))
|
||||||
{
|
{
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
nMDX = (int)size / 36;
|
uint32 doodadCount = size / sizeof(ADT::MDDF);
|
||||||
for (int i=0; i<nMDX; ++i)
|
for (uint32 i = 0; i < doodadCount; ++i)
|
||||||
{
|
{
|
||||||
uint32 id;
|
ADT::MDDF doodadDef;
|
||||||
ADT.read(&id, 4);
|
_file.read(&doodadDef, sizeof(ADT::MDDF));
|
||||||
ModelInstance inst(ADT, ModelInstanceNames[id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
if (!(doodadDef.Flags & 0x40))
|
||||||
|
{
|
||||||
|
Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string fileName = Trinity::StringFormat("FILE%08X.xxx", doodadDef.Id);
|
||||||
|
ExtractSingleModel(fileName);
|
||||||
|
Doodad::Extract(doodadDef, fileName.c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] ModelInstanceNames;
|
delete[] ModelInstanceNames;
|
||||||
ModelInstanceNames = nullptr;
|
ModelInstanceNames = nullptr;
|
||||||
}
|
}
|
||||||
@@ -206,12 +214,23 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
{
|
{
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
nWMO = (int)size / 64;
|
uint32 mapObjectCount = size / sizeof(ADT::MODF);
|
||||||
for (int i=0; i<nWMO; ++i)
|
for (uint32 i = 0; i < mapObjectCount; ++i)
|
||||||
{
|
{
|
||||||
uint32 id;
|
ADT::MODF mapObjDef;
|
||||||
ADT.read(&id, 4);
|
_file.read(&mapObjDef, sizeof(ADT::MODF));
|
||||||
WMOInstance inst(ADT, WmoInstanceNames[id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
if (!(mapObjDef.Flags & 0x8))
|
||||||
|
{
|
||||||
|
MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||||
|
Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string fileName = Trinity::StringFormat("FILE%08X.xxx", mapObjDef.Id);
|
||||||
|
ExtractSingleWmo(fileName);
|
||||||
|
MapObject::Extract(mapObjDef, fileName.c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||||
|
Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] WmoInstanceNames;
|
delete[] WmoInstanceNames;
|
||||||
@@ -220,10 +239,10 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
//======================
|
//======================
|
||||||
ADT.seek(nextpos);
|
_file.seek(nextpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ADT.close();
|
_file.close();
|
||||||
fclose(dirfile);
|
fclose(dirfile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -259,6 +278,6 @@ bool ADTFile::initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 o
|
|||||||
|
|
||||||
ADTFile::~ADTFile()
|
ADTFile::~ADTFile()
|
||||||
{
|
{
|
||||||
ADT.close();
|
_file.close();
|
||||||
delete dirfileCache;
|
delete dirfileCache;
|
||||||
}
|
}
|
||||||
@@ -23,88 +23,33 @@
|
|||||||
#include "wmo.h"
|
#include "wmo.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
#define TILESIZE (533.33333f)
|
#pragma pack(push, 1)
|
||||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
namespace ADT
|
||||||
#define UNITSIZE (CHUNKSIZE / 8.0f)
|
|
||||||
|
|
||||||
class Liquid;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
float x;
|
struct MDDF
|
||||||
float y;
|
{
|
||||||
float z;
|
uint32 Id;
|
||||||
}svec;
|
uint32 UniqueId;
|
||||||
|
Vec3D Position;
|
||||||
|
Vec3D Rotation;
|
||||||
|
uint16 Scale;
|
||||||
|
uint16 Flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct vec
|
struct MODF
|
||||||
{
|
{
|
||||||
double x;
|
uint32 Id;
|
||||||
double y;
|
uint32 UniqueId;
|
||||||
double z;
|
Vec3D Position;
|
||||||
};
|
Vec3D Rotation;
|
||||||
|
AaBox3D Bounds;
|
||||||
struct triangle
|
uint16 Flags;
|
||||||
{
|
uint16 DoodadSet; // // can be larger than number of doodad sets in WMO
|
||||||
vec v[3];
|
uint16 NameSet;
|
||||||
};
|
uint16 Scale;
|
||||||
|
};
|
||||||
typedef struct
|
}
|
||||||
{
|
#pragma pack(pop)
|
||||||
float v9[16*8+1][16*8+1];
|
|
||||||
float v8[16*8][16*8];
|
|
||||||
}Cell;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double v9[9][9];
|
|
||||||
double v8[8][8];
|
|
||||||
uint16 area_id;
|
|
||||||
//Liquid *lq;
|
|
||||||
float waterlevel[9][9];
|
|
||||||
uint8 flag;
|
|
||||||
}chunk;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
chunk ch[16][16];
|
|
||||||
}mcell;
|
|
||||||
|
|
||||||
struct MapChunkHeader
|
|
||||||
{
|
|
||||||
uint32 flags;
|
|
||||||
uint32 ix;
|
|
||||||
uint32 iy;
|
|
||||||
uint32 nLayers;
|
|
||||||
uint32 nDoodadRefs;
|
|
||||||
uint32 ofsHeight;
|
|
||||||
uint32 ofsNormal;
|
|
||||||
uint32 ofsLayer;
|
|
||||||
uint32 ofsRefs;
|
|
||||||
uint32 ofsAlpha;
|
|
||||||
uint32 sizeAlpha;
|
|
||||||
uint32 ofsShadow;
|
|
||||||
uint32 sizeShadow;
|
|
||||||
uint32 areaid;
|
|
||||||
uint32 nMapObjRefs;
|
|
||||||
uint32 holes;
|
|
||||||
uint16 s1;
|
|
||||||
uint16 s2;
|
|
||||||
uint32 d1;
|
|
||||||
uint32 d2;
|
|
||||||
uint32 d3;
|
|
||||||
uint32 predTex;
|
|
||||||
uint32 nEffectDoodad;
|
|
||||||
uint32 ofsSndEmitters;
|
|
||||||
uint32 nSndEmitters;
|
|
||||||
uint32 ofsLiquid;
|
|
||||||
uint32 sizeLiquid;
|
|
||||||
float zpos;
|
|
||||||
float xpos;
|
|
||||||
float ypos;
|
|
||||||
uint32 textureId;
|
|
||||||
uint32 props;
|
|
||||||
uint32 effectId;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ADTOutputCache
|
struct ADTOutputCache
|
||||||
{
|
{
|
||||||
@@ -115,15 +60,13 @@ struct ADTOutputCache
|
|||||||
class ADTFile
|
class ADTFile
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
MPQFile ADT;
|
MPQFile _file;
|
||||||
std::string Adtfilename;
|
std::string Adtfilename;
|
||||||
bool cacheable;
|
bool cacheable;
|
||||||
std::vector<ADTOutputCache>* dirfileCache;
|
std::vector<ADTOutputCache>* dirfileCache;
|
||||||
public:
|
public:
|
||||||
ADTFile(char* filename, bool cache);
|
ADTFile(char* filename, bool cache);
|
||||||
~ADTFile();
|
~ADTFile();
|
||||||
int nWMO;
|
|
||||||
int nMDX;
|
|
||||||
std::string* WmoInstanceNames;
|
std::string* WmoInstanceNames;
|
||||||
std::string* ModelInstanceNames;
|
std::string* ModelInstanceNames;
|
||||||
bool init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId);
|
bool init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId);
|
||||||
|
|||||||
@@ -20,13 +20,17 @@
|
|||||||
#include "dbcfile.h"
|
#include "dbcfile.h"
|
||||||
#include "adtfile.h"
|
#include "adtfile.h"
|
||||||
#include "vmapexport.h"
|
#include "vmapexport.h"
|
||||||
|
#include "VMapDefinitions.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
bool ExtractSingleModel(std::string& fname)
|
bool ExtractSingleModel(std::string& fname)
|
||||||
{
|
{
|
||||||
if (fname.substr(fname.length() - 4, 4) == ".mdx")
|
if (fname.length() < 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string extension = fname.substr(fname.length() - 4, 4);
|
||||||
|
if (extension == ".mdx" || extension == ".MDX" || extension == ".mdl" || extension == ".MDL")
|
||||||
{
|
{
|
||||||
fname.erase(fname.length() - 2, 2);
|
fname.erase(fname.length() - 2, 2);
|
||||||
fname.append("2");
|
fname.append("2");
|
||||||
@@ -76,6 +80,8 @@ void ExtractGameobjectModels()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, model_list);
|
||||||
|
|
||||||
for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it)
|
for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it)
|
||||||
{
|
{
|
||||||
path = it->getString(1);
|
path = it->getString(1);
|
||||||
@@ -91,12 +97,14 @@ void ExtractGameobjectModels()
|
|||||||
if (!ch_ext)
|
if (!ch_ext)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strToLower(ch_ext);
|
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (!strcmp(ch_ext, ".wmo"))
|
uint8 isWmo = 0;
|
||||||
|
if (!strcmp(ch_ext, ".WMO") && !strcmp(ch_ext, ".wmo"))
|
||||||
|
{
|
||||||
|
isWmo = 1;
|
||||||
result = ExtractSingleWmo(path);
|
result = ExtractSingleWmo(path);
|
||||||
else if (!strcmp(ch_ext, ".mdl")) // TODO: extract .mdl files, if needed
|
}
|
||||||
|
else if (!strcmp(ch_ext, ".MDL") && !strcmp(ch_ext, ".mdl")) // TODO: extract .mdl files, if needed
|
||||||
continue;
|
continue;
|
||||||
else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2"))
|
else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2"))
|
||||||
result = ExtractSingleModel(path);
|
result = ExtractSingleModel(path);
|
||||||
@@ -106,6 +114,7 @@ void ExtractGameobjectModels()
|
|||||||
uint32 displayId = it->getUInt(0);
|
uint32 displayId = it->getUInt(0);
|
||||||
uint32 path_length = strlen(name);
|
uint32 path_length = strlen(name);
|
||||||
fwrite(&displayId, sizeof(uint32), 1, model_list);
|
fwrite(&displayId, sizeof(uint32), 1, model_list);
|
||||||
|
fwrite(&isWmo, sizeof(uint8), 1, model_list);
|
||||||
fwrite(&path_length, sizeof(uint32), 1, model_list);
|
fwrite(&path_length, sizeof(uint32), 1, model_list);
|
||||||
fwrite(name, sizeof(char), path_length, model_list);
|
fwrite(name, sizeof(char), path_length, model_list);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vmapexport.h"
|
#include "vmapexport.h"
|
||||||
|
#include "Errors.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "wmo.h"
|
#include "wmo.h"
|
||||||
#include "adtfile.h"
|
#include "adtfile.h"
|
||||||
#include "mpqfile.h"
|
#include "mpqfile.h"
|
||||||
#include <cassert>
|
#include "VMapDefinitions.h"
|
||||||
|
#include <G3D/Quat.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
extern HANDLE WorldMpq;
|
extern HANDLE WorldMpq;
|
||||||
|
|
||||||
@@ -79,7 +82,7 @@ bool Model::ConvertToVMAPModel(const char * outfilename)
|
|||||||
printf("Can't create the output file '%s'\n",outfilename);
|
printf("Can't create the output file '%s'\n",outfilename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fwrite(szRawVMAPMagic, 8, 1, output);
|
fwrite(VMAP::RAW_VMAP_MAGIC, 8, 1, output);
|
||||||
uint32 nVertices = header.nBoundingVertices;
|
uint32 nVertices = header.nBoundingVertices;
|
||||||
fwrite(&nVertices, sizeof(int), 1, output);
|
fwrite(&nVertices, sizeof(int), 1, output);
|
||||||
uint32 nofgroups = 1;
|
uint32 nofgroups = 1;
|
||||||
@@ -135,39 +138,23 @@ bool Model::ConvertToVMAPModel(const char * outfilename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vec3D fixCoordSystem(Vec3D v)
|
Vec3D fixCoordSystem(Vec3D const& v)
|
||||||
{
|
{
|
||||||
return Vec3D(v.x, v.z, -v.y);
|
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, uint32 originalMapId,
|
||||||
|
FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||||
{
|
{
|
||||||
return Vec3D(v.x, v.z, v.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
|
||||||
: id(0), scale(0), flags(0)
|
|
||||||
{
|
|
||||||
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?
|
// scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float?
|
||||||
sc = scale / 1024.0f;
|
float sc = doodadDef.Scale / 1024.0f;
|
||||||
|
|
||||||
char tempname[512];
|
char tempname[512];
|
||||||
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName);
|
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName);
|
||||||
FILE* input = fopen(tempname, "r+b");
|
FILE* input = fopen(tempname, "r+b");
|
||||||
|
|
||||||
if (!input)
|
if (!input)
|
||||||
{
|
|
||||||
//printf("ModelInstance::ModelInstance couldn't open %s\n", tempname);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
fseek(input, 8, SEEK_SET); // get the correct no of vertices
|
fseek(input, 8, SEEK_SET); // get the correct no of vertices
|
||||||
int nVertices;
|
int nVertices;
|
||||||
@@ -177,22 +164,25 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID
|
|||||||
if (count != 1 || nVertices == 0)
|
if (count != 1 || nVertices == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint16 adtId = 0;// not used for models
|
Vec3D position = fixCoords(doodadDef.Position);
|
||||||
|
|
||||||
|
uint16 nameSet = 0;// not used for models
|
||||||
|
uint32 uniqueId = GenerateUniqueObjectId(doodadDef.UniqueId, 0);
|
||||||
uint32 flags = MOD_M2;
|
uint32 flags = MOD_M2;
|
||||||
if (tileX == 65 && tileY == 65)
|
if (tileX == 65 && tileY == 65)
|
||||||
flags |= MOD_WORLDSPAWN;
|
flags |= MOD_WORLDSPAWN;
|
||||||
if (mapID != originalMapId)
|
if (mapID != originalMapId)
|
||||||
flags |= MOD_PARENT_SPAWN;
|
flags |= MOD_PARENT_SPAWN;
|
||||||
|
|
||||||
//write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, name
|
//write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name
|
||||||
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
|
fwrite(&nameSet, sizeof(uint16), 1, pDirfile);
|
||||||
fwrite(&id, sizeof(uint32), 1, pDirfile);
|
fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&pos, sizeof(float), 3, pDirfile);
|
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||||
fwrite(&rot, sizeof(float), 3, pDirfile);
|
fwrite(&doodadDef.Rotation, sizeof(Vec3D), 1, pDirfile);
|
||||||
fwrite(&sc, sizeof(float), 1, pDirfile);
|
fwrite(&sc, sizeof(float), 1, pDirfile);
|
||||||
uint32 nlen=strlen(ModelInstName);
|
uint32 nlen=strlen(ModelInstName);
|
||||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||||
@@ -204,41 +194,134 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID
|
|||||||
ADTOutputCache& cacheModelData = dirfileCache->back();
|
ADTOutputCache& cacheModelData = dirfileCache->back();
|
||||||
cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN;
|
cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN;
|
||||||
cacheModelData.Data.resize(
|
cacheModelData.Data.resize(
|
||||||
sizeof(uint16) + // adtId
|
sizeof(uint16) + // nameSet
|
||||||
sizeof(uint32) + // id
|
sizeof(uint32) + // uniqueId
|
||||||
sizeof(float) * 3 + // pos
|
sizeof(Vec3D) + // position
|
||||||
sizeof(float) * 3 + // rot
|
sizeof(Vec3D) + // doodadDef.Rotation
|
||||||
sizeof(float) + // sc
|
sizeof(float) + // sc
|
||||||
sizeof(uint32) + // nlen
|
sizeof(uint32) + // nlen
|
||||||
nlen); // ModelInstName
|
nlen); // ModelInstName
|
||||||
|
|
||||||
uint8* cacheData = cacheModelData.Data.data();
|
uint8* cacheData = cacheModelData.Data.data();
|
||||||
#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count;
|
#define CACHE_WRITE(value, size, cnt, dest) memcpy(dest, value, size * cnt); dest += size * cnt;
|
||||||
|
|
||||||
CACHE_WRITE(&adtId, sizeof(uint16), 1, cacheData);
|
CACHE_WRITE(&nameSet, sizeof(uint16), 1, cacheData);
|
||||||
CACHE_WRITE(&id, sizeof(uint32), 1, cacheData);
|
CACHE_WRITE(&uniqueId, sizeof(uint32), 1, cacheData);
|
||||||
CACHE_WRITE(&pos, sizeof(float), 3, cacheData);
|
CACHE_WRITE(&position, sizeof(Vec3D), 1, cacheData);
|
||||||
CACHE_WRITE(&rot, sizeof(float), 3, cacheData);
|
CACHE_WRITE(&doodadDef.Rotation, sizeof(Vec3D), 1, cacheData);
|
||||||
CACHE_WRITE(&sc, sizeof(float), 1, cacheData);
|
CACHE_WRITE(&sc, sizeof(float), 1, cacheData);
|
||||||
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
||||||
CACHE_WRITE(ModelInstName, sizeof(char), nlen, cacheData);
|
CACHE_WRITE(ModelInstName, sizeof(char), nlen, cacheData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId,
|
||||||
|
FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
FixNameCase(ModelInstName, nlen);
|
||||||
|
FixNameSpaces(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[512];
|
||||||
|
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;
|
||||||
|
if (mapID != originalMapId)
|
||||||
|
tcflags |= MOD_PARENT_SPAWN;
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
|
if (dirfileCache)
|
||||||
|
{
|
||||||
|
dirfileCache->emplace_back();
|
||||||
|
ADTOutputCache& cacheModelData = dirfileCache->back();
|
||||||
|
cacheModelData.Flags = tcflags & ~MOD_PARENT_SPAWN;
|
||||||
|
cacheModelData.Data.resize(
|
||||||
|
sizeof(uint16) + // nameSet
|
||||||
|
sizeof(uint32) + // uniqueId
|
||||||
|
sizeof(Vec3D) + // position
|
||||||
|
sizeof(Vec3D) + // rotation
|
||||||
|
sizeof(float) + // doodad.Scale
|
||||||
|
sizeof(uint32) + // nlen
|
||||||
|
nlen); // ModelInstName
|
||||||
|
|
||||||
|
uint8* cacheData = cacheModelData.Data.data();
|
||||||
|
CACHE_WRITE(&nameSet, sizeof(uint16), 1, cacheData);
|
||||||
|
CACHE_WRITE(&uniqueId, sizeof(uint32), 1, cacheData);
|
||||||
|
CACHE_WRITE(&position, sizeof(Vec3D), 1, cacheData);
|
||||||
|
CACHE_WRITE(&rotation, sizeof(Vec3D), 1, cacheData);
|
||||||
|
CACHE_WRITE(&doodad.Scale, sizeof(float), 1, cacheData);
|
||||||
|
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
||||||
|
CACHE_WRITE(ModelInstName, sizeof(char), nlen, cacheData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef CACHE_WRITE
|
#undef CACHE_WRITE
|
||||||
}
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
); */
|
|
||||||
}
|
|
||||||
@@ -25,8 +25,10 @@
|
|||||||
|
|
||||||
class MPQFile;
|
class MPQFile;
|
||||||
struct ADTOutputCache;
|
struct ADTOutputCache;
|
||||||
|
struct WMODoodadData;
|
||||||
|
namespace ADT { struct MDDF; struct MODF; }
|
||||||
|
|
||||||
Vec3D fixCoordSystem(Vec3D v);
|
Vec3D fixCoordSystem(Vec3D const& v);
|
||||||
|
|
||||||
class Model
|
class Model
|
||||||
{
|
{
|
||||||
@@ -51,17 +53,13 @@ public:
|
|||||||
~Model() { _unload(); }
|
~Model() { _unload(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModelInstance
|
namespace Doodad
|
||||||
{
|
{
|
||||||
public:
|
void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId,
|
||||||
uint32 id;
|
FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||||
Vec3D pos, rot;
|
|
||||||
uint16 scale, flags;
|
|
||||||
float sc;
|
|
||||||
|
|
||||||
ModelInstance() : id(0), scale(0), flags(0), sc(0.0f) {}
|
void ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId,
|
||||||
ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||||
|
}
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -137,6 +137,12 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AaBox3D
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec3D min;
|
||||||
|
Vec3D max;
|
||||||
|
};
|
||||||
|
|
||||||
class Vec2D
|
class Vec2D
|
||||||
{
|
{
|
||||||
@@ -245,4 +251,9 @@ inline void rotate(float x0, float y0, float *x, float *y, float angle)
|
|||||||
*y = xa*sinf(angle) + ya*cosf(angle) + y0;
|
*y = xa*sinf(angle) + ya*cosf(angle) + y0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Quaternion
|
||||||
|
{
|
||||||
|
float X, Y, Z, W;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -127,12 +127,11 @@ std::unordered_map<uint32, LiquidTypeEntry> LiquidTypes;
|
|||||||
char output_path[128]=".";
|
char output_path[128]=".";
|
||||||
char input_path[1024]=".";
|
char input_path[1024]=".";
|
||||||
bool preciseVectorData = false;
|
bool preciseVectorData = false;
|
||||||
|
std::unordered_map<std::string, WMODoodadData> WmoDoodads;
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
//static const char * szWorkDirMaps = ".\\Maps";
|
|
||||||
char const* szWorkDirWmo = "./Buildings";
|
char const* szWorkDirWmo = "./Buildings";
|
||||||
char const* szRawVMAPMagic = "VMAP045";
|
|
||||||
|
|
||||||
bool LoadLocaleMPQFile(int locale)
|
bool LoadLocaleMPQFile(int locale)
|
||||||
{
|
{
|
||||||
@@ -247,7 +246,12 @@ void LoadCommonMPQFiles(uint32 build)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::pair<uint32, uint16>, uint32> uniqueObjectIds;
|
||||||
|
|
||||||
|
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId)
|
||||||
|
{
|
||||||
|
return uniqueObjectIds.emplace(std::make_pair(clientId, clientDoodadId), uniqueObjectIds.size() + 1).first->second;
|
||||||
|
}
|
||||||
// Local testing functions
|
// Local testing functions
|
||||||
|
|
||||||
bool FileExists(char const* file)
|
bool FileExists(char const* file)
|
||||||
@@ -260,15 +264,6 @@ bool FileExists(char const* file)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strToLower(char* str)
|
|
||||||
{
|
|
||||||
while(*str)
|
|
||||||
{
|
|
||||||
*str=tolower(*str);
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copied from contrib/extractor/System.cpp
|
// copied from contrib/extractor/System.cpp
|
||||||
void ReadLiquidMaterialTable()
|
void ReadLiquidMaterialTable()
|
||||||
{
|
{
|
||||||
@@ -360,11 +355,13 @@ bool ExtractWmo()
|
|||||||
bool ExtractSingleWmo(std::string& fname)
|
bool ExtractSingleWmo(std::string& fname)
|
||||||
{
|
{
|
||||||
// Copy files from archive
|
// Copy files from archive
|
||||||
|
std::string originalName = fname;
|
||||||
|
|
||||||
char szLocalFile[1024];
|
char szLocalFile[1024];
|
||||||
const char * plain_name = GetPlainName(fname.c_str());
|
char* plain_name = GetPlainName(&fname[0]);
|
||||||
|
FixNameCase(plain_name, strlen(plain_name));
|
||||||
|
FixNameSpaces(plain_name, strlen(plain_name));
|
||||||
sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name);
|
sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name);
|
||||||
FixNameCase(szLocalFile,strlen(szLocalFile));
|
|
||||||
|
|
||||||
if (FileExists(szLocalFile))
|
if (FileExists(szLocalFile))
|
||||||
return true;
|
return true;
|
||||||
@@ -388,8 +385,8 @@ bool ExtractSingleWmo(std::string& fname)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool file_ok = true;
|
bool file_ok = true;
|
||||||
std::cout << "Extracting " << fname << std::endl;
|
std::cout << "Extracting " << originalName << std::endl;
|
||||||
WMORoot froot(fname);
|
WMORoot froot(originalName);
|
||||||
if (!froot.open())
|
if (!froot.open())
|
||||||
{
|
{
|
||||||
printf("Couldn't open RootWmo!!!\n");
|
printf("Couldn't open RootWmo!!!\n");
|
||||||
@@ -402,6 +399,8 @@ bool ExtractSingleWmo(std::string& fname)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
froot.ConvertToVMAPRootWmo(output);
|
froot.ConvertToVMAPRootWmo(output);
|
||||||
|
WMODoodadData& doodads = WmoDoodads[plain_name];
|
||||||
|
std::swap(doodads, froot.DoodadData);
|
||||||
int Wmo_nVertices = 0;
|
int Wmo_nVertices = 0;
|
||||||
//printf("root has %d groups\n", froot->nGroups);
|
//printf("root has %d groups\n", froot->nGroups);
|
||||||
if (froot.nGroups !=0)
|
if (froot.nGroups !=0)
|
||||||
@@ -417,14 +416,25 @@ bool ExtractSingleWmo(std::string& fname)
|
|||||||
|
|
||||||
std::string s = groupFileName;
|
std::string s = groupFileName;
|
||||||
WMOGroup fgroup(s);
|
WMOGroup fgroup(s);
|
||||||
if (!fgroup.open())
|
if (!fgroup.open(&froot))
|
||||||
{
|
{
|
||||||
printf("Could not open all Group file for: %s\n", plain_name);
|
printf("Could not open all Group file for: %s\n", plain_name);
|
||||||
file_ok = false;
|
file_ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData);
|
Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,11 @@
|
|||||||
#ifndef VMAPEXPORT_H
|
#ifndef VMAPEXPORT_H
|
||||||
#define VMAPEXPORT_H
|
#define VMAPEXPORT_H
|
||||||
|
|
||||||
|
#include "Define.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct WMODoodadData;
|
||||||
|
|
||||||
enum ModelFlags
|
enum ModelFlags
|
||||||
{
|
{
|
||||||
@@ -30,10 +34,10 @@ enum ModelFlags
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const char * szWorkDirWmo;
|
extern const char * szWorkDirWmo;
|
||||||
extern const char * szRawVMAPMagic; // vmap magic string for extracted raw vmap data
|
extern std::unordered_map<std::string, WMODoodadData> WmoDoodads;
|
||||||
|
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId);
|
||||||
|
|
||||||
bool FileExists(const char * file);
|
bool FileExists(const char * file);
|
||||||
void strToLower(char* str);
|
|
||||||
|
|
||||||
bool ExtractSingleWmo(std::string& fname);
|
bool ExtractSingleWmo(std::string& fname);
|
||||||
bool ExtractSingleModel(std::string& fname);
|
bool ExtractSingleModel(std::string& fname);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#include "vmapexport.h"
|
#include "vmapexport.h"
|
||||||
#include "wdtfile.h"
|
#include "wdtfile.h"
|
||||||
#include "adtfile.h"
|
#include "adtfile.h"
|
||||||
|
#include "StringFormat.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
char * wdtGetPlainName(char * FileName)
|
char * wdtGetPlainName(char * FileName)
|
||||||
@@ -104,13 +104,23 @@ bool WDTFile::init(uint32 mapId)
|
|||||||
// global wmo instance data
|
// global wmo instance data
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
int32 gnWMO = (int)size / 64;
|
uint32 mapObjectCount = size / sizeof(ADT::MODF);
|
||||||
|
for (uint32 i = 0; i < mapObjectCount; ++i)
|
||||||
for (int i = 0; i < gnWMO; ++i)
|
|
||||||
{
|
{
|
||||||
int id;
|
ADT::MODF mapObjDef;
|
||||||
_file.read(&id, 4);
|
_file.read(&mapObjDef, sizeof(ADT::MODF));
|
||||||
WMOInstance inst(_file, _wmoNames[id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr);
|
if (!(mapObjDef.Flags & 0x8))
|
||||||
|
{
|
||||||
|
MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr);
|
||||||
|
Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, mapId, 65, 65, mapId, dirfile, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string fileName = Trinity::StringFormat("FILE%08X.xxx", mapObjDef.Id);
|
||||||
|
ExtractSingleWmo(fileName);
|
||||||
|
MapObject::Extract(mapObjDef, fileName.c_str(), mapId, 65, 65, mapId, dirfile, nullptr);
|
||||||
|
Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, mapId, 65, 65, mapId, dirfile, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+141
-148
@@ -17,20 +17,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vmapexport.h"
|
#include "vmapexport.h"
|
||||||
#include "wmo.h"
|
|
||||||
#include "adtfile.h"
|
#include "adtfile.h"
|
||||||
|
#include "mpqfile.h"
|
||||||
#include "vec3d.h"
|
#include "vec3d.h"
|
||||||
|
#include "VMapDefinitions.h"
|
||||||
|
#include "wmo.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <map>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cassert>
|
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
#include "mpqfile.h"
|
|
||||||
|
|
||||||
extern uint16 *LiqType;
|
extern uint16 *LiqType;
|
||||||
|
|
||||||
WMORoot::WMORoot(std::string &filename)
|
WMORoot::WMORoot(std::string const& filename)
|
||||||
: filename(filename), col(0), nTextures(0), nGroups(0), nP(0), nLights(0),
|
: filename(filename), col(0), nTextures(0), nGroups(0), nP(0), nLights(0),
|
||||||
nModels(0), nDoodads(0), nDoodadSets(0), RootWMOID(0), liquidType(0)
|
nModels(0), nDoodads(0), nDoodadSets(0), RootWMOID(0), liquidType(0)
|
||||||
{
|
{
|
||||||
@@ -78,6 +77,37 @@ bool WMORoot::open()
|
|||||||
f.read(&liquidType, 4);
|
f.read(&liquidType, 4);
|
||||||
break;
|
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);
|
||||||
|
FixNameCase(s, strlen(s));
|
||||||
|
FixNameSpaces(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"))
|
else if (!strcmp(fourcc,"MOTX"))
|
||||||
{
|
{
|
||||||
@@ -94,15 +124,6 @@ bool WMORoot::open()
|
|||||||
else if (!strcmp(fourcc,"MOLT"))
|
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"))
|
else if (!strcmp(fourcc,"MOSB"))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -129,7 +150,7 @@ bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile)
|
|||||||
{
|
{
|
||||||
//printf("Convert RootWmo...\n");
|
//printf("Convert RootWmo...\n");
|
||||||
|
|
||||||
fwrite(szRawVMAPMagic, 1, 8, pOutfile);
|
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, pOutfile);
|
||||||
unsigned int nVectors = 0;
|
unsigned int nVectors = 0;
|
||||||
fwrite(&nVectors,sizeof(nVectors), 1, pOutfile); // will be filled later
|
fwrite(&nVectors,sizeof(nVectors), 1, pOutfile); // will be filled later
|
||||||
fwrite(&nGroups, 4, 1, pOutfile);
|
fwrite(&nGroups, 4, 1, pOutfile);
|
||||||
@@ -141,14 +162,14 @@ WMOGroup::WMOGroup(const std::string &filename) :
|
|||||||
filename(filename), MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0),
|
filename(filename), MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0),
|
||||||
hlq(0), LiquEx(0), LiquBytes(0), groupName(0), descGroupName(0), mogpFlags(0),
|
hlq(0), LiquEx(0), LiquBytes(0), groupName(0), descGroupName(0), mogpFlags(0),
|
||||||
moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
|
moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
|
||||||
liquidType(0), groupWMOID(0), mopy_size(0), moba_size(0), LiquEx_size(0),
|
groupLiquid(0), groupWMOID(0), mopy_size(0), moba_size(0), LiquEx_size(0),
|
||||||
nVertices(0), nTriangles(0), liquflags(0)
|
nVertices(0), nTriangles(0), liquflags(0)
|
||||||
{
|
{
|
||||||
memset(bbcorn1, 0, sizeof(bbcorn1));
|
memset(bbcorn1, 0, sizeof(bbcorn1));
|
||||||
memset(bbcorn2, 0, sizeof(bbcorn2));
|
memset(bbcorn2, 0, sizeof(bbcorn2));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WMOGroup::open()
|
bool WMOGroup::open(WMORoot* rootWMO)
|
||||||
{
|
{
|
||||||
MPQFile f(WorldMpq, filename.c_str());
|
MPQFile f(WorldMpq, filename.c_str());
|
||||||
if (f.isEof ())
|
if (f.isEof ())
|
||||||
@@ -170,7 +191,7 @@ bool WMOGroup::open()
|
|||||||
fourcc[4] = 0;
|
fourcc[4] = 0;
|
||||||
size_t nextpos = f.getPos() + size;
|
size_t nextpos = f.getPos() + size;
|
||||||
|
|
||||||
if (!strcmp(fourcc,"MOGP"))//header
|
if (!strcmp(fourcc,"MOGP")) //header
|
||||||
{
|
{
|
||||||
f.read(&groupName, 4);
|
f.read(&groupName, 4);
|
||||||
f.read(&descGroupName, 4);
|
f.read(&descGroupName, 4);
|
||||||
@@ -183,8 +204,19 @@ bool WMOGroup::open()
|
|||||||
f.read(&nBatchB, 2);
|
f.read(&nBatchB, 2);
|
||||||
f.read(&nBatchC, 4);
|
f.read(&nBatchC, 4);
|
||||||
f.read(&fogIdx, 4);
|
f.read(&fogIdx, 4);
|
||||||
f.read(&liquidType, 4);
|
f.read(&groupLiquid, 4);
|
||||||
f.read(&groupWMOID,4);
|
f.read(&groupWMOID, 4);
|
||||||
|
|
||||||
|
// according to WoW.Dev Wiki:
|
||||||
|
if (rootWMO->liquidType & 4)
|
||||||
|
groupLiquid = GetLiquidTypeId(groupLiquid);
|
||||||
|
else if (groupLiquid == 15)
|
||||||
|
groupLiquid = 0;
|
||||||
|
else
|
||||||
|
groupLiquid = GetLiquidTypeId(groupLiquid + 1);
|
||||||
|
|
||||||
|
if (groupLiquid)
|
||||||
|
liquflags |= 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (!strcmp(fourcc,"MOPY"))
|
else if (!strcmp(fourcc,"MOPY"))
|
||||||
@@ -217,11 +249,16 @@ bool WMOGroup::open()
|
|||||||
moba_size = size/2;
|
moba_size = size/2;
|
||||||
f.read(MOBA, size);
|
f.read(MOBA, size);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(fourcc, "MODR"))
|
||||||
|
{
|
||||||
|
DoodadReferences.resize(size / sizeof(uint16));
|
||||||
|
f.read(DoodadReferences.data(), size);
|
||||||
|
}
|
||||||
else if (!strcmp(fourcc,"MLIQ"))
|
else if (!strcmp(fourcc,"MLIQ"))
|
||||||
{
|
{
|
||||||
liquflags |= 1;
|
liquflags |= 1;
|
||||||
hlq = new WMOLiquidHeader();
|
hlq = new WMOLiquidHeader();
|
||||||
f.read(hlq, 0x1E);
|
f.read(hlq, sizeof(WMOLiquidHeader));
|
||||||
LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts;
|
LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts;
|
||||||
LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts];
|
LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts];
|
||||||
f.read(LiquEx, LiquEx_size);
|
f.read(LiquEx, LiquEx_size);
|
||||||
@@ -229,6 +266,19 @@ bool WMOGroup::open()
|
|||||||
LiquBytes = new char[nLiquBytes];
|
LiquBytes = new char[nLiquBytes];
|
||||||
f.read(LiquBytes, nLiquBytes);
|
f.read(LiquBytes, nLiquBytes);
|
||||||
|
|
||||||
|
// Determine legacy liquid type
|
||||||
|
if (!groupLiquid)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < hlq->xtiles * hlq->ytiles; ++i)
|
||||||
|
{
|
||||||
|
if ((LiquBytes[i] & 0xF) != 15)
|
||||||
|
{
|
||||||
|
groupLiquid = GetLiquidTypeId((LiquBytes[i] & 0xF) + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
|
/* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
|
||||||
llog << filename;
|
llog << filename;
|
||||||
llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
|
llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
|
||||||
@@ -242,7 +292,7 @@ bool WMOGroup::open()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool preciseVectorData)
|
int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, bool preciseVectorData)
|
||||||
{
|
{
|
||||||
fwrite(&mogpFlags,sizeof(uint32),1,output);
|
fwrite(&mogpFlags,sizeof(uint32),1,output);
|
||||||
fwrite(&groupWMOID,sizeof(uint32),1,output);
|
fwrite(&groupWMOID,sizeof(uint32),1,output);
|
||||||
@@ -401,78 +451,54 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------LIQU------------------------
|
//------LIQU------------------------
|
||||||
if (LiquEx_size != 0)
|
if (liquflags & 3)
|
||||||
{
|
{
|
||||||
int LIQU_h[] = {0x5551494C, static_cast<int>(sizeof(WMOLiquidHeader) + LiquEx_size) + hlq->xtiles*hlq->ytiles};// "LIQU"
|
int LIQU_totalSize = sizeof(uint32);
|
||||||
|
if (liquflags & 1)
|
||||||
|
{
|
||||||
|
LIQU_totalSize += sizeof(WMOLiquidHeader);
|
||||||
|
LIQU_totalSize += LiquEx_size / sizeof(WMOLiquidVert) * sizeof(float);
|
||||||
|
LIQU_totalSize += hlq->xtiles * hlq->ytiles;
|
||||||
|
}
|
||||||
|
int LIQU_h[] = { 0x5551494C, LIQU_totalSize };// "LIQU"
|
||||||
fwrite(LIQU_h, 4, 2, output);
|
fwrite(LIQU_h, 4, 2, output);
|
||||||
|
|
||||||
// according to WoW.Dev Wiki:
|
|
||||||
uint32 liquidEntry;
|
|
||||||
if (rootWMO->liquidType & 4)
|
|
||||||
liquidEntry = liquidType;
|
|
||||||
else if (liquidType == 15)
|
|
||||||
liquidEntry = 0;
|
|
||||||
else
|
|
||||||
liquidEntry = liquidType + 1;
|
|
||||||
|
|
||||||
if (!liquidEntry)
|
|
||||||
{
|
|
||||||
int v1; // edx@1
|
|
||||||
int v2; // eax@1
|
|
||||||
|
|
||||||
v1 = hlq->xtiles * hlq->ytiles;
|
|
||||||
v2 = 0;
|
|
||||||
if (v1 > 0)
|
|
||||||
{
|
|
||||||
while ((LiquBytes[v2] & 0xF) == 15)
|
|
||||||
{
|
|
||||||
++v2;
|
|
||||||
if (v2 >= v1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v2 < v1 && (LiquBytes[v2] & 0xF) != 15)
|
|
||||||
liquidEntry = (LiquBytes[v2] & 0xF) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (liquidEntry && liquidEntry < 21)
|
|
||||||
{
|
|
||||||
switch ((liquidEntry - 1) & 3)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
liquidEntry = ((mogpFlags & 0x80000) != 0) + 13;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
liquidEntry = 14;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
liquidEntry = 19;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
liquidEntry = 20;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hlq->type = liquidEntry;
|
|
||||||
|
|
||||||
/* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
|
/* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
|
||||||
llog << filename;
|
llog << filename;
|
||||||
llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->liquidType << " group:" << liquidType << ")\n";
|
llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->flags << " group:" << flags << ")\n";
|
||||||
llog.close(); */
|
llog.close(); */
|
||||||
|
|
||||||
fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
|
fwrite(&groupLiquid, sizeof(uint32), 1, output);
|
||||||
// only need height values, the other values are unknown anyway
|
if (liquflags & 1)
|
||||||
for (uint32 i = 0; i<LiquEx_size/sizeof(WMOLiquidVert); ++i)
|
{
|
||||||
fwrite(&LiquEx[i].height, sizeof(float), 1, output);
|
fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
|
||||||
// todo: compress to bit field
|
// only need height values, the other values are unknown anyway
|
||||||
fwrite(LiquBytes, 1, hlq->xtiles*hlq->ytiles, output);
|
for (uint32 i = 0; i < LiquEx_size / sizeof(WMOLiquidVert); ++i)
|
||||||
|
fwrite(&LiquEx[i].height, sizeof(float), 1, output);
|
||||||
|
// todo: compress to bit field
|
||||||
|
fwrite(LiquBytes, 1, hlq->xtiles * hlq->ytiles, output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nColTriangles;
|
return nColTriangles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 WMOGroup::GetLiquidTypeId(uint32 liquidTypeId)
|
||||||
|
{
|
||||||
|
if (liquidTypeId < 21 && liquidTypeId)
|
||||||
|
{
|
||||||
|
switch (((static_cast<uint8>(liquidTypeId) - 1) & 3))
|
||||||
|
{
|
||||||
|
case 0: return ((mogpFlags & 0x80000) != 0) + 13;
|
||||||
|
case 1: return 14;
|
||||||
|
case 2: return 19;
|
||||||
|
case 3: return 20;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return liquidTypeId;
|
||||||
|
}
|
||||||
|
|
||||||
WMOGroup::~WMOGroup()
|
WMOGroup::~WMOGroup()
|
||||||
{
|
{
|
||||||
delete [] MOPY;
|
delete [] MOPY;
|
||||||
@@ -484,33 +510,11 @@ WMOGroup::~WMOGroup()
|
|||||||
delete [] LiquBytes;
|
delete [] LiquBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||||
: currx(0), curry(0), wmo(nullptr), doodadset(0), pos(), indx(0), id(0)
|
|
||||||
{
|
{
|
||||||
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]); // bounding box corners
|
|
||||||
f.read(ff,12);
|
|
||||||
pos3 = Vec3D(ff[0],ff[1],ff[2]); // bounding box corners
|
|
||||||
|
|
||||||
uint16 fflags;
|
|
||||||
f.read(&fflags, 2);
|
|
||||||
|
|
||||||
uint16 doodadSet;
|
|
||||||
f.read(&doodadSet, 2);
|
|
||||||
|
|
||||||
uint16 trash,adtId;
|
|
||||||
f.read(&adtId,2);
|
|
||||||
f.read(&trash,2);
|
|
||||||
|
|
||||||
// destructible wmo, do not dump. we can handle the vmap for these
|
// destructible wmo, do not dump. we can handle the vmap for these
|
||||||
// in dynamic tree (gameobject vmaps)
|
// in dynamic tree (gameobject vmaps)
|
||||||
if ((fflags & 0x01) != 0)
|
if ((mapObjDef.Flags & 0x1) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//-----------add_in _dir_file----------------
|
//-----------add_in _dir_file----------------
|
||||||
@@ -534,37 +538,40 @@ WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint
|
|||||||
if (count != 1 || nVertices == 0)
|
if (count != 1 || nVertices == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float x,z;
|
Vec3D position = mapObjDef.Position;
|
||||||
x = pos.x;
|
|
||||||
z = pos.z;
|
float x, z;
|
||||||
if (x==0 && z == 0)
|
x = position.x;
|
||||||
|
z = position.z;
|
||||||
|
if (x == 0 && z == 0)
|
||||||
{
|
{
|
||||||
pos.x = 533.33333f*32;
|
position.x = 533.33333f * 32;
|
||||||
pos.z = 533.33333f*32;
|
position.z = 533.33333f * 32;
|
||||||
}
|
}
|
||||||
pos = fixCoords(pos);
|
position = fixCoords(position);
|
||||||
pos2 = fixCoords(pos2);
|
AaBox3D bounds;
|
||||||
pos3 = fixCoords(pos3);
|
bounds.min = fixCoords(mapObjDef.Bounds.min);
|
||||||
|
bounds.max = fixCoords(mapObjDef.Bounds.max);
|
||||||
|
|
||||||
float scale = 1.0f;
|
float scale = 1.0f;
|
||||||
|
uint32 uniqueId = GenerateUniqueObjectId(mapObjDef.UniqueId, 0);
|
||||||
uint32 flags = MOD_HAS_BOUND;
|
uint32 flags = MOD_HAS_BOUND;
|
||||||
if (tileX == 65 && tileY == 65)
|
if (tileX == 65 && tileY == 65)
|
||||||
flags |= MOD_WORLDSPAWN;
|
flags |= MOD_WORLDSPAWN;
|
||||||
if (mapID != originalMapId)
|
if (mapID != originalMapId)
|
||||||
flags |= MOD_PARENT_SPAWN;
|
flags |= MOD_PARENT_SPAWN;
|
||||||
|
|
||||||
//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(&mapID, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
|
fwrite(&mapObjDef.NameSet, sizeof(uint16), 1, pDirfile);
|
||||||
fwrite(&id, sizeof(uint32), 1, pDirfile);
|
fwrite(&uniqueId, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(&pos, sizeof(float), 3, pDirfile);
|
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||||
fwrite(&rot, sizeof(float), 3, pDirfile);
|
fwrite(&mapObjDef.Rotation, sizeof(Vec3D), 1, pDirfile);
|
||||||
fwrite(&scale, sizeof(float), 1, pDirfile);
|
fwrite(&scale, sizeof(float), 1, pDirfile);
|
||||||
fwrite(&pos2, sizeof(float), 3, pDirfile);
|
fwrite(&bounds, sizeof(AaBox3D), 1, pDirfile);
|
||||||
fwrite(&pos3, sizeof(float), 3, pDirfile);
|
|
||||||
uint32 nlen = strlen(WmoInstName);
|
uint32 nlen = strlen(WmoInstName);
|
||||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||||
fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
|
fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
|
||||||
@@ -575,41 +582,27 @@ WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint
|
|||||||
ADTOutputCache& cacheModelData = dirfileCache->back();
|
ADTOutputCache& cacheModelData = dirfileCache->back();
|
||||||
cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN;
|
cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN;
|
||||||
cacheModelData.Data.resize(
|
cacheModelData.Data.resize(
|
||||||
sizeof(uint16) + // adtId
|
sizeof(uint16) + // mapObjDef.NameSet
|
||||||
sizeof(uint32) + // id
|
sizeof(uint32) + // uniqueId
|
||||||
sizeof(float) * 3 + // pos
|
sizeof(Vec3D) + // position
|
||||||
sizeof(float) * 3 + // rot
|
sizeof(Vec3D) + // mapObjDef.Rotation
|
||||||
sizeof(float) + // scale
|
sizeof(float) + // scale
|
||||||
sizeof(float) * 3 + // pos2
|
sizeof(AaBox3D) + // bounds
|
||||||
sizeof(float) * 3 + // pos3
|
|
||||||
sizeof(uint32) + // nlen
|
sizeof(uint32) + // nlen
|
||||||
nlen); // WmoInstName
|
nlen); // WmoInstName
|
||||||
|
|
||||||
uint8* cacheData = cacheModelData.Data.data();
|
uint8* cacheData = cacheModelData.Data.data();
|
||||||
#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count;
|
#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count;
|
||||||
|
|
||||||
CACHE_WRITE(&adtId, sizeof(uint16), 1, cacheData);
|
CACHE_WRITE(&mapObjDef.NameSet, sizeof(uint16), 1, cacheData);
|
||||||
CACHE_WRITE(&id, sizeof(uint32), 1, cacheData);
|
CACHE_WRITE(&uniqueId, sizeof(uint32), 1, cacheData);
|
||||||
CACHE_WRITE(&pos, sizeof(float), 3, cacheData);
|
CACHE_WRITE(&position, sizeof(Vec3D), 1, cacheData);
|
||||||
CACHE_WRITE(&rot, sizeof(float), 3, cacheData);
|
CACHE_WRITE(&mapObjDef.Rotation, sizeof(Vec3D), 1, cacheData);
|
||||||
CACHE_WRITE(&scale, sizeof(float), 1, cacheData);
|
CACHE_WRITE(&scale, sizeof(float), 1, cacheData);
|
||||||
CACHE_WRITE(&pos2, sizeof(float), 3, cacheData);
|
CACHE_WRITE(&bounds, sizeof(AaBox3D), 1, cacheData);
|
||||||
CACHE_WRITE(&pos3, sizeof(float), 3, cacheData);
|
|
||||||
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
||||||
CACHE_WRITE(WmoInstName, sizeof(char), nlen, cacheData);
|
CACHE_WRITE(WmoInstName, sizeof(char), nlen, cacheData);
|
||||||
|
|
||||||
#undef CACHE_WRITE
|
#undef CACHE_WRITE
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
@@ -18,11 +18,10 @@
|
|||||||
|
|
||||||
#ifndef WMO_H
|
#ifndef WMO_H
|
||||||
#define WMO_H
|
#define WMO_H
|
||||||
#define TILESIZE (533.33333f)
|
|
||||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
|
#include <memory>
|
||||||
#include "vec3d.h"
|
#include "vec3d.h"
|
||||||
#include "mpqfile.h"
|
#include "mpqfile.h"
|
||||||
|
|
||||||
@@ -43,10 +42,40 @@ class WMOInstance;
|
|||||||
class WMOManager;
|
class WMOManager;
|
||||||
class MPQFile;
|
class MPQFile;
|
||||||
struct ADTOutputCache;
|
struct ADTOutputCache;
|
||||||
|
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... */
|
/* 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); }
|
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
|
class WMORoot
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -57,23 +86,25 @@ public:
|
|||||||
float bbcorn1[3];
|
float bbcorn1[3];
|
||||||
float bbcorn2[3];
|
float bbcorn2[3];
|
||||||
|
|
||||||
WMORoot(std::string& filename);
|
WMODoodadData DoodadData;
|
||||||
|
std::unordered_set<uint32> ValidDoodadNames;
|
||||||
|
|
||||||
|
WMORoot(std::string const& filename);
|
||||||
|
|
||||||
bool open();
|
bool open();
|
||||||
bool ConvertToVMAPRootWmo(FILE* output);
|
bool ConvertToVMAPRootWmo(FILE* output);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
struct WMOLiquidHeader
|
struct WMOLiquidHeader
|
||||||
{
|
{
|
||||||
int xverts, yverts, xtiles, ytiles;
|
int xverts, yverts, xtiles, ytiles;
|
||||||
float pos_x;
|
float pos_x;
|
||||||
float pos_y;
|
float pos_y;
|
||||||
float pos_z;
|
float pos_z;
|
||||||
short type;
|
short material;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
|
|
||||||
struct WMOLiquidVert
|
struct WMOLiquidVert
|
||||||
{
|
{
|
||||||
uint16 unk1;
|
uint16 unk1;
|
||||||
@@ -107,7 +138,7 @@ public:
|
|||||||
uint16 moprNItems;
|
uint16 moprNItems;
|
||||||
uint16 nBatchA;
|
uint16 nBatchA;
|
||||||
uint16 nBatchB;
|
uint16 nBatchB;
|
||||||
uint32 nBatchC, fogIdx, liquidType, groupWMOID;
|
uint32 nBatchC, fogIdx, groupLiquid, groupWMOID;
|
||||||
|
|
||||||
int mopy_size, moba_size;
|
int mopy_size, moba_size;
|
||||||
int LiquEx_size;
|
int LiquEx_size;
|
||||||
@@ -115,29 +146,19 @@ public:
|
|||||||
int nTriangles; // number when loaded
|
int nTriangles; // number when loaded
|
||||||
uint32 liquflags;
|
uint32 liquflags;
|
||||||
|
|
||||||
|
std::vector<uint16> DoodadReferences;
|
||||||
|
|
||||||
WMOGroup(std::string const& filename);
|
WMOGroup(std::string const& filename);
|
||||||
~WMOGroup();
|
~WMOGroup();
|
||||||
|
|
||||||
bool open();
|
bool open(WMORoot* rootWMO);
|
||||||
int ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData);
|
int ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData);
|
||||||
|
uint32 GetLiquidTypeId(uint32 liquidTypeId);
|
||||||
};
|
};
|
||||||
|
|
||||||
class WMOInstance
|
namespace MapObject
|
||||||
{
|
{
|
||||||
static std::set<int> ids;
|
void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||||
public:
|
}
|
||||||
std::string MapName;
|
|
||||||
int currx;
|
|
||||||
int curry;
|
|
||||||
WMOGroup* wmo;
|
|
||||||
int doodadset;
|
|
||||||
Vec3D pos;
|
|
||||||
Vec3D pos2, pos3, rot;
|
|
||||||
uint32 indx, id;
|
|
||||||
|
|
||||||
WMOInstance(MPQFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
|
||||||
|
|
||||||
static void reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in new issue
Block a user