root/trunk/contrib/extractor/adt.cpp @ 177

Revision 2, 12.6 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#define _CRT_SECURE_NO_DEPRECATE
2
3#ifdef WIN32
4#include <windows.h>
5#endif
6
7#include <string.h>
8#include <stdio.h>
9#include <math.h>
10#include <string>
11#include <map>
12#include <vector>
13#include <set>
14
15#include "adt.h"
16#include "mpq_libmpq.h"
17
18//#include <windows.h>
19unsigned int iRes=256;
20extern uint16*areas;
21
22vec wmoc;
23
24Cell * cell;
25uint32 wmo_count;
26mcell *mcells;
27
28int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
29int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
30
31bool LoadADT(char* filename)
32{
33    size_t size;
34    MPQFile mf(filename);
35
36    if(mf.isEof())
37    {
38        //printf("No such file.\n");
39        return false;
40    }
41    mcells=new mcell;
42
43    wmoc.x =65*TILESIZE;
44    wmoc.z =65*TILESIZE;
45
46    size_t mcnk_offsets[256], mcnk_sizes[256];
47
48    wmo_count=0;
49    bool found=false;
50    //uint32 fs=mf.getSize()-3;
51    //while (mf.getPos()<fs)
52    while (!mf.isEof())
53    {
54        uint32 fourcc;
55        mf.read(&fourcc,4);
56        mf.read(&size, 4);
57
58        size_t nextpos = mf.getPos() + size;
59        switch(fourcc)
60        {
61            case 0x4d43494e:                                // MCIN
62            {
63                //printf("Found chunks info\n");
64                // mapchunk offsets/sizes
65                for (int i=0; i<256; i++)
66                {
67                    mf.read(&mcnk_offsets[i],4);
68                    mf.read(&mcnk_sizes[i],4);
69                    mf.seekRelative(8);
70                }
71                break;
72            }
73            case 0x4d4f4446:                                // MODF
74            {
75                /*
76                if(size)
77                {
78                    //printf("\nwmo count %d\n",size/64);
79                    wmo_count =size/64;
80                    for (int i=0; i<wmo_count; i++)
81                    {
82                        int id;
83                        mf.read(&id, 4);
84                        WMO *wmo = (WMO*)wmomanager.items[wmomanager.get(wmos[id])];
85                        WMOInstance inst(wmo, mf);
86                        wmois.push_back(inst);
87                    }
88
89                }*/
90                break;
91            }
92            case 0x4d574d4f:                                // MWMO
93            {
94                /*
95                if (size)
96                {
97                    char *buf = new char[size];
98                    mf.read(buf, size);
99                    char *p=buf;
100                    while (p<buf+size)
101                    {
102                    std::string path(p);
103                        p+=strlen(p)+1;
104                        fixname(path);
105
106                        wmomanager.add(path);
107                        wmos.push_back(path);
108                    }
109                    delete[] buf;
110                }*/
111                break;
112            }
113            case 0x4d564552:                                // MVER
114            case 0x4d484452:                                // MHDR header
115            case 0x4d434e4b:                                // MCNK
116            case 0x4d544558:                                // MTEX textures (strings)
117            case 0x4d4d4458:                                // MMDX m2 models (strings)
118            case 0x4d4d4944:                                // MMID offsets for strings in MMDX
119            case 0x4d574944:                                // MWID offsets for strings in MWMO
120            case 0x4d444446:                                // MDDF
121            case 0x4d46424f:                                // MFBO new in BC
122            case 0x4d48324f:                                // MH2O new in WotLK
123                break;
124            default:
125            {
126                // mf.seekRelative(-3);
127                printf("Unhandled map chunk: %u\n",fourcc);
128                break;
129            }
130        }
131        mf.seek(nextpos);
132    }
133
134    //printf("Loading chunks info\n");
135    // read individual map chunks
136    for (int j=0; j<16; j++)
137        for (int i=0; i<16; i++)
138        {
139            mf.seek((int)mcnk_offsets[j*16+i]);
140            LoadMapChunk(mf,&(mcells->ch[i][j]));
141        }
142
143    /*
144    for(uint32 t=0;t<wmo_count ;t++)
145    {
146        wmois[t].draw();
147    }*/
148
149    mf.close();
150    return true;
151}
152
153struct MapChunkHeader {
154    uint32 flags;
155    uint32 ix;
156    uint32 iy;
157    uint32 nLayers;
158    uint32 nDoodadRefs;
159    uint32 ofsHeight;
160    uint32 ofsNormal;
161    uint32 ofsLayer;
162    uint32 ofsRefs;
163    uint32 ofsAlpha;
164    uint32 sizeAlpha;
165    uint32 ofsShadow;
166    uint32 sizeShadow;
167    uint32 areaid;
168    uint32 nMapObjRefs;
169    uint32 holes;
170    uint16 s1;
171    uint16 s2;
172    uint32 d1;
173    uint32 d2;
174    uint32 d3;
175    uint32 predTex;
176    uint32 nEffectDoodad;
177    uint32 ofsSndEmitters;
178    uint32 nSndEmitters;
179    uint32 ofsLiquid;
180    uint32 sizeLiquid;
181    float  zpos;
182    float  xpos;
183    float  ypos;
184    uint32 textureId;
185    uint32 props;
186    uint32 effectId;
187};
188
189bool isHole(int holes, int i, int j)
190{
191    int testi = i/2;
192    int testj = j/4;
193    if(testi>3) testi = 3;
194    if(testj>3) testj = 3;
195        return (holes & holetab_h[testi] & holetab_v[testj])!=0;
196}
197
198inline
199void LoadMapChunk(MPQFile & mf, chunk*_chunk)
200{
201    float h;
202    uint32 fourcc;
203    uint32 size;
204    MapChunkHeader header;
205
206    mf.seekRelative(4);
207    mf.read(&size, 4);
208
209    size_t lastpos = mf.getPos() + size;
210    mf.read(&header, 0x80);
211    _chunk->area_id =header.areaid ;
212    _chunk->flag =0;
213
214    float xbase = header.xpos;
215    float ybase = header.ypos;
216    float zbase = header.zpos;
217    zbase = TILESIZE*32-zbase;
218    xbase = TILESIZE*32-xbase;
219    if(wmoc.x >xbase)wmoc.x =xbase;
220    if(wmoc.z >zbase)wmoc.z =zbase;
221    int chunkflags = header.flags;
222    float zmin=999999999.0f;
223    float zmax=-999999999.0f;
224    //must be there, bl!zz uses some crazy format
225    int nTextures;
226    while (mf.getPos() < lastpos)
227    {
228        mf.read(&fourcc,4);
229        mf.read(&size, 4);
230        //if(size!=580)
231        //    printf("\n sz=%d",size);
232        size_t nextpos = mf.getPos()  + size;
233        if(fourcc==0x4d435654)                              // MCVT
234        {
235            for (int j=0; j<17; j++)
236                for (int i=0; i<((j%2)?8:9); i++)
237                {
238                    mf.read(&h,4);
239                    float z=h+ybase;
240                    if (j%2)
241                    {
242                        if(isHole(header.holes,i,j))
243                            _chunk->v8[i][j/2] = -1000;
244                        else
245                            _chunk->v8[i][j/2] = z;
246                    }
247                    else
248                    {
249                        if(isHole(header.holes,i,j))
250                            _chunk->v9[i][j/2] = -1000;
251                        else
252                            _chunk->v9[i][j/2] = z;
253                    }
254
255                    if(z>zmax)zmax=z;
256                    //if(z<zmin)zmin=z;
257                }
258        }
259        else if(fourcc==0x4d434e52)                         // MCNR
260        {
261            nextpos = mf.getPos() + 0x1C0; // size fix
262        }
263        else if(fourcc==0x4d434c51)                         // MCLQ
264        {
265            // liquid / water level
266            //bool haswater;
267            char fcc1[5];
268            mf.read(fcc1,4);
269            flipcc(fcc1);
270            fcc1[4]=0;
271
272            if (!strcmp(fcc1,"MCSE"))
273            {
274                for(int i=0;i<9;i++)
275                    for(int j=0;j<9;j++)
276                        _chunk->waterlevel[i][j]=-999999; // no liquid/water
277            }
278            else
279            {
280                float maxheight;
281                mf.read(&maxheight, 4);
282
283                for(int j=0;j<9;j++)
284                    for(int i=0;i<9;i++)
285                    {
286                        mf.read(&h, 4);
287                        mf.read(&h, 4);
288                        if(h > maxheight)
289                            _chunk->waterlevel[i][j]=-999999;
290                        else
291                            _chunk->waterlevel[i][j]=h;
292                    }
293
294                if(chunkflags & 4 || chunkflags & 8)
295                    _chunk->flag |=1;
296                if(chunkflags & 16)
297                    _chunk->flag |=2;
298
299            }
300            break;
301        }
302        else if (fourcc==0x4d434c59)                        // MCLY
303        {
304            // texture info
305            nTextures = (int)size;
306        }
307        else if (fourcc==0x4d43414c)                        // MCAL
308        {
309            if (nTextures<=0)
310                continue;
311        }
312
313        mf.seek(nextpos);
314    }
315}
316
317double solve (vec *v,vec *p)
318{
319    double 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);
320    double 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);
321    double 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);
322    double 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);
323    //-d
324
325    //plane equation ax+by+cz+d=0
326    return ((a*p->x+c*p->z-d)/b);
327}
328
329inline
330double GetZ(double x,double z)
331{
332    vec v[3];
333    vec p;
334
335    //bool inWMO=false;
336
337    //if(!inWMO)
338    {
339        //find out quadrant
340        int xc=(int)(x/UNITSIZE);
341        int zc=(int)(z/UNITSIZE);
342        if(xc>127)xc=127;
343        if(zc>127)zc=127;
344
345        double lx=x-xc*UNITSIZE;
346        double lz=z-zc*UNITSIZE;
347        p.x=lx;
348        p.z=lz;
349
350        v[0].x=UNITSIZE/2;
351        v[0].y =cell->v8[xc][zc];
352        v[0].z=UNITSIZE/2;
353
354        if(lx>lz)
355        {
356            v[1].x=UNITSIZE;
357            v[1].y =cell->v9[xc+1][zc];
358            v[1].z=0;
359        }
360        else
361        {
362            v[1].x=0.0;
363            v[1].y =cell->v9[xc][zc+1];
364            v[1].z=UNITSIZE;
365        }
366
367        if(lz>UNITSIZE-lx)
368        {
369            v[2].x=UNITSIZE;
370            v[2].y =cell->v9[xc+1][zc+1];
371            v[2].z=UNITSIZE;
372        }
373        else
374        {
375            v[2].x=0;
376            v[2].y=cell->v9[xc][zc];
377            v[2].z=0;
378        }
379
380        return -solve(v,&p);
381    }
382}
383
384inline
385void TransformWaterData()
386{
387    cell= new Cell;
388
389    for(int x=0;x<128;x++)
390        for(int y=0;y<128;y++)
391            cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8];
392
393    //and the last 1
394    cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8];
395}
396
397inline
398void TransformData()
399{
400    cell= new Cell;
401
402    for(int x=0;x<128;x++)
403    {
404        for(int y=0;y<128;y++)
405        {
406            cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8];
407            cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8];
408        }
409
410        //extra 1 point on bounds
411        cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8];
412        //x==y
413        cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8];
414
415    }
416
417    //and the last 1
418    cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
419
420    delete mcells;
421}
422
423const char MAP_MAGIC[] = "MAP_2.00";
424
425bool ConvertADT(char * filename,char * filename2)
426{
427    //if(!strstr(filename,"oth_32_48"))return false;
428    if(!LoadADT(filename))
429        return false;
430
431    FILE *output=fopen(filename2,"wb");
432    if(!output)
433    {
434        printf("Can't create the output file '%s'\n",filename2);
435        return false;
436    }
437
438    // write magic header
439    fwrite(MAP_MAGIC,1,8,output);
440
441    for(unsigned int x=0;x<16;x++)
442    {
443        for(unsigned int y=0;y<16;y++)
444        {
445            if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D)
446            {
447                if(areas[mcells->ch[y][x].area_id]==0xffff)
448                    printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id);
449
450                fwrite(&areas[mcells->ch[y][x].area_id],1,2,output);
451            }
452            else
453            {
454                uint16 flag=0xffff;
455                fwrite(&flag,1,2,output);
456            }
457        }
458    }
459
460    for(unsigned int x=0;x<16;x++)
461        for(unsigned int y=0;y<16;y++)
462            fwrite(&mcells->ch[y][x].flag,1,1,output);
463
464    TransformWaterData();
465
466    for(unsigned int x=0;x<128;x++)
467        for(unsigned int y=0;y<128;y++)
468            fwrite(&cell->v9[y][x],1,sizeof(float),output);
469
470    delete cell;
471    TransformData();
472
473    for(unsigned int x=0;x<iRes;x++)
474    for(unsigned int y=0;y<iRes;y++)
475    {
476        float z=(float)GetZ(
477                    (((double)(y))*TILESIZE)/((double)(iRes-1)),
478                    (((double)(x))*TILESIZE)/((double)(iRes-1)));
479
480        fwrite(&z,1,sizeof(z),output);
481    }
482
483    fclose(output);
484    delete cell;
485/*
486    for (std::vector<std::string>::iterator it = wmos.begin(); it != wmos.end(); ++it)
487    wmomanager.delbyname(*it);
488
489    wmos.clear();
490    wmois.clear();
491
492    for (std::vector<model>::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it)
493    {
494        it->tr.clear();
495
496    }
497    //printf("\n %d \n",in);
498    wmomodel.clear();
499    //polygons.clear();*/
500    return true;
501}
Note: See TracBrowser for help on using the browser.