Tools/Mapextractor: Implemented liquid object detection

(cherry picked from commit 82bf263f92)
This commit is contained in:
Shauren
2018-03-24 20:07:05 +01:00
parent fee666f02f
commit e6bfa71e4d
2 changed files with 109 additions and 85 deletions

View File

@@ -32,6 +32,7 @@
#include <G3D/Plane.h>
#include <boost/filesystem.hpp>
#include <unordered_map>
extern ArchiveSet gOpenArchives;
@@ -41,8 +42,13 @@ typedef struct
uint32 id;
} map_id;
struct LiquidTypeEntry
{
uint8 SoundBank;
};
std::vector<map_id> map_ids;
std::vector<uint16> LiqType;
std::unordered_map<uint32, LiquidTypeEntry> LiquidTypes;
#define MAX_PATH_LENGTH 128
char output_path[MAX_PATH_LENGTH] = ".";
char input_path[MAX_PATH_LENGTH] = ".";
@@ -240,14 +246,13 @@ void ReadLiquidTypeTableDBC()
exit(1);
}
size_t liqTypeCount = dbc.getRecordCount();
size_t liqTypeMaxId = dbc.getMaxId();
LiqType.resize(liqTypeMaxId + 1, 0xFFFF);
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! (" SZFMTD " LiqTypes loaded)\n", liqTypeCount);
printf("Done! (" SZFMTD " LiquidTypes loaded)\n", LiquidTypes.size());
}
//
@@ -666,65 +671,59 @@ 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++)
int32 count = 0;
uint64 existsMask = h2o->GetLiquidExistsBitmap(h);
for (int32 y = 0; y < h->Height; 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->OffsetY;
for (int32 x = 0; x < h->Width; x++)
{
int cx = j * ADT_CELL_SIZE + x + h->xOffset;
if (show & 1)
int32 cx = j * ADT_CELL_SIZE + x + h->OffsetX;
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;
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->Height; 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->OffsetY;
for (int32 x = 0; x <= h->Width; 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->OffsetX;
liquid_height[cy][cx] = h2o->GetLiquidHeight(h, pos);
// Dark water detect
if (liquid_flags[i][j] & MAP_LIQUID_TYPE_OCEAN && h2o->GetLiquidDepth(h, pos) == -1)
liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER;
pos++;
}
}

View File

@@ -174,20 +174,25 @@ public:
}
};
#define ADT_LIQUID_HEADER_FULL_LIGHT 0x01
#define ADT_LIQUID_HEADER_NO_HIGHT 0x02
enum class LiquidVertexFormatType : uint16
{
HeightDepth = 0,
HeightTextureCoord = 1,
Depth = 2,
};
struct adt_liquid_header{
uint16 liquidType; // Index from LiquidType.dbc
uint16 formatFlags;
float heightLevel1;
float heightLevel2;
uint8 xOffset;
uint8 yOffset;
uint8 width;
uint8 height;
uint32 offsData2a;
uint32 offsData2b;
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;
};
//
@@ -203,63 +208,83 @@ public:
uint32 size;
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);
return 0;
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)
float GetLiquidHeight(adt_liquid_instance const* h, int32 pos) const
{
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
return 0;
if (h->offsData2b)
return (float *)((uint8*)this + 8 + h->offsData2b);
return 0;
}
if (!h->OffsetVertexData)
return 0.0f;
uint8 *getLiquidLightMap(adt_liquid_header *h)
{
if (h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT)
return 0;
if (h->offsData2b)
switch (h->LiquidVertexFormat)
{
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);
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->Width + 1) * (h->Height + 1) * 4))[pos];
case LiquidVertexFormatType::HeightTextureCoord:
return 0;
case LiquidVertexFormatType::Depth:
return ((int8 const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
default:
break;
}
return 0;
}
uint32 *getLiquidFullLightMap(adt_liquid_header *h)
uint16 const* GetLiquidTextureCoordMap(adt_liquid_instance const* h, int32 pos) const
{
if (!(h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT))
return 0;
if (h->offsData2b)
if (!h->OffsetVertexData)
return nullptr;
switch (h->LiquidVertexFormat)
{
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);
case LiquidVertexFormatType::HeightDepth:
case LiquidVertexFormatType::Depth:
return nullptr;
case LiquidVertexFormatType::HeightTextureCoord:
return (uint16 const*)((uint8 const*)this + 8 + h->OffsetVertexData + 4 * ((h->Width + 1) * (h->Height + 1) + pos));
default:
break;
}
return 0;
return nullptr;
}
uint64 getLiquidShowMap(adt_liquid_header *h)
uint64 GetLiquidExistsBitmap(adt_liquid_instance const* h) const
{
if (h->offsData2a)
return *((uint64 *)((uint8*)this + 8 + h->offsData2a));
if (h->OffsetExistsBitmap)
return *((uint64 *)((uint8*)this + 8 + h->OffsetExistsBitmap));
else
return 0xFFFFFFFFFFFFFFFFuLL;
}
};
//