mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 09:17:18 +00:00
feat(Tools/Mapextractor): Implemented liquid object detection (#11402)
* . * . * . * . * . * . * . * Delete Utils.cpp
This commit is contained in:
committed by
GitHub
parent
5036360c1e
commit
a31a30566e
@@ -327,7 +327,7 @@ namespace VMAP
|
||||
float pos_x;
|
||||
float pos_y;
|
||||
float pos_z;
|
||||
short type;
|
||||
short material;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
//=================================================================
|
||||
@@ -532,19 +532,29 @@ namespace VMAP
|
||||
delete[] vectorarray;
|
||||
}
|
||||
// ----- liquid
|
||||
liquid = 0;
|
||||
if (liquidflags & 1)
|
||||
liquid = nullptr;
|
||||
if (liquidflags & 3)
|
||||
{
|
||||
WMOLiquidHeader hlq;
|
||||
READ_OR_RETURN(&blockId, 4);
|
||||
CMP_OR_RETURN(blockId, "LIQU");
|
||||
READ_OR_RETURN(&blocksize, sizeof(int));
|
||||
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
|
||||
liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type);
|
||||
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);
|
||||
uint32 liquidType;
|
||||
READ_OR_RETURN(&liquidType, sizeof(uint32));
|
||||
if (liquidflags & 1)
|
||||
{
|
||||
WMOLiquidHeader hlq;
|
||||
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;
|
||||
|
||||
@@ -107,8 +107,16 @@ namespace VMAP
|
||||
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3& corner, uint32 type):
|
||||
iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
|
||||
{
|
||||
iHeight = new float[(width + 1) * (height + 1)];
|
||||
iFlags = new uint8[width * height];
|
||||
if (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(0), iFlags(0)
|
||||
@@ -157,6 +165,13 @@ namespace VMAP
|
||||
|
||||
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;
|
||||
uint32 tx = uint32(tx_f);
|
||||
if (tx_f < 0.0f || tx >= iTilesX)
|
||||
@@ -219,8 +234,8 @@ namespace VMAP
|
||||
{
|
||||
return 2 * sizeof(uint32) +
|
||||
sizeof(Vector3) +
|
||||
(iTilesX + 1) * (iTilesY + 1) * sizeof(float) +
|
||||
iTilesX * iTilesY;
|
||||
sizeof(uint32) +
|
||||
(iFlags ? ((iTilesX + 1) * (iTilesY + 1) * sizeof(float) + iTilesX * iTilesY) : sizeof(float));
|
||||
}
|
||||
|
||||
bool WmoLiquid::writeToFile(FILE* wf)
|
||||
@@ -231,12 +246,17 @@ namespace VMAP
|
||||
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
|
||||
fwrite(&iType, sizeof(uint32), 1, wf) == 1)
|
||||
{
|
||||
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
||||
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
||||
if (iTilesX && iTilesY)
|
||||
{
|
||||
size = iTilesX * iTilesY;
|
||||
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
||||
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
||||
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;
|
||||
@@ -252,13 +272,21 @@ namespace VMAP
|
||||
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
|
||||
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
|
||||
{
|
||||
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
||||
liquid->iHeight = new float[size];
|
||||
if (fread(liquid->iHeight, sizeof(float), size, rf) == size)
|
||||
if (liquid->iTilesX && liquid->iTilesY)
|
||||
{
|
||||
size = liquid->iTilesX * liquid->iTilesY;
|
||||
liquid->iFlags = new uint8[size];
|
||||
result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size;
|
||||
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
||||
liquid->iHeight = new float[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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
const char VMAP_MAGIC[] = "VMAP_4.6";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP046"; // used in extracted vmap files with raw data
|
||||
const char VMAP_MAGIC[] = "VMAP_4.7";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data
|
||||
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
|
||||
|
||||
// defined in TileAssembler.cpp currently...
|
||||
|
||||
@@ -1336,7 +1336,8 @@ GridMap::GridMap()
|
||||
_maxHeight = nullptr;
|
||||
_minHeight = nullptr;
|
||||
// Liquid data
|
||||
_liquidType = 0;
|
||||
_liquidGlobalEntry = 0;
|
||||
_liquidGlobalFlags = 0;
|
||||
_liquidOffX = 0;
|
||||
_liquidOffY = 0;
|
||||
_liquidWidth = 0;
|
||||
@@ -1513,7 +1514,8 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
|
||||
if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt)
|
||||
return false;
|
||||
|
||||
_liquidType = header.liquidType;
|
||||
_liquidGlobalEntry = header.liquidType;
|
||||
_liquidGlobalFlags = header.liquidFlags;
|
||||
_liquidOffX = header.offsetX;
|
||||
_liquidOffY = header.offsetY;
|
||||
_liquidWidth = header.width;
|
||||
@@ -1893,7 +1895,7 @@ inline LiquidData const GridMap::GetLiquidData(float x, float y, float z, float
|
||||
LiquidData liquidData;
|
||||
|
||||
// Check water type (if no water return)
|
||||
if (_liquidType || _liquidFlags)
|
||||
if (_liquidGlobalFlags || _liquidFlags)
|
||||
{
|
||||
// Get cell
|
||||
float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
|
||||
@@ -1903,38 +1905,34 @@ inline LiquidData const GridMap::GetLiquidData(float x, float y, float z, float
|
||||
int y_int = (int) cy & (MAP_RESOLUTION - 1);
|
||||
|
||||
// Check water type in cell
|
||||
int idx = (x_int >> 3) * 16 + (y_int >> 3);
|
||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidType;
|
||||
uint32 entry = 0;
|
||||
if (_liquidEntry)
|
||||
int idx=(x_int>>3)*16 + (y_int>>3);
|
||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidGlobalFlags;
|
||||
uint32 entry = _liquidEntry ? _liquidEntry[idx] : _liquidGlobalEntry;
|
||||
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;
|
||||
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
||||
uint32 liqTypeIdx = liquidEntry->Type;
|
||||
if (entry < 21)
|
||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
||||
{
|
||||
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];
|
||||
if (!overrideLiquid && area->zone)
|
||||
{
|
||||
area = sAreaTableStore.LookupEntry(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))
|
||||
{
|
||||
entry = overrideLiquid;
|
||||
liqTypeIdx = liq->Type;
|
||||
}
|
||||
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
||||
{
|
||||
entry = overrideLiquid;
|
||||
liqTypeIdx = liq->Type;
|
||||
}
|
||||
}
|
||||
|
||||
type |= 1 << liqTypeIdx;
|
||||
}
|
||||
|
||||
type |= 1 << liqTypeIdx;
|
||||
}
|
||||
|
||||
// Check req liquid type mask
|
||||
|
||||
@@ -128,7 +128,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -158,7 +159,6 @@ enum LiquidStatus
|
||||
#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_WMO_WATER 0x20
|
||||
|
||||
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
|
||||
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
|
||||
@@ -227,7 +227,8 @@ class GridMap
|
||||
uint8* _liquidFlags;
|
||||
float* _liquidMap;
|
||||
uint16 _gridArea;
|
||||
uint16 _liquidType;
|
||||
uint16 _liquidGlobalEntry;
|
||||
uint8 _liquidGlobalFlags;
|
||||
uint8 _liquidOffX;
|
||||
uint8 _liquidOffY;
|
||||
uint8 _liquidWidth;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "direct.h"
|
||||
@@ -62,8 +63,13 @@ typedef struct
|
||||
uint32 id;
|
||||
} map_id;
|
||||
|
||||
map_id* map_ids;
|
||||
uint16* LiqType;
|
||||
struct LiquidTypeEntry
|
||||
{
|
||||
uint8 SoundBank;
|
||||
};
|
||||
|
||||
std::vector<map_id> map_ids;
|
||||
std::unordered_map<uint32, LiquidTypeEntry> LiquidTypes;
|
||||
#define MAX_PATH_LENGTH 128
|
||||
char output_path[MAX_PATH_LENGTH] = ".";
|
||||
char input_path[MAX_PATH_LENGTH] = ".";
|
||||
@@ -271,7 +277,7 @@ uint32 ReadMapDBC()
|
||||
}
|
||||
|
||||
size_t map_count = dbc.getRecordCount();
|
||||
map_ids = new map_id[map_count];
|
||||
map_ids.resize(map_count);
|
||||
for (uint32 x = 0; x < map_count; ++x)
|
||||
{
|
||||
map_ids[x].id = dbc.getRecord(x).getUInt(0);
|
||||
@@ -291,15 +297,13 @@ void ReadLiquidTypeTableDBC()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t liqTypeCount = dbc.getRecordCount();
|
||||
size_t liqTypeMaxId = dbc.getMaxId();
|
||||
LiqType = new uint16[liqTypeMaxId + 1];
|
||||
memset(LiqType, 0xff, (liqTypeMaxId + 1) * sizeof(uint16));
|
||||
for (uint32 x = 0; x < dbc.getRecordCount(); ++x)
|
||||
{
|
||||
LiquidTypeEntry& liquidType = LiquidTypes[dbc.getRecord(x).getUInt(0)];
|
||||
liquidType.SoundBank = dbc.getRecord(x).getUInt(3);
|
||||
}
|
||||
|
||||
for (uint32 x = 0; x < liqTypeCount; ++x)
|
||||
LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
|
||||
|
||||
printf("Done! (%u LiqTypes loaded)\n", (uint32)liqTypeCount);
|
||||
printf("Done! (%lu LiquidTypes loaded)\n", LiquidTypes.size());
|
||||
}
|
||||
|
||||
//
|
||||
@@ -357,7 +361,6 @@ struct map_heightHeader
|
||||
#define MAP_LIQUID_TYPE_SLIME 0x08
|
||||
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
#define MAP_LIQUID_NO_TYPE 0x0001
|
||||
#define MAP_LIQUID_NO_HEIGHT 0x0002
|
||||
@@ -365,7 +368,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -720,73 +724,57 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
adt_MH2O* h2o = adt.a_grid->getMH2O();
|
||||
if (h2o)
|
||||
{
|
||||
for (int i = 0; i < ADT_CELLS_PER_GRID; i++)
|
||||
for (int32 i = 0; i < ADT_CELLS_PER_GRID; i++)
|
||||
{
|
||||
for (int j = 0; j < ADT_CELLS_PER_GRID; j++)
|
||||
for (int32 j = 0; j < ADT_CELLS_PER_GRID; j++)
|
||||
{
|
||||
adt_liquid_header* h = h2o->getLiquidData(i, j);
|
||||
adt_liquid_instance const* h = h2o->GetLiquidInstance(i,j);
|
||||
if (!h)
|
||||
continue;
|
||||
|
||||
int count = 0;
|
||||
uint64 show = h2o->getLiquidShowMap(h);
|
||||
for (int y = 0; y < h->height; y++)
|
||||
adt_liquid_attributes attrs = h2o->GetLiquidAttributes(i, j);
|
||||
|
||||
int32 count = 0;
|
||||
uint64 existsMask = h2o->GetLiquidExistsBitmap(h);
|
||||
for (int32 y = 0; y < h->GetHeight(); y++)
|
||||
{
|
||||
int cy = i * ADT_CELL_SIZE + y + h->yOffset;
|
||||
for (int x = 0; x < h->width; x++)
|
||||
int32 cy = i * ADT_CELL_SIZE + y + h->GetOffsetY();
|
||||
for (int32 x = 0; x < h->GetWidth(); x++)
|
||||
{
|
||||
int cx = j * ADT_CELL_SIZE + x + h->xOffset;
|
||||
if (show & 1)
|
||||
int32 cx = j * ADT_CELL_SIZE + x + h->GetOffsetX();
|
||||
if (existsMask & 1)
|
||||
{
|
||||
liquid_show[cy][cx] = true;
|
||||
++count;
|
||||
}
|
||||
show >>= 1;
|
||||
existsMask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
liquid_entry[i][j] = h->liquidType;
|
||||
switch (LiqType[h->liquidType])
|
||||
liquid_entry[i][j] = h->LiquidType;
|
||||
switch (LiquidTypes.at(h->LiquidType).SoundBank)
|
||||
{
|
||||
case LIQUID_TYPE_WATER:
|
||||
liquid_flags[i][j] |= MAP_LIQUID_TYPE_WATER;
|
||||
break;
|
||||
case LIQUID_TYPE_OCEAN:
|
||||
liquid_flags[i][j] |= MAP_LIQUID_TYPE_OCEAN;
|
||||
break;
|
||||
case LIQUID_TYPE_MAGMA:
|
||||
liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA;
|
||||
break;
|
||||
case LIQUID_TYPE_SLIME:
|
||||
liquid_flags[i][j] |= MAP_LIQUID_TYPE_SLIME;
|
||||
break;
|
||||
case LIQUID_TYPE_WATER: liquid_flags[i][j] |= MAP_LIQUID_TYPE_WATER; break;
|
||||
case LIQUID_TYPE_OCEAN: liquid_flags[i][j] |= MAP_LIQUID_TYPE_OCEAN; if (attrs.Deep) liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER; break;
|
||||
case LIQUID_TYPE_MAGMA: liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA; break;
|
||||
case LIQUID_TYPE_SLIME: liquid_flags[i][j] |= MAP_LIQUID_TYPE_SLIME; break;
|
||||
default:
|
||||
printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, inputPath.c_str(), i, j);
|
||||
printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->LiquidType, inputPath.c_str(), i, j);
|
||||
break;
|
||||
}
|
||||
// Dark water detect
|
||||
if (LiqType[h->liquidType] == LIQUID_TYPE_OCEAN)
|
||||
{
|
||||
uint8* lm = h2o->getLiquidLightMap(h);
|
||||
if (!lm)
|
||||
liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER;
|
||||
}
|
||||
|
||||
if (!count && liquid_flags[i][j])
|
||||
printf("Wrong liquid detect in MH2O chunk");
|
||||
|
||||
float* height = h2o->getLiquidHeightMap(h);
|
||||
int pos = 0;
|
||||
for (int y = 0; y <= h->height; y++)
|
||||
int32 pos = 0;
|
||||
for (int32 y = 0; y <= h->GetHeight(); y++)
|
||||
{
|
||||
int cy = i * ADT_CELL_SIZE + y + h->yOffset;
|
||||
for (int x = 0; x <= h->width; x++)
|
||||
int cy = i * ADT_CELL_SIZE + y + h->GetOffsetY();
|
||||
for (int32 x = 0; x <= h->GetWidth(); x++)
|
||||
{
|
||||
int cx = j * ADT_CELL_SIZE + x + h->xOffset;
|
||||
if (height)
|
||||
liquid_height[cy][cx] = height[pos];
|
||||
else
|
||||
liquid_height[cy][cx] = h->heightLevel1;
|
||||
int32 cx = j * ADT_CELL_SIZE + x + h->GetOffsetX();
|
||||
liquid_height[cy][cx] = h2o->GetLiquidHeight(h, pos);
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
@@ -796,13 +784,14 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
//============================================
|
||||
// Pack liquid data
|
||||
//============================================
|
||||
uint8 type = liquid_flags[0][0];
|
||||
uint16 firstLiquidType = liquid_entry[0][0];
|
||||
uint8 firstLiquidFlag = liquid_flags[0][0];
|
||||
bool fullType = false;
|
||||
for (int y = 0; y < ADT_CELLS_PER_GRID; y++)
|
||||
{
|
||||
for (int x = 0; x < ADT_CELLS_PER_GRID; x++)
|
||||
{
|
||||
if (liquid_flags[y][x] != type)
|
||||
if (liquid_entry[y][x] != firstLiquidType || liquid_flags[y][x] != firstLiquidFlag)
|
||||
{
|
||||
fullType = true;
|
||||
y = ADT_CELLS_PER_GRID;
|
||||
@@ -814,7 +803,7 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
map_liquidHeader liquidHeader;
|
||||
|
||||
// no water data (if all grid have 0 liquid type)
|
||||
if (type == 0 && !fullType)
|
||||
if (firstLiquidFlag == 0 && !fullType)
|
||||
{
|
||||
// No liquid data
|
||||
map.liquidMapOffset = 0;
|
||||
@@ -873,7 +862,10 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
liquidHeader.flags |= MAP_LIQUID_NO_TYPE;
|
||||
|
||||
if (liquidHeader.flags & MAP_LIQUID_NO_TYPE)
|
||||
liquidHeader.liquidType = type;
|
||||
{
|
||||
liquidHeader.liquidFlags = firstLiquidFlag;
|
||||
liquidHeader.liquidType = firstLiquidType;
|
||||
}
|
||||
else
|
||||
map.liquidMapSize += sizeof(liquid_entry) + sizeof(liquid_flags);
|
||||
|
||||
@@ -1020,7 +1012,6 @@ void ExtractMapsFromMpq(uint32 build)
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
delete[] map_ids;
|
||||
}
|
||||
|
||||
bool ExtractFile( char const* mpq_name, std::string const& filename )
|
||||
|
||||
@@ -177,21 +177,36 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#define ADT_LIQUID_HEADER_FULL_LIGHT 0x01
|
||||
#define ADT_LIQUID_HEADER_NO_HIGHT 0x02
|
||||
|
||||
struct adt_liquid_header
|
||||
enum class LiquidVertexFormatType : uint16
|
||||
{
|
||||
uint16 liquidType; // Index from LiquidType.dbc
|
||||
uint16 formatFlags;
|
||||
float heightLevel1;
|
||||
float heightLevel2;
|
||||
uint8 xOffset;
|
||||
uint8 yOffset;
|
||||
uint8 width;
|
||||
uint8 height;
|
||||
uint32 offsData2a;
|
||||
uint32 offsData2b;
|
||||
HeightDepth = 0,
|
||||
HeightTextureCoord = 1,
|
||||
Depth = 2,
|
||||
};
|
||||
|
||||
struct adt_liquid_instance
|
||||
{
|
||||
uint16 LiquidType; // Index from LiquidType.db2
|
||||
LiquidVertexFormatType LiquidVertexFormat;
|
||||
float MinHeightLevel;
|
||||
float MaxHeightLevel;
|
||||
uint8 OffsetX;
|
||||
uint8 OffsetY;
|
||||
uint8 Width;
|
||||
uint8 Height;
|
||||
uint32 OffsetExistsBitmap;
|
||||
uint32 OffsetVertexData;
|
||||
|
||||
uint8 GetOffsetX() const { return OffsetX; }
|
||||
uint8 GetOffsetY() const { return OffsetY; }
|
||||
uint8 GetWidth() const { return Width; }
|
||||
uint8 GetHeight() const { return Height; }
|
||||
};
|
||||
|
||||
struct adt_liquid_attributes
|
||||
{
|
||||
uint64 Fishable;
|
||||
uint64 Deep;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -209,59 +224,99 @@ public:
|
||||
|
||||
struct adt_LIQUID
|
||||
{
|
||||
uint32 offsData1;
|
||||
uint32 OffsetInstances;
|
||||
uint32 used;
|
||||
uint32 offsData2;
|
||||
uint32 OffsetAttributes;
|
||||
} liquid[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
|
||||
|
||||
bool prepareLoadedData();
|
||||
|
||||
adt_liquid_header* getLiquidData(int x, int y)
|
||||
adt_liquid_instance const* GetLiquidInstance(int32 x, int32 y) const
|
||||
{
|
||||
if (liquid[x][y].used && liquid[x][y].offsData1)
|
||||
return (adt_liquid_header*)((uint8*)this + 8 + liquid[x][y].offsData1);
|
||||
if (liquid[x][y].used && liquid[x][y].OffsetInstances)
|
||||
return (adt_liquid_instance *)((uint8*)this + 8 + liquid[x][y].OffsetInstances);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float* getLiquidHeightMap(adt_liquid_header* h)
|
||||
adt_liquid_attributes GetLiquidAttributes(int32 x, int32 y) const
|
||||
{
|
||||
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
|
||||
return nullptr;
|
||||
if (h->offsData2b)
|
||||
return (float*)((uint8*)this + 8 + h->offsData2b);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8* getLiquidLightMap(adt_liquid_header* h)
|
||||
{
|
||||
if (h->formatFlags & ADT_LIQUID_HEADER_FULL_LIGHT)
|
||||
return nullptr;
|
||||
if (h->offsData2b)
|
||||
if (liquid[x][y].used)
|
||||
{
|
||||
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
|
||||
return (uint8*)((uint8*)this + 8 + h->offsData2b);
|
||||
return (uint8*)((uint8*)this + 8 + h->offsData2b + (h->width + 1) * (h->height + 1) * 4);
|
||||
if (liquid[x][y].OffsetAttributes)
|
||||
return *((adt_liquid_attributes *)((uint8*)this + 8 + liquid[x][y].OffsetAttributes));
|
||||
return { 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF };
|
||||
}
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
uint16 GetLiquidType(adt_liquid_instance const* h) const
|
||||
{
|
||||
if (h->LiquidVertexFormat == LiquidVertexFormatType::Depth)
|
||||
return 2;
|
||||
|
||||
return h->LiquidType;
|
||||
}
|
||||
|
||||
float GetLiquidHeight(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
return 0.0f;
|
||||
|
||||
switch (h->LiquidVertexFormat)
|
||||
{
|
||||
case LiquidVertexFormatType::HeightDepth:
|
||||
case LiquidVertexFormatType::HeightTextureCoord:
|
||||
return ((float const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
|
||||
case LiquidVertexFormatType::Depth:
|
||||
return 0.0f;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
int8 GetLiquidDepth(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
return -1;
|
||||
|
||||
switch (h->LiquidVertexFormat)
|
||||
{
|
||||
case LiquidVertexFormatType::HeightDepth:
|
||||
return ((int8 const*)((int8 const*)this + 8 + h->OffsetVertexData + (h->GetWidth() + 1) * (h->GetHeight() + 1) * 4))[pos];
|
||||
case LiquidVertexFormatType::HeightTextureCoord:
|
||||
return 0;
|
||||
case LiquidVertexFormatType::Depth:
|
||||
return ((int8 const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 const* GetLiquidTextureCoordMap(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
return nullptr;
|
||||
|
||||
switch (h->LiquidVertexFormat)
|
||||
{
|
||||
case LiquidVertexFormatType::HeightDepth:
|
||||
case LiquidVertexFormatType::Depth:
|
||||
return nullptr;
|
||||
case LiquidVertexFormatType::HeightTextureCoord:
|
||||
return (uint16 const*)((uint8 const*)this + 8 + h->OffsetVertexData + 4 * ((h->GetWidth() + 1) * (h->GetHeight() + 1) + pos));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32* getLiquidFullLightMap(adt_liquid_header* h)
|
||||
uint64 GetLiquidExistsBitmap(adt_liquid_instance const* h) const
|
||||
{
|
||||
if (!(h->formatFlags & ADT_LIQUID_HEADER_FULL_LIGHT))
|
||||
return nullptr;
|
||||
if (h->offsData2b)
|
||||
{
|
||||
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
|
||||
return (uint32*)((uint8*)this + 8 + h->offsData2b);
|
||||
return (uint32*)((uint8*)this + 8 + h->offsData2b + (h->width + 1) * (h->height + 1) * 4);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64 getLiquidShowMap(adt_liquid_header* h)
|
||||
{
|
||||
if (h->offsData2a)
|
||||
return *((uint64*)((uint8*)this + 8 + h->offsData2a));
|
||||
if (h->OffsetExistsBitmap)
|
||||
return *((uint64 *)((uint8*)this + 8 + h->OffsetExistsBitmap));
|
||||
else
|
||||
return 0xFFFFFFFFFFFFFFFFuLL;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -75,7 +76,6 @@ struct map_liquidHeader
|
||||
#define MAP_LIQUID_TYPE_MAGMA 0x04
|
||||
#define MAP_LIQUID_TYPE_SLIME 0x08
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
uint32 GetLiquidFlags(uint32 liquidId);
|
||||
|
||||
@@ -172,8 +172,10 @@ namespace MMAP
|
||||
// data used later
|
||||
uint16 holes[16][16];
|
||||
memset(holes, 0, sizeof(holes));
|
||||
uint8 liquid_type[16][16];
|
||||
memset(liquid_type, 0, sizeof(liquid_type));
|
||||
uint16 liquid_entry[16][16];
|
||||
memset(liquid_entry, 0, sizeof(liquid_entry));
|
||||
uint8 liquid_flags[16][16];
|
||||
memset(liquid_flags, 0, sizeof(liquid_flags));
|
||||
G3D::Array<int> ltriangles;
|
||||
G3D::Array<int> ttriangles;
|
||||
|
||||
@@ -284,75 +286,87 @@ namespace MMAP
|
||||
float* liquid_map = nullptr;
|
||||
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_TYPE))
|
||||
if (fread(liquid_type, sizeof(liquid_type), 1, mapFile) != 1)
|
||||
{
|
||||
if (fread(liquid_entry, sizeof(liquid_entry), 1, mapFile) != 1)
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
if (fread(liquid_flags, sizeof(liquid_flags), 1, mapFile) != 1)
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill_n(&liquid_entry[0][0], 16 * 16, lheader.liquidType);
|
||||
std::fill_n(&liquid_flags[0][0], 16 * 16, lheader.liquidFlags);
|
||||
}
|
||||
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
{
|
||||
uint32 toRead = lheader.width * lheader.height;
|
||||
liquid_map = new float [toRead];
|
||||
if (fread(liquid_map, sizeof(float), toRead, mapFile) != toRead)
|
||||
{
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
delete[] liquid_map;
|
||||
liquid_map = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (liquid_map)
|
||||
int count = meshData.liquidVerts.size() / 3;
|
||||
float xoffset = (float(tileX)-32)*GRID_SIZE;
|
||||
float yoffset = (float(tileY)-32)*GRID_SIZE;
|
||||
|
||||
float coord[3];
|
||||
int row, col;
|
||||
|
||||
// generate coordinates
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
{
|
||||
int count = meshData.liquidVerts.size() / 3;
|
||||
float xoffset = (float(tileX) - 32) * GRID_SIZE;
|
||||
float yoffset = (float(tileY) - 32) * GRID_SIZE;
|
||||
|
||||
float coord[3];
|
||||
int row, col;
|
||||
|
||||
// generate coordinates
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
int j = 0;
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
{
|
||||
int j = 0;
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
|
||||
if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height ||
|
||||
col < lheader.offsetX || col >= lheader.offsetX + lheader.width)
|
||||
{
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
|
||||
if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height ||
|
||||
col < lheader.offsetX || col >= lheader.offsetX + lheader.width)
|
||||
{
|
||||
// dummy vert using invalid height
|
||||
meshData.liquidVerts.append((xoffset + col * GRID_PART_SIZE) * -1, INVALID_MAP_LIQ_HEIGHT, (yoffset + row * GRID_PART_SIZE) * -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map);
|
||||
meshData.liquidVerts.append(coord[0]);
|
||||
meshData.liquidVerts.append(coord[2]);
|
||||
meshData.liquidVerts.append(coord[1]);
|
||||
j++;
|
||||
// dummy vert using invalid height
|
||||
meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, INVALID_MAP_LIQ_HEIGHT, (yoffset+row*GRID_PART_SIZE)*-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map);
|
||||
meshData.liquidVerts.append(coord[0]);
|
||||
meshData.liquidVerts.append(coord[2]);
|
||||
meshData.liquidVerts.append(coord[1]);
|
||||
j++;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
{
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
{
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
meshData.liquidVerts.append((xoffset + col * GRID_PART_SIZE) * -1, lheader.liquidLevel, (yoffset + row * GRID_PART_SIZE) * -1);
|
||||
}
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, lheader.liquidLevel, (yoffset+row*GRID_PART_SIZE)*-1);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] liquid_map;
|
||||
delete[] liquid_map;
|
||||
|
||||
int indices[] = { 0, 0, 0 };
|
||||
int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM - TOP;
|
||||
getLoopVars(portion, loopStart, loopEnd, loopInc);
|
||||
int indices[] = { 0, 0, 0 };
|
||||
int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP;
|
||||
getLoopVars(portion, loopStart, loopEnd, loopInc);
|
||||
|
||||
// generate triangles
|
||||
for (int i = loopStart; i < loopEnd; i += loopInc)
|
||||
for (int j = TOP; j <= BOTTOM; j += triInc)
|
||||
{
|
||||
getHeightTriangle(i, Spot(j), indices, true);
|
||||
ltriangles.append(indices[2] + count);
|
||||
ltriangles.append(indices[1] + count);
|
||||
ltriangles.append(indices[0] + count);
|
||||
}
|
||||
// generate triangles
|
||||
for (int i = loopStart; i < loopEnd; i += loopInc)
|
||||
{
|
||||
for (int j = TOP; j <= BOTTOM; j += triInc)
|
||||
{
|
||||
getHeightTriangle(i, Spot(j), indices, true);
|
||||
ltriangles.append(indices[2] + count);
|
||||
ltriangles.append(indices[1] + count);
|
||||
ltriangles.append(indices[0] + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +413,7 @@ namespace MMAP
|
||||
}
|
||||
else
|
||||
{
|
||||
liquidType = getLiquidType(i, liquid_type);
|
||||
liquidType = getLiquidType(i, liquid_flags);
|
||||
if (liquidType & MAP_LIQUID_TYPE_DARK_WATER)
|
||||
{
|
||||
// players should not be here, so logically neither should creatures
|
||||
@@ -708,7 +722,7 @@ namespace MMAP
|
||||
copyIndices(tempTriangles, meshData.solidTris, offset, isM2);
|
||||
|
||||
// now handle liquid data
|
||||
if (liquid)
|
||||
if (liquid && liquid->GetFlagsStorage())
|
||||
{
|
||||
std::vector<G3D::Vector3> liqVerts;
|
||||
std::vector<int> liqTris;
|
||||
|
||||
@@ -22,91 +22,7 @@
|
||||
#include "mpq_libmpq04.h"
|
||||
#include "wmo.h"
|
||||
|
||||
#define TILESIZE (533.33333f)
|
||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
||||
#define UNITSIZE (CHUNKSIZE / 8.0f)
|
||||
|
||||
class Liquid;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} svec;
|
||||
|
||||
struct vec
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct triangle
|
||||
{
|
||||
vec v[3];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
namespace ADT
|
||||
{
|
||||
struct MDDF
|
||||
@@ -127,7 +43,7 @@ namespace ADT
|
||||
Vec3D Rotation;
|
||||
AaBox3D Bounds;
|
||||
uint16 Flags;
|
||||
uint16 DoodadSet; // can be larger than number of doodad sets in WMO
|
||||
uint16 DoodadSet;
|
||||
uint16 NameSet;
|
||||
uint16 Scale;
|
||||
};
|
||||
|
||||
@@ -163,7 +163,7 @@ bool ExtractSingleWmo(std::string& fname)
|
||||
|
||||
string s = groupFileName;
|
||||
WMOGroup fgroup(s);
|
||||
if (!fgroup.open())
|
||||
if (!fgroup.open(&froot))
|
||||
{
|
||||
printf("Could not open all Group file for: %s\n", plain_name);
|
||||
file_ok = false;
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
const char VMAP_MAGIC[] = "VMAP_4.6";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP046"; // used in extracted vmap files with raw data
|
||||
const char VMAP_MAGIC[] = "VMAP_4.7";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data
|
||||
}
|
||||
|
||||
enum ModelFlags
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
WMORoot::WMORoot(std::string const& filename)
|
||||
: filename(filename), color(0), nTextures(0), nGroups(0), nPortals(0), nLights(0),
|
||||
nDoodadNames(0), nDoodadDefs(0), nDoodadSets(0), RootWMOID(0), liquidType(0)
|
||||
nDoodadNames(0), nDoodadDefs(0), nDoodadSets(0), RootWMOID(0), flags(0)
|
||||
{
|
||||
memset(bbcorn1, 0, sizeof(bbcorn1));
|
||||
memset(bbcorn2, 0, sizeof(bbcorn2));
|
||||
@@ -71,7 +71,7 @@ bool WMORoot::open()
|
||||
f.read(&RootWMOID, 4);
|
||||
f.read(bbcorn1, 12);
|
||||
f.read(bbcorn2, 12);
|
||||
f.read(&liquidType, 4);
|
||||
f.read(&flags, 4);
|
||||
}
|
||||
else if (!strcmp(fourcc, "MODS"))
|
||||
{
|
||||
@@ -158,14 +158,14 @@ WMOGroup::WMOGroup(std::string const& filename) :
|
||||
filename(std::move(filename)), MOPY(nullptr), MOVI(nullptr), MoviEx(nullptr), MOVT(nullptr), MOBA(nullptr), MobaEx(nullptr),
|
||||
hlq(nullptr), LiquEx(nullptr), LiquBytes(nullptr), groupName(0), descGroupName(0), mogpFlags(0),
|
||||
moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
|
||||
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)
|
||||
{
|
||||
memset(bbcorn1, 0, sizeof(bbcorn1));
|
||||
memset(bbcorn2, 0, sizeof(bbcorn2));
|
||||
}
|
||||
|
||||
bool WMOGroup::open()
|
||||
bool WMOGroup::open(WMORoot* rootWMO)
|
||||
{
|
||||
MPQFile f(filename.c_str());
|
||||
if (f.isEof ())
|
||||
@@ -202,8 +202,19 @@ bool WMOGroup::open()
|
||||
f.read(&nBatchB, 2);
|
||||
f.read(&nBatchC, 4);
|
||||
f.read(&fogIdx, 4);
|
||||
f.read(&liquidType, 4);
|
||||
f.read(&groupLiquid, 4);
|
||||
f.read(&groupWMOID, 4);
|
||||
|
||||
// according to WoW.Dev Wiki:
|
||||
if (rootWMO->flags & 4)
|
||||
groupLiquid = GetLiquidTypeId(groupLiquid);
|
||||
else if (groupLiquid == 15)
|
||||
groupLiquid = 0;
|
||||
else
|
||||
groupLiquid = GetLiquidTypeId(groupLiquid + 1);
|
||||
|
||||
if (groupLiquid)
|
||||
liquflags |= 2;
|
||||
}
|
||||
else if (!strcmp(fourcc, "MOPY"))
|
||||
{
|
||||
@@ -252,6 +263,19 @@ bool WMOGroup::open()
|
||||
LiquBytes = new char[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);
|
||||
llog << filename;
|
||||
llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
|
||||
@@ -423,78 +447,55 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool precise
|
||||
}
|
||||
|
||||
//------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);
|
||||
|
||||
// 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);
|
||||
llog << filename;
|
||||
llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->liquidType << " group:" << liquidType << ")\n";
|
||||
llog.close(); */
|
||||
|
||||
fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
|
||||
// only need height values, the other values are unknown anyway
|
||||
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);
|
||||
fwrite(&groupLiquid, sizeof(uint32), 1, output);
|
||||
if (liquflags & 1)
|
||||
{
|
||||
fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
|
||||
// only need height values, the other values are unknown anyway
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
delete [] MOPY;
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
#include "vec3d.h"
|
||||
#include "loadlib/loadlib.h"
|
||||
|
||||
#define TILESIZE (533.33333f)
|
||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
||||
|
||||
// MOPY flags
|
||||
enum MopyFlags
|
||||
{
|
||||
@@ -84,7 +81,7 @@ private:
|
||||
std::string filename;
|
||||
public:
|
||||
unsigned int color;
|
||||
uint32 nTextures, nGroups, nPortals, nLights, nDoodadNames, nDoodadDefs, nDoodadSets, RootWMOID, liquidType;
|
||||
uint32 nTextures, nGroups, nPortals, nLights, nDoodadNames, nDoodadDefs, nDoodadSets, RootWMOID, flags;
|
||||
float bbcorn1[3];
|
||||
float bbcorn2[3];
|
||||
|
||||
@@ -105,7 +102,7 @@ struct WMOLiquidHeader
|
||||
float pos_x;
|
||||
float pos_y;
|
||||
float pos_z;
|
||||
short type;
|
||||
short material;
|
||||
};
|
||||
|
||||
struct WMOLiquidVert
|
||||
@@ -141,7 +138,7 @@ public:
|
||||
uint16 moprNItems;
|
||||
uint16 nBatchA;
|
||||
uint16 nBatchB;
|
||||
uint32 nBatchC, fogIdx, liquidType, groupWMOID;
|
||||
uint32 nBatchC, fogIdx, groupLiquid, groupWMOID;
|
||||
|
||||
int mopy_size, moba_size;
|
||||
int LiquEx_size;
|
||||
@@ -154,8 +151,9 @@ public:
|
||||
WMOGroup(std::string const& filename);
|
||||
~WMOGroup();
|
||||
|
||||
bool open();
|
||||
bool open(WMORoot* rootWMO);
|
||||
int ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData);
|
||||
uint32 GetLiquidTypeId(uint32 liquidTypeId);
|
||||
};
|
||||
|
||||
namespace MapObject
|
||||
|
||||
Reference in New Issue
Block a user