aboutsummaryrefslogtreecommitdiff
path: root/src/tools/vmap4_extractor
diff options
context:
space:
mode:
authorKa0z <misaeleim@hotmail.cl>2012-02-10 18:40:05 -0300
committerKa0z <misaeleim@hotmail.cl>2012-02-10 18:40:05 -0300
commit6627fe72039153b00bb87775867e09453f2b24e6 (patch)
treec9c7c70c2f021392b6761e15ad6b5a3c7d7d7074 /src/tools/vmap4_extractor
parent8c2526e7d0f8cd516e0a3d3ebd6e554774c76c7b (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.txt48
-rw-r--r--src/tools/vmap4_extractor/adtfile.cpp219
-rw-r--r--src/tools/vmap4_extractor/adtfile.h143
-rw-r--r--src/tools/vmap4_extractor/dbcfile.cpp95
-rw-r--r--src/tools/vmap4_extractor/dbcfile.h155
-rw-r--r--src/tools/vmap4_extractor/gameobject_extract.cpp99
-rw-r--r--src/tools/vmap4_extractor/loadlib/loadlib.h77
-rw-r--r--src/tools/vmap4_extractor/model.cpp199
-rw-r--r--src/tools/vmap4_extractor/model.h78
-rw-r--r--src/tools/vmap4_extractor/modelheaders.h99
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq.cpp111
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq04.h91
-rw-r--r--src/tools/vmap4_extractor/vec3d.h230
-rw-r--r--src/tools/vmap4_extractor/vmapexport.cpp552
-rw-r--r--src/tools/vmap4_extractor/vmapexport.h42
-rw-r--r--src/tools/vmap4_extractor/wdtfile.cpp134
-rw-r--r--src/tools/vmap4_extractor/wdtfile.h29
-rw-r--r--src/tools/vmap4_extractor/wmo.cpp523
-rw-r--r--src/tools/vmap4_extractor/wmo.h136
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