root/trunk/extras/map_extractor/adt.cpp @ 3153

Revision 3153, 14.2 kB (checked in by Hoffa, 7 months ago)

Applied 3.3.2 misc fixes by Terrorblade -> http://arcemu.org/forums/index.php?showtopic=20707

  • Property svn:eol-style set to native
  • Property ff set to
    *.asax = svn:eol-style=native
    *.ascx = svn:eol-style=native
    *.aspx = svn:eol-style=native
    *.asmx = svn:eol-style=native
    *.ashx = svn:eol-style=native
    *.asp = svn:eol-style=native
    *.browser = svn:eol-style=native
    *.build = svn:eol-style=native
    *.c = svn:eol-style=native
    *.config = svn:eol-style=native
    *.cpp = svn:eol-style=native
    *.cs = svn:eol-style=native
    *.csproj = svn:eol-style=native
    *.css = svn:eol-style=native
    *.cfc = svn:eol-style=native
    *.cfm = svn:eol-style=native
    *.cst = svn:eol-style=native
    *.dll = svn:executable
    *.exe = svn:executable
    *.h = svn:eol-style=native
    *.htc = svn:eol-style=native
    *.html = svn:eol-style=native
    *.htm = svn:eol-style=native
    *.jpg = svn:mime-type=image/jpeg
    *.jpeg = svn:mime-type=image/jpeg
    *.js = svn:eol-style=native
    *.mds = svn:eol-style=native
    *.mdp = svn:eol-style=native
    *.php = svn:eol-style=native
    *.pl = svn:eol-style=native
    *.png = svn:mime-type=image/png
    *.rest = svn:eol-style=native
    *.resx = svn:eol-style=native
    *.sh = svn:eol-style=native;svn:executable
    *.skin = svn:eol-style=native
    *.sln = svn:eol-style=native
    *.sql = svn:eol-style=native
    *.svg = svn:eol-style=native
    *.txt = svn:eol-style=native
    *.theme = svn:eol-style=native
    *.vb = svn:eol-style=native
    *.xml = svn:eol-style=native
    *.xsd = svn:eol-style=native
    *.xsl = svn:eol-style=native
    Makefile = svn:eol-style=native
    README = svn:eol-style=native
    CHANGELOG = svn:eol-style=native
    LICENSE = svn:eol-style=native
