root/trunk/src/shared/vmap/TileAssembler.cpp @ 37

Revision 2, 25.2 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19#include <G3D/Vector3.h>
20#include <G3D/Triangle.h>
21
22#include "TileAssembler.h"
23#include "CoordModelMapping.h"
24#include "ModelContainer.h"
25
26#include <limits.h>
27#include <string.h>
28
29#ifdef _ASSEMBLER_DEBUG
30FILE *g_df = NULL;
31#endif
32
33using namespace G3D;
34
35namespace VMAP
36{
37    //=================================================================
38
39    Vector3 ModelPosition::transform(const Vector3& pIn) const
40    {
41        //return(pIn);
42        Vector3 out = pIn * iScale;
43        out = izMatrix * out;
44        out = ixMatrix * out;
45        out = iyMatrix * out;
46        return(out);
47
48    }
49    //=================================================================
50
51    TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
52    {
53        iCurrentUniqueNameId = 0;
54        iFilterMethod = NULL;
55        iSrcDir = pSrcDirName;
56        iDestDir = pDestDirName;
57        //mkdir(iDestDir);
58        init();
59    }
60
61    //=================================================================
62
63    TileAssembler::~TileAssembler()
64    {
65        delete iCoordModelMapping;
66    }
67
68    //=================================================================
69
70    void TileAssembler::init()
71    {
72        iCoordModelMapping = new CoordModelMapping();
73        addWorldAreaMapId(0);                               //Azeroth
74        addWorldAreaMapId(1);                               //Kalimdor
75        addWorldAreaMapId(530);                             //Expansion01
76    }
77    //=================================================================
78
79    std::string getModNameFromModPosName(const std::string& pModPosName)
80    {
81
82        size_t spos = pModPosName.find_first_of('#');
83        std::string modelFileName = pModPosName.substr(0,spos);
84        return(modelFileName);
85    }
86
87    //=================================================================
88
89    unsigned int TileAssembler::getUniqueNameId(const std::string pName)
90    {
91        unsigned int result;
92
93        if(!iUniqueNameIds.containsKey(pName))
94        {
95            ++iCurrentUniqueNameId;
96            iUniqueNameIds.set(pName, iCurrentUniqueNameId);
97        }
98        result = iUniqueNameIds.get(pName);
99        return result;
100    }
101
102    //=================================================================
103
104    std::string TileAssembler::getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName)
105    {
106        size_t spos;
107        char buffer[20];
108
109        std::string modelFileName = getModNameFromModPosName(pModPosName);
110        //std::string fext = pModPosName.substr(modelFileName.length(),pModPosName.length());
111        unsigned int fextId = getUniqueNameId(pModPosName);
112        sprintf(buffer, "_%07d",fextId);
113        std::string fext(buffer);
114        spos = modelFileName.find_last_of('/');
115        std::string fname = modelFileName.substr(spos+1, modelFileName.length());
116        spos = fname.find_last_of('.');
117        fname = fname.substr(0,spos);
118        sprintf(buffer, "%03u", pMapId);
119        std::string dirEntry(buffer);
120        dirEntry.append("_");
121        dirEntry.append(fname);
122        dirEntry.append(fext);
123        dirEntry.append(".vmap");
124        return(dirEntry);
125    }
126
127    //=================================================================
128
129    void emptyArray(Array<ModelContainer*>& mc)
130    {
131        int no=mc.size();
132        while(no > 0)
133        {
134            --no;
135            delete mc[no];
136            mc.remove(no);
137        }
138    }
139
140    //=================================================================
141    bool TileAssembler::convertWorld()
142    {
143
144        #ifdef _ASSEMBLER_DEBUG
145        #   ifdef _DEBUG
146        ::g_df = fopen("../TileAssembler_debug.txt", "wb");
147        #   else
148        ::g_df = fopen("../TileAssembler_release.txt", "wb");
149        #   endif
150        #endif
151
152        bool result = true;
153        std::string fname = iSrcDir;
154        fname.append("/");
155        fname.append("dir");
156        iCoordModelMapping->setModelNameFilterMethod(iFilterMethod);
157        iCoordModelMapping->readCoordinateMapping(fname);
158
159        Array<unsigned int> mapIds = iCoordModelMapping->getMaps();
160        if(mapIds.size() == 0)
161        {
162            result = false;
163        }
164        for(int i=0; i<mapIds.size() && result; ++i)
165        {
166            unsigned int mapId = mapIds[i];
167
168            #ifdef _ASSEMBLER_DEBUG
169            if(mapId == 0)                                  // "Azeroth" just for debug
170            {
171                for(int x=28; x<29 && result; ++x)          //debug
172                {
173                    for(int y=28; y<29 && result; ++y)
174                    {
175                        #else
176                        // ignore DeeprunTram (369) it is too large for short vector and not important
177                        // ignore test (13), Test (29) , development (451)
178                        if(mapId != 369 && mapId != 13 && mapId != 29 && mapId != 451)
179                        {
180                            for(int x=0; x<66 && result; ++x)
181                            {
182                                for(int y=0; y<66 && result; ++y)
183                                {
184                                    #endif
185                                    Array<ModelContainer*> mc;
186                                    std::string dirname;
187                                    char buffer[100];
188                                    if(iCoordModelMapping->isWorldAreaMap(mapId) && x<65 && y<65)
189                                    {
190                                        sprintf(buffer, "%03u_%d_%d",mapId,y,x); // Let's flip x and y here
191                                        dirname = std::string(buffer);
192                                    }
193                                    else
194                                    {
195                                        sprintf(buffer, "%03u",mapId);
196                                        dirname = std::string(buffer);
197                                    }
198                                    result = fillModelContainerArray(dirname, mapId, x, y, mc);
199                                    emptyArray(mc);
200                                }
201                            }
202                        }
203                    }
204                    #ifdef _ASSEMBLER_DEBUG
205                    if(::g_df) fclose(::g_df);
206                    #endif
207
208                    return result;
209                }
210
211                //=================================================================
212
213                bool TileAssembler::fillModelContainerArray(const std::string& pDirFileName, unsigned int pMapId, int pXPos, int pYPos, Array<ModelContainer*>& pMC)
214                {
215                    bool result = true;
216                    ModelContainer* modelContainer;
217
218                    NameCollection nameCollection = iCoordModelMapping->getFilenamesForCoordinate(pMapId, pXPos, pYPos);
219                    if(nameCollection.size() > 0)
220                    {
221                        result = false;
222                        char dirfilename[500];
223                        sprintf(dirfilename,"%s/%s.vmdir",iDestDir.c_str(),pDirFileName.c_str());
224                        FILE *dirfile = fopen(dirfilename, "ab");
225                        if(dirfile)
226                        {
227                            result = true;
228                            char destnamebuffer[500];
229                            char fullnamedestnamebuffer[500];
230                            if(nameCollection.iMainFiles.size() >0)
231                            {
232                                sprintf(destnamebuffer,"%03u_%i_%i.vmap",pMapId, pYPos, pXPos); // flip it here too
233                                std::string checkDoubleStr = std::string(dirfilename);
234                                checkDoubleStr.append("##");
235                                checkDoubleStr.append(std::string(destnamebuffer));
236                                // Check, if same file already is in the same dir file
237                                if(!iCoordModelMapping->isAlreadyProcessedSingleFile(checkDoubleStr))
238                                {
239                                    iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
240                                    fprintf(dirfile, "%s\n",destnamebuffer);
241                                    sprintf(fullnamedestnamebuffer,"%s/%s",iDestDir.c_str(),destnamebuffer);
242                                    modelContainer = processNames(nameCollection.iMainFiles, fullnamedestnamebuffer);
243                                    if(modelContainer)
244                                    {
245                                        pMC.append(modelContainer);
246                                    }
247                                    else
248                                    {
249                                        result = false;
250                                    }
251                                }
252                            }
253                            // process the large singe files
254                            int pos = 0;
255                            while(result && (pos < nameCollection.iSingeFiles.size()))
256                            {
257                                std::string destFileName = iDestDir;
258                                destFileName.append("/");
259                                std::string dirEntryName = getDirEntryNameFromModName(pMapId,nameCollection.iSingeFiles[pos]);
260                                std::string checkDoubleStr = std::string(dirfilename);
261                                checkDoubleStr.append("##");
262                                checkDoubleStr.append(nameCollection.iSingeFiles[pos]);
263                                // Check, if same file already is in the same dir file
264                                if(!iCoordModelMapping->isAlreadyProcessedSingleFile(checkDoubleStr))
265                                {
266                                    iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
267                                    fprintf(dirfile, "%s\n",dirEntryName.c_str());
268                                    destFileName.append(dirEntryName);
269
270                                    Array<std::string> positionarray;
271                                    positionarray.append(nameCollection.iSingeFiles[pos]);
272
273                                    if(!iCoordModelMapping->isAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]))
274                                    {
275                                        modelContainer = processNames(positionarray, destFileName.c_str());
276                                        iCoordModelMapping->addAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]);
277                                        if(modelContainer)
278                                        {
279                                            pMC.append(modelContainer);
280                                        }
281                                        else
282                                        {
283                                            result = false;
284                                        }
285                                    }
286                                }
287                                ++pos;
288                            }
289                            fclose(dirfile);
290                        }
291                    }
292                    return(result);
293                }
294
295                //=================================================================
296
297                void removeEntriesFromTree(AABSPTree<SubModel *>* pTree)
298                {
299                    Array<SubModel *> submodelArray;
300                    pTree->getMembers(submodelArray);
301                    int no = submodelArray.size();
302                    while(no > 0)
303                    {
304                        --no;
305                        delete submodelArray[no];
306                    }
307                }
308
309                //=================================================================
310
311                ModelContainer* TileAssembler::processNames(const Array<std::string>& pPositions, const char* pDestFileName)
312                {
313                    ModelContainer *modelContainer = 0;
314
315                    Vector3 basepos = Vector3(0,0,0);
316                    AABSPTree<SubModel *>* mainTree = new AABSPTree<SubModel *>();
317
318                    int pos = 0;
319
320                    bool result = true;
321                    while(result && (pos < pPositions.size()))
322                    {
323                        std::string modelPosString = pPositions[pos];
324                        std::string modelFileName = getModNameFromModPosName(modelPosString);
325
326                        if(!fillModelIntoTree(mainTree, basepos, modelPosString, modelFileName))
327                        {
328                            result = false;
329                            break;
330                        }
331                        ++pos;
332                    }
333                    if(result && mainTree->size() > 0)
334                    {
335                        mainTree->balance();
336                        modelContainer = new ModelContainer(mainTree);
337                        modelContainer->writeFile(pDestFileName);
338                    }
339                    removeEntriesFromTree(mainTree);
340
341                    delete mainTree;
342
343                    return(modelContainer);
344                }
345
346                //=================================================================
347                bool TileAssembler::readRawFile(std::string& pModelFilename,  ModelPosition& pModelPosition, AABSPTree<SubModel *> *pMainTree)
348                {
349                    bool result = false;
350
351                    std::string filename = iSrcDir;
352                    if(filename.length() >0)
353                        filename.append("/");
354                    filename.append(pModelFilename);
355                    FILE *rf = fopen(filename.c_str(), "rb");
356                    if(!rf)
357                    {
358                        // depending on the extractor version, the data could be located in the root dir
359                        std::string baseModelFilename = pModelFilename.substr((pModelFilename.find_first_of("/")+1),pModelFilename.length());
360                        filename = iSrcDir;
361                        if(filename.length() >0)
362                            filename.append("/");
363                        filename.append(baseModelFilename);
364                        rf = fopen(filename.c_str(), "rb");
365                    }
366                    char ident[8];
367
368                    int trianglecount =0;
369
370                    #ifdef _ASSEMBLER_DEBUG
371                    int startgroup = 0;                     //2;
372                    int endgroup = INT_MAX;                 //2;
373                    fprintf(::g_df,"-------------------------------------------------\n");
374                    fprintf(::g_df,"%s\n", pModelFilename.c_str());
375                    fprintf(::g_df,"-------------------------------------------------\n");
376                    #else
377                    int startgroup = 0;
378                    int endgroup = INT_MAX;
379                    #endif
380
381                    if(rf)
382                    {
383                        if(fread(&ident, 8, 1, rf) != 1) { fclose(rf); return(false); }
384                        if(strcmp(ident, "VMAP001") == 0)
385                        {
386                            // OK, do nothing
387                        }
388                        else if(strcmp(ident, "VMAP002") == 0)
389                        {
390                            // we have to read one int. This is needed during the export and we have to skip it here
391                            int tempNVectors;
392                            if(fread(&tempNVectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
393
394                        }
395                        else
396                        {
397                            // wrong version
398                            fclose(rf);
399                            return(false);
400                        }
401                        G3D::uint32 groups;
402                        char blockId[5];
403                        blockId[4] = 0;
404                        int blocksize;
405
406                        if(fread(&groups, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
407
408                        for(int g=0;g<(int)groups;g++)
409                        {
410                            // group MUST NOT have more then 65536 indexes !! Array will have a problem with that !! (strange ...)
411                            Array<int> tempIndexArray;
412                            Array<Vector3> tempVertexArray;
413
414                            AABSPTree<Triangle> *gtree = new AABSPTree<Triangle>();
415
416                            G3D::uint32 flags;
417                            if(fread(&flags, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
418
419                            G3D::uint32 branches;
420                            if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
421                            if(strcmp(blockId, "GRP ") != 0) { fclose(rf); return(false); }
422                            if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
423                            if(fread(&branches, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
424                            for(int b=0;b<(int)branches; b++)
425                            {
426                                G3D::uint32 indexes;
427                                // indexes for each branch (not used jet)
428                                if(fread(&indexes, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
429                            }
430
431                            // ---- indexes
432                            if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
433                            if(strcmp(blockId, "INDX") != 0) { fclose(rf); return(false); }
434                            if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
435                            unsigned int nindexes;
436                            if(fread(&nindexes, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
437                            if(nindexes >0)
438                            {
439                                unsigned short *indexarray = new unsigned short[nindexes*sizeof(unsigned short)];
440                                if(fread(indexarray, sizeof(unsigned short), nindexes, rf) != nindexes) { fclose(rf); return(false); }
441                                for(int i=0;i<(int)nindexes; i++)
442                                {
443                                    unsigned short val = indexarray[i];
444                                    tempIndexArray.append(val);
445                                }
446                                delete indexarray;
447                            }
448
449                            // ---- vectors
450                            if(fread(&blockId, 4, 1, rf) != 1) {fclose(rf); return(false); }
451                            if(strcmp(blockId, "VERT") != 0) { fclose(rf); return(false); }
452                            if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
453                            unsigned int nvectors;
454                            if(fread(&nvectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
455                            float *vectorarray = 0;
456                            if(nvectors >0)
457                            {
458                                vectorarray = new float[nvectors*sizeof(float)*3];
459                                if(fread(vectorarray, sizeof(float)*3, nvectors, rf) != nvectors) { fclose(rf); return(false); }
460                            }
461                            // ----- liquit
462                            if(flags & 1)
463                            {
464                                // we have liquit -> not handled yet ... skip
465                                if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
466                                if(strcmp(blockId, "LIQU") != 0) { fclose(rf); return(false); }
467                                if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
468                                fseek(rf, blocksize, SEEK_CUR);
469                            }
470
471                            for(unsigned int i=0, indexNo=0; indexNo<nvectors; indexNo++)
472                            {
473                                Vector3 v = Vector3(vectorarray[i+2], vectorarray[i+1], vectorarray[i+0]);
474                                i+=3;
475                                v = pModelPosition.transform(v);
476
477                                float swapy = v.y;
478                                v.y = v.x;
479                                v.x = swapy;
480
481                                tempVertexArray.append(v);
482                            }
483
484                            // ---- calculate triangles
485                            int rest = nindexes%3;
486                            if(rest != 0)
487                            {
488                                nindexes -= rest;
489                            }
490
491                            for(unsigned int i=0;i<(nindexes);)
492                            {
493                                Triangle t = Triangle(tempVertexArray[tempIndexArray[i+2]], tempVertexArray[tempIndexArray[i+1]], tempVertexArray[tempIndexArray[i+0]] );
494                                i+=3;
495                                ++trianglecount;
496                                if(g>= startgroup && g <= endgroup)
497                                {
498                                    gtree->insert(t);
499                                }
500                            }
501
502                            if(vectorarray != 0)
503                            {
504                                delete vectorarray;
505                            }
506
507                            if(gtree->size() >0)
508                            {
509                                gtree->balance();
510                                SubModel *sm = new SubModel(gtree);
511                                #ifdef _ASSEMBLER_DEBUG
512                                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());
513                                if(sm->getNTriangles() !=  gtree->memberTable.size())
514                                {
515                                    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());
516                                }
517                                #endif
518                                sm->setBasePosition(pModelPosition.iPos);
519                                pMainTree->insert(sm);
520                            }
521                            delete gtree;
522                        }
523                        fclose(rf);
524                        result = true;
525                    }
526                    return(result);
527                }
528
529                //=================================================================
530
531                bool TileAssembler::fillModelIntoTree(AABSPTree<SubModel *> *pMainTree, const Vector3& pBasePos, std::string& pPos, std::string& pModelFilename)
532                {
533                    bool result = false;
534                    ModelPosition modelPosition;
535                    getModelPosition(pPos, modelPosition);
536                    // all should be relative to object base position
537                    modelPosition.moveToBasePos(pBasePos);
538
539                    modelPosition.init();
540
541                    if(readRawFile(pModelFilename,  modelPosition, pMainTree))
542                    {
543                        result = true;
544                    }
545
546                    return result;
547                }
548
549                //=================================================================
550                void TileAssembler::getModelPosition(std::string& pPosString, ModelPosition& pModelPosition)
551                {
552                    float vposarray[3];
553                    float vdirarray[3];
554                    float scale;
555
556                    size_t spos = pPosString.find_first_of('#');
557                    std::string stripedPosString = pPosString.substr(spos+1,pPosString.length());
558
559                    sscanf(stripedPosString.c_str(), "%f,%f,%f_%f,%f,%f_%f",
560                        &vposarray[0],&vposarray[1],&vposarray[2],
561                        &vdirarray[0],&vdirarray[1],&vdirarray[2],
562                        &scale);
563
564                    pModelPosition.iPos = Vector3(vposarray[0], vposarray[1], vposarray[2]);
565                    pModelPosition.iDir = Vector3(vdirarray[0], vdirarray[1], vdirarray[2]);
566                    pModelPosition.iScale = scale;
567
568                }
569                //==========================================
570
571            }                                               // VMAP
Note: See TracBrowser for help on using the browser.