From e77716188861d4aa83b227a90e04a66b63baeb1f Mon Sep 17 00:00:00 2001 From: click Date: Sat, 5 Jun 2010 00:59:25 +0200 Subject: HIGHLY EXPERIMENTAL - USE AT YOUR OWN RISK Implement the use of the new vmap3-format by Lynx3d (mad props to you for this, and thanks for the talks earlier) + reduced Vmap size to less than one third, and improve precision + indoor/outdoor check which allows automatic unmounting of players + additional area information from WMOAreaTable.dbc, removed existing "hacks" + WMO liquid information for swimming and fishing correctly in buildings/cities/caves/instances (lava and slime WILL hurt from now on!) - buildfiles for windows are not properly done, and will need to be sorted out NOTE: Do NOT annoy Lynx3d about this, any issues with this "port" is entirely our fault ! THIS REVISION IS CONSIDERED UNSTABLE AND CONTAINS WORK IN PROGRESS - USE AT YOUR OWN RISK! --HG-- branch : trunk --- src/shared/vmap/TileAssembler.cpp | 770 ++++++++++++++++---------------------- 1 file changed, 331 insertions(+), 439 deletions(-) (limited to 'src/shared/vmap/TileAssembler.cpp') 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 - * - * Copyright (C) 2008-2010 Trinity + * Copyright (C) 2005-2010 MaNGOS * * 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 -#include - +#include "WorldModel.h" #include "TileAssembler.h" -#include "CoordModelMapping.h" -#include "ModelContainer.h" +#include "MapTree.h" +#include "BIH.h" +#include "VMapDefinitions.h" -#include -#include +#include +#include +#include +#include -#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 +{ + 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 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 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::getBounds); + + // ===> possibly move this code to StaticMapTree class + std::map modelNodeIdx; + for (uint32 i=0; i(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 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; ssecond->UniqueEntries[tile->second]; + success = success && ModelSpawn::writeToFile(tilefile, spawn2); + // MapTree nodes to update when loading tile: + std::map::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::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& 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 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 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(spawn.ID, spawn)); + current->TileEntries.insert(pair(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& 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 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* pTree) - { - Array 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& pPositions, const char* pDestFileName) - { - ModelContainer *modelContainer = 0; + for (uint32 g=0; g* mainTree = new AABSPTree(); + 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 *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 groupsArray; + + for (uint32 g=0; g tempIndexArray; - Array tempVertexArray; + std::vector triangles; + std::vector vertexArray; - AABSPTree *gtree = new AABSPTree(); + 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; b0) + 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; i0) + 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 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= 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 *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 +} -- cgit v1.2.3