aboutsummaryrefslogtreecommitdiff
path: root/src/shared/vmap/TileAssembler.cpp
diff options
context:
space:
mode:
authorNeo2003 <none@none>2008-10-02 16:23:55 -0500
committerNeo2003 <none@none>2008-10-02 16:23:55 -0500
commit9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch)
treeb5d1ba94a656e6679f8737f9ea6bed1239b73b14 /src/shared/vmap/TileAssembler.cpp
[svn] * Proper SVN structureinit
--HG-- branch : trunk
Diffstat (limited to 'src/shared/vmap/TileAssembler.cpp')
-rw-r--r--src/shared/vmap/TileAssembler.cpp571
1 files changed, 571 insertions, 0 deletions
diff --git a/src/shared/vmap/TileAssembler.cpp b/src/shared/vmap/TileAssembler.cpp
new file mode 100644
index 00000000000..a51e2c86d63
--- /dev/null
+++ b/src/shared/vmap/TileAssembler.cpp
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * 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 <G3D/Vector3.h>
+#include <G3D/Triangle.h>
+
+#include "TileAssembler.h"
+#include "CoordModelMapping.h"
+#include "ModelContainer.h"
+
+#include <limits.h>
+#include <string.h>
+
+#ifdef _ASSEMBLER_DEBUG
+FILE *g_df = NULL;
+#endif
+
+using namespace G3D;
+
+namespace VMAP
+{
+ //=================================================================
+
+ Vector3 ModelPosition::transform(const Vector3& pIn) const
+ {
+ //return(pIn);
+ Vector3 out = pIn * iScale;
+ out = izMatrix * out;
+ out = ixMatrix * out;
+ out = iyMatrix * out;
+ return(out);
+
+ }
+ //=================================================================
+
+ TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
+ {
+ iCurrentUniqueNameId = 0;
+ iFilterMethod = NULL;
+ iSrcDir = pSrcDirName;
+ iDestDir = pDestDirName;
+ //mkdir(iDestDir);
+ init();
+ }
+
+ //=================================================================
+
+ TileAssembler::~TileAssembler()
+ {
+ delete iCoordModelMapping;
+ }
+
+ //=================================================================
+
+ void TileAssembler::init()
+ {
+ iCoordModelMapping = new CoordModelMapping();
+ addWorldAreaMapId(0); //Azeroth
+ addWorldAreaMapId(1); //Kalimdor
+ addWorldAreaMapId(530); //Expansion01
+ }
+ //=================================================================
+
+ std::string getModNameFromModPosName(const std::string& pModPosName)
+ {
+
+ size_t spos = pModPosName.find_first_of('#');
+ std::string modelFileName = pModPosName.substr(0,spos);
+ return(modelFileName);
+ }
+
+ //=================================================================
+
+ unsigned int TileAssembler::getUniqueNameId(const std::string pName)
+ {
+ unsigned int result;
+
+ if(!iUniqueNameIds.containsKey(pName))
+ {
+ ++iCurrentUniqueNameId;
+ iUniqueNameIds.set(pName, iCurrentUniqueNameId);
+ }
+ result = iUniqueNameIds.get(pName);
+ return result;
+ }
+
+ //=================================================================
+
+ std::string TileAssembler::getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName)
+ {
+ size_t spos;
+ char buffer[20];
+
+ std::string modelFileName = getModNameFromModPosName(pModPosName);
+ //std::string fext = pModPosName.substr(modelFileName.length(),pModPosName.length());
+ unsigned int fextId = getUniqueNameId(pModPosName);
+ sprintf(buffer, "_%07d",fextId);
+ std::string fext(buffer);
+ spos = modelFileName.find_last_of('/');
+ std::string fname = modelFileName.substr(spos+1, modelFileName.length());
+ spos = fname.find_last_of('.');
+ fname = fname.substr(0,spos);
+ sprintf(buffer, "%03u", pMapId);
+ std::string dirEntry(buffer);
+ dirEntry.append("_");
+ dirEntry.append(fname);
+ dirEntry.append(fext);
+ dirEntry.append(".vmap");
+ return(dirEntry);
+ }
+
+ //=================================================================
+
+ void emptyArray(Array<ModelContainer*>& mc)
+ {
+ int no=mc.size();
+ while(no > 0)
+ {
+ --no;
+ delete mc[no];
+ mc.remove(no);
+ }
+ }
+
+ //=================================================================
+ bool TileAssembler::convertWorld()
+ {
+
+ #ifdef _ASSEMBLER_DEBUG
+ # ifdef _DEBUG
+ ::g_df = fopen("../TileAssembler_debug.txt", "wb");
+ # else
+ ::g_df = fopen("../TileAssembler_release.txt", "wb");
+ # endif
+ #endif
+
+ bool result = true;
+ std::string fname = iSrcDir;
+ fname.append("/");
+ fname.append("dir");
+ iCoordModelMapping->setModelNameFilterMethod(iFilterMethod);
+ iCoordModelMapping->readCoordinateMapping(fname);
+
+ Array<unsigned int> mapIds = iCoordModelMapping->getMaps();
+ if(mapIds.size() == 0)
+ {
+ result = false;
+ }
+ for(int i=0; i<mapIds.size() && result; ++i)
+ {
+ unsigned int mapId = mapIds[i];
+
+ #ifdef _ASSEMBLER_DEBUG
+ if(mapId == 0) // "Azeroth" just for debug
+ {
+ for(int x=28; x<29 && result; ++x) //debug
+ {
+ for(int y=28; y<29 && result; ++y)
+ {
+ #else
+ // ignore DeeprunTram (369) it is too large for short vector and not important
+ // ignore test (13), Test (29) , development (451)
+ if(mapId != 369 && mapId != 13 && mapId != 29 && mapId != 451)
+ {
+ for(int x=0; x<66 && result; ++x)
+ {
+ for(int y=0; y<66 && result; ++y)
+ {
+ #endif
+ Array<ModelContainer*> mc;
+ std::string dirname;
+ char buffer[100];
+ if(iCoordModelMapping->isWorldAreaMap(mapId) && x<65 && y<65)
+ {
+ sprintf(buffer, "%03u_%d_%d",mapId,y,x); // Let's flip x and y here
+ dirname = std::string(buffer);
+ }
+ else
+ {
+ sprintf(buffer, "%03u",mapId);
+ dirname = std::string(buffer);
+ }
+ result = fillModelContainerArray(dirname, mapId, x, y, mc);
+ emptyArray(mc);
+ }
+ }
+ }
+ }
+ #ifdef _ASSEMBLER_DEBUG
+ if(::g_df) fclose(::g_df);
+ #endif
+
+ return result;
+ }
+
+ //=================================================================
+
+ bool TileAssembler::fillModelContainerArray(const std::string& pDirFileName, unsigned int pMapId, int pXPos, int pYPos, Array<ModelContainer*>& pMC)
+ {
+ bool result = true;
+ ModelContainer* modelContainer;
+
+ NameCollection nameCollection = iCoordModelMapping->getFilenamesForCoordinate(pMapId, pXPos, pYPos);
+ if(nameCollection.size() > 0)
+ {
+ result = false;
+ char dirfilename[500];
+ sprintf(dirfilename,"%s/%s.vmdir",iDestDir.c_str(),pDirFileName.c_str());
+ FILE *dirfile = fopen(dirfilename, "ab");
+ if(dirfile)
+ {
+ result = true;
+ char destnamebuffer[500];
+ char fullnamedestnamebuffer[500];
+ if(nameCollection.iMainFiles.size() >0)
+ {
+ sprintf(destnamebuffer,"%03u_%i_%i.vmap",pMapId, pYPos, pXPos); // flip it here too
+ std::string checkDoubleStr = std::string(dirfilename);
+ checkDoubleStr.append("##");
+ checkDoubleStr.append(std::string(destnamebuffer));
+ // Check, if same file already is in the same dir file
+ if(!iCoordModelMapping->isAlreadyProcessedSingleFile(checkDoubleStr))
+ {
+ iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
+ fprintf(dirfile, "%s\n",destnamebuffer);
+ sprintf(fullnamedestnamebuffer,"%s/%s",iDestDir.c_str(),destnamebuffer);
+ modelContainer = processNames(nameCollection.iMainFiles, fullnamedestnamebuffer);
+ if(modelContainer)
+ {
+ pMC.append(modelContainer);
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ }
+ // process the large singe files
+ int pos = 0;
+ while(result && (pos < nameCollection.iSingeFiles.size()))
+ {
+ std::string destFileName = iDestDir;
+ destFileName.append("/");
+ std::string dirEntryName = getDirEntryNameFromModName(pMapId,nameCollection.iSingeFiles[pos]);
+ std::string checkDoubleStr = std::string(dirfilename);
+ checkDoubleStr.append("##");
+ checkDoubleStr.append(nameCollection.iSingeFiles[pos]);
+ // Check, if same file already is in the same dir file
+ if(!iCoordModelMapping->isAlreadyProcessedSingleFile(checkDoubleStr))
+ {
+ iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
+ fprintf(dirfile, "%s\n",dirEntryName.c_str());
+ destFileName.append(dirEntryName);
+
+ Array<std::string> positionarray;
+ positionarray.append(nameCollection.iSingeFiles[pos]);
+
+ if(!iCoordModelMapping->isAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]))
+ {
+ modelContainer = processNames(positionarray, destFileName.c_str());
+ iCoordModelMapping->addAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]);
+ if(modelContainer)
+ {
+ pMC.append(modelContainer);
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ }
+ ++pos;
+ }
+ fclose(dirfile);
+ }
+ }
+ return(result);
+ }
+
+ //=================================================================
+
+ void removeEntriesFromTree(AABSPTree<SubModel *>* pTree)
+ {
+ Array<SubModel *> submodelArray;
+ pTree->getMembers(submodelArray);
+ int no = submodelArray.size();
+ while(no > 0)
+ {
+ --no;
+ delete submodelArray[no];
+ }
+ }
+
+ //=================================================================
+
+ ModelContainer* TileAssembler::processNames(const Array<std::string>& pPositions, const char* pDestFileName)
+ {
+ ModelContainer *modelContainer = 0;
+
+ Vector3 basepos = Vector3(0,0,0);
+ AABSPTree<SubModel *>* mainTree = new AABSPTree<SubModel *>();
+
+ int pos = 0;
+
+ bool result = true;
+ while(result && (pos < pPositions.size()))
+ {
+ std::string modelPosString = pPositions[pos];
+ std::string modelFileName = getModNameFromModPosName(modelPosString);
+
+ if(!fillModelIntoTree(mainTree, basepos, modelPosString, modelFileName))
+ {
+ result = false;
+ break;
+ }
+ ++pos;
+ }
+ if(result && mainTree->size() > 0)
+ {
+ mainTree->balance();
+ modelContainer = new ModelContainer(mainTree);
+ modelContainer->writeFile(pDestFileName);
+ }
+ removeEntriesFromTree(mainTree);
+
+ delete mainTree;
+
+ return(modelContainer);
+ }
+
+ //=================================================================
+ bool TileAssembler::readRawFile(std::string& pModelFilename, ModelPosition& pModelPosition, AABSPTree<SubModel *> *pMainTree)
+ {
+ bool result = false;
+
+ std::string filename = iSrcDir;
+ if(filename.length() >0)
+ filename.append("/");
+ filename.append(pModelFilename);
+ FILE *rf = fopen(filename.c_str(), "rb");
+ if(!rf)
+ {
+ // depending on the extractor version, the data could be located in the root dir
+ std::string baseModelFilename = pModelFilename.substr((pModelFilename.find_first_of("/")+1),pModelFilename.length());
+ filename = iSrcDir;
+ if(filename.length() >0)
+ filename.append("/");
+ filename.append(baseModelFilename);
+ rf = fopen(filename.c_str(), "rb");
+ }
+ char ident[8];
+
+ int trianglecount =0;
+
+ #ifdef _ASSEMBLER_DEBUG
+ int startgroup = 0; //2;
+ int endgroup = INT_MAX; //2;
+ fprintf(::g_df,"-------------------------------------------------\n");
+ fprintf(::g_df,"%s\n", pModelFilename.c_str());
+ fprintf(::g_df,"-------------------------------------------------\n");
+ #else
+ int startgroup = 0;
+ int endgroup = INT_MAX;
+ #endif
+
+ if(rf)
+ {
+ if(fread(&ident, 8, 1, rf) != 1) { fclose(rf); return(false); }
+ if(strcmp(ident, "VMAP001") == 0)
+ {
+ // OK, do nothing
+ }
+ else if(strcmp(ident, "VMAP002") == 0)
+ {
+ // we have to read one int. This is needed during the export and we have to skip it here
+ int tempNVectors;
+ if(fread(&tempNVectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
+
+ }
+ else
+ {
+ // wrong version
+ fclose(rf);
+ return(false);
+ }
+ G3D::uint32 groups;
+ char blockId[5];
+ blockId[4] = 0;
+ int blocksize;
+
+ if(fread(&groups, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
+
+ for(int g=0;g<(int)groups;g++)
+ {
+ // group MUST NOT have more then 65536 indexes !! Array will have a problem with that !! (strange ...)
+ Array<int> tempIndexArray;
+ Array<Vector3> tempVertexArray;
+
+ AABSPTree<Triangle> *gtree = new AABSPTree<Triangle>();
+
+ G3D::uint32 flags;
+ if(fread(&flags, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
+
+ G3D::uint32 branches;
+ if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
+ if(strcmp(blockId, "GRP ") != 0) { fclose(rf); return(false); }
+ if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
+ if(fread(&branches, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
+ for(int b=0;b<(int)branches; b++)
+ {
+ G3D::uint32 indexes;
+ // indexes for each branch (not used jet)
+ if(fread(&indexes, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
+ }
+
+ // ---- indexes
+ if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
+ if(strcmp(blockId, "INDX") != 0) { fclose(rf); return(false); }
+ if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
+ unsigned int nindexes;
+ if(fread(&nindexes, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
+ if(nindexes >0)
+ {
+ unsigned short *indexarray = new unsigned short[nindexes*sizeof(unsigned short)];
+ if(fread(indexarray, sizeof(unsigned short), nindexes, rf) != nindexes) { fclose(rf); return(false); }
+ for(int i=0;i<(int)nindexes; i++)
+ {
+ unsigned short val = indexarray[i];
+ tempIndexArray.append(val);
+ }
+ delete indexarray;
+ }
+
+ // ---- vectors
+ if(fread(&blockId, 4, 1, rf) != 1) {fclose(rf); return(false); }
+ if(strcmp(blockId, "VERT") != 0) { fclose(rf); return(false); }
+ if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
+ unsigned int nvectors;
+ if(fread(&nvectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
+ float *vectorarray = 0;
+ if(nvectors >0)
+ {
+ vectorarray = new float[nvectors*sizeof(float)*3];
+ if(fread(vectorarray, sizeof(float)*3, nvectors, rf) != nvectors) { fclose(rf); return(false); }
+ }
+ // ----- liquit
+ if(flags & 1)
+ {
+ // we have liquit -> not handled yet ... skip
+ if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
+ if(strcmp(blockId, "LIQU") != 0) { fclose(rf); return(false); }
+ if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
+ fseek(rf, blocksize, SEEK_CUR);
+ }
+
+ for(unsigned int i=0, indexNo=0; indexNo<nvectors; indexNo++)
+ {
+ Vector3 v = Vector3(vectorarray[i+2], vectorarray[i+1], vectorarray[i+0]);
+ i+=3;
+ v = pModelPosition.transform(v);
+
+ float swapy = v.y;
+ v.y = v.x;
+ v.x = swapy;
+
+ tempVertexArray.append(v);
+ }
+
+ // ---- calculate triangles
+ int rest = nindexes%3;
+ if(rest != 0)
+ {
+ nindexes -= rest;
+ }
+
+ for(unsigned int i=0;i<(nindexes);)
+ {
+ Triangle t = Triangle(tempVertexArray[tempIndexArray[i+2]], tempVertexArray[tempIndexArray[i+1]], tempVertexArray[tempIndexArray[i+0]] );
+ i+=3;
+ ++trianglecount;
+ if(g>= startgroup && g <= endgroup)
+ {
+ gtree->insert(t);
+ }
+ }
+
+ if(vectorarray != 0)
+ {
+ delete vectorarray;
+ }
+
+ if(gtree->size() >0)
+ {
+ gtree->balance();
+ SubModel *sm = new SubModel(gtree);
+ #ifdef _ASSEMBLER_DEBUG
+ if(::g_df) fprintf(::g_df,"group trianglies: %d, Tris: %d, Nodes: %d, gtree.triangles: %d\n", g, sm->getNTriangles(), sm->getNNodes(), gtree->memberTable.size());
+ if(sm->getNTriangles() != gtree->memberTable.size())
+ {
+ if(::g_df) fprintf(::g_df,"ERROR !!!! group trianglies: %d, Tris: %d, Nodes: %d, gtree.triangles: %d\n", g, sm->getNTriangles(), sm->getNNodes(), gtree->memberTable.size());
+ }
+ #endif
+ sm->setBasePosition(pModelPosition.iPos);
+ pMainTree->insert(sm);
+ }
+ delete gtree;
+ }
+ fclose(rf);
+ result = true;
+ }
+ return(result);
+ }
+
+ //=================================================================
+
+ bool TileAssembler::fillModelIntoTree(AABSPTree<SubModel *> *pMainTree, const Vector3& pBasePos, std::string& pPos, std::string& pModelFilename)
+ {
+ bool result = false;
+ ModelPosition modelPosition;
+ getModelPosition(pPos, modelPosition);
+ // all should be relative to object base position
+ modelPosition.moveToBasePos(pBasePos);
+
+ modelPosition.init();
+
+ if(readRawFile(pModelFilename, modelPosition, pMainTree))
+ {
+ result = true;
+ }
+
+ return result;
+ }
+
+ //=================================================================
+ void TileAssembler::getModelPosition(std::string& pPosString, ModelPosition& pModelPosition)
+ {
+ float vposarray[3];
+ float vdirarray[3];
+ float scale;
+
+ size_t spos = pPosString.find_first_of('#');
+ std::string stripedPosString = pPosString.substr(spos+1,pPosString.length());
+
+ sscanf(stripedPosString.c_str(), "%f,%f,%f_%f,%f,%f_%f",
+ &vposarray[0],&vposarray[1],&vposarray[2],
+ &vdirarray[0],&vdirarray[1],&vdirarray[2],
+ &scale);
+
+ pModelPosition.iPos = Vector3(vposarray[0], vposarray[1], vposarray[2]);
+ pModelPosition.iDir = Vector3(vdirarray[0], vdirarray[1], vdirarray[2]);
+ pModelPosition.iScale = scale;
+
+ }
+ //==========================================
+
+ } // VMAP