Fixed some typos, updated areaflags enum
[getmangos.git] / contrib / extractor / adt.cpp
blobb7f54f8ad5fba403dd52e39454977bd9a2cb6bcc
1 #define _CRT_SECURE_NO_DEPRECATE
3 #ifdef WIN32
4 #include <windows.h>
5 #endif
7 #include <string.h>
8 #include <stdio.h>
9 #include <math.h>
10 #include <string>
11 #include <map>
12 #include <vector>
13 #include <set>
15 #include "adt.h"
16 #include "mpq_libmpq.h"
18 unsigned int iRes=256;
19 extern uint16 *areas;
21 extern uint32 maxAreaId;
23 vec wmoc;
25 Cell * cell;
26 uint32 wmo_count;
27 mcell *mcells;
28 int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
29 int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
31 bool LoadADT(char* filename)
33 size_t size;
34 MPQFile mf(filename);
36 if(mf.isEof())
38 //printf("No such file %s\n",filename);
39 return false;
41 mcells=new mcell;
43 wmoc.x =65*TILESIZE;
44 wmoc.z =65*TILESIZE;
46 size_t mcnk_offsets[256], mcnk_sizes[256];
48 wmo_count=0;
49 bool found=false;
51 MH2O_presence = false;
52 chunk_num = 0;
53 k = 0;
54 while (!mf.isEof())
56 uint32 fourcc;
57 mf.read(&fourcc,4);
58 mf.read(&size, 4);
60 size_t nextpos = mf.getPos() + size;
62 //if(fourcc==0x4d484452) // MHDR header
63 //if(fourcc==0x4d564552) // MVER
64 if(fourcc==0x4d43494e) // MCIN
66 for (int i=0; i<256; ++i)
68 mf.read(&mcnk_offsets[i],4);
69 mf.read(&mcnk_sizes[i],4);
70 mf.seekRelative(8);
73 //if(fourcc==0x4d544558) // MTEX textures (strings)
74 //if(fourcc==0x4d4d4458) // MMDX m2 models (strings)
75 //if(fourcc==0x4d4d4944) // MMID offsets for strings in MMDX
76 //if(fourcc==0x4d574d4f) // MWMO
77 //if(fourcc==0x4d574944) // MWID offsets for strings in MWMO
78 //if(fourcc==0x4d444446) // MDDF
79 //if(fourcc==0x4d4f4446) // MODF
80 if(fourcc==0x4d48324f && size) // MH2O new in WotLK
82 MH2O_presence = true;
83 // çäåñü íàäî çàïîìíèòü áàçîâóþ ïîçèöèþ â ôàéëå òê âñå ñìåùåíèÿ áóäóò îò íåãî
84 uint32 base_pos = mf.getPos();
85 uint32 header_pos = 0;
86 LiqOffsData = new MH2O_offsData;
87 LiqChunkData1 = new MH2O_Data1;
88 ChunkLiqHeight = new float[81];
89 for(;chunk_num < 256; ++chunk_num)
91 mf.read(LiqOffsData,12);
92 header_pos = mf.getPos();
93 if(LiqOffsData->offsData1 !=0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü
95 // ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà
96 mf.seek(base_pos + LiqOffsData->offsData1);
97 mf.read(LiqChunkData1,24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1
98 // çàíîñèì äàííûå ôëàãà äëÿ êóñêà
99 if(LiqChunkData1->flags & 4 || LiqChunkData1->flags & 8)
100 MapLiqFlag[chunk_num] |= 1;
101 if(LiqChunkData1->flags & 16)
102 MapLiqFlag[chunk_num] |= 2;
103 // ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû
104 for(int j=0;j<81;++j)
106 ChunkLiqHeight[j] = -999999; // no liquid/water
108 // òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå
109 for(int b=0; b <= LiqChunkData1->height; ++b)
111 for(int c=LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset+LiqChunkData1->width); ++c)
113 int n = (9*(LiqChunkData1->yOffset + b))+c;
114 ChunkLiqHeight[n] = LiqChunkData1->heightLevel1;
117 mf.seek(header_pos); // è íå çàáûòü âåðíóòüñÿ íà èñõîäíóþ ïîçèöèþ èìåííî Â ÕÈÄÅÐÅ
119 else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû
121 for(int j=0; j<81; ++j)
122 ChunkLiqHeight[j] = -999999; // no liquid/water
124 if(!(chunk_num%16))
125 m = 1024*(chunk_num/16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024
126 k = m +(chunk_num%16)*8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà
127 // çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81
128 // ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ
129 for(int p=0;p<72;p+=9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì
131 for(int s=0; s<8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128
133 MapLiqHeight[k] = ChunkLiqHeight[p+s];
134 ++k;
136 k=k+120;
139 delete LiqOffsData;
140 delete LiqChunkData1;
141 delete []ChunkLiqHeight;
144 //case 0x4d434e4b: // MCNK
145 //case 0x4d46424f: // MFBO new in BC
146 //case 0x4d545846: // MTXF new in WotLK
147 mf.seek(nextpos);
150 //printf("Loading chunks info\n");
151 // read individual map chunks
152 for (int j=0; j<16; ++j)
154 for (int i=0; i<16; ++i)
156 mf.seek((int)mcnk_offsets[j*16+i]);
157 LoadMapChunk(mf,&(mcells->ch[i][j]));
158 ++chunk_num;
161 mf.close();
162 return true;
165 bool isHole(int holes, int i, int j)
167 int testi = i/2;
168 int testj = j/4;
169 if(testi>3) testi = 3;
170 if(testj>3) testj = 3;
171 return (holes & holetab_h[testi] & holetab_v[testj])!=0;
174 inline void LoadMapChunk(MPQFile & mf, chunk*_chunk)
176 float h;
177 uint32 fourcc;
178 uint32 size;
179 MapChunkHeader header;
181 mf.seekRelative(4);
182 mf.read(&size, 4);
184 size_t lastpos = mf.getPos() + size;
185 mf.read(&header, 0x80); // what if header size got changed?
186 _chunk->area_id =header.areaid ;
188 float xbase = header.xpos;
189 float ybase = header.ypos;
190 float zbase = header.zpos;
191 zbase = TILESIZE*32-zbase;
192 xbase = TILESIZE*32-xbase;
193 if(wmoc.x >xbase)wmoc.x =xbase;
194 if(wmoc.z >zbase)wmoc.z =zbase;
195 int chunkflags = header.flags;
196 float zmin=999999999.0f;
197 float zmax=-999999999.0f;
198 // must be there, bl!zz uses some crazy format
199 while (mf.getPos() < lastpos)
201 mf.read(&fourcc,4);
202 mf.read(&size, 4);
203 size_t nextpos = mf.getPos() + size;
204 if(fourcc==0x4d435654) // MCVT
206 for (int j=0; j<17; ++j)
207 for (int i=0; i<((j%2)?8:9); ++i)
209 mf.read(&h,4);
210 float z=h+ybase;
211 if (j%2)
213 if(isHole(header.holes,i,j))
214 _chunk->v8[i][j/2] = -1000;
215 else
216 _chunk->v8[i][j/2] = z;
218 else
220 if(isHole(header.holes,i,j))
221 _chunk->v9[i][j/2] = -1000;
222 else
223 _chunk->v9[i][j/2] = z;
226 if(z>zmax)zmax=z;
227 //if(z<zmin)zmin=z;
230 else if(fourcc==0x4d434e52) // MCNR
232 nextpos = mf.getPos() + 0x1C0; // size fix
234 else if(fourcc==0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ
236 // liquid / water level
237 char fcc1[5];
238 mf.read(fcc1,4);
239 flipcc(fcc1);
240 fcc1[4]=0;
241 ChunkLiqHeight = new float[81];
243 if (!strcmp(fcc1,"MCSE"))
245 for(int j=0;j<81;++j)
247 ChunkLiqHeight[j] = -999999; // no liquid/water
250 else
252 float maxheight;
253 mf.read(&maxheight, 4);
254 for(int j=0;j<81;++j)
256 mf.read(&h, 4);
257 mf.read(&h, 4);
258 if(h > maxheight)
259 ChunkLiqHeight[j] = -999999;
260 else
261 ChunkLiqHeight[j] = h;
264 if(chunkflags & 4 || chunkflags & 8)
265 MapLiqFlag[chunk_num] |= 1;
266 if(chunkflags & 16)
267 MapLiqFlag[chunk_num] |= 2;
269 // çàïîëíåì òàê æå êàê â MH2O
270 if(!(chunk_num%16))
271 m = 1024*(chunk_num/16);
272 k = m +(chunk_num%16)*8;
274 for(int p=0;p<72;p+=9)
276 for(int s=0; s<8; ++s)
278 MapLiqHeight[k] = ChunkLiqHeight[p+s];
279 ++k;
281 k=k+120;
283 delete []ChunkLiqHeight;
284 break;
286 mf.seek(nextpos);
290 double solve (vec *v,vec *p)
292 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);
293 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);
294 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);
295 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);
296 // -d
298 // plane equation ax+by+cz+d=0
299 return ((a*p->x+c*p->z-d)/b);
302 inline double GetZ(double x, double z)
304 vec v[3];
305 vec p;
307 // find out quadrant
308 int xc=(int)(x/UNITSIZE);
309 int zc=(int)(z/UNITSIZE);
310 if(xc>127)xc=127;
311 if(zc>127)zc=127;
313 double lx=x-xc*UNITSIZE;
314 double lz=z-zc*UNITSIZE;
315 p.x=lx;
316 p.z=lz;
318 v[0].x=UNITSIZE/2;
319 v[0].y =cell->v8[xc][zc];
320 v[0].z=UNITSIZE/2;
322 if(lx>lz)
324 v[1].x=UNITSIZE;
325 v[1].y =cell->v9[xc+1][zc];
326 v[1].z=0;
328 else
330 v[1].x=0.0;
331 v[1].y =cell->v9[xc][zc+1];
332 v[1].z=UNITSIZE;
335 if(lz>UNITSIZE-lx)
337 v[2].x=UNITSIZE;
338 v[2].y =cell->v9[xc+1][zc+1];
339 v[2].z=UNITSIZE;
341 else
343 v[2].x=0;
344 v[2].y=cell->v9[xc][zc];
345 v[2].z=0;
348 return -solve(v,&p);
352 inline void TransformData()
354 cell= new Cell;
356 for(int x=0;x<128;++x)
358 for(int y=0;y<128;++y)
360 cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8];
361 cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8];
364 // extra 1 point on bounds
365 cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8];
366 // x==y
367 cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8];
371 // and the last 1
372 cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
374 delete mcells;
377 const char MAP_MAGIC[] = "MAP_2.01";
379 bool ConvertADT(char * filename,char * filename2)
381 MapLiqHeight = new float[16384];
382 MapLiqFlag = new char[256];
383 for(int j = 0; j < 256; ++j)
384 MapLiqFlag[j] = 0;
385 for(int j = 0; j < 16384; ++j)
386 MapLiqHeight[j] = -999999;
388 if(!LoadADT(filename))
390 delete [] MapLiqHeight;
391 delete [] MapLiqFlag;
392 return false;
395 FILE *output=fopen(filename2,"wb");
396 if(!output)
398 printf("Can't create the output file '%s'\n",filename2);
399 delete [] MapLiqHeight;
400 delete [] MapLiqFlag;
401 return false;
404 // write magic header
405 fwrite(MAP_MAGIC,1,8,output);
407 for(unsigned int x=0;x<16;++x)
409 for(unsigned int y=0;y<16;++y)
411 if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId)
413 if(areas[mcells->ch[y][x].area_id]==0xffff)
414 printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id);
416 fwrite(&areas[mcells->ch[y][x].area_id],1,2,output);
418 else
420 uint16 flag=0xffff;
421 fwrite(&flag,1,2,output);
426 fwrite(MapLiqFlag,1,256,output);
427 delete [] MapLiqFlag;
429 fwrite(MapLiqHeight,sizeof(float),16384,output);
430 delete [] MapLiqHeight;
432 TransformData();
434 for(unsigned int x=0;x<iRes;++x)
436 for(unsigned int y=0;y<iRes;++y)
438 float z=(float)GetZ(
439 (((double)(y))*TILESIZE)/((double)(iRes-1)),
440 (((double)(x))*TILESIZE)/((double)(iRes-1)));
442 fwrite(&z,1,sizeof(z),output);
446 fclose(output);
447 delete cell;
449 return true;