diff options
| author | Ka0z <misaeleim@hotmail.cl> | 2012-02-10 18:40:05 -0300 |
|---|---|---|
| committer | Ka0z <misaeleim@hotmail.cl> | 2012-02-10 18:40:05 -0300 |
| commit | 6627fe72039153b00bb87775867e09453f2b24e6 (patch) | |
| tree | c9c7c70c2f021392b6761e15ad6b5a3c7d7d7074 /src/tools/vmap4_extractor | |
| parent | 8c2526e7d0f8cd516e0a3d3ebd6e554774c76c7b (diff) | |
Core/Collision: Edit source files to represent the recent changes in the extractors (v4.00 2012_02) to avoid confusion with old extractors (v3.00 2010_07)
Diffstat (limited to 'src/tools/vmap4_extractor')
| -rw-r--r-- | src/tools/vmap4_extractor/CMakeLists.txt | 48 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/adtfile.cpp | 219 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/adtfile.h | 143 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/dbcfile.cpp | 95 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/dbcfile.h | 155 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/gameobject_extract.cpp | 99 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/loadlib/loadlib.h | 77 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/model.cpp | 199 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/model.h | 78 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/modelheaders.h | 99 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/mpq_libmpq.cpp | 111 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/mpq_libmpq04.h | 91 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/vec3d.h | 230 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/vmapexport.cpp | 552 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/vmapexport.h | 42 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/wdtfile.cpp | 134 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/wdtfile.h | 29 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/wmo.cpp | 523 | ||||
| -rw-r--r-- | src/tools/vmap4_extractor/wmo.h | 136 |
19 files changed, 3060 insertions, 0 deletions
diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt new file mode 100644 index 00000000000..1c44b01bbec --- /dev/null +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2005-2009 MaNGOS project <http://getmangos.com/> +# Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +file(GLOB_RECURSE sources *.cpp *.h) + +# uncomment next line to disable debug mode +add_definitions("-DIOMAP_DEBUG") + +# build setup currently only supports libmpq 0.4.x +add_definitions("-DUSE_LIBMPQ04") +add_definitions("-Wall") +add_definitions("-ggdb") +add_definitions("-O3") + +if( UNIX ) + include_directories( + ${CMAKE_SOURCE_DIR}/dep/libmpq + ) +elseif( WIN32 ) + include_directories( + ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/libmpq/win + ) +endif() + +add_executable(vmap4extractor ${sources}) + +target_link_libraries(vmap4extractor + ${BZIP2_LIBRARIES} + ${ZLIB_LIBRARIES} + mpq +) + +add_dependencies(vmap4extractor mpq) + +if( UNIX ) + install(TARGETS vmap4extractor DESTINATION bin) +elseif( WIN32 ) + install(TARGETS vmap4extractor DESTINATION "${CMAKE_INSTALL_PREFIX}") +endif() diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp new file mode 100644 index 00000000000..a966172a3be --- /dev/null +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vmapexport.h" +#include "adtfile.h" + +#include <algorithm> +#include <cstdio> + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +const char * GetPlainName(const char * FileName) +{ + const char * szTemp; + + if((szTemp = strrchr(FileName, '\\')) != NULL) + FileName = szTemp + 1; + return FileName; +} + +char * GetPlainName(char * FileName) +{ + char * szTemp; + + if((szTemp = strrchr(FileName, '\\')) != NULL) + FileName = szTemp + 1; + return FileName; +} + +void fixnamen(char *name, size_t len) +{ + 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; + } else if ((i==0 || !isalpha(name[i-1])) && name[i]>='a' && name[i]<='z') + { + name[i] &= ~0x20; + } + } + //extension in lowercase + for(size_t i=len-3; i<len; i++) + name[i] |= 0x20; +} + +void fixname2(char *name, size_t len) +{ + for (size_t i=0; i<len-3; i++) + { + if(name[i] == ' ') + name[i] = '_'; + } +} + +char * GetExtension(char * FileName) +{ + char * szTemp; + if((szTemp = strrchr(FileName, '.')) != NULL) + return szTemp; + return NULL; +} + +ADTFile::ADTFile(char* filename): ADT(filename) +{ + Adtfilename.append(filename); +} + +bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) +{ + if(ADT.isEof ()) + return false; + + uint32 size; + + string xMap; + string yMap; + + Adtfilename.erase(Adtfilename.find(".adt"),4); + string TempMapNumber; + TempMapNumber = Adtfilename.substr(Adtfilename.length()-6,6); + xMap = TempMapNumber.substr(TempMapNumber.find("_")+1,(TempMapNumber.find_last_of("_")-1) - (TempMapNumber.find("_"))); + yMap = TempMapNumber.substr(TempMapNumber.find_last_of("_")+1,(TempMapNumber.length()) - (TempMapNumber.find_last_of("_"))); + Adtfilename.erase((Adtfilename.length()-xMap.length()-yMap.length()-2), (xMap.length()+yMap.length()+2)); + string AdtMapNumber = xMap + ' ' + yMap + ' ' + GetPlainName((char*)Adtfilename.c_str()); + //printf("Processing map %s...\n", AdtMapNumber.c_str()); + //printf("MapNumber = %s\n", TempMapNumber.c_str()); + //printf("xMap = %s\n", xMap.c_str()); + //printf("yMap = %s\n", yMap.c_str()); + + std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; + FILE *dirfile; + dirfile = fopen(dirname.c_str(), "ab"); + if(!dirfile) + { + printf("Can't open dirfile!'%s'\n", dirname.c_str()); + return false; + } + + while (!ADT.isEof()) + { + char fourcc[5]; + ADT.read(&fourcc,4); + ADT.read(&size, 4); + flipcc(fourcc); + fourcc[4] = 0; + + size_t nextpos = ADT.getPos() + size; + + if (!strcmp(fourcc,"MCIN")) + { + } + else if (!strcmp(fourcc,"MTEX")) + { + } + else if (!strcmp(fourcc,"MMDX")) + { + if (size) + { + char *buf = new char[size]; + ADT.read(buf, size); + char *p=buf; + int t=0; + ModelInstansName = new string[size]; + while (p<buf+size) + { + fixnamen(p,strlen(p)); + char* s = GetPlainName(p); + fixname2(s,strlen(s)); + + ModelInstansName[t++] = s; + + string path(p); + ExtractSingleModel(path); + + p = p+strlen(p)+1; + } + delete[] buf; + } + } + else if (!strcmp(fourcc,"MWMO")) + { + if (size) + { + char *buf = new char[size]; + ADT.read(buf, size); + char *p=buf; + int q = 0; + WmoInstansName = new string[size]; + while (p<buf+size) + { + string path(p); + char* s=GetPlainName(p); + fixnamen(s,strlen(s)); + fixname2(s,strlen(s)); + p=p+strlen(p)+1; + WmoInstansName[q++] = s; + } + delete[] buf; + } + } + //====================== + else if (!strcmp(fourcc,"MDDF")) + { + if (size) + { + nMDX = (int)size / 36; + for (int i=0; i<nMDX; ++i) + { + uint32 id; + ADT.read(&id, 4); + ModelInstance inst(ADT,ModelInstansName[id].c_str(), map_num, tileX, tileY, dirfile); + } + delete[] ModelInstansName; + } + } + else if (!strcmp(fourcc,"MODF")) + { + if (size) + { + nWMO = (int)size / 64; + for (int i=0; i<nWMO; ++i) + { + uint32 id; + ADT.read(&id, 4); + WMOInstance inst(ADT,WmoInstansName[id].c_str(), map_num, tileX, tileY, dirfile); + } + delete[] WmoInstansName; + } + } + //====================== + ADT.seek(nextpos); + } + ADT.close(); + fclose(dirfile); + return true; +} + +ADTFile::~ADTFile() +{ + ADT.close(); +} diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h new file mode 100644 index 00000000000..08814996f68 --- /dev/null +++ b/src/tools/vmap4_extractor/adtfile.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ADT_H +#define ADT_H + +#include "mpq_libmpq04.h" +#include "wmo.h" +#include "model.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; +}; + + +class ADTFile +{ +public: + ADTFile(char* filename); + ~ADTFile(); + int nWMO; + int nMDX; + string* WmoInstansName; + string* ModelInstansName; + bool init(uint32 map_num, uint32 tileX, uint32 tileY); + //void LoadMapChunks(); + + //uint32 wmo_count; +/* + const mcell& Getmcell() const + { + return Mcell; + } +*/ +private: + //size_t mcnk_offsets[256], mcnk_sizes[256]; + MPQFile ADT; + //mcell Mcell; + string Adtfilename; +}; + +const char * GetPlainName(const char * FileName); +char * GetPlainName(char * FileName); +char * GetExtension(char * FileName); +void fixnamen(char *name, size_t len); +void fixname2(char *name, size_t len); +//void fixMapNamen(char *name, size_t len); + +#endif diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp new file mode 100644 index 00000000000..2474cea5259 --- /dev/null +++ b/src/tools/vmap4_extractor/dbcfile.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "dbcfile.h" +#include "mpq_libmpq04.h" +#undef min +#undef max + +#include <cstdio> + +DBCFile::DBCFile(const std::string &filename) : filename(filename) +{ + data = NULL; +} + +bool DBCFile::open() +{ + MPQFile f(filename.c_str()); + + // Need some error checking, otherwise an unhandled exception error occurs + // if people screw with the data path. + if (f.isEof() == true) + return false; + + unsigned char header[4]; + unsigned int na,nb,es,ss; + + f.read(header,4); // File Header + + if (header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3] != 'C') + { + f.close(); + data = NULL; + printf("Critical Error: An error occured while trying to read the DBCFile %s.", filename.c_str()); + return false; + } + + //assert(header[0]=='W' && header[1]=='D' && header[2]=='B' && header[3] == 'C'); + + f.read(&na,4); // Number of records + f.read(&nb,4); // Number of fields + f.read(&es,4); // Size of a record + f.read(&ss,4); // String size + + recordSize = es; + recordCount = na; + fieldCount = nb; + stringSize = ss; + //assert(fieldCount*4 == recordSize); + assert(fieldCount*4 >= recordSize); + + data = new unsigned char[recordSize*recordCount+stringSize]; + stringTable = data + recordSize*recordCount; + f.read(data,recordSize*recordCount+stringSize); + f.close(); + return true; +} + +DBCFile::~DBCFile() +{ + delete [] data; +} + +DBCFile::Record DBCFile::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +DBCFile::Iterator DBCFile::begin() +{ + assert(data); + return Iterator(*this, data); +} + +DBCFile::Iterator DBCFile::end() +{ + assert(data); + return Iterator(*this, stringTable); +} diff --git a/src/tools/vmap4_extractor/dbcfile.h b/src/tools/vmap4_extractor/dbcfile.h new file mode 100644 index 00000000000..56cce9a521c --- /dev/null +++ b/src/tools/vmap4_extractor/dbcfile.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBCFILE_H +#define DBCFILE_H + +#include <cassert> +#include <string> + +class DBCFile +{ +public: + DBCFile(const std::string &filename); + ~DBCFile(); + + // Open database. It must be openened before it can be used. + bool open(); + + // TODO: Add a close function? + + // Database exceptions + class Exception + { + public: + Exception(const std::string &message): message(message) + { } + virtual ~Exception() + { } + const std::string &getMessage() {return message;} + private: + std::string message; + }; + + // + class NotFound: public Exception + { + public: + NotFound(): Exception("Key was not found") + { } + }; + + // Iteration over database + class Iterator; + class Record + { + public: + Record& operator= (const Record& r) + { + file = r.file; + offset = r.offset; + return *this; + } + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast<float*>(offset+field*4); + } + unsigned int getUInt(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast<unsigned int*>(offset+(field*4)); + } + int getInt(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast<int*>(offset+field*4); + } + unsigned char getByte(size_t ofs) const + { + assert(ofs < file.recordSize); + return *reinterpret_cast<unsigned char*>(offset+ofs); + } + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + //char * tmp = (char*)file.stringTable + stringOffset; + //unsigned char * tmp2 = file.stringTable + stringOffset; + return reinterpret_cast<char*>(file.stringTable + stringOffset); + } + private: + Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} + DBCFile &file; + unsigned char *offset; + + friend class DBCFile; + friend class Iterator; + }; + + /* Iterator that iterates over records */ + class Iterator + { + public: + Iterator(DBCFile &file, unsigned char *offset): + record(file, offset) {} + /// Advance (prefix only) + Iterator & operator++() { + record.offset += record.file.recordSize; + return *this; + } + /// Return address of current instance + Record const & operator*() const { return record; } + const Record* operator->() const { + return &record; + } + /// Comparison + bool operator==(const Iterator &b) const + { + return record.offset == b.record.offset; + } + bool operator!=(const Iterator &b) const + { + return record.offset != b.record.offset; + } + private: + Record record; + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + Iterator begin(); + /// Get begin iterator over records + Iterator end(); + /// Trivial + size_t getRecordCount() const { return recordCount;} + size_t getFieldCount() const { return fieldCount; } + +private: + std::string filename; + size_t recordSize; + size_t recordCount; + size_t fieldCount; + size_t stringSize; + unsigned char *data; + unsigned char *stringTable; +}; + +#endif diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp new file mode 100644 index 00000000000..8a1f67cd2c2 --- /dev/null +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -0,0 +1,99 @@ +#include "model.h" +#include "dbcfile.h" +#include "adtfile.h" +#include "vmapexport.h" + +#include <algorithm> +#include <stdio.h> + +bool ExtractSingleModel(std::string& fname) +{ + char * name = GetPlainName((char*)fname.c_str()); + char * ext = GetExtension(name); + + // < 3.1.0 ADT MMDX section store filename.mdx filenames for corresponded .m2 file + if (!strcmp(ext, ".mdx")) + { + // replace .mdx -> .m2 + fname.erase(fname.length()-2,2); + fname.append("2"); + } + // >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file + // nothing do + + std::string output(szWorkDirWmo); + output += "/"; + output += name; + + if (FileExists(output.c_str())) + return true; + + Model mdl(fname); + if (!mdl.open()) + return false; + + return mdl.ConvertToVMAPModel(output.c_str()); +} + +void ExtractGameobjectModels() +{ + printf("Extracting GameObject models..."); + DBCFile dbc("DBFilesClient\\GameObjectDisplayInfo.dbc"); + if(!dbc.open()) + { + printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n"); + exit(1); + } + + std::string basepath = szWorkDirWmo; + basepath += "/"; + std::string path; + + FILE * model_list = fopen((basepath + "temp_gameobject_models").c_str(), "wb"); + + for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it) + { + path = it->getString(1); + + if (path.length() < 4) + continue; + + fixnamen((char*)path.c_str(), path.size()); + char * name = GetPlainName((char*)path.c_str()); + fixname2(name, strlen(name)); + + char * ch_ext = GetExtension(name); + if (!ch_ext) + continue; + + strToLower(ch_ext); + + bool result = false; + if (!strcmp(ch_ext, ".wmo")) + { + result = ExtractSingleWmo(path); + } + else if (!strcmp(ch_ext, ".mdl")) + { + // TODO: extract .mdl files, if needed + continue; + } + else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2")) + { + result = ExtractSingleModel(path); + } + + if (result) + { + uint32 displayId = it->getUInt(0); + uint32 path_length = strlen(name); + fwrite(&displayId, sizeof(uint32), 1, model_list); + fwrite(&path_length, sizeof(uint32), 1, model_list); + fwrite(name, sizeof(char), path_length, model_list); + } + } + + fclose(model_list); + + printf("Done!\n"); +} diff --git a/src/tools/vmap4_extractor/loadlib/loadlib.h b/src/tools/vmap4_extractor/loadlib/loadlib.h new file mode 100644 index 00000000000..61865c4b436 --- /dev/null +++ b/src/tools/vmap4_extractor/loadlib/loadlib.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LOAD_LIB_H +#define LOAD_LIB_H + +#ifdef WIN32 +typedef __int64 int64; +typedef __int32 int32; +typedef __int16 int16; +typedef __int8 int8; +typedef unsigned __int64 uint64; +typedef unsigned __int32 uint32; +typedef unsigned __int16 uint16; +typedef unsigned __int8 uint8; +#else +#include <stdint.h> +#ifndef uint64_t +#ifdef __linux__ +#include <linux/types.h> +#endif +#endif +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; +#endif + +#define FILE_FORMAT_VERSION 18 + +// +// File version chunk +// +struct file_MVER +{ + union{ + uint32 fcc; + char fcc_txt[4]; + }; + uint32 size; + uint32 ver; +}; + +class FileLoader{ + uint8 *data; + uint32 data_size; +public: + virtual bool prepareLoadedData(); + uint8 *GetData() {return data;} + uint32 GetDataSize() {return data_size;} + + file_MVER *version; + FileLoader(); + ~FileLoader(); + bool loadFile(char *filename, bool log = true); + virtual void free(); +}; +#endif diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp new file mode 100644 index 00000000000..117c594b41a --- /dev/null +++ b/src/tools/vmap4_extractor/model.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vmapexport.h" +#include "model.h" +#include "wmo.h" +#include "mpq_libmpq04.h" +#include <cassert> +#include <algorithm> +#include <cstdio> + +Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0) +{ +} + +bool Model::open() +{ + MPQFile f(filename.c_str()); + + ok = !f.isEof(); + + if (!ok) + { + f.close(); + printf("Error loading model %s\n", filename.c_str()); + return false; + } + + _unload(); + + memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); + if(header.nBoundingTriangles > 0) + { + f.seek(0); + f.seekRelative(header.ofsBoundingVertices); + vertices = new Vec3D[header.nBoundingVertices]; + f.read(vertices,header.nBoundingVertices*12); + for (uint32 i=0; i<header.nBoundingVertices; i++) + { + vertices[i] = fixCoordSystem(vertices[i]); + } + f.seek(0); + f.seekRelative(header.ofsBoundingTriangles); + indices = new uint16[header.nBoundingTriangles]; + f.read(indices,header.nBoundingTriangles*2); + f.close(); + } + else + { + //printf("not included %s\n", filename.c_str()); + f.close(); + return false; + } + return true; +} + +bool Model::ConvertToVMAPModel(const char * outfilename) +{ + int N[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + FILE * output=fopen(outfilename,"wb"); + if(!output) + { + printf("Can't create the output file '%s'\n",outfilename); + return false; + } + fwrite(szRawVMAPMagic,8,1,output); + uint32 nVertices = 0; + nVertices = header.nBoundingVertices; + fwrite(&nVertices, sizeof(int), 1, output); + uint32 nofgroups = 1; + fwrite(&nofgroups,sizeof(uint32), 1, output); + fwrite(N,4*3,1,output);// rootwmoid, flags, groupid + fwrite(N,sizeof(float),3*2,output);//bbox, only needed for WMO currently + fwrite(N,4,1,output);// liquidflags + fwrite("GRP ",4,1,output); + uint32 branches = 1; + int wsize; + wsize = sizeof(branches) + sizeof(uint32) * branches; + fwrite(&wsize, sizeof(int), 1, output); + fwrite(&branches,sizeof(branches), 1, output); + uint32 nIndexes = 0; + nIndexes = header.nBoundingTriangles; + fwrite(&nIndexes,sizeof(uint32), 1, output); + fwrite("INDX",4, 1, output); + wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes; + fwrite(&wsize, sizeof(int), 1, output); + fwrite(&nIndexes, sizeof(uint32), 1, output); + if(nIndexes >0) + { + fwrite(indices, sizeof(unsigned short), nIndexes, output); + } + fwrite("VERT",4, 1, output); + wsize = sizeof(int) + sizeof(float) * 3 * nVertices; + fwrite(&wsize, sizeof(int), 1, output); + fwrite(&nVertices, sizeof(int), 1, output); + if(nVertices >0) + { + for(uint32 vpos=0; vpos <nVertices; ++vpos) + { + std::swap(vertices[vpos].y, vertices[vpos].z); + } + fwrite(vertices, sizeof(float)*3, nVertices, output); + } + + fclose(output); + + return true; +} + + +Vec3D fixCoordSystem(Vec3D v) +{ + return Vec3D(v.x, v.z, -v.y); +} + +Vec3D fixCoordSystem2(Vec3D v) +{ + return Vec3D(v.x, v.z, v.y); +} + +ModelInstance::ModelInstance(MPQFile &f,const char* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) +{ + float ff[3]; + f.read(&id, 4); + f.read(ff,12); + pos = fixCoords(Vec3D(ff[0],ff[1],ff[2])); + f.read(ff,12); + rot = Vec3D(ff[0],ff[1],ff[2]); + f.read(&scale,4); + // scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float? + sc = scale / 1024.0f; + + char tempname[512]; + sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName); + FILE *input; + input = fopen(tempname, "r+b"); + + if(!input) + { + //printf("ModelInstance::ModelInstance couldn't open %s\n", tempname); + return; + } + + fseek(input, 8, SEEK_SET); // get the correct no of vertices + int nVertices; + fread(&nVertices, sizeof (int), 1, input); + fclose(input); + + if(nVertices == 0) + return; + + uint16 adtId = 0;// not used for models + uint32 flags = MOD_M2; + if(tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; + //write mapID, tileX, tileY, Flags, ID, 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(&adtId, sizeof(uint16), 1, pDirfile); + fwrite(&id, sizeof(uint32), 1, pDirfile); + fwrite(&pos, sizeof(float), 3, pDirfile); + fwrite(&rot, sizeof(float), 3, pDirfile); + fwrite(&sc, sizeof(float), 1, pDirfile); + uint32 nlen=strlen(ModelInstName); + fwrite(&nlen, sizeof(uint32), 1, pDirfile); + fwrite(ModelInstName, sizeof(char), nlen, pDirfile); + + /* int realx1 = (int) ((float) pos.x / 533.333333f); + int realy1 = (int) ((float) pos.z / 533.333333f); + int realx2 = (int) ((float) pos.x / 533.333333f); + int realy2 = (int) ((float) pos.z / 533.333333f); + + fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n", + MapName, + ModelInstName, + (float) pos.x, (float) pos.y, (float) pos.z, + (float) rot.x, (float) rot.y, (float) rot.z, + sc, + nVertices, + realx1, realy1, + realx2, realy2 + ); */ +} diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h new file mode 100644 index 00000000000..a6f4e27583c --- /dev/null +++ b/src/tools/vmap4_extractor/model.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MODEL_H +#define MODEL_H + +#include "loadlib/loadlib.h" +#include "vec3d.h" +//#include "mpq.h" +#include "modelheaders.h" +#include <vector> + +class Model; +class WMOInstance; +class MPQFile; + +Vec3D fixCoordSystem(Vec3D v); + +class Model +{ +public: + ModelHeader header; + uint32 offsBB_vertices, offsBB_indices; + Vec3D *BB_vertices, *vertices; + uint16 *BB_indices, *indices; + size_t nIndices; + + bool open(); + bool ConvertToVMAPModel(const char * outfilename); + + bool ok; + + Model(std::string &filename); + ~Model() {_unload();} + +private: + void _unload() + { + delete[] vertices; + delete[] indices; + vertices = NULL; + indices = NULL; + } + std::string filename; + char outfilename; +}; + +class ModelInstance +{ +public: + Model *model; + + uint32 id; + Vec3D pos, rot; + unsigned int d1, scale; + float w,sc; + + ModelInstance() {} + ModelInstance(MPQFile &f,const char* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile); + +}; + +#endif diff --git a/src/tools/vmap4_extractor/modelheaders.h b/src/tools/vmap4_extractor/modelheaders.h new file mode 100644 index 00000000000..d859fd3511e --- /dev/null +++ b/src/tools/vmap4_extractor/modelheaders.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MODELHEADERS_H +#define MODELHEADERS_H + +/* typedef unsigned char uint8; +typedef char int8; +typedef unsigned short uint16; +typedef short int16; +typedef unsigned int uint32; +typedef int int32; */ + +#pragma pack(push,1) + +struct ModelHeader +{ + char id[4]; + uint8 version[4]; + uint32 nameLength; + uint32 nameOfs; + uint32 type; + uint32 nGlobalSequences; + uint32 ofsGlobalSequences; + uint32 nAnimations; + uint32 ofsAnimations; + uint32 nAnimationLookup; + uint32 ofsAnimationLookup; + uint32 nBones; + uint32 ofsBones; + uint32 nKeyBoneLookup; + uint32 ofsKeyBoneLookup; + uint32 nVertices; + uint32 ofsVertices; + uint32 nViews; + uint32 nColors; + uint32 ofsColors; + uint32 nTextures; + uint32 ofsTextures; + uint32 nTransparency; + uint32 ofsTransparency; + uint32 nTextureanimations; + uint32 ofsTextureanimations; + uint32 nTexReplace; + uint32 ofsTexReplace; + uint32 nRenderFlags; + uint32 ofsRenderFlags; + uint32 nBoneLookupTable; + uint32 ofsBoneLookupTable; + uint32 nTexLookup; + uint32 ofsTexLookup; + uint32 nTexUnits; + uint32 ofsTexUnits; + uint32 nTransLookup; + uint32 ofsTransLookup; + uint32 nTexAnimLookup; + uint32 ofsTexAnimLookup; + float floats[14]; + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + uint32 nAttachments; + uint32 ofsAttachments; + uint32 nAttachLookup; + uint32 ofsAttachLookup; + uint32 nAttachments_2; + uint32 ofsAttachments_2; + uint32 nLights; + uint32 ofsLights; + uint32 nCameras; + uint32 ofsCameras; + uint32 nCameraLookup; + uint32 ofsCameraLookup; + uint32 nRibbonEmitters; + uint32 ofsRibbonEmitters; + uint32 nParticleEmitters; + uint32 ofsParticleEmitters; +}; + +#pragma pack(pop) +#endif diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp new file mode 100644 index 00000000000..528b9679a58 --- /dev/null +++ b/src/tools/vmap4_extractor/mpq_libmpq.cpp @@ -0,0 +1,111 @@ +#include "mpq_libmpq04.h" +#include <deque> +#include <cstdio> + +ArchiveSet gOpenArchives; + +MPQArchive::MPQArchive(const char* filename) +{ + int result = libmpq__archive_open(&mpq_a, filename, -1); + printf("Opening %s\n", filename); + if(result) { + switch(result) { + case LIBMPQ_ERROR_OPEN : + printf("Error opening archive '%s': Does file really exist?\n", filename); + break; + case LIBMPQ_ERROR_FORMAT : /* bad file format */ + printf("Error opening archive '%s': Bad file format\n", filename); + break; + case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ + printf("Error opening archive '%s': Seeking in file failed\n", filename); + break; + case LIBMPQ_ERROR_READ : /* Read error in archive */ + printf("Error opening archive '%s': Read error in archive\n", filename); + break; + case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ + printf("Error opening archive '%s': Maybe not enough memory\n", filename); + break; + default: + printf("Error opening archive '%s': Unknown error\n", filename); + break; + } + return; + } + gOpenArchives.push_front(this); +} + +void MPQArchive::close() +{ + //gOpenArchives.erase(erase(&mpq_a); + libmpq__archive_close(mpq_a); +} + +MPQFile::MPQFile(const char* filename): + eof(false), + buffer(0), + pointer(0), + size(0) +{ + for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) + { + mpq_archive *mpq_a = (*i)->mpq_a; + + uint32 filenum; + if(libmpq__file_number(mpq_a, filename, &filenum)) continue; + libmpq__off_t transferred; + libmpq__file_unpacked_size(mpq_a, filenum, &size); + + // HACK: in patch.mpq some files don't want to open and give 1 for filesize + if (size<=1) { + // printf("info: file %s has size %d; considered dummy file.\n", filename, size); + eof = true; + buffer = 0; + return; + } + buffer = new char[size]; + + //libmpq_file_getdata + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ + return; + + } + eof = true; + buffer = 0; +} + +size_t MPQFile::read(void* dest, size_t bytes) +{ + if (eof) return 0; + + size_t rpos = pointer + bytes; + if (rpos > size) { + bytes = size - pointer; + eof = true; + } + + memcpy(dest, &(buffer[pointer]), bytes); + + pointer = rpos; + + return bytes; +} + +void MPQFile::seek(int offset) +{ + pointer = offset; + eof = (pointer >= size); +} + +void MPQFile::seekRelative(int offset) +{ + pointer += offset; + eof = (pointer >= size); +} + +void MPQFile::close() +{ + if (buffer) delete[] buffer; + buffer = 0; + eof = true; +} diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h new file mode 100644 index 00000000000..4b0a2465bfd --- /dev/null +++ b/src/tools/vmap4_extractor/mpq_libmpq04.h @@ -0,0 +1,91 @@ +#define _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_WARNINGS + +#ifndef MPQ_H +#define MPQ_H + +#include "loadlib/loadlib.h" +#include "libmpq/mpq.h" +#include <string.h> +#include <ctype.h> +#include <vector> +#include <iostream> +#include <deque> + +using namespace std; + +class MPQArchive +{ + +public: + mpq_archive_s *mpq_a; + + MPQArchive(const char* filename); + void close(); + + void GetFileListTo(vector<string>& filelist) { + uint32 filenum; + if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; + libmpq__off_t size, transferred; + libmpq__file_unpacked_size(mpq_a, filenum, &size); + + char *buffer = new char[size]; + + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + + char seps[] = "\n"; + char *token; + + token = strtok( buffer, seps ); + uint32 counter = 0; + while ((token != NULL) && (counter < size)) { + //cout << token << endl; + token[strlen(token) - 1] = 0; + string s = token; + filelist.push_back(s); + counter += strlen(token) + 2; + token = strtok(NULL, seps); + } + + delete[] buffer; + } +}; +typedef std::deque<MPQArchive*> ArchiveSet; + +class MPQFile +{ + //MPQHANDLE handle; + bool eof; + char *buffer; + libmpq__off_t pointer,size; + + // disable copying + MPQFile(const MPQFile &f) {} + void operator=(const MPQFile &f) {} + +public: + MPQFile(const char* filename); // filenames are not case sensitive + ~MPQFile() { close(); } + size_t read(void* dest, size_t bytes); + size_t getSize() { return size; } + size_t getPos() { return pointer; } + char* getBuffer() { return buffer; } + char* getPointer() { return buffer + pointer; } + bool isEof() { return eof; } + void seek(int offset); + void seekRelative(int offset); + void close(); +}; + +inline void flipcc(char *fcc) +{ + char t; + t=fcc[0]; + fcc[0]=fcc[3]; + fcc[3]=t; + t=fcc[1]; + fcc[1]=fcc[2]; + fcc[2]=t; +} + +#endif diff --git a/src/tools/vmap4_extractor/vec3d.h b/src/tools/vmap4_extractor/vec3d.h new file mode 100644 index 00000000000..06a5b730f16 --- /dev/null +++ b/src/tools/vmap4_extractor/vec3d.h @@ -0,0 +1,230 @@ +#ifndef VEC3D_H +#define VEC3D_H + +#include <iostream> +#include <cmath> + +class Vec3D +{ +public: + float x,y,z; + + Vec3D(float x0 = 0.0f, float y0 = 0.0f, float z0 = 0.0f) : x(x0), y(y0), z(z0) {} + + Vec3D(const Vec3D& v) : x(v.x), y(v.y), z(v.z) {} + + Vec3D& operator= (const Vec3D &v) { + x = v.x; + y = v.y; + z = v.z; + return *this; + } + + Vec3D operator+ (const Vec3D &v) const + { + Vec3D r(x+v.x,y+v.y,z+v.z); + return r; + } + + Vec3D operator- (const Vec3D &v) const + { + Vec3D r(x-v.x,y-v.y,z-v.z); + return r; + } + + float operator* (const Vec3D &v) const + { + return x*v.x + y*v.y + z*v.z; + } + + Vec3D operator* (float d) const + { + Vec3D r(x*d,y*d,z*d); + return r; + } + + friend Vec3D operator* (float d, const Vec3D& v) + { + return v * d; + } + + Vec3D operator% (const Vec3D &v) const + { + Vec3D r(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); + return r; + } + + Vec3D& operator+= (const Vec3D &v) + { + x += v.x; + y += v.y; + z += v.z; + return *this; + } + + Vec3D& operator-= (const Vec3D &v) + { + x -= v.x; + y -= v.y; + z -= v.z; + return *this; + } + + Vec3D& operator*= (float d) + { + x *= d; + y *= d; + z *= d; + return *this; + } + + float lengthSquared() const + { + return x*x+y*y+z*z; + } + + float length() const + { + return sqrt(x*x+y*y+z*z); + } + + Vec3D& normalize() + { + this->operator*= (1.0f/length()); + return *this; + } + + Vec3D operator~ () const + { + Vec3D r(*this); + r.normalize(); + return r; + } + + friend std::istream& operator>>(std::istream& in, Vec3D& v) + { + in >> v.x >> v.y >> v.z; + return in; + } + + friend std::ostream& operator<<(std::ostream& out, const Vec3D& v) + { + out << v.x << " " << v.y << " " << v.z; + return out; + } + + operator float*() + { + return (float*)this; + } +}; + + +class Vec2D +{ +public: + float x,y; + + Vec2D(float x0 = 0.0f, float y0 = 0.0f) : x(x0), y(y0) {} + + Vec2D(const Vec2D& v) : x(v.x), y(v.y) {} + + Vec2D& operator= (const Vec2D &v) { + x = v.x; + y = v.y; + return *this; + } + + Vec2D operator+ (const Vec2D &v) const + { + Vec2D r(x+v.x,y+v.y); + return r; + } + + Vec2D operator- (const Vec2D &v) const + { + Vec2D r(x-v.x,y-v.y); + return r; + } + + float operator* (const Vec2D &v) const + { + return x*v.x + y*v.y; + } + + Vec2D operator* (float d) const + { + Vec2D r(x*d,y*d); + return r; + } + + friend Vec2D operator* (float d, const Vec2D& v) + { + return v * d; + } + + Vec2D& operator+= (const Vec2D &v) + { + x += v.x; + y += v.y; + return *this; + } + + Vec2D& operator-= (const Vec2D &v) + { + x -= v.x; + y -= v.y; + return *this; + } + + Vec2D& operator*= (float d) + { + x *= d; + y *= d; + return *this; + } + + float lengthSquared() const + { + return x*x+y*y; + } + + float length() const + { + return sqrt(x*x+y*y); + } + + Vec2D& normalize() + { + this->operator*= (1.0f/length()); + return *this; + } + + Vec2D operator~ () const + { + Vec2D r(*this); + r.normalize(); + return r; + } + + + friend std::istream& operator>>(std::istream& in, Vec2D& v) + { + in >> v.x >> v.y; + return in; + } + + operator float*() + { + return (float*)this; + } +}; + +inline void rotate(float x0, float y0, float *x, float *y, float angle) +{ + float xa = *x - x0, ya = *y - y0; + *x = xa*cosf(angle) - ya*sinf(angle) + x0; + *y = xa*sinf(angle) + ya*cosf(angle) + y0; +} + +#endif diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp new file mode 100644 index 00000000000..599290a9254 --- /dev/null +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _CRT_SECURE_NO_DEPRECATE +#include <cstdio> +#include <iostream> +#include <vector> +#include <list> +#include <errno.h> + +#ifdef WIN32 + #include <Windows.h> + #include <sys/stat.h> + #include <direct.h> + #define mkdir _mkdir +#else + #include <sys/stat.h> +#endif + +#undef min +#undef max + +//#pragma warning(disable : 4505) +//#pragma comment(lib, "Winmm.lib") + +#include <map> + +//From Extractor +#include "adtfile.h" +#include "wdtfile.h" +#include "dbcfile.h" +#include "wmo.h" +#include "mpq_libmpq04.h" + +#include "vmapexport.h" + +//------------------------------------------------------------------------------ +// Defines + +#define MPQ_BLOCK_SIZE 0x1000 + +//----------------------------------------------------------------------------- + +extern ArchiveSet gOpenArchives; + +typedef struct +{ + char name[64]; + unsigned int id; +}map_id; + +map_id * map_ids; +uint16 *LiqType = 0; +uint32 map_count; +char output_path[128]="."; +char input_path[1024]="."; +bool hasInputPathParam = false; +bool preciseVectorData = false; + +// Constants + +//static const char * szWorkDirMaps = ".\\Maps"; +const char* szWorkDirWmo = "./Buildings"; +const char* szRawVMAPMagic = "VMAP004"; + +// Local testing functions + +bool FileExists(const char* file) +{ + if (FILE* n = fopen(file, "rb")) + { + fclose(n); + return true; + } + return false; +} + +void strToLower(char* str) +{ + while(*str) + { + *str=tolower(*str); + ++str; + } +} + +// copied from contrib/extractor/System.cpp +void ReadLiquidTypeTableDBC() +{ + printf("Read LiquidType.dbc file..."); + DBCFile dbc("DBFilesClient\\LiquidType.dbc"); + if(!dbc.open()) + { + printf("Fatal error: Invalid LiquidType.dbc file format!\n"); + exit(1); + } + + size_t LiqType_count = dbc.getRecordCount(); + size_t LiqType_maxid = dbc.getRecord(LiqType_count - 1).getUInt(0); + LiqType = new uint16[LiqType_maxid + 1]; + memset(LiqType, 0xff, (LiqType_maxid + 1) * sizeof(uint16)); + + for(uint32 x = 0; x < LiqType_count; ++x) + LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); + + printf("Done! (%u LiqTypes loaded)\n", (unsigned int)LiqType_count); +} + +bool ExtractWmo() +{ + bool success = true; + + //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"}; + + for (ArchiveSet::const_iterator ar_itr = gOpenArchives.begin(); ar_itr != gOpenArchives.end() && success; ++ar_itr) + { + vector<string> filelist; + + (*ar_itr)->GetFileListTo(filelist); + for (vector<string>::iterator fname = filelist.begin(); fname != filelist.end() && success; ++fname) + { + if (fname->find(".wmo") != string::npos) + success = ExtractSingleWmo(*fname); + } + } + + if (success) + printf("\nExtract wmo complete (No (fatal) errors)\n"); + + return success; +} + +bool ExtractSingleWmo(std::string& fname) +{ + // Copy files from archive + + char szLocalFile[1024]; + const char * plain_name = GetPlainName(fname.c_str()); + sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name); + fixnamen(szLocalFile,strlen(szLocalFile)); + + if (FileExists(szLocalFile)) + return true; + + int p = 0; + //Select root wmo files + const char * rchr = strrchr(plain_name, '_'); + if(rchr != NULL) + { + char cpy[4]; + strncpy((char*)cpy,rchr,4); + for (int i=0;i < 4; ++i) + { + int m = cpy[i]; + if(isdigit(m)) + p++; + } + } + + if (p == 3) + return true; + + bool file_ok = true; + std::cout << "Extracting " << fname << std::endl; + WMORoot froot(fname); + if(!froot.open()) + { + printf("Couldn't open RootWmo!!!\n"); + return true; + } + FILE *output = fopen(szLocalFile,"wb"); + if(!output) + { + printf("couldn't open %s for writing!\n", szLocalFile); + return false; + } + froot.ConvertToVMAPRootWmo(output); + int Wmo_nVertices = 0; + //printf("root has %d groups\n", froot->nGroups); + if (froot.nGroups !=0) + { + for (uint32 i = 0; i < froot.nGroups; ++i) + { + char temp[1024]; + strcpy(temp, fname.c_str()); + temp[fname.length()-4] = 0; + char groupFileName[1024]; + sprintf(groupFileName,"%s_%03d.wmo",temp, i); + //printf("Trying to open groupfile %s\n",groupFileName); + + string s = groupFileName; + WMOGroup fgroup(s); + if(!fgroup.open()) + { + printf("Could not open all Group file for: %s\n", plain_name); + file_ok = false; + break; + } + + Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData); + } + } + + fseek(output, 8, SEEK_SET); // store the correct no of vertices + fwrite(&Wmo_nVertices,sizeof(int),1,output); + fclose(output); + + // Delete the extracted file in the case of an error + if (!file_ok) + remove(szLocalFile); + return true; +} + +void ParsMapFiles() +{ + char fn[512]; + //char id_filename[64]; + char id[10]; + for (unsigned int i=0; i<map_count; ++i) + { + sprintf(id,"%03u",map_ids[i].id); + sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name); + WDTFile WDT(fn,map_ids[i].name); + if(WDT.init(id, map_ids[i].id)) + { + printf("Processing Map %u\n[", map_ids[i].id); + for (int x=0; x<64; ++x) + { + for (int y=0; y<64; ++y) + { + if (ADTFile *ADT = WDT.GetMap(x,y)) + { + //sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!! + ADT->init(map_ids[i].id, x, y); + delete ADT; + } + } + printf("#"); + fflush(stdout); + } + printf("]\n"); + } + } +} + +void getGamePath() +{ +#ifdef _WIN32 + HKEY key; + DWORD t,s; + LONG l; + s = sizeof(input_path); + memset(input_path,0,s); + l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\World of Warcraft",0,KEY_QUERY_VALUE,&key); + //l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\Burning Crusade Closed Beta",0,KEY_QUERY_VALUE,&key); + l = RegQueryValueEx(key,"InstallPath",0,&t,(LPBYTE)input_path,&s); + RegCloseKey(key); + if (strlen(input_path) > 0) + { + if (input_path[strlen(input_path) - 1] != '\\') strcat(input_path, "\\"); + } + strcat(input_path,"Data\\"); +#else + strcpy(input_path,"Data/"); +#endif +} + +bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames) +{ + int i; + char path[512]; + + for (i = 1; i <= 99; i++) + { + if (i != 1) + { + sprintf(path, "%s-%d.MPQ", scanmatch, i); + } + else + { + sprintf(path, "%s.MPQ", scanmatch); + } +#ifdef __linux__ + if(FILE* h = fopen64(path, "rb")) +#else + if(FILE* h = fopen(path, "rb")) +#endif + { + fclose(h); + //matches.push_back(path); + pArchiveNames.push_back(path); + } + } + + return(true); +} + +bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames) +{ + if(!hasInputPathParam) + getGamePath(); + + printf("\nGame path: %s\n", input_path); + + char path[512]; + string in_path(input_path); + std::vector<std::string> locales, searchLocales; + + searchLocales.push_back("enGB"); + searchLocales.push_back("enUS"); + searchLocales.push_back("deDE"); + searchLocales.push_back("esES"); + searchLocales.push_back("frFR"); + searchLocales.push_back("koKR"); + searchLocales.push_back("zhCN"); + searchLocales.push_back("zhTW"); + searchLocales.push_back("enCN"); + searchLocales.push_back("enTW"); + searchLocales.push_back("esMX"); + searchLocales.push_back("ruRU"); + + for (std::vector<std::string>::iterator i = searchLocales.begin(); i != searchLocales.end(); ++i) + { + std::string localePath = in_path + *i; + // check if locale exists: + struct stat status; + if (stat(localePath.c_str(), &status)) + continue; + if ((status.st_mode & S_IFDIR) == 0) + continue; + printf("Found locale '%s'\n", i->c_str()); + locales.push_back(*i); + } + printf("\n"); + + // open locale expansion and common files + printf("Adding data files from locale directories.\n"); + for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) + { + pArchiveNames.push_back(in_path + *i + "/locale-" + *i + ".MPQ"); + pArchiveNames.push_back(in_path + *i + "/expansion-locale-" + *i + ".MPQ"); + pArchiveNames.push_back(in_path + *i + "/lichking-locale-" + *i + ".MPQ"); + } + + // open expansion and common files + pArchiveNames.push_back(input_path + string("common.MPQ")); + pArchiveNames.push_back(input_path + string("common-2.MPQ")); + pArchiveNames.push_back(input_path + string("expansion.MPQ")); + pArchiveNames.push_back(input_path + string("lichking.MPQ")); + + // now, scan for the patch levels in the core dir + printf("Scanning patch levels from data directory.\n"); + sprintf(path, "%spatch", input_path); + if (!scan_patches(path, pArchiveNames)) + return(false); + + // now, scan for the patch levels in locale dirs + printf("Scanning patch levels from locale directories.\n"); + bool foundOne = false; + for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) + { + printf("Locale: %s\n", i->c_str()); + sprintf(path, "%s%s/patch-%s", input_path, i->c_str(), i->c_str()); + if(scan_patches(path, pArchiveNames)) + foundOne = true; + } + + printf("\n"); + + if(!foundOne) + { + printf("no locale found\n"); + return false; + } + + return true; +} + +bool processArgv(int argc, char ** argv, const char *versionString) +{ + bool result = true; + hasInputPathParam = false; + bool preciseVectorData = false; + + for(int i=1; i< argc; ++i) + { + if(strcmp("-s",argv[i]) == 0) + { + preciseVectorData = false; + } + else if(strcmp("-d",argv[i]) == 0) + { + if((i+1)<argc) + { + hasInputPathParam = true; + strcpy(input_path, argv[i+1]); + if (input_path[strlen(input_path) - 1] != '\\' || input_path[strlen(input_path) - 1] != '/') + strcat(input_path, "/"); + ++i; + } + else + { + result = false; + } + } + else if(strcmp("-?",argv[1]) == 0) + { + result = false; + } + else if(strcmp("-l",argv[i]) == 0) + { + preciseVectorData = true; + } + else + { + result = false; + break; + } + } + if(!result) + { + printf("Extract %s.\n",versionString); + printf("%s [-?][-s][-l][-d <path>]\n", argv[0]); + printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n"); + printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n"); + printf(" -d <path>: Path to the vector data source folder.\n"); + printf(" -? : This message.\n"); + } + return result; +} + + +//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// Main +// +// The program must be run with two command line arguments +// +// Arg1 - The source MPQ name (for testing reading and file find) +// Arg2 - Listfile name +// + +int main(int argc, char ** argv) +{ + bool success=true; + const char *versionString = "V4.00 2012_02"; + + // Use command line arguments, when some + if(!processArgv(argc, argv, versionString)) + return 1; + + // some simple check if working dir is dirty + else + { + std::string sdir = std::string(szWorkDirWmo) + "/dir"; + std::string sdir_bin = std::string(szWorkDirWmo) + "/dir_bin"; + struct stat status; + if (!stat(sdir.c_str(), &status) || !stat(sdir_bin.c_str(), &status)) + { + printf("Your output directory seems to be polluted, please use an empty directory!\n"); + printf("<press return to exit>"); + char garbage[2]; + scanf("%c", garbage); + return 1; + } + } + + printf("Extract %s. Beginning work ....\n",versionString); + //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // Create the working directory + if(mkdir(szWorkDirWmo +#ifdef __linux__ + , 0711 +#endif + )) + success = (errno == EEXIST); + + // prepare archive name list + std::vector<std::string> archiveNames; + fillArchiveNameVector(archiveNames); + for (size_t i=0; i < archiveNames.size(); ++i) + { + MPQArchive *archive = new MPQArchive(archiveNames[i].c_str()); + if(!gOpenArchives.size() || gOpenArchives.front() != archive) + delete archive; + } + + if(gOpenArchives.empty()) + { + printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n",input_path); + return 1; + } + ReadLiquidTypeTableDBC(); + + // extract data + if(success) + success = ExtractWmo(); + + //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + //map.dbc + if(success) + { + DBCFile * dbc = new DBCFile("DBFilesClient\\Map.dbc"); + if(!dbc->open()) + { + delete dbc; + printf("FATAL ERROR: Map.dbc not found in data file.\n"); + return 1; + } + map_count=dbc->getRecordCount (); + map_ids=new map_id[map_count]; + for(unsigned int x=0;x<map_count;++x) + { + map_ids[x].id=dbc->getRecord (x).getUInt(0); + strcpy(map_ids[x].name,dbc->getRecord(x).getString(1)); + printf("Map - %s\n",map_ids[x].name); + } + + + delete dbc; + ParsMapFiles(); + delete [] map_ids; + //nError = ERROR_SUCCESS; + // Extract models, listed in DameObjectDisplayInfo.dbc + ExtractGameobjectModels(); + } + + printf("\n"); + if(!success) + { + printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString, preciseVectorData); + getchar(); + } + + printf("Extract %s. Work complete. No errors.\n",versionString); + delete [] LiqType; + return 0; +} diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h new file mode 100644 index 00000000000..b407e7a106e --- /dev/null +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef VMAPEXPORT_H +#define VMAPEXPORT_H + +#include <string> + +enum ModelFlags +{ + MOD_M2 = 1, + MOD_WORLDSPAWN = 1<<1, + MOD_HAS_BOUND = 1<<2 +}; + +extern const char * szWorkDirWmo; +extern const char * szRawVMAPMagic; // vmap magic string for extracted raw vmap data + +bool FileExists(const char * file); +void strToLower(char* str); + +bool ExtractSingleWmo(std::string& fname); +bool ExtractSingleModel(std::string& fname); + +void ExtractGameobjectModels(); + +#endif diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp new file mode 100644 index 00000000000..e3ee545db19 --- /dev/null +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vmapexport.h" +#include "wdtfile.h" +#include "adtfile.h" +#include <cstdio> + +char * wdtGetPlainName(char * FileName) +{ + char * szTemp; + + if((szTemp = strrchr(FileName, '\\')) != NULL) + FileName = szTemp + 1; + return FileName; +} + +WDTFile::WDTFile(char* file_name, char* file_name1):WDT(file_name) +{ + filename.append(file_name1,strlen(file_name1)); +} + +bool WDTFile::init(char *map_id, unsigned int mapID) +{ + if (WDT.isEof()) + { + //printf("Can't find WDT file.\n"); + return false; + } + + char fourcc[5]; + uint32 size; + + std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; + FILE *dirfile; + dirfile = fopen(dirname.c_str(), "ab"); + if(!dirfile) + { + printf("Can't open dirfile!'%s'\n", dirname.c_str()); + return false; + } + + while (!WDT.isEof()) + { + WDT.read(fourcc,4); + WDT.read(&size, 4); + + flipcc(fourcc); + fourcc[4] = 0; + + size_t nextpos = WDT.getPos() + size; + + if (!strcmp(fourcc,"MAIN")) + { + } + if (!strcmp(fourcc,"MWMO")) + { + // global map objects + if (size) + { + char *buf = new char[size]; + WDT.read(buf, size); + char *p=buf; + int q = 0; + gWmoInstansName = new string[size]; + while (p<buf+size) + { + string path(p); + char* s=wdtGetPlainName(p); + fixnamen(s,strlen(s)); + p=p+strlen(p)+1; + gWmoInstansName[q++] = s; + } + delete[] buf; + } + } + else if (!strcmp(fourcc,"MODF")) + { + // global wmo instance data + if (size) + { + gnWMO = (int)size / 64; + string gWMO_mapname; + string fake_mapname; + fake_mapname = "65 65 "; + //gWMO_mapname = fake_mapname + filename; + gWMO_mapname = fake_mapname + std::string(map_id); + for (int i=0; i<gnWMO; ++i) + { + int id; + WDT.read(&id, 4); + WMOInstance inst(WDT,gWmoInstansName[id].c_str(),mapID, 65, 65, dirfile); + } + delete[] gWmoInstansName; + } + } + WDT.seek((int)nextpos); + } + + WDT.close(); + fclose(dirfile); + return true; +} + +WDTFile::~WDTFile(void) +{ + WDT.close(); +} + +ADTFile* WDTFile::GetMap(int x, int z) +{ + if(!(x>=0 && z >= 0 && x<64 && z<64)) + return NULL; + + char name[512]; + + sprintf(name,"World\\Maps\\%s\\%s_%d_%d.adt", filename.c_str(), filename.c_str(), x, z); + return new ADTFile(name); +} diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h new file mode 100644 index 00000000000..f3d71c41791 --- /dev/null +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -0,0 +1,29 @@ +#ifndef WDTFILE_H +#define WDTFILE_H + +#include "mpq_libmpq04.h" +#include "wmo.h" +#include <string> +#include "stdlib.h" + +class ADTFile; + +class WDTFile +{ +public: + WDTFile(char* file_name, char* file_name1); + ~WDTFile(void); + bool init(char *map_id, unsigned int mapID); + + string* gWmoInstansName; + int gnWMO, nMaps; + + ADTFile* GetMap(int x, int z); + +private: + MPQFile WDT; + bool maps[64][64]; + string filename; +}; + +#endif diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp new file mode 100644 index 00000000000..58957e007c1 --- /dev/null +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vmapexport.h" +#include "wmo.h" +#include "vec3d.h" +#include <cstdio> +#include <cstdlib> +#include <cassert> +#include <map> +#include <fstream> +#undef min +#undef max +#include "mpq_libmpq04.h" + +using namespace std; +extern uint16 *LiqType; + +WMORoot::WMORoot(std::string &filename) : filename(filename) +{ +} + +bool WMORoot::open() +{ + MPQFile f(filename.c_str()); + if(f.isEof ()) + { + printf("No such file.\n"); + return false; + } + + uint32 size; + char fourcc[5]; + + while (!f.isEof()) + { + f.read(fourcc,4); + f.read(&size, 4); + + flipcc(fourcc); + fourcc[4] = 0; + + size_t nextpos = f.getPos() + size; + + if (!strcmp(fourcc,"MOHD"))//header + { + f.read(&nTextures, 4); + f.read(&nGroups, 4); + f.read(&nP, 4); + f.read(&nLights, 4); + f.read(&nModels, 4); + f.read(&nDoodads, 4); + f.read(&nDoodadSets, 4); + f.read(&col, 4); + f.read(&RootWMOID, 4); + f.read(bbcorn1,12); + f.read(bbcorn2,12); + f.read(&liquidType, 4); + break; + } + /* + else if (!strcmp(fourcc,"MOTX")) + { + } + else if (!strcmp(fourcc,"MOMT")) + { + } + else if (!strcmp(fourcc,"MOGN")) + { + } + else if (!strcmp(fourcc,"MOGI")) + { + } + else if (!strcmp(fourcc,"MOLT")) + { + } + else if (!strcmp(fourcc,"MODN")) + { + } + else if (!strcmp(fourcc,"MODS")) + { + } + else if (!strcmp(fourcc,"MODD")) + { + } + else if (!strcmp(fourcc,"MOSB")) + { + } + else if (!strcmp(fourcc,"MOPV")) + { + } + else if (!strcmp(fourcc,"MOPT")) + { + } + else if (!strcmp(fourcc,"MOPR")) + { + } + else if (!strcmp(fourcc,"MFOG")) + { + } + */ + f.seek((int)nextpos); + } + f.close (); + return true; +} + +bool WMORoot::ConvertToVMAPRootWmo(FILE *pOutfile) +{ + //printf("Convert RootWmo...\n"); + + fwrite(szRawVMAPMagic,1,8,pOutfile); + unsigned int nVectors = 0; + fwrite(&nVectors,sizeof(nVectors),1,pOutfile); // will be filled later + fwrite(&nGroups,4,1,pOutfile); + fwrite(&RootWMOID,4,1,pOutfile); + return true; +} + +WMORoot::~WMORoot() +{ +} + +WMOGroup::WMOGroup(std::string &filename) : filename(filename), + MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0), hlq(0), LiquEx(0), LiquBytes(0) +{ +} + +bool WMOGroup::open() +{ + MPQFile f(filename.c_str()); + if(f.isEof ()) + { + printf("No such file.\n"); + return false; + } + uint32 size; + char fourcc[5]; + while (!f.isEof()) + { + f.read(fourcc,4); + f.read(&size, 4); + flipcc(fourcc); + if (!strcmp(fourcc,"MOGP"))//Fix sizeoff = Data size. + { + size = 68; + } + fourcc[4] = 0; + size_t nextpos = f.getPos() + size; + LiquEx_size = 0; + liquflags = 0; + + if (!strcmp(fourcc,"MOGP"))//header + { + f.read(&groupName, 4); + f.read(&descGroupName, 4); + f.read(&mogpFlags, 4); + f.read(bbcorn1, 12); + f.read(bbcorn2, 12); + f.read(&moprIdx, 2); + f.read(&moprNItems, 2); + f.read(&nBatchA, 2); + f.read(&nBatchB, 2); + f.read(&nBatchC, 4); + f.read(&fogIdx, 4); + f.read(&liquidType, 4); + f.read(&groupWMOID,4); + + } + else if (!strcmp(fourcc,"MOPY")) + { + MOPY = new char[size]; + mopy_size = size; + nTriangles = (int)size / 2; + f.read(MOPY, size); + } + else if (!strcmp(fourcc,"MOVI")) + { + MOVI = new uint16[size/2]; + f.read(MOVI, size); + } + else if (!strcmp(fourcc,"MOVT")) + { + MOVT = new float[size/4]; + f.read(MOVT, size); + nVertices = (int)size / 12; + } + else if (!strcmp(fourcc,"MONR")) + { + } + else if (!strcmp(fourcc,"MOTV")) + { + } + else if (!strcmp(fourcc,"MOBA")) + { + MOBA = new uint16[size/2]; + moba_size = size/2; + f.read(MOBA, size); + } + else if (!strcmp(fourcc,"MLIQ")) + { + liquflags |= 1; + hlq = new WMOLiquidHeader; + f.read(hlq, 0x1E); + LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts; + LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts]; + f.read(LiquEx, LiquEx_size); + int nLiquBytes = hlq->xtiles * hlq->ytiles; + LiquBytes = new char[nLiquBytes]; + f.read(LiquBytes, nLiquBytes); + + /* 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]; + llog << "\nlpos: " << hlq->pos_x << ", " << hlq->pos_y << ", " << hlq->pos_z; + llog << "\nx-/yvert: " << hlq->xverts << "/" << hlq->yverts << " size: " << size << " expected size: " << 30 + hlq->xverts*hlq->yverts*8 + hlq->xtiles*hlq->ytiles << std::endl; + llog.close(); */ + } + f.seek((int)nextpos); + } + f.close(); + return true; +} + +int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool pPreciseVectorData) +{ + fwrite(&mogpFlags,sizeof(uint32),1,output); + fwrite(&groupWMOID,sizeof(uint32),1,output); + // group bound + fwrite(bbcorn1, sizeof(float), 3, output); + fwrite(bbcorn2, sizeof(float), 3, output); + fwrite(&liquflags,sizeof(uint32),1,output); + int nColTriangles = 0; + if(pPreciseVectorData) + { + char GRP[] = "GRP "; + fwrite(GRP,1,4,output); + + int k = 0; + int moba_batch = moba_size/12; + MobaEx = new int[moba_batch*4]; + for(int i=8; i<moba_size; i+=12) + { + MobaEx[k++] = MOBA[i]; + } + int moba_size_grp = moba_batch*4+4; + fwrite(&moba_size_grp,4,1,output); + fwrite(&moba_batch,4,1,output); + fwrite(MobaEx,4,k,output); + delete [] MobaEx; + + uint32 nIdexes = nTriangles * 3; + + if(fwrite("INDX",4, 1, output) != 1) + { + printf("Error while writing file nbraches ID"); + exit(0); + } + int wsize = sizeof(uint32) + sizeof(unsigned short) * nIdexes; + if(fwrite(&wsize, sizeof(int), 1, output) != 1) + { + printf("Error while writing file wsize"); + // no need to exit? + } + if(fwrite(&nIdexes, sizeof(uint32), 1, output) != 1) + { + printf("Error while writing file nIndexes"); + exit(0); + } + if(nIdexes >0) + { + if(fwrite(MOVI, sizeof(unsigned short), nIdexes, output) != nIdexes) + { + printf("Error while writing file indexarray"); + exit(0); + } + } + + if(fwrite("VERT",4, 1, output) != 1) + { + printf("Error while writing file nbraches ID"); + exit(0); + } + wsize = sizeof(int) + sizeof(float) * 3 * nVertices; + if(fwrite(&wsize, sizeof(int), 1, output) != 1) + { + printf("Error while writing file wsize"); + // no need to exit? + } + if(fwrite(&nVertices, sizeof(int), 1, output) != 1) + { + printf("Error while writing file nVertices"); + exit(0); + } + if(nVertices >0) + { + if(fwrite(MOVT, sizeof(float)*3, nVertices, output) != nVertices) + { + printf("Error while writing file vectors"); + exit(0); + } + } + + nColTriangles = nTriangles; + } + else + { + char GRP[] = "GRP "; + fwrite(GRP,1,4,output); + int k = 0; + int moba_batch = moba_size/12; + MobaEx = new int[moba_batch*4]; + for(int i=8; i<moba_size; i+=12) + { + MobaEx[k++] = MOBA[i]; + } + + int moba_size_grp = moba_batch*4+4; + fwrite(&moba_size_grp,4,1,output); + fwrite(&moba_batch,4,1,output); + fwrite(MobaEx,4,k,output); + delete [] MobaEx; + + //-------INDX------------------------------------ + //-------MOPY-------- + MoviEx = new uint16[nTriangles*3]; // "worst case" size... + int *IndexRenum = new int[nVertices]; + memset(IndexRenum, 0xFF, nVertices*sizeof(int)); + for (int i=0; i<nTriangles; ++i) + { + // Skip no collision triangles + if (MOPY[2*i]&WMO_MATERIAL_NO_COLLISION || + !(MOPY[2*i]&(WMO_MATERIAL_HINT|WMO_MATERIAL_COLLIDE_HIT)) ) + continue; + // Use this triangle + for (int j=0; j<3; ++j) + { + IndexRenum[MOVI[3*i + j]] = 1; + MoviEx[3*nColTriangles + j] = MOVI[3*i + j]; + } + ++nColTriangles; + } + + // assign new vertex index numbers + int nColVertices = 0; + for (uint32 i=0; i<nVertices; ++i) + { + if (IndexRenum[i] == 1) + { + IndexRenum[i] = nColVertices; + ++nColVertices; + } + } + + // translate triangle indices to new numbers + for (int i=0; i<3*nColTriangles; ++i) + { + assert(MoviEx[i] < nVertices); + MoviEx[i] = IndexRenum[MoviEx[i]]; + } + + // write triangle indices + int INDX[] = {0x58444E49, nColTriangles*6+4, nColTriangles*3}; + fwrite(INDX,4,3,output); + fwrite(MoviEx,2,nColTriangles*3,output); + + // write vertices + int VERT[] = {0x54524556, nColVertices*3*sizeof(float)+4, nColVertices};// "VERT" + int check = 3*nColVertices; + fwrite(VERT,4,3,output); + for (uint32 i=0; i<nVertices; ++i) + if(IndexRenum[i] >= 0) + check -= fwrite(MOVT+3*i, sizeof(float), 3, output); + + assert(check==0); + + delete [] MoviEx; + delete [] IndexRenum; + } + + //------LIQU------------------------ + if(LiquEx_size != 0) + { + int LIQU_h[] = {0x5551494C, 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 = 1; // first entry, generic "Water" + else + liquidEntry = liquidType + 1; + // overwrite material type in header... + hlq->type = LiqType[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); + } + + return nColTriangles; +} + +WMOGroup::~WMOGroup() +{ + delete [] MOPY; + delete [] MOVI; + delete [] MOVT; + delete [] MOBA; + delete hlq; + delete [] LiquEx; + delete [] LiquBytes; +} + +WMOInstance::WMOInstance(MPQFile &f,const char* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) +{ + pos = Vec3D(0,0,0); + + float ff[3]; + f.read(&id, 4); + f.read(ff,12); + pos = Vec3D(ff[0],ff[1],ff[2]); + f.read(ff,12); + rot = Vec3D(ff[0],ff[1],ff[2]); + f.read(ff,12); + pos2 = Vec3D(ff[0],ff[1],ff[2]); + f.read(ff,12); + pos3 = Vec3D(ff[0],ff[1],ff[2]); + f.read(&d2,4); + + uint16 trash,adtId; + f.read(&adtId,2); + f.read(&trash,2); + + //-----------add_in _dir_file---------------- + + char tempname[512]; + sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName); + FILE *input; + input = fopen(tempname, "r+b"); + + if(!input) + { + printf("WMOInstance::WMOInstance: couldn't open %s\n", tempname); + return; + } + + fseek(input, 8, SEEK_SET); // get the correct no of vertices + int nVertices; + fread(&nVertices, sizeof (int), 1, input); + fclose(input); + + if(nVertices == 0) + return; + + float x,z; + x = pos.x; + z = pos.z; + if(x==0 && z == 0) + { + pos.x = 533.33333f*32; + pos.z = 533.33333f*32; + } + pos = fixCoords(pos); + pos2 = fixCoords(pos2); + pos3 = fixCoords(pos3); + + float scale = 1.0f; + uint32 flags = MOD_HAS_BOUND; + if(tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; + //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, 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(&adtId, sizeof(uint16), 1, pDirfile); + fwrite(&id, sizeof(uint32), 1, pDirfile); + fwrite(&pos, sizeof(float), 3, pDirfile); + fwrite(&rot, sizeof(float), 3, pDirfile); + fwrite(&scale, sizeof(float), 1, pDirfile); + fwrite(&pos2, sizeof(float), 3, pDirfile); + fwrite(&pos3, sizeof(float), 3, pDirfile); + uint32 nlen=strlen(WmoInstName); + fwrite(&nlen, sizeof(uint32), 1, pDirfile); + fwrite(WmoInstName, sizeof(char), nlen, pDirfile); + + /* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n", + MapName, + WmoInstName, + (float) x, (float) pos.y, (float) z, + (float) rot.x, (float) rot.y, (float) rot.z, + nVertices, + realx1, realy1, + realx2, realy2 + ); */ + + // fclose(dirfile); +} diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h new file mode 100644 index 00000000000..d1f7b82f0c6 --- /dev/null +++ b/src/tools/vmap4_extractor/wmo.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WMO_H +#define WMO_H +#define TILESIZE (533.33333f) +#define CHUNKSIZE ((TILESIZE) / 16.0f) + +#include <string> +#include <set> +#include "vec3d.h" +#include "loadlib/loadlib.h" + +// MOPY flags +#define WMO_MATERIAL_NOCAMCOLLIDE 0x01 +#define WMO_MATERIAL_DETAIL 0x02 +#define WMO_MATERIAL_NO_COLLISION 0x04 +#define WMO_MATERIAL_HINT 0x08 +#define WMO_MATERIAL_RENDER 0x10 +#define WMO_MATERIAL_COLLIDE_HIT 0x20 +#define WMO_MATERIAL_WALL_SURFACE 0x40 + +class WMOInstance; +class WMOManager; +class MPQFile; + +/* for whatever reason a certain company just can't stick to one coordinate system... */ +static inline Vec3D fixCoords(const Vec3D &v){ return Vec3D(v.z, v.x, v.y); } + +class WMORoot +{ +public: + uint32 nTextures, nGroups, nP, nLights, nModels, nDoodads, nDoodadSets, RootWMOID, liquidType; + unsigned int col; + float bbcorn1[3]; + float bbcorn2[3]; + + WMORoot(std::string &filename); + ~WMORoot(); + + bool open(); + bool ConvertToVMAPRootWmo(FILE *output); +private: + std::string filename; + char outfilename; +}; + +struct WMOLiquidHeader +{ + int xverts, yverts, xtiles, ytiles; + float pos_x; + float pos_y; + float pos_z; + short type; +}; + +struct WMOLiquidVert +{ + uint16 unk1; + uint16 unk2; + float height; +}; + +class WMOGroup +{ +public: + // MOGP + int groupName, descGroupName, mogpFlags; + float bbcorn1[3]; + float bbcorn2[3]; + uint16 moprIdx; + uint16 moprNItems; + uint16 nBatchA; + uint16 nBatchB; + uint32 nBatchC, fogIdx, liquidType, groupWMOID; + + int mopy_size,moba_size; + int LiquEx_size; + unsigned int nVertices; // number when loaded + int nTriangles; // number when loaded + char *MOPY; + uint16 *MOVI; + uint16 *MoviEx; + float *MOVT; + uint16 *MOBA; + int *MobaEx; + WMOLiquidHeader *hlq; + WMOLiquidVert *LiquEx; + char *LiquBytes; + uint32 liquflags; + + WMOGroup(std::string &filename); + ~WMOGroup(); + + bool open(); + int ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool pPreciseVectorData); + +private: + std::string filename; + char outfilename; +}; + +class WMOInstance +{ + static std::set<int> ids; +public: + std::string MapName; + int currx; + int curry; + WMOGroup *wmo; + Vec3D pos; + Vec3D pos2, pos3, rot; + uint32 indx,id, d2, d3; + int doodadset; + + WMOInstance(MPQFile &f,const char* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile); + + static void reset(); +}; + +#endif |