Line 
1#ifdef WIN32
2#include <windows.h>
3#endif
4
5#include <string.h>
6#include <stdio.h>
7#include <math.h>
8#include <string>
9#include <map>
10#include <vector>
11#include <set>
12
13#include "adt.h"
14#include "mpq_libmpq.h"
15
16//#include <windows.h>
17unsigned int iRes=256;
18extern uint16*areas;
19
20#define SMALL_MAPFILES
21#define PACK_MAPS
22#define MAP_RESOLUTION 256
23
24#define TilesCount 64
25#define TileSize 533.33333f
26#define _minY (-TilesCount*TileSize/2)
27#define _minX (-TilesCount*TileSize/2)
28
29#define _maxY (TilesCount*TileSize/2)
30#define _maxX (TilesCount*TileSize/2)
31
32#define CellsPerTile 8
33#define _cellSize (TileSize/CellsPerTile)
34#define _sizeX (TilesCount*CellsPerTile)
35#define _sizeY (TilesCount*CellsPerTile)
36
37//#pragma pack(push, 1)
38
39typedef struct
40{
41    uint16    AreaID[16/CellsPerTile][16/CellsPerTile];
42    uint8    LiquidType[16/CellsPerTile][16/CellsPerTile];
43    float    LiquidLevel[16/CellsPerTile][16/CellsPerTile];
44    float    Z[MAP_RESOLUTION/CellsPerTile][MAP_RESOLUTION/CellsPerTile];
45}MapCellInfo; 
46
47
48///This is temp. method.
49typedef struct
50{
51    uint16    AreaID[16][16];
52    uint8    LiquidType[16][16];
53    float    LiquidLevel[16][16];
54    float    Z[MAP_RESOLUTION][MAP_RESOLUTION];
55}MapTileInfo; 
56
57typedef struct
58{
59    float z[256][256];
60}zstore;
61//#pragma pack(pop)
62vec wmoc;
63
64Cell * cell;
65uint32 wmo_count;
66mcell *mcells;
67zstore * cz;
68
69mcell * mcell_cache[64][64];
70zstore * cell_cache[64][64];
71
72typedef struct
73{
74    uint32 ofsInformation;
75    uint32 layerCount;
76    uint32 ofsData;
77}MH2Oheader;
78
79typedef struct
80{
81    uint16 type;
82    uint16 flags;
83    float levels[2];
84    char x, y, w, h;
85    uint32 offsData2a;
86    uint32 offsData2b;
87}MH2Oinformation;
88
89
90void reset()
91{
92    for(uint32 i = 0; i < 64; ++i)
93    {
94        for(uint32 j = 0; j < 64; ++j)
95        {
96            mcell_cache[i][j] = 0;
97            cell_cache[i][j] = 0;
98        }
99    }
100}
101void CleanCache()
102{
103    for(uint32 i = 0; i < 64; ++i)
104    {
105        for(uint32 j = 0; j < 64; ++j)
106        {
107            if(cell_cache[i][j] != 0)
108            {
109                delete cell_cache[i][j];
110                cell_cache[i][j] = 0;
111            }
112
113            if(mcell_cache[i][j] != 0)
114            {
115                delete mcell_cache[i][j];
116                mcell_cache[i][j] = 0;
117            }
118
119        }
120    }
121}
122
123bool LoadADT(char* filename)
124{
125        size_t size;
126        MPQFile mf(filename);
127
128        if(mf.isEof ())
129        {
130                //printf("No such file.\n");   
131                return false;
132        }
133        mcells=new mcell;
134
135        wmoc.x =65*TILESIZE;
136        wmoc.z =65*TILESIZE;
137
138        size_t mcnk_offsets[256], mcnk_sizes[256];
139
140        MH2Oheader mh2oheader[256]; memset(&mh2oheader,0,sizeof(MH2Oheader)*256);
141        uint32 mh2o_base=0;
142
143        wmo_count=0;
144        bool found=false;
145        //uint32 fs=mf.getSize ()-3;
146        //while (mf.getPos ()<fs)
147        while (!mf.isEof  ())
148        {
149                uint32 fourcc;         
150                mf.read(&fourcc,4);
151                mf.read(&size, 4);
152
153                size_t nextpos = mf.getPos () + size;
154                if(fourcc==0x4d43494e) //MCIN
155                {
156                //      printf("Found chunks info\n");
157                        // mapchunk offsets/sizes
158                        for (int i=0; i<256; i++)
159                        {
160                                mf.read(&mcnk_offsets[i],4);
161                                mf.read(&mcnk_sizes[i],4);
162                                mf.seekRelative(8);
163                        }
164                //break;
165                }
166                else 
167                if(fourcc==0x4d48324f) //MH2O
168                {
169                        mh2o_base=mf.getPos();
170                        for (int i=0; i<256; i++)
171                        {
172                                mf.read(&mh2oheader[i],sizeof(MH2Oheader));
173                        }
174                //break;
175                }
176                else 
177                        if(fourcc==0x4d4f4446) //MODF
178                        {
179                       
180                        /*      if(size)
181                                {       
182                                        //printf("\nwmo count %d\n",size/64);
183                                        wmo_count =size/64;
184                                        for (int i=0; i<wmo_count; i++)
185                                        {
186                                                int id;
187                                                mf.read(&id, 4);
188                                                WMO *wmo = (WMO*)wmomanager.items[wmomanager.get(wmos[id])];
189                                                WMOInstance inst(wmo, mf);
190                                                wmois.push_back(inst);
191                                        }
192
193                                }*/
194                       
195                        }else 
196                        if(fourcc==0x4d574d4f)//mwmo
197                        {
198                                /*if (size)
199                                {
200                                        char *buf = new char[size];
201                                        mf.read(buf, size);
202                                        char *p=buf;
203                                        while (p<buf+size)
204                                        {
205                                        std::string path(p);
206                                                p+=strlen(p)+1;
207                                                fixname(path);
208                                               
209                                                wmomanager.add(path);
210                                                wmos.push_back(path);
211                                        }
212                                        delete[] buf;
213                            }*/
214                        }
215                //      else mf.seekRelative(-3);
216
217                mf.seek(nextpos);
218        }
219                //printf("Loading chunks info\n");
220                // read individual map chunks
221                for (int j=0; j<16; j++) 
222                        for (int i=0; i<16; i++) 
223                        {
224
225                                mf.seek((int)mcnk_offsets[j*16+i]);
226                                LoadMapChunk (mf,&(mcells->ch [i][j]));
227
228                                if (mh2oheader[j*16+i].layerCount>0) {
229                                        mf.seek((int)mh2oheader[j*16+i].ofsInformation+mh2o_base);
230                                        LoadH2OChunk(mf,&(mcells->ch [i][j]),mh2o_base);
231                                }
232
233                        }
234
235                /*      for(uint32 t=0;t<wmo_count ;t++)
236                        {
237                                wmois[t].draw ();
238
239                        }*/
240        mf.close ();
241        return true;
242}
243
244
245
246struct MapChunkHeader {
247        uint32 flags;
248        uint32 ix;
249        uint32 iy;
250        uint32 nLayers;
251        uint32 nDoodadRefs;
252        uint32 ofsHeight;
253        uint32 ofsNormal;
254        uint32 ofsLayer;
255        uint32 ofsRefs;
256        uint32 ofsAlpha;
257        uint32 sizeAlpha;
258        uint32 ofsShadow;
259        uint32 sizeShadow;
260        uint32 areaid;
261        uint32 nMapObjRefs;
262        uint32 holes;
263        uint16 s1;
264        uint16 s2;
265        uint32 d1;
266        uint32 d2;
267        uint32 d3;
268        uint32 predTex;
269        uint32 nEffectDoodad;
270        uint32 ofsSndEmitters;
271        uint32 nSndEmitters;
272        uint32 ofsLiquid;
273        uint32 sizeLiquid;
274        float  zpos;
275        float  xpos;
276        float  ypos;
277        uint32 textureId;
278        uint32 props;
279        uint32 effectId;
280};
281
282
283inline
284void LoadMapChunk(MPQFile & mf, chunk*_chunk)
285{
286       
287        float h;
288        uint32 fourcc;
289        uint32 size;
290        MapChunkHeader header;
291       
292        mf.seekRelative(4);
293        mf.read(&size, 4);
294
295        size_t lastpos = mf.getPos() + size;
296        mf.read(&header, 0x80);
297        _chunk->area_id =header.areaid ;
298        _chunk->flag =0;
299
300        float xbase = header.xpos;
301        float ybase = header.ypos;
302        float zbase = header.zpos;
303        zbase = TILESIZE*32-zbase;
304        xbase = TILESIZE*32-xbase;
305        if(wmoc.x >xbase)wmoc.x =xbase;
306        if(wmoc.z >zbase)wmoc.z =zbase;
307        int chunkflags = header.flags;
308        float zmin=999999999.0f;
309        float zmax=-999999999.0f;
310        //must be there, bl!zz uses some crazy format
311        int nTextures;
312        while (mf.getPos ()<lastpos)
313        {
314                mf.read(&fourcc,4);
315                mf.read(&size, 4);
316        //      if(size!=580)
317        //      printf("\n sz=%d",size);
318                size_t nextpos = mf.getPos()  + size;
319                if(fourcc==0x4d435654) //MCVT
320                 {
321                        for (int j=0; j<17; j++)
322                        for (int i=0; i<((j%2)?8:9); i++) 
323                                {
324                                        mf.read(&h,4);
325                                        float z=h+ybase;
326                                        if (j%2)
327                                                _chunk->v8[i][j/2] = z;
328                                        else
329                                                _chunk->v9[i][j/2] = z;
330
331                                        if(z>zmax)zmax=z;
332                                //      if(z<zmin)zmin=z;
333                                }
334                }
335                 else
336                        if(fourcc==0x4d434e52) //MCNR
337                        {
338                        nextpos = mf.getPos() + 0x1C0; // size fix
339
340                        }
341            if(fourcc=0xefb88b70)
342            {
343             nextpos = mf.getPos() + 0x1199;
344            }
345
346                else
347                        /*if(fourcc==0x4d434c51) //MCLQ
348                        {
349                                // liquid / water level
350                        //      bool haswater;
351                                char fcc1[5];
352                                mf.read(fcc1,4);
353                                flipcc(fcc1);
354                                fcc1[4]=0;
355
356                                if (!strcmp(fcc1,"MCSE"))
357                {
358                    for(int i=0;i<9;i++)
359                        for(int j=0;j<9;j++)
360                            _chunk->waterlevel[i][j]=-999999; // no liquid/water
361                }
362                else
363                                {
364                    float maxheight;
365                    mf.read(&maxheight, 4);
366                                       
367                    for(int j=0;j<9;j++)
368                        for(int i=0;i<9;i++)
369                        {
370                            mf.read(&h, 4);
371                            mf.read(&h, 4);
372                            if(h > maxheight)
373                                _chunk->waterlevel[i][j]=-999999;
374                            else
375                                _chunk->waterlevel[i][j]=h;
376                        }
377
378                    if(chunkflags & 4 || chunkflags & 8)
379                                                _chunk->flag |=1;
380                                        if(chunkflags & 16)
381                                                _chunk->flag |=2;
382
383
384
385                                }
386                               
387
388                        break;*/
389            if(fourcc==0x4d434c51) //MCLQ
390            {
391                // liquid / water level
392                //      bool haswater;
393                char fcc1[5];
394                mf.read(fcc1,4);
395                flipcc(fcc1);
396                fcc1[4]=0;
397                if (strcmp(fcc1,"MCSE"))
398
399                    //  if(size)
400
401
402
403
404
405                {
406                    //chunkflag
407
408
409                    mf.seekRelative(-4);
410                    mf.read(&_chunk->waterlevel,4);
411
412
413
414
415
416
417
418
419
420                    /*if(chunkflags & 4 || chunkflags & 8)
421                        _chunk->flag |=1;
422                    if(chunkflags & 16)
423                        _chunk->flag |=2;*/
424                    if(!_chunk->flag)
425                        _chunk->flag = chunkflags;
426                    else
427                        printf("%02X", _chunk->flag);
428
429
430
431                }
432
433
434                break;
435                        }else if (fourcc==0x4d434c59) //MCLY
436                        {
437                        // texture info
438                        nTextures = (int)size;
439                        }else if (fourcc==0x4d43414c) //MCAL
440                        {
441                       
442                        if (nTextures<=0) 
443                        continue;
444                        }
445               
446
447
448                mf.seek(nextpos);
449        }
450       
451       
452        printf("");
453}
454
455
456inline
457void LoadH2OChunk(MPQFile & mf, chunk*_chunk, uint32 base)
458{
459        MH2Oinformation mh2oinfo; memset(&mh2oinfo,0,sizeof(MH2Oinformation));
460        mf.read(&mh2oinfo,sizeof(MH2Oinformation));
461//      if (mh2oinfo.w>0 && mh2oinfo.h>0) { //Cell has some water...
462                //If the type flag does not contain the water bit, and the cell has lake(0) or ocean(2) water, then set it, as this was the old flag for fishable water for the MCLQ structure - compatibility above all.
463                if ( (_chunk->flag&1)==0 && (mh2oinfo.type==0 || mh2oinfo.type==2) ) _chunk->flag|=1;
464                if ( (_chunk->flag&1)==0 && mh2oinfo.type==5 && (mh2oinfo.flags==0 || mh2oinfo.flags==2)) _chunk->flag|=1;
465                //The two liquid levels are sometimes NOT equal; if they define the highest and lowest levels, then choose the lowest one for fishing; but for now this will be sufficient.
466                if ( mh2oinfo.flags & 2 ) _chunk->waterlevel=mh2oinfo.levels[0];
467                else if (mh2oinfo.offsData2b) {
468                        mf.seek((int)mh2oinfo.offsData2b+base);
469                        float level;
470                        mf.read(&level, 4);
471                        _chunk->waterlevel=level;
472                } else _chunk->waterlevel=mh2oinfo.levels[0]; //Better than nothing.
473//      } else { //No water here - this should be impossible, as in this case this part wouldn't even exist and layerCount would be zero, but it's better to be prepared for everything.
474//              _chunk->waterlevel=-999999;
475//      }
476
477        return;
478}
479
480
481double solve (vec *v,vec *p)
482{
483double a = v[0].y *(v[1].z - v[2].z) + v[1].y *(v[2].z - v[0].z) + v[2].y *(v[0].z - v[1].z);
484double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x);
485double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y);
486double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z);
487//-d
488
489//plane equation ax+by+cz+d=0
490return ((a*p->x+c*p->z-d)/b);
491}
492
493
494inline
495double GetZ(double x,double z)
496{
497
498        vec v[3];
499        vec p;
500       
501        //bool inWMO=false;
502       
503        //if(!inWMO)
504        {
505                //find out quadrant
506                int xc=(int)(x/UNITSIZE);
507                int zc=(int)(z/UNITSIZE);
508                if(xc>127)xc=127;
509                if(zc>127)zc=127;
510
511                double lx=x-xc*UNITSIZE;
512                double lz=z-zc*UNITSIZE;
513                p.x=lx;
514                p.z=lz;
515       
516
517                v[0].x=UNITSIZE/2;
518                v[0].y =cell->v8[xc][zc];
519                v[0].z=UNITSIZE/2;
520
521       
522                if(lx>lz)
523                {
524                                v[1].x=UNITSIZE;
525                                v[1].y =cell->v9[xc+1][zc];
526                                v[1].z=0;
527                }else
528                {
529                                v[1].x=0.0;
530                                v[1].y =cell->v9[xc][zc+1];
531                                v[1].z=UNITSIZE;
532                }
533
534                if(lz>UNITSIZE-lx)
535                {
536                                v[2].x=UNITSIZE;
537                                v[2].y =cell->v9[xc+1][zc+1];
538                                v[2].z=UNITSIZE;
539
540                }else
541                {
542                                v[2].x=0;
543                                v[2].y=cell->v9[xc][zc];
544                                v[2].z=0;
545                }
546
547                return -solve(v,&p);
548        }
549       
550}
551
552/*inline
553void TransformWaterData()
554{
555    cell= new Cell;
556
557    for(int x=0;x<128;x++)
558        for(int y=0;y<128;y++)
559            cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8];
560
561    //and the last 1
562    cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8];
563}*/
564
565inline
566void TransformData()
567{
568        cell= new Cell;
569
570        for(int x=0;x<128;x++)
571        {
572                for(int y=0;y<128;y++)
573                {
574            cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8];
575            cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8];
576                }
577
578                //extra 1 point on bounds
579                cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8];
580                //x==y
581                cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8];
582
583        }
584
585
586        //and the last 1
587        cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
588}
589
590bool ConvertADT(uint32 x, uint32 y, FILE * out_file, char* name)
591{
592    // Figure out what rock we're under :P
593    uint32 tile_x = x / CellsPerTile;
594    uint32 tile_y = y / CellsPerTile;
595
596    // For some odd reason, this stuff is reversed.. who knows why..
597    char mpq_filename[256];
598    sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", name, name, tile_y, tile_x);
599   
600    // See if we have it cached first.
601    if(mcell_cache[tile_y][tile_x] == 0 && cell_cache[tile_y][tile_x] == 0)
602    {
603        if(!LoadADT(mpq_filename))
604            return false;
605
606        TransformData();
607        mcell_cache[tile_y][tile_x] = mcells;
608
609        // Cache z information.
610        cz = new zstore;
611        for(uint32 cx = 0; cx < MAP_RESOLUTION; ++cx)
612        {
613            for(uint32 cy = 0; cy < MAP_RESOLUTION; ++cy)
614            {
615                float cfz=(float)GetZ(
616                    (((double)(cy))*TILESIZE)/((double)(iRes-1)),
617                    (((double)(cx))*TILESIZE)/((double)(iRes-1)));
618                cz->z[cx][cy] = cfz;
619            }
620        }
621
622        cell_cache[tile_y][tile_x] = cz;
623        delete cell;
624    }
625    else
626    {
627        mcells = mcell_cache[tile_y][tile_x];
628        cz = cell_cache[tile_y][tile_x];
629    }
630
631    // This is our output data.
632    MapCellInfo out;
633
634    // Write out the area/water information.
635    for(uint32 xc=(x%CellsPerTile)*16/CellsPerTile;xc<(x%CellsPerTile)*16/CellsPerTile+16/CellsPerTile;xc++)
636    {
637        for(uint32 yc=(y%CellsPerTile)*16/CellsPerTile;yc<(y%CellsPerTile)*16/CellsPerTile+16/CellsPerTile;yc++)
638        {
639            uint32 lx=xc%(16/CellsPerTile);
640            uint32 ly=yc%(16/CellsPerTile);
641            out.AreaID[lx][ly] = mcells->ch[yc][xc].area_id;
642            out.LiquidType[lx][ly] = mcells->ch[yc][xc].flag;
643            out.LiquidLevel[lx][ly] = mcells->ch[yc][xc].waterlevel;
644        }
645    }
646
647
648    // Convert it into antrix cell format.
649    for(uint32 cx=(x%CellsPerTile)*MAP_RESOLUTION/CellsPerTile;cx<(x%CellsPerTile)*MAP_RESOLUTION/CellsPerTile+MAP_RESOLUTION/CellsPerTile;cx++)
650    {
651        for(uint32 cy=(y%CellsPerTile)*MAP_RESOLUTION/CellsPerTile;cy<(y%CellsPerTile)*MAP_RESOLUTION/CellsPerTile+MAP_RESOLUTION/CellsPerTile;cy++)
652        {
653            uint32 lx=cx%(MAP_RESOLUTION/CellsPerTile);
654            uint32 ly=cy%(MAP_RESOLUTION/CellsPerTile);
655            out.Z[lx][ly] = cz->z[cx][cy];
656        }
657    }
658
659    // Write out to file.
660    fwrite(&out, sizeof(out), 1, out_file);
661        return true;
662}
Note: See TracBrowser for help on using the browser.