diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/map_extractor/System.cpp | 113 | ||||
-rw-r--r-- | src/tools/map_extractor/adt.h | 137 | ||||
-rw-r--r-- | src/tools/mmaps_generator/TerrainBuilder.cpp | 122 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/adtfile.h | 86 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vmapexport.cpp | 2 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vmapexport.h | 4 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wmo.cpp | 125 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wmo.h | 12 |
8 files changed, 288 insertions, 313 deletions
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 62ac294ace..6e62cfa15c 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -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 < liqTypeCount; ++x) - LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); + for (uint32 x = 0; x < dbc.getRecordCount(); ++x) + { + LiquidTypeEntry& liquidType = LiquidTypes[dbc.getRecord(x).getUInt(0)]; + liquidType.SoundBank = 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 ) diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h index e6f94a8825..01917e66f9 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -177,21 +177,36 @@ 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 +struct adt_liquid_instance { - uint16 liquidType; // Index from LiquidType.dbc - uint16 formatFlags; - float heightLevel1; - float heightLevel2; - uint8 xOffset; - uint8 yOffset; - uint8 width; - uint8 height; - uint32 offsData2a; - uint32 offsData2b; + 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; + if (liquid[x][y].used) + { + if (liquid[x][y].OffsetAttributes) + return *((adt_liquid_attributes *)((uint8*)this + 8 + liquid[x][y].OffsetAttributes)); + return { 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF }; + } + return { 0, 0 }; } - uint8* getLiquidLightMap(adt_liquid_header* h) + uint16 GetLiquidType(adt_liquid_instance const* h) const { - if (h->formatFlags & ADT_LIQUID_HEADER_FULL_LIGHT) - return nullptr; - if (h->offsData2b) + 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) { - 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 nullptr; + + 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; } - 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)) + if (!h->OffsetVertexData) return nullptr; - if (h->offsData2b) + + 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->GetWidth() + 1) * (h->GetHeight() + 1) + pos)); + default: + break; } 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; } diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index fa0581f98c..04e4ac76cd 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -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; + 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; + float coord[3]; + int row, col; - // generate coordinates - if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) + // 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; + 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++; + 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++; } - 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; diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index ce6182cc28..f91a215dd8 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -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; }; diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 1b334d432a..38ae3b9355 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -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; diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index 096f84b7f9..4f51ae165f 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -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 diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 885a8f4bdf..a7b94a24f2 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -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" - 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 LIQU_totalSize = sizeof(uint32); + if (liquflags & 1) { - 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; - } + LIQU_totalSize += sizeof(WMOLiquidHeader); + LIQU_totalSize += LiquEx_size / sizeof(WMOLiquidVert) * sizeof(float); + LIQU_totalSize += hlq->xtiles * hlq->ytiles; } - hlq->type = liquidEntry; + int LIQU_h[] = { 0x5551494C, LIQU_totalSize };// "LIQU" + fwrite(LIQU_h, 4, 2, output); /* 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; diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index c7437247eb..d87edf3c83 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -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 |