diff options
author | Neo2003 <none@none> | 2008-10-02 16:23:55 -0500 |
---|---|---|
committer | Neo2003 <none@none> | 2008-10-02 16:23:55 -0500 |
commit | 9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch) | |
tree | b5d1ba94a656e6679f8737f9ea6bed1239b73b14 /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.cpp | 571 |
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 |