diff options
Diffstat (limited to 'src/shared/vmap/TileAssembler.cpp')
-rw-r--r-- | src/shared/vmap/TileAssembler.cpp | 770 |
1 files changed, 331 insertions, 439 deletions
diff --git a/src/shared/vmap/TileAssembler.cpp b/src/shared/vmap/TileAssembler.cpp index a79f609fa49..d01b54a7564 100644 --- a/src/shared/vmap/TileAssembler.cpp +++ b/src/shared/vmap/TileAssembler.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2005-2010 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 @@ -10,44 +8,50 @@ * * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <G3D/Vector3.h> -#include <G3D/Triangle.h> - +#include "WorldModel.h" #include "TileAssembler.h" -#include "CoordModelMapping.h" -#include "ModelContainer.h" +#include "MapTree.h" +#include "BIH.h" +#include "VMapDefinitions.h" -#include <limits.h> -#include <string.h> +#include <set> +#include <iomanip> +#include <sstream> +#include <iomanip> -#ifdef _ASSEMBLER_DEBUG -FILE *g_df = NULL; -#endif +using G3D::Vector3; +using G3D::AABox; +using G3D::inf; +using std::pair; -using namespace G3D; +template<> struct BoundsTrait<VMAP::ModelSpawn*> +{ + static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } +}; namespace VMAP { - //================================================================= + bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len) + { + if (fread(dest, sizeof(char), len, rf) != len) return false; + return memcmp(dest, compare, len) == 0; + } Vector3 ModelPosition::transform(const Vector3& pIn) const { - //return(pIn); Vector3 out = pIn * iScale; - out = izMatrix * out; - out = ixMatrix * out; - out = iyMatrix * out; + out = iRotation * out; return(out); - } + //================================================================= TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) @@ -57,320 +61,300 @@ namespace VMAP iSrcDir = pSrcDirName; iDestDir = pDestDirName; //mkdir(iDestDir); - init(); + //init(); } - //================================================================= - TileAssembler::~TileAssembler() { - delete iCoordModelMapping; + //delete iCoordModelMapping; } - //================================================================= - - void TileAssembler::init() + bool TileAssembler::convertWorld2() { - iCoordModelMapping = new CoordModelMapping(); - addWorldAreaMapId(0); //Azeroth - addWorldAreaMapId(1); //Kalimdor - addWorldAreaMapId(530); //Expansion01 - addWorldAreaMapId(571); //Expansion02 - } - //================================================================= + std::set<std::string> spawnedModelFiles; + bool success = readMapSpawns(); + if (!success) + return false; - std::string getModNameFromModPosName(const std::string& pModPosName) - { - size_t spos = pModPosName.find_first_of('#'); - std::string modelFileName = pModPosName.substr(0,spos); - return(modelFileName); - } + // export Map data + for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) + { + // build global map tree + std::vector<ModelSpawn*> mapSpawns; + UniqueEntryMap::iterator entry; + for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) + { + // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail + if (entry->second.flags & MOD_M2) + { + if (!calculateTransformedBound(entry->second)) + break; + } + else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ + { + // TODO: remove extractor hack and uncomment below line: + //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); + entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); + } + mapSpawns.push_back(&(entry->second)); + spawnedModelFiles.insert(entry->second.name); + } - //================================================================= + BIH pTree; + pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); + + // ===> possibly move this code to StaticMapTree class + std::map<uint32, uint32> modelNodeIdx; + for (uint32 i=0; i<mapSpawns.size(); ++i) + modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i)); + if (!modelNodeIdx.empty()) + printf("min GUID: %u, max GUID: %u\n", modelNodeIdx.begin()->first, modelNodeIdx.rbegin()->first); + + // write map tree file + std::stringstream mapfilename; + mapfilename << iDestDir << "/" << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; + FILE *mapfile = fopen(mapfilename.str().c_str(), "wb"); + if (!mapfile) + { + success = false; + printf("Cannot open %s\n", mapfilename.str().c_str()); + break; + } - unsigned int TileAssembler::getUniqueNameId(const std::string pName) - { - unsigned int result; + //general info + if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; + uint32 globalTileID = StaticMapTree::packTileID(65, 65); + pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID); + char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO + if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; + // Nodes + if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; + if (success) success = pTree.writeToFile(mapfile); + // global map spawns (WDT), if any (most instances) + if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; + + for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) + { + success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); + } - if(!iUniqueNameIds.containsKey(pName)) - { - ++iCurrentUniqueNameId; - iUniqueNameIds.set(pName, iCurrentUniqueNameId); - } - result = iUniqueNameIds.get(pName); - return result; - } + fclose(mapfile); - //================================================================= + // <==== - 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); - } + // write map tile files, similar to ADT files, only with extra BSP tree node info + TileMap &tileEntries = map_iter->second->TileEntries; + TileMap::iterator tile; + for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) + { + const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; + if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... + continue; + uint32 nSpawns = tileEntries.count(tile->first); + std::stringstream tilefilename; + tilefilename.fill('0'); + tilefilename << iDestDir << "/" << std::setw(3) << map_iter->first << "_"; + uint32 x, y; + StaticMapTree::unpackTileID(tile->first, x, y); + tilefilename << std::setw(2) << x << "_" << std::setw(2) << y << ".vmtile"; + FILE *tilefile = fopen(tilefilename.str().c_str(), "wb"); + // write number of tile spawns + if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; + // write tile spawns + for (uint32 s=0; s<nSpawns; ++s) + { + if (s) + ++tile; + const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; + success = success && ModelSpawn::writeToFile(tilefile, spawn2); + // MapTree nodes to update when loading tile: + std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID); + if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; + } + fclose(tilefile); + } + // break; //test, extract only first map; TODO: remvoe this line + } - //================================================================= + // export objects + std::cout << "\nConverting Model Files" << std::endl; + for (std::set<std::string>::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile) + { + std::cout << "Converting " << *mfile << std::endl; + if (!convertRawFile(*mfile)) + { + std::cout << "error converting " << *mfile << std::endl; + success = false; + break; + } + } - void emptyArray(Array<ModelContainer*>& mc) - { - int no=mc.size(); - while(no > 0) + //cleanup: + for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) { - --no; - delete mc[no]; - mc.remove(no); + delete map_iter->second; } + return success; } - //================================================================= - bool TileAssembler::convertWorld() + bool TileAssembler::readMapSpawns() { - #ifdef _ASSEMBLER_DEBUG - # ifdef _DEBUG - ::g_df = fopen("../TileAssembler_debug.txt", "wb"); - # else - ::g_df = fopen("../TileAssembler_release.txt", "wb"); - # endif - #endif - - std::string fname = iSrcDir; - fname.append("/"); - fname.append("dir"); - iCoordModelMapping->setModelNameFilterMethod(iFilterMethod); - - printf("Read coordinate mapping...\n"); - if(!iCoordModelMapping->readCoordinateMapping(fname)) - return false; - - Array<unsigned int> mapIds = iCoordModelMapping->getMaps(); - if(mapIds.size() == 0) + std::string fname = iSrcDir + "/dir_bin"; + FILE *dirf = fopen(fname.c_str(), "rb"); + if (!dirf) { - printf("Fatal error: empty map list!\n"); + printf("Could not read dir_bin file!\n"); return false; } - - for (int i=0; i<mapIds.size(); ++i) + printf("Read coordinate mapping...\n"); + uint32 mapID, tileX, tileY, check=0; + G3D::Vector3 v1, v2; + ModelSpawn spawn; + while (!feof(dirf)) { - unsigned int mapId = mapIds[i]; + check = 0; + // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name + check += fread(&mapID, sizeof(uint32), 1, dirf); + if (check == 0) // EoF... + break; + check += fread(&tileX, sizeof(uint32), 1, dirf); + check += fread(&tileY, sizeof(uint32), 1, dirf); + if (!ModelSpawn::readFromFile(dirf, spawn)) + break; - #ifdef _ASSEMBLER_DEBUG - if(mapId == 0) // "Azeroth" just for debug + MapSpawns *current; + MapData::iterator map_iter = mapData.find(mapID); + if (map_iter == mapData.end()) { - for (int x=28; x<29; ++x) //debug - { - for (int y=28; y<29; ++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; ++x) - { - for (int y=0; y<66; ++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); - printf("%s...\n",dirname.c_str()); - } - else - { - sprintf(buffer, "%03u",mapId); - dirname = std::string(buffer); - - // prevent spam for small maps - if(x==0 && y==0) - printf("%s...\n",dirname.c_str()); - } - - bool result = fillModelContainerArray(dirname, mapId, x, y, mc); - emptyArray(mc); - - if(!result) - return false; - } - } + printf("spawning Map %d\n", mapID); + mapData[mapID] = current = new MapSpawns(); } + else current = (*map_iter).second; + current->UniqueEntries.insert(pair<uint32, ModelSpawn>(spawn.ID, spawn)); + current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); } - #ifdef _ASSEMBLER_DEBUG - if(::g_df) fclose(::g_df); - #endif - - return true; + bool success = (ferror(dirf) == 0); + fclose(dirf); + return success; } - //================================================================= - - bool TileAssembler::fillModelContainerArray(const std::string& pDirFileName, unsigned int pMapId, int pXPos, int pYPos, Array<ModelContainer*>& pMC) + bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) { - ModelContainer* modelContainer; - - NameCollection nameCollection = iCoordModelMapping->getFilenamesForCoordinate(pMapId, pXPos, pYPos); - if(nameCollection.size() == 0) - return true; // no data... + std::string modelFilename = iSrcDir + "/" + spawn.name; + ModelPosition modelPosition; + modelPosition.iDir = spawn.iRot; + modelPosition.iScale = spawn.iScale; + modelPosition.init(); - char dirfilename[500]; - sprintf(dirfilename,"%s/%s.vmdir",iDestDir.c_str(),pDirFileName.c_str()); - FILE *dirfile = fopen(dirfilename, "ab"); - if(!dirfile) + FILE *rf = fopen(modelFilename.c_str(), "rb"); + if (!rf) { - printf("ERROR: Can't create file %s",dirfilename); + printf("ERROR: Can't open model file: %s\n", modelFilename.c_str()); return false; } - 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 - printf("warning: (if) problems in processing data for %s\n",destnamebuffer); - } - } - // process the large singe files - int pos = 0; - while(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); + AABox modelBound; + bool boundEmpty=true; + char ident[8]; - Array<std::string> positionarray; - positionarray.append(nameCollection.iSingeFiles[pos]); + int readOperation = 1; - if(!iCoordModelMapping->isAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos])) - { - modelContainer = processNames(positionarray, destFileName.c_str()); - iCoordModelMapping->addAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]); - if(modelContainer) - pMC.append(modelContainer); - else - printf("warning: (while) problems in processing data for %s\n",destFileName.c_str()); - } - } - ++pos; - } + // temporary use defines to simplify read/check code (close file and return at fail) + #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ + fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; + #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ + fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } - fclose(dirfile); - return true; - } + READ_OR_RETURN(&ident, 8); + CMP_OR_RETURN(ident, "VMAP003"); - //================================================================= + // we have to read one int. This is needed during the export and we have to skip it here + uint32 tempNVectors; + READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); - void removeEntriesFromTree(AABSPTree<SubModel *>* pTree) - { - Array<SubModel *> submodelArray; - pTree->getMembers(submodelArray); - int no = submodelArray.size(); - while(no > 0) - { - --no; - delete submodelArray[no]; - } - } + uint32 groups, wmoRootId; + char blockId[5]; + blockId[4] = 0; + int blocksize; + float *vectorarray = 0; - //================================================================= + READ_OR_RETURN(&groups, sizeof(uint32)); + READ_OR_RETURN(&wmoRootId, sizeof(uint32)); + if (groups != 1) printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); - ModelContainer* TileAssembler::processNames(const Array<std::string>& pPositions, const char* pDestFileName) - { - ModelContainer *modelContainer = 0; + for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... + { + fseek(rf, 3*sizeof(uint32) + 6*sizeof(float), SEEK_CUR); - Vector3 basepos = Vector3(0,0,0); - AABSPTree<SubModel *>* mainTree = new AABSPTree<SubModel *>(); + READ_OR_RETURN(&blockId, 4); + CMP_OR_RETURN(blockId, "GRP "); + READ_OR_RETURN(&blocksize, sizeof(int)); + fseek(rf, blocksize, SEEK_CUR); - int pos = 0; + // ---- indexes + READ_OR_RETURN(&blockId, 4); + CMP_OR_RETURN(blockId, "INDX"); + READ_OR_RETURN(&blocksize, sizeof(int)); + fseek(rf, blocksize, SEEK_CUR); - bool result = true; - while(result && (pos < pPositions.size())) - { - std::string modelPosString = pPositions[pos]; - std::string modelFileName = getModNameFromModPosName(modelPosString); + // ---- vectors + READ_OR_RETURN(&blockId, 4); + CMP_OR_RETURN(blockId, "VERT"); + READ_OR_RETURN(&blocksize, sizeof(int)); + uint32 nvectors; + READ_OR_RETURN(&nvectors, sizeof(uint32)); - if(!fillModelIntoTree(mainTree, basepos, modelPosString, modelFileName)) + if (nvectors >0) { - result = false; - break; + vectorarray = new float[nvectors*3]; + READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); + } + else + { + std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; + return false; } - ++pos; - } - if(result && mainTree->size() > 0) - { - mainTree->balance(); - modelContainer = new ModelContainer(mainTree); - modelContainer->writeFile(pDestFileName); - } - removeEntriesFromTree(mainTree); - delete mainTree; + for (uint32 i=0, indexNo=0; indexNo<nvectors; indexNo++, i+=3) + { + Vector3 v = Vector3(vectorarray[i+0], vectorarray[i+1], vectorarray[i+2]); + v = modelPosition.transform(v); - return(modelContainer); + if (boundEmpty) + modelBound = AABox(v, v), boundEmpty=false; + else + modelBound.merge(v); + } + delete[] vectorarray; + // drop of temporary use defines + #undef READ_OR_RETURN + #undef CMP_OR_RETURN + } + spawn.iBound = modelBound + spawn.iPos; + spawn.flags |= MOD_HAS_BOUND; + fclose(rf); + return true; } + struct WMOLiquidHeader + { + int xverts, yverts, xtiles, ytiles; + float pos_x; + float pos_y; + float pos_z; + short type; + }; //================================================================= - bool TileAssembler::readRawFile(std::string& pModelFilename, ModelPosition& pModelPosition, AABSPTree<SubModel *> *pMainTree) + bool TileAssembler::convertRawFile(const std::string& pModelFilename) { + bool success = true; std::string filename = iSrcDir; - if(filename.length() >0) + 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"); - } - if(!rf) + if (!rf) { printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str()); printf("... or form: %s",filename.c_str() ); @@ -379,95 +363,74 @@ namespace VMAP 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 + int readOperation = 1; // temporary use defines to simplify read/check code (close file and return at fail) #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ - fclose(rf); return(false); } + fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ - fclose(rf); return(false); } + fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } READ_OR_RETURN(&ident, 8); - 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; - READ_OR_RETURN(&tempNVectors, sizeof(int)); + CMP_OR_RETURN(ident, "VMAP003"); - } - else - { - // wrong version - fclose(rf); - return(false); - } - G3D::uint32 groups; + // we have to read one int. This is needed during the export and we have to skip it here + uint32 tempNVectors; + READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); + + uint32 groups; + uint32 RootWMOID; char blockId[5]; blockId[4] = 0; int blocksize; - READ_OR_RETURN(&groups, sizeof(G3D::uint32)); + READ_OR_RETURN(&groups, sizeof(uint32)); + READ_OR_RETURN(&RootWMOID, sizeof(uint32)); - for (int g=0; g<(int)groups; g++) + std::vector<GroupModel> groupsArray; + + for (uint32 g=0; g<groups; ++g) { - // group MUST NOT have more then 65536 indexes !! Array will have a problem with that !! (strange ...) - Array<int> tempIndexArray; - Array<Vector3> tempVertexArray; + std::vector<MeshTriangle> triangles; + std::vector<Vector3> vertexArray; - AABSPTree<Triangle> *gtree = new AABSPTree<Triangle>(); + uint32 mogpflags, GroupWMOID; + READ_OR_RETURN(&mogpflags, sizeof(uint32)); + READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); - // add free gtree at fail - #undef READ_OR_RETURN - #undef CMP_OR_RETURN - #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ - fclose(rf); delete gtree; return(false); } - #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ - fclose(rf); delete gtree; return(false); } + float bbox1[3], bbox2[3]; + READ_OR_RETURN(bbox1, sizeof(float)*3); + READ_OR_RETURN(bbox2, sizeof(float)*3); - G3D::uint32 flags; - READ_OR_RETURN(&flags, sizeof(G3D::uint32)); + uint32 liquidflags; + READ_OR_RETURN(&liquidflags, sizeof(uint32)); - G3D::uint32 branches; + // will this ever be used? what is it good for anyway?? + uint32 branches; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "GRP "); READ_OR_RETURN(&blocksize, sizeof(int)); - READ_OR_RETURN(&branches, sizeof(G3D::uint32)); - for (int b=0; b<(int)branches; b++) + READ_OR_RETURN(&branches, sizeof(uint32)); + for (uint32 b=0; b<branches; ++b) { - G3D::uint32 indexes; + uint32 indexes; // indexes for each branch (not used jet) - READ_OR_RETURN(&indexes, sizeof(G3D::uint32)); + READ_OR_RETURN(&indexes, sizeof(uint32)); } // ---- indexes READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "INDX"); READ_OR_RETURN(&blocksize, sizeof(int)); - unsigned int nindexes; - READ_OR_RETURN(&nindexes, sizeof(G3D::uint32)); - if(nindexes >0) + uint32 nindexes; + READ_OR_RETURN(&nindexes, sizeof(uint32)); + if (nindexes >0) { - unsigned short *indexarray = new unsigned short[nindexes*sizeof(unsigned short)]; - READ_OR_RETURN(indexarray, nindexes*sizeof(unsigned short)); - for (int i=0; i<(int)nindexes; i++) + uint16 *indexarray = new uint16[nindexes]; + READ_OR_RETURN(indexarray, nindexes*sizeof(uint16)); + for (uint32 i=0; i<nindexes; i+=3) { - unsigned short val = indexarray[i]; - tempIndexArray.append(val); + triangles.push_back(MeshTriangle(indexarray[i], indexarray[i+1], indexarray[i+2])); } delete[] indexarray; } @@ -476,127 +439,56 @@ namespace VMAP READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "VERT"); READ_OR_RETURN(&blocksize, sizeof(int)); - unsigned int nvectors; - READ_OR_RETURN(&nvectors, sizeof(int)); - - float *vectorarray = 0; - - // add vectorarray free - #undef READ_OR_RETURN - #undef CMP_OR_RETURN - #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ - fclose(rf); delete gtree; delete[] vectorarray; return(false); } - #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ - fclose(rf); delete gtree; delete[] vectorarray; return(false); } + uint32 nvectors; + READ_OR_RETURN(&nvectors, sizeof(uint32)); - if(nvectors >0) + if (nvectors >0) { - vectorarray = new float[nvectors*sizeof(float)*3]; + float *vectorarray = new float[nvectors*3]; READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); + for (uint32 i=0; i<nvectors; ++i) + { + vertexArray.push_back( Vector3(vectorarray + 3*i) ); + } + delete[] vectorarray; } - // ----- liquit - if(flags & 1) + // ----- liquid + WmoLiquid *liquid = 0; + if (liquidflags& 1) { - // we have liquit -> not handled yet ... skip + WMOLiquidHeader hlq; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "LIQU"); READ_OR_RETURN(&blocksize, sizeof(int)); - fseek(rf, blocksize, SEEK_CUR); + READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader)); + liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type); + uint32 size = hlq.xverts*hlq.yverts; + READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float)); + size = hlq.xtiles*hlq.ytiles; + READ_OR_RETURN(liquid->GetFlagsStorage(), size); } - 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); - } - } + groupsArray.push_back(GroupModel(mogpflags, GroupWMOID, AABox(Vector3(bbox1), Vector3(bbox2)))); + groupsArray.back().setMeshData(vertexArray, triangles); + groupsArray.back().setLiquidData(liquid); // drop of temporary use defines #undef READ_OR_RETURN #undef CMP_OR_RETURN - 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); - return true; - } - - //================================================================= - - bool TileAssembler::fillModelIntoTree(AABSPTree<SubModel *> *pMainTree, const Vector3& pBasePos, std::string& pPos, std::string& pModelFilename) - { - ModelPosition modelPosition; - getModelPosition(pPos, modelPosition); - // all should be relative to object base position - modelPosition.moveToBasePos(pBasePos); - modelPosition.init(); - - return readRawFile(pModelFilename, modelPosition, pMainTree); - } - - //================================================================= - 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; + // write WorldModel + WorldModel model; + model.setRootWmoID(RootWMOID); + if (groupsArray.size()) + { + model.setGroupModels(groupsArray); + success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); + } + //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; + return success; } - //========================================== -} // VMAP +} |