diff --git a/bin/stuffextract_svn.exe b/bin/stuffextract_svn.exe index b74b765..ba6e709 100644 Binary files a/bin/stuffextract_svn.exe and b/bin/stuffextract_svn.exe differ diff --git a/src/Client/GUI/CM2MeshFileLoader.cpp b/src/Client/GUI/CM2MeshFileLoader.cpp index cee3335..64ec6b7 100644 --- a/src/Client/GUI/CM2MeshFileLoader.cpp +++ b/src/Client/GUI/CM2MeshFileLoader.cpp @@ -214,7 +214,7 @@ for(u32 i=0;idrop(); + Mesh->drop(); // crash on vc9 Mesh=new SMesh(); diff --git a/src/Client/GUI/CM2MeshFileLoader.h b/src/Client/GUI/CM2MeshFileLoader.h index a856aa0..615869b 100644 --- a/src/Client/GUI/CM2MeshFileLoader.h +++ b/src/Client/GUI/CM2MeshFileLoader.h @@ -2,34 +2,13 @@ #include "irrlicht/IMeshLoader.h" #include #include +#include namespace irr { namespace scene { -class CM2MeshFileLoader : public IMeshLoader -{ -public: - - //! Constructor - CM2MeshFileLoader(IrrlichtDevice* device, c8* basedir); - - //! destructor - virtual ~CM2MeshFileLoader(); - - //! returns true if the file maybe is able to be loaded by this class - //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName)const; - - //! creates/loads an animated mesh from the file. - //! \return Pointer to the created mesh. Returns 0 if loading failed. - //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). - //! See IUnknown::drop() for more information. - virtual scene::IAnimatedMesh* createMesh(irr::io::IReadFile* file); -private: - - struct ModelHeader { c8 id[4]; u8 version[4]; @@ -111,8 +90,37 @@ struct ModelHeader { u32 nParticleEmitters; // V u32 ofsParticleEmitters; -} header; +}; +struct TextureDefinition { + u32 texType; + u16 unk; + u16 texFlags; + u32 texFileLen; + u32 texFileOfs; +}; + +class CM2MeshFileLoader : public IMeshLoader +{ +public: + + //! Constructor + CM2MeshFileLoader(IrrlichtDevice* device, c8* basedir); + + //! destructor + virtual ~CM2MeshFileLoader(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".cob") + virtual bool isALoadableFileExtension(const c8* fileName)const; + + //! creates/loads an animated mesh from the file. + //! \return Pointer to the created mesh. Returns 0 if loading failed. + //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). + //! See IUnknown::drop() for more information. + virtual scene::IAnimatedMesh* createMesh(irr::io::IReadFile* file); +private: + ModelHeader header; struct ModelVertex { core::vector3df pos;//Use Irrlicht Vector here! @@ -143,14 +151,6 @@ struct ModelViewSubmesh { float unkf[4]; }; -struct TextureDefinition { - u32 texType; - u16 unk; - u16 texFlags; - u32 texFileLen; - u32 texFileOfs; -}; - struct TextureUnit{ u16 Flags; s16 renderOrder; diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index ca7d81f..a41b6a8 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -121,7 +121,7 @@ void PseuGUI::_Init(void) //... // register external loaders for not supported filetypes - scene::CM2MeshFileLoader* m2loader = new scene::CM2MeshFileLoader(_device); + scene::CM2MeshFileLoader* m2loader = new scene::CM2MeshFileLoader(_device, "data"); _smgr->addExternalMeshLoader(m2loader); _initialized = true; diff --git a/src/tools/stuffextract/StuffExtract.cpp b/src/tools/stuffextract/StuffExtract.cpp index 9b49d75..6a154ee 100644 --- a/src/tools/stuffextract/StuffExtract.cpp +++ b/src/tools/stuffextract/StuffExtract.cpp @@ -12,7 +12,9 @@ #include "DBCFieldData.h" #include "Locale.h" #include "ProgressBar.h" +#include "../../Client/Gui/CM2MeshFileLoader.h" +int replaceSpaces (int i) { return i==(int)' ' ? (int)'_' : i; } std::map mapNames; @@ -637,47 +639,6 @@ void ExtractMapDependencies(void) CreateDir(pathwmo.c_str()); uint32 wmosdone=0,texdone=0,mdone=0; - if(doTextures) - { - printf("Extracting textures...\n"); - bar = new barGoLink(texNames.size(), true); - for(std::set::iterator i = texNames.begin(); i != texNames.end(); i++) - { - bar->step(); - mpqfn = i->name; - altfn = i->alt; - if(altfn.empty()) - altfn = mpqfn; - if(!mpqtex.FileExists((char*)mpqfn.c_str())) - continue; - realfn = pathtex + "/" + _PathToFileName(altfn); - std::fstream fh; - fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary); - if(fh.is_open()) - { - ByteBuffer& bb = mpqtex.ExtractFile((char*)mpqfn.c_str()); - fh.write((const char*)bb.contents(),bb.size()); - if(doMd5) - { - MD5Hash h; - h.Update((uint8*)bb.contents(), bb.size()); - h.Finalize(); - uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH]; - md5Tex[_PathToFileName(realfn)] = md5ptr; - memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH); - } - texdone++; - } - else - printf("Could not write texture %s\n",realfn.c_str()); - fh.close(); - } - printf("\n"); - if(texNames.size()) - OutMD5((char*)pathtex.c_str(),md5Tex); - delete bar; - } - if(doModels) { printf("Extracting models...\n"); @@ -712,6 +673,9 @@ void ExtractMapDependencies(void) { ByteBuffer& bb = mpqmodel.ExtractFile((char*)mpqfn.c_str()); fh.write((const char*)bb.contents(),bb.size()); + if (doTextures) + FetchTexturesFromModel(bb); + if(doMd5) { MD5Hash h; @@ -733,9 +697,69 @@ void ExtractMapDependencies(void) delete bar; } - if(doWmos) + if(doTextures) { printf("Extracting textures...\n"); + bar = new barGoLink(texNames.size(), true); + for(std::set::iterator i = texNames.begin(); i != texNames.end(); i++) + { + bar->step(); + mpqfn = i->name; + altfn = i->alt; + if(altfn.empty()) + altfn = mpqfn; + if(!mpqtex.FileExists((char*)mpqfn.c_str())) + continue; + + // prepare lowercased and "underlined" path for file + std::string copy = mpqfn; + std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower); + std::transform(copy.begin(), copy.end(), copy.begin(), replaceSpaces); + if (copy.find_first_of("/\\") != std::string::npos) + { + std::string copy2 = copy; + char* tok = strtok((char*)copy2.c_str(),"/\\"); + std::string fullpath = pathtex; + while (tok && !strstr(tok, ".")) + { + fullpath += "/"; + fullpath += tok; + CreateDir(fullpath.c_str()); + tok = strtok(NULL, "/\\"); + } + } + + realfn = pathtex + "/" + copy; //_PathToFileName(altfn); + std::fstream fh; + fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary); + if(fh.is_open()) + { + ByteBuffer& bb = mpqtex.ExtractFile((char*)mpqfn.c_str()); + fh.write((const char*)bb.contents(),bb.size()); + if(doMd5) + { + MD5Hash h; + h.Update((uint8*)bb.contents(), bb.size()); + h.Finalize(); + uint8 *md5ptr = new uint8[MD5_DIGEST_LENGTH]; + md5Tex[_PathToFileName(realfn)] = md5ptr; + memcpy(md5ptr, h.GetDigest(), MD5_DIGEST_LENGTH); + } + texdone++; + } + else + printf("Could not write texture %s\n",realfn.c_str()); + fh.close(); + } + printf("\n"); + if(texNames.size()) + OutMD5((char*)pathtex.c_str(),md5Tex); + delete bar; + } + + if(doWmos) + { + printf("Extracting WMOS...\n"); bar = new barGoLink(wmoNames.size(),true); for(std::set::iterator i = wmoNames.begin(); i != wmoNames.end(); i++) { @@ -866,4 +890,39 @@ void ADT_FillModelData(const uint8* data,std::set& st) ADT_ExportStringSetByOffset(data,OFFSET_MODELS,st,"DIMM"); } +void FetchTexturesFromModel(ByteBuffer& bb) +{ + bb.rpos(0); + irr::scene::ModelHeader header; + bb.read((uint8*)&header, sizeof(header)); + if (header.version[0] != 4 && header.version[1] != 1 && header.version[2] != 0 && header.version[3] != 0) { + printf("Not model file!"); + return; + } + + irr::core::array M2MTextureDef; + M2MTextureDef.clear(); + irr::scene::TextureDefinition tempM2TexDef; + + bb.rpos(header.ofsTextures); + for(irr::u32 i=0;i&, char*); void ADT_FillTextureData(const uint8*,std::set&);