[6895] Fix unexpected change backported in [6889]. Rebuild ad.exe with recent changes.
[getmangos.git] / contrib / extractor / adt.cpp
blobc6cb5dba0391a461d04d93559d51c63ab28dbd92
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 //#include <windows.h>
19 unsigned int iRes=256;
20 extern uint16*areas;
22 vec wmoc;
24 Cell * cell;
25 uint32 wmo_count;
26 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.\n");
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;
50 //uint32 fs=mf.getSize()-3;
51 //while (mf.getPos()<fs)
52 while (!mf.isEof())
54 uint32 fourcc;
55 mf.read(&fourcc,4);
56 mf.read(&size, 4);
58 size_t nextpos = mf.getPos() + size;
59 switch(fourcc)
61 case 0x4d43494e: // MCIN
63 //printf("Found chunks info\n");
64 // mapchunk offsets/sizes
65 for (int i=0; i<256; i++)
67 mf.read(&mcnk_offsets[i],4);
68 mf.read(&mcnk_sizes[i],4);
69 mf.seekRelative(8);
71 break;
73 case 0x4d4f4446: // MODF
76 if(size)
78 //printf("\nwmo count %d\n",size/64);
79 wmo_count =size/64;
80 for (int i=0; i<wmo_count; i++)
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);
88 }*/
89 break;
91 case 0x4d574d4f: // MWMO
94 if (size)
96 char *buf = new char[size];
97 mf.read(buf, size);
98 char *p=buf;
99 while (p<buf+size)
101 std::string path(p);
102 p+=strlen(p)+1;
103 fixname(path);
105 wmomanager.add(path);
106 wmos.push_back(path);
108 delete[] buf;
110 break;
112 case 0x4d564552: // MVER
113 case 0x4d484452: // MHDR header
114 case 0x4d434e4b: // MCNK
115 case 0x4d544558: // MTEX textures (strings)
116 case 0x4d4d4458: // MMDX m2 models (strings)
117 case 0x4d4d4944: // MMID offsets for strings in MMDX
118 case 0x4d574944: // MWID offsets for strings in MWMO
119 case 0x4d444446: // MDDF
120 case 0x4d46424f: // MFBO new in BC
121 case 0x4d48324f: // MH2O new in WotLK
122 case 0x4D545846: // MTXF new in WotLK
123 break;
124 default:
126 // mf.seekRelative(-3);
127 printf("Unhandled map chunk: %u\n",fourcc);
128 break;
131 mf.seek(nextpos);
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++)
139 mf.seek((int)mcnk_offsets[j*16+i]);
140 LoadMapChunk(mf,&(mcells->ch[i][j]));
144 for(uint32 t=0;t<wmo_count ;t++)
146 wmois[t].draw();
149 mf.close();
150 return true;
153 struct 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;
189 bool isHole(int holes, int i, int j)
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;
198 inline
199 void LoadMapChunk(MPQFile & mf, chunk*_chunk)
201 float h;
202 uint32 fourcc;
203 uint32 size;
204 MapChunkHeader header;
206 mf.seekRelative(4);
207 mf.read(&size, 4);
209 size_t lastpos = mf.getPos() + size;
210 mf.read(&header, 0x80);
211 _chunk->area_id =header.areaid ;
212 _chunk->flag =0;
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)
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
235 for (int j=0; j<17; j++)
236 for (int i=0; i<((j%2)?8:9); i++)
238 mf.read(&h,4);
239 float z=h+ybase;
240 if (j%2)
242 if(isHole(header.holes,i,j))
243 _chunk->v8[i][j/2] = -1000;
244 else
245 _chunk->v8[i][j/2] = z;
247 else
249 if(isHole(header.holes,i,j))
250 _chunk->v9[i][j/2] = -1000;
251 else
252 _chunk->v9[i][j/2] = z;
255 if(z>zmax)zmax=z;
256 //if(z<zmin)zmin=z;
259 else if(fourcc==0x4d434e52) // MCNR
261 nextpos = mf.getPos() + 0x1C0; // size fix
263 else if(fourcc==0x4d434c51) // MCLQ
265 // liquid / water level
266 //bool haswater;
267 char fcc1[5];
268 mf.read(fcc1,4);
269 flipcc(fcc1);
270 fcc1[4]=0;
272 if (!strcmp(fcc1,"MCSE"))
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
278 else
280 float maxheight;
281 mf.read(&maxheight, 4);
283 for(int j=0;j<9;j++)
284 for(int i=0;i<9;i++)
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;
294 if(chunkflags & 4 || chunkflags & 8)
295 _chunk->flag |=1;
296 if(chunkflags & 16)
297 _chunk->flag |=2;
299 break;
301 else if (fourcc==0x4d434c59) // MCLY
303 // texture info
304 nTextures = (int)size;
306 else if (fourcc==0x4d43414c) // MCAL
308 if (nTextures<=0)
309 continue;
312 mf.seek(nextpos);
316 double solve (vec *v,vec *p)
318 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);
319 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);
320 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);
321 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);
322 //-d
324 //plane equation ax+by+cz+d=0
325 return ((a*p->x+c*p->z-d)/b);
328 inline
329 double GetZ(double x,double z)
331 vec v[3];
332 vec p;
334 //bool inWMO=false;
336 //if(!inWMO)
338 //find out quadrant
339 int xc=(int)(x/UNITSIZE);
340 int zc=(int)(z/UNITSIZE);
341 if(xc>127)xc=127;
342 if(zc>127)zc=127;
344 double lx=x-xc*UNITSIZE;
345 double lz=z-zc*UNITSIZE;
346 p.x=lx;
347 p.z=lz;
349 v[0].x=UNITSIZE/2;
350 v[0].y =cell->v8[xc][zc];
351 v[0].z=UNITSIZE/2;
353 if(lx>lz)
355 v[1].x=UNITSIZE;
356 v[1].y =cell->v9[xc+1][zc];
357 v[1].z=0;
359 else
361 v[1].x=0.0;
362 v[1].y =cell->v9[xc][zc+1];
363 v[1].z=UNITSIZE;
366 if(lz>UNITSIZE-lx)
368 v[2].x=UNITSIZE;
369 v[2].y =cell->v9[xc+1][zc+1];
370 v[2].z=UNITSIZE;
372 else
374 v[2].x=0;
375 v[2].y=cell->v9[xc][zc];
376 v[2].z=0;
379 return -solve(v,&p);
383 inline
384 void TransformWaterData()
386 cell= new Cell;
388 for(int x=0;x<128;x++)
389 for(int y=0;y<128;y++)
390 cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8];
392 //and the last 1
393 cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8];
396 inline
397 void TransformData()
399 cell= new Cell;
401 for(int x=0;x<128;x++)
403 for(int y=0;y<128;y++)
405 cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8];
406 cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8];
409 //extra 1 point on bounds
410 cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8];
411 //x==y
412 cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8];
416 //and the last 1
417 cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
419 delete mcells;
422 const char MAP_MAGIC[] = "MAP_2.00";
424 bool ConvertADT(char * filename,char * filename2)
426 //if(!strstr(filename,"oth_32_48"))return false;
427 if(!LoadADT(filename))
428 return false;
430 FILE *output=fopen(filename2,"wb");
431 if(!output)
433 printf("Can't create the output file '%s'\n",filename2);
434 return false;
437 // write magic header
438 fwrite(MAP_MAGIC,1,8,output);
440 for(unsigned int x=0;x<16;x++)
442 for(unsigned int y=0;y<16;y++)
444 if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D)
446 if(areas[mcells->ch[y][x].area_id]==0xffff)
447 printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id);
449 fwrite(&areas[mcells->ch[y][x].area_id],1,2,output);
451 else
453 uint16 flag=0xffff;
454 fwrite(&flag,1,2,output);
459 for(unsigned int x=0;x<16;x++)
460 for(unsigned int y=0;y<16;y++)
461 fwrite(&mcells->ch[y][x].flag,1,1,output);
463 TransformWaterData();
465 for(unsigned int x=0;x<128;x++)
466 for(unsigned int y=0;y<128;y++)
467 fwrite(&cell->v9[y][x],1,sizeof(float),output);
469 delete cell;
470 TransformData();
472 for(unsigned int x=0;x<iRes;x++)
473 for(unsigned int y=0;y<iRes;y++)
475 float z=(float)GetZ(
476 (((double)(y))*TILESIZE)/((double)(iRes-1)),
477 (((double)(x))*TILESIZE)/((double)(iRes-1)));
479 fwrite(&z,1,sizeof(z),output);
482 fclose(output);
483 delete cell;
485 for (std::vector<std::string>::iterator it = wmos.begin(); it != wmos.end(); ++it)
486 wmomanager.delbyname(*it);
488 wmos.clear();
489 wmois.clear();
491 for (std::vector<model>::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it)
493 it->tr.clear();
496 //printf("\n %d \n",in);
497 wmomodel.clear();
498 //polygons.clear();*/
499 return true;