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

Revision 102, 25.3 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

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