diff options
author | Shauren <shauren.trinity@gmail.com> | 2018-04-21 16:57:41 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2019-02-23 22:00:05 +0100 |
commit | 8d19fcbc469e0b37a323c876a15097fbe848d884 (patch) | |
tree | a87fe928d6754ea667ec3f1ff055a0870b1d1baa | |
parent | 0e083a035646942a2d10b79b77f47f950b755a2c (diff) |
Tools/vmapextractor: Improved vmap detail level by extracting wmo doodads (tables, chairs etc)
(cherry picked from commit fb0a1de5c1b96268ab4b4b383973699c81810724)
-rw-r--r-- | src/tools/vmap4_extractor/adtfile.cpp | 24 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/adtfile.h | 2 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/gameobject_extract.cpp | 16 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/model.cpp | 109 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/model.h | 7 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vec3d.h | 5 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vmapexport.cpp | 35 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vmapexport.h | 7 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wdtfile.cpp | 1 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wmo.cpp | 55 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wmo.h | 37 |
11 files changed, 244 insertions, 54 deletions
diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index 588cfb5dc78..8cd31d1442b 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -21,10 +21,7 @@ #include "StringFormat.h" #include <algorithm> #include <cstdio> - -#ifdef WIN32 -#define snprintf _snprintf -#endif +#include "Errors.h" char const* GetPlainName(char const* FileName) { @@ -46,7 +43,10 @@ char* GetPlainName(char* FileName) void fixnamen(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 (i > 0 && name[i] >= 'A' && name[i] <= 'Z' && isalpha(name[i-1])) name[i] |= 0x20; @@ -60,11 +60,12 @@ void fixnamen(char* name, size_t len) void fixname2(char* name, size_t len) { - for (size_t i=0; i<len-3; i++) - { - if(name[i] == ' ') + if (len < 3) + return; + + for (size_t i = 0; i < len - 3; i++) + if (name[i] == ' ') name[i] = '_'; - } } char* GetExtension(char* FileName) @@ -123,7 +124,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) char* s = GetPlainName(p); fixname2(s, strlen(s)); - ModelInstanceNames.push_back(s); + ModelInstanceNames.emplace_back(s); std::string path(p); ExtractSingleModel(path); @@ -147,7 +148,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) char* s = GetPlainName(p); fixnamen(s, strlen(s)); fixname2(s, strlen(s)); - WmoInstanceNames.push_back(s); + WmoInstanceNames.emplace_back(s); ExtractSingleWmo(path); @@ -180,6 +181,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) ADT::MODF mapObjDef; _file.read(&mapObjDef, sizeof(ADT::MODF)); MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), map_num, tileX, tileY, dirfile); + Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, map_num, tileX, tileY, dirfile); } } } diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index 7a421cafeae..01de1fcad30 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -44,7 +44,7 @@ namespace ADT Vec3D Rotation; AaBox3D Bounds; uint16 Flags; - uint16 DoodadSet; + uint16 DoodadSet; // can be larger than number of doodad sets in WMO uint16 NameSet; uint16 Scale; }; diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index 253d70880e9..2d3425afe64 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -26,11 +26,11 @@ bool ExtractSingleModel(std::string& fname) { - char * name = GetPlainName((char*)fname.c_str()); - char * ext = GetExtension(name); + if (fname.length() < 4) + return false; - // < 3.1.0 ADT MMDX section store filename.mdx filenames for corresponded .m2 file - if (!strcmp(ext, ".mdx")) + std::string extension = fname.substr(fname.length() - 4, 4); + if (extension == ".mdx" || extension == ".MDX" || extension == ".mdl" || extension == ".MDL") { // replace .mdx -> .m2 fname.erase(fname.length()-2,2); @@ -39,6 +39,12 @@ bool ExtractSingleModel(std::string& fname) // >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file // nothing do + std::string originalName = fname; + + char* name = GetPlainName((char*)fname.c_str()); + fixnamen(name, strlen(name)); + fixname2(name, strlen(name)); + std::string output(szWorkDirWmo); output += "/"; output += name; @@ -46,7 +52,7 @@ bool ExtractSingleModel(std::string& fname) if (FileExists(output.c_str())) return true; - Model mdl(fname); + Model mdl(originalName); if (!mdl.open()) return false; diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 1d20441bbca..2ed71ecb0e8 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -17,14 +17,16 @@ */ #include "vmapexport.h" +#include "Errors.h" #include "model.h" #include "wmo.h" #include "adtfile.h" #include "mpq_libmpq04.h" #include "VMapDefinitions.h" -#include <cassert> +#include <G3D/Quat.h> #include <algorithm> #include <cstdio> +#include <limits> Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0) { @@ -134,21 +136,13 @@ bool Model::ConvertToVMAPModel(const char * outfilename) } -Vec3D fixCoordSystem(Vec3D v) +Vec3D fixCoordSystem(Vec3D const& v) { return Vec3D(v.x, v.z, -v.y); } -Vec3D fixCoordSystem2(Vec3D v) -{ - return Vec3D(v.x, v.z, v.y); -} - void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile) { - // scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float? - float sc = doodadDef.Scale / 1024.0f; - char tempname[512]; sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName); FILE* input = fopen(tempname, "r+b"); @@ -164,20 +158,24 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint if (count != 1 || nVertices == 0) return; + // scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float? + float sc = doodadDef.Scale / 1024.0f; + Vec3D position = fixCoords(doodadDef.Position); uint16 nameSet = 0;// not used for models - uint32 flags = MOD_M2; + uint32 uniqueId = GenerateUniqueObjectId(doodadDef.UniqueId, 0); + uint32 tcflags = MOD_M2; if (tileX == 65 && tileY == 65) - flags |= MOD_WORLDSPAWN; + tcflags |= MOD_WORLDSPAWN; //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); fwrite(&tileX, sizeof(uint32), 1, pDirfile); fwrite(&tileY, sizeof(uint32), 1, pDirfile); - fwrite(&flags, sizeof(uint32), 1, pDirfile); + fwrite(&tcflags, sizeof(uint32), 1, pDirfile); fwrite(&nameSet, sizeof(uint16), 1, pDirfile); - fwrite(&doodadDef.UniqueId, sizeof(uint32), 1, pDirfile); + fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); fwrite(&position, sizeof(Vec3D), 1, pDirfile); fwrite(&doodadDef.Rotation, sizeof(Vec3D), 1, pDirfile); fwrite(&sc, sizeof(float), 1, pDirfile); @@ -185,3 +183,86 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(ModelInstName, sizeof(char), nlen, pDirfile); } + +void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile) +{ + if (wmo.DoodadSet >= doodadData.Sets.size()) + return; + + G3D::Vector3 wmoPosition(wmo.Position.z, wmo.Position.x, wmo.Position.y); + G3D::Matrix3 wmoRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::toRadians(wmo.Rotation.y), G3D::toRadians(wmo.Rotation.x), G3D::toRadians(wmo.Rotation.z)); + + uint16 doodadId = 0; + WMO::MODS const& doodadSetData = doodadData.Sets[wmo.DoodadSet]; + for (uint16 doodadIndex : doodadData.References) + { + if (doodadIndex < doodadSetData.StartIndex || + doodadIndex >= doodadSetData.StartIndex + doodadSetData.Count) + continue; + + WMO::MODD const& doodad = doodadData.Spawns[doodadIndex]; + + char ModelInstName[1024]; + sprintf(ModelInstName, "%s", GetPlainName(&doodadData.Paths[doodad.NameIndex])); + uint32 nlen = strlen(ModelInstName); + fixnamen(ModelInstName, nlen); + fixname2(ModelInstName, nlen); + if (nlen > 3) + { + char const* extension = &ModelInstName[nlen - 4]; + if (!strcmp(extension, ".mdx") || !strcmp(extension, ".mdl")) + { + ModelInstName[nlen - 2] = '2'; + ModelInstName[nlen - 1] = '\0'; + } + } + + char tempname[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; + + //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); + } +} + diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index 0bfdecbd6e9..b851b80c8fa 100644 --- a/src/tools/vmap4_extractor/model.h +++ b/src/tools/vmap4_extractor/model.h @@ -25,9 +25,10 @@ #include <vector> class MPQFile; -namespace ADT { struct MDDF; } +struct WMODoodadData; +namespace ADT { struct MDDF; struct MODF; } -Vec3D fixCoordSystem(Vec3D v); +Vec3D fixCoordSystem(Vec3D const& v); class Model { @@ -55,6 +56,8 @@ public: namespace Doodad { void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile); + + void ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile); } #endif diff --git a/src/tools/vmap4_extractor/vec3d.h b/src/tools/vmap4_extractor/vec3d.h index 04fe0f7d218..41978398976 100644 --- a/src/tools/vmap4_extractor/vec3d.h +++ b/src/tools/vmap4_extractor/vec3d.h @@ -253,4 +253,9 @@ inline void rotate(float x0, float y0, float* x, float* y, float angle) *y = xa*sinf(angle) + ya*cosf(angle) + y0; } +struct Quaternion +{ + float X, Y, Z, W; +}; + #endif diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index aacae392ab9..34730d05a1b 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -32,6 +32,7 @@ #include <cstdio> #include <iostream> +#include <map> #include <vector> #include <errno.h> @@ -59,12 +60,19 @@ char output_path[128]="."; char input_path[1024]="."; bool hasInputPathParam = false; bool preciseVectorData = false; +std::unordered_map<std::string, WMODoodadData> WmoDoodads; // Constants -//static const char * szWorkDirMaps = ".\\Maps"; char const* szWorkDirWmo = "./Buildings"; +std::map<std::pair<uint32, uint16>, uint32> uniqueObjectIds; + +uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId) +{ + return uniqueObjectIds.emplace(std::make_pair(clientId, clientDoodadId), uniqueObjectIds.size() + 1).first->second; +} + // Local testing functions bool FileExists(char const* file) @@ -89,11 +97,13 @@ void strToLower(char* str) bool ExtractSingleWmo(std::string& fname) { // Copy files from archive + std::string originalName = fname; char szLocalFile[1024]; - const char * plain_name = GetPlainName(fname.c_str()); + char* plain_name = GetPlainName(&fname[0]); + fixnamen(plain_name, strlen(plain_name)); + fixname2(plain_name, strlen(plain_name)); sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name); - fixnamen(szLocalFile,strlen(szLocalFile)); if (FileExists(szLocalFile)) return true; @@ -117,9 +127,9 @@ bool ExtractSingleWmo(std::string& fname) return true; bool file_ok = true; - printf("Extracting %s\n", fname.c_str()); - WMORoot froot(fname); - if(!froot.open()) + printf("Extracting %s\n", originalName.c_str()); + WMORoot froot(originalName); + if (!froot.open()) { printf("Couldn't open RootWmo!!!\n"); return true; @@ -131,6 +141,8 @@ bool ExtractSingleWmo(std::string& fname) return false; } froot.ConvertToVMAPRootWmo(output); + WMODoodadData& doodads = WmoDoodads[plain_name]; + std::swap(doodads, froot.DoodadData); int Wmo_nVertices = 0; //printf("root has %d groups\n", froot->nGroups); if (froot.nGroups !=0) @@ -154,6 +166,17 @@ bool ExtractSingleWmo(std::string& fname) } 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); + } } } diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index c46f9ceb971..deb7f47dedf 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -19,7 +19,9 @@ #ifndef VMAPEXPORT_H #define VMAPEXPORT_H +#include "Define.h" #include <string> +#include <unordered_map> enum ModelFlags { @@ -28,7 +30,12 @@ enum ModelFlags MOD_HAS_BOUND = 1<<2 }; +struct WMODoodadData; + extern const char * szWorkDirWmo; +extern std::unordered_map<std::string, WMODoodadData> WmoDoodads; + +uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId); bool FileExists(const char * file); void strToLower(char* str); diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index faa66ca1031..4bcfa1941cb 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -104,6 +104,7 @@ bool WDTFile::init(uint32 mapId) ADT::MODF mapObjDef; _file.read(&mapObjDef, sizeof(ADT::MODF)); MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), mapId, 65, 65, dirfile); + Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, mapId, 65, 65, dirfile); } } } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index bc50bb117b9..7fda8c57b16 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -18,18 +18,20 @@ #include "vmapexport.h" #include "adtfile.h" -#include "wmo.h" #include "vec3d.h" #include "mpq_libmpq04.h" #include "VMapDefinitions.h" +#include "wmo.h" +#include <fstream> +#include <map> #include <cstdio> #include <cstdlib> #include <cassert> #undef min #undef max -WMORoot::WMORoot(std::string &filename) +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), flags(0) { @@ -73,31 +75,52 @@ bool WMORoot::open() f.read(bbcorn1, 12); f.read(bbcorn2, 12); f.read(&flags, 4); - break; } - /* - else if (!strcmp(fourcc,"MOTX")) + else if (!strcmp(fourcc, "MODS")) { + DoodadData.Sets.resize(size / sizeof(WMO::MODS)); + f.read(DoodadData.Sets.data(), size); } - else if (!strcmp(fourcc,"MOMT")) + else if (!strcmp(fourcc,"MODN")) { + char* ptr = f.getPointer(); + char* end = ptr + size; + DoodadData.Paths = std::make_unique<char[]>(size); + memcpy(DoodadData.Paths.get(), ptr, size); + while (ptr < end) + { + std::string path = ptr; + + char* s = GetPlainName(ptr); + fixnamen(s, strlen(s)); + fixname2(s, strlen(s)); + + uint32 doodadNameIndex = ptr - f.getPointer(); + ptr += path.length() + 1; + + if (ExtractSingleModel(path)) + ValidDoodadNames.insert(doodadNameIndex); + } } - else if (!strcmp(fourcc,"MOGN")) + else if (!strcmp(fourcc,"MODD")) { + DoodadData.Spawns.resize(size / sizeof(WMO::MODD)); + f.read(DoodadData.Spawns.data(), size); } - else if (!strcmp(fourcc,"MOGI")) + /* + else if (!strcmp(fourcc,"MOTX")) { } - else if (!strcmp(fourcc,"MOLT")) + else if (!strcmp(fourcc,"MOMT")) { } - else if (!strcmp(fourcc,"MODN")) + else if (!strcmp(fourcc,"MOGN")) { } - else if (!strcmp(fourcc,"MODS")) + else if (!strcmp(fourcc,"MOGI")) { } - else if (!strcmp(fourcc,"MODD")) + else if (!strcmp(fourcc,"MOLT")) { } else if (!strcmp(fourcc,"MOSB")) @@ -226,6 +249,11 @@ bool WMOGroup::open(WMORoot* rootWMO) moba_size = size/2; f.read(MOBA, size); } + else if (!strcmp(fourcc,"MODR")) + { + DoodadReferences.resize(size / sizeof(uint16)); + f.read(DoodadReferences.data(), size); + } else if (!strcmp(fourcc,"MLIQ")) { liquflags |= 1; @@ -526,6 +554,7 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin bounds.max = fixCoords(mapObjDef.Bounds.max); float scale = 1.0f; + uint32 uniqueId = GenerateUniqueObjectId(mapObjDef.UniqueId, 0); uint32 flags = MOD_HAS_BOUND; if (tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name @@ -534,7 +563,7 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin fwrite(&tileY, sizeof(uint32), 1, pDirfile); fwrite(&flags, sizeof(uint32), 1, pDirfile); fwrite(&mapObjDef.NameSet, sizeof(uint16), 1, pDirfile); - fwrite(&mapObjDef.UniqueId, sizeof(uint32), 1, pDirfile); + fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); fwrite(&position, sizeof(Vec3D), 1, pDirfile); fwrite(&mapObjDef.Rotation, sizeof(Vec3D), 1, pDirfile); fwrite(&scale, sizeof(float), 1, pDirfile); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index ee02e97e869..5341daf6dcb 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -20,7 +20,7 @@ #define WMO_H #include <string> -#include <set> +#include <unordered_set> #include <vector> #include "vec3d.h" #include "loadlib/loadlib.h" @@ -43,9 +43,37 @@ class WMOManager; class MPQFile; namespace ADT { struct MODF; } +namespace WMO +{ + struct MODS + { + char Name[20]; + uint32 StartIndex; // index of first doodad instance in this set + uint32 Count; // number of doodad instances in this set + char _pad[4]; + }; + + struct MODD + { + uint32 NameIndex : 24; + Vec3D Position; + Quaternion Rotation; + float Scale; + uint32 Color; + }; +} + /* for whatever reason a certain company just can't stick to one coordinate system... */ static inline Vec3D fixCoords(Vec3D const& v){ return Vec3D(v.z, v.x, v.y); } +struct WMODoodadData +{ + std::vector<WMO::MODS> Sets; + std::unique_ptr<char[]> Paths; + std::vector<WMO::MODD> Spawns; + std::unordered_set<uint16> References; +}; + class WMORoot { private: @@ -56,7 +84,10 @@ public: float bbcorn1[3]; float bbcorn2[3]; - WMORoot(std::string& filename); + WMODoodadData DoodadData; + std::unordered_set<uint32> ValidDoodadNames; + + WMORoot(std::string const& filename); bool open(); bool ConvertToVMAPRootWmo(FILE* output); @@ -114,6 +145,8 @@ public: int nTriangles; // number when loaded uint32 liquflags; + std::vector<uint16> DoodadReferences; + WMOGroup(std::string const& filename); ~WMOGroup(); |