aboutsummaryrefslogtreecommitdiff
path: root/contrib/extractor/adt.cpp
diff options
context:
space:
mode:
authorNeo2003 <none@none>2008-10-02 16:23:55 -0500
committerNeo2003 <none@none>2008-10-02 16:23:55 -0500
commit9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch)
treeb5d1ba94a656e6679f8737f9ea6bed1239b73b14 /contrib/extractor/adt.cpp
[svn] * Proper SVN structureinit
--HG-- branch : trunk
Diffstat (limited to 'contrib/extractor/adt.cpp')
-rw-r--r--contrib/extractor/adt.cpp501
1 files changed, 501 insertions, 0 deletions
diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp
new file mode 100644
index 00000000000..26adaa28537
--- /dev/null
+++ b/contrib/extractor/adt.cpp
@@ -0,0 +1,501 @@
+#define _CRT_SECURE_NO_DEPRECATE
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <string>
+#include <map>
+#include <vector>
+#include <set>
+
+#include "adt.h"
+#include "mpq_libmpq.h"
+
+//#include <windows.h>
+unsigned int iRes=256;
+extern uint16*areas;
+
+vec wmoc;
+
+Cell * cell;
+uint32 wmo_count;
+mcell *mcells;
+
+int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
+int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
+
+bool LoadADT(char* filename)
+{
+ size_t size;
+ MPQFile mf(filename);
+
+ if(mf.isEof())
+ {
+ //printf("No such file.\n");
+ return false;
+ }
+ mcells=new mcell;
+
+ wmoc.x =65*TILESIZE;
+ wmoc.z =65*TILESIZE;
+
+ size_t mcnk_offsets[256], mcnk_sizes[256];
+
+ wmo_count=0;
+ bool found=false;
+ //uint32 fs=mf.getSize()-3;
+ //while (mf.getPos()<fs)
+ while (!mf.isEof())
+ {
+ uint32 fourcc;
+ mf.read(&fourcc,4);
+ mf.read(&size, 4);
+
+ size_t nextpos = mf.getPos() + size;
+ switch(fourcc)
+ {
+ case 0x4d43494e: // MCIN
+ {
+ //printf("Found chunks info\n");
+ // mapchunk offsets/sizes
+ for (int i=0; i<256; i++)
+ {
+ mf.read(&mcnk_offsets[i],4);
+ mf.read(&mcnk_sizes[i],4);
+ mf.seekRelative(8);
+ }
+ break;
+ }
+ case 0x4d4f4446: // MODF
+ {
+ /*
+ if(size)
+ {
+ //printf("\nwmo count %d\n",size/64);
+ wmo_count =size/64;
+ for (int i=0; i<wmo_count; i++)
+ {
+ int id;
+ mf.read(&id, 4);
+ WMO *wmo = (WMO*)wmomanager.items[wmomanager.get(wmos[id])];
+ WMOInstance inst(wmo, mf);
+ wmois.push_back(inst);
+ }
+
+ }*/
+ break;
+ }
+ case 0x4d574d4f: // MWMO
+ {
+ /*
+ if (size)
+ {
+ char *buf = new char[size];
+ mf.read(buf, size);
+ char *p=buf;
+ while (p<buf+size)
+ {
+ std::string path(p);
+ p+=strlen(p)+1;
+ fixname(path);
+
+ wmomanager.add(path);
+ wmos.push_back(path);
+ }
+ delete[] buf;
+ }*/
+ break;
+ }
+ case 0x4d564552: // MVER
+ case 0x4d484452: // MHDR header
+ case 0x4d434e4b: // MCNK
+ case 0x4d544558: // MTEX textures (strings)
+ case 0x4d4d4458: // MMDX m2 models (strings)
+ case 0x4d4d4944: // MMID offsets for strings in MMDX
+ case 0x4d574944: // MWID offsets for strings in MWMO
+ case 0x4d444446: // MDDF
+ case 0x4d46424f: // MFBO new in BC
+ case 0x4d48324f: // MH2O new in WotLK
+ break;
+ default:
+ {
+ // mf.seekRelative(-3);
+ printf("Unhandled map chunk: %u\n",fourcc);
+ break;
+ }
+ }
+ mf.seek(nextpos);
+ }
+
+ //printf("Loading chunks info\n");
+ // read individual map chunks
+ for (int j=0; j<16; j++)
+ for (int i=0; i<16; i++)
+ {
+ mf.seek((int)mcnk_offsets[j*16+i]);
+ LoadMapChunk(mf,&(mcells->ch[i][j]));
+ }
+
+ /*
+ for(uint32 t=0;t<wmo_count ;t++)
+ {
+ wmois[t].draw();
+ }*/
+
+ mf.close();
+ return true;
+}
+
+struct MapChunkHeader {
+ uint32 flags;
+ uint32 ix;
+ uint32 iy;
+ uint32 nLayers;
+ uint32 nDoodadRefs;
+ uint32 ofsHeight;
+ uint32 ofsNormal;
+ uint32 ofsLayer;
+ uint32 ofsRefs;
+ uint32 ofsAlpha;
+ uint32 sizeAlpha;
+ uint32 ofsShadow;
+ uint32 sizeShadow;
+ uint32 areaid;
+ uint32 nMapObjRefs;
+ uint32 holes;
+ uint16 s1;
+ uint16 s2;
+ uint32 d1;
+ uint32 d2;
+ uint32 d3;
+ uint32 predTex;
+ uint32 nEffectDoodad;
+ uint32 ofsSndEmitters;
+ uint32 nSndEmitters;
+ uint32 ofsLiquid;
+ uint32 sizeLiquid;
+ float zpos;
+ float xpos;
+ float ypos;
+ uint32 textureId;
+ uint32 props;
+ uint32 effectId;
+};
+
+bool isHole(int holes, int i, int j)
+{
+ int testi = i/2;
+ int testj = j/4;
+ if(testi>3) testi = 3;
+ if(testj>3) testj = 3;
+ return (holes & holetab_h[testi] & holetab_v[testj])!=0;
+}
+
+inline
+void LoadMapChunk(MPQFile & mf, chunk*_chunk)
+{
+ float h;
+ uint32 fourcc;
+ uint32 size;
+ MapChunkHeader header;
+
+ mf.seekRelative(4);
+ mf.read(&size, 4);
+
+ size_t lastpos = mf.getPos() + size;
+ mf.read(&header, 0x80);
+ _chunk->area_id =header.areaid ;
+ _chunk->flag =0;
+
+ float xbase = header.xpos;
+ float ybase = header.ypos;
+ float zbase = header.zpos;
+ zbase = TILESIZE*32-zbase;
+ xbase = TILESIZE*32-xbase;
+ if(wmoc.x >xbase)wmoc.x =xbase;
+ if(wmoc.z >zbase)wmoc.z =zbase;
+ int chunkflags = header.flags;
+ float zmin=999999999.0f;
+ float zmax=-999999999.0f;
+ //must be there, bl!zz uses some crazy format
+ int nTextures;
+ while (mf.getPos() < lastpos)
+ {
+ mf.read(&fourcc,4);
+ mf.read(&size, 4);
+ //if(size!=580)
+ // printf("\n sz=%d",size);
+ size_t nextpos = mf.getPos() + size;
+ if(fourcc==0x4d435654) // MCVT
+ {
+ for (int j=0; j<17; j++)
+ for (int i=0; i<((j%2)?8:9); i++)
+ {
+ mf.read(&h,4);
+ float z=h+ybase;
+ if (j%2)
+ {
+ if(isHole(header.holes,i,j))
+ _chunk->v8[i][j/2] = -1000;
+ else
+ _chunk->v8[i][j/2] = z;
+ }
+ else
+ {
+ if(isHole(header.holes,i,j))
+ _chunk->v9[i][j/2] = -1000;
+ else
+ _chunk->v9[i][j/2] = z;
+ }
+
+ if(z>zmax)zmax=z;
+ //if(z<zmin)zmin=z;
+ }
+ }
+ else if(fourcc==0x4d434e52) // MCNR
+ {
+ nextpos = mf.getPos() + 0x1C0; // size fix
+ }
+ else if(fourcc==0x4d434c51) // MCLQ
+ {
+ // liquid / water level
+ //bool haswater;
+ char fcc1[5];
+ mf.read(fcc1,4);
+ flipcc(fcc1);
+ fcc1[4]=0;
+
+ if (!strcmp(fcc1,"MCSE"))
+ {
+ for(int i=0;i<9;i++)
+ for(int j=0;j<9;j++)
+ _chunk->waterlevel[i][j]=-999999; // no liquid/water
+ }
+ else
+ {
+ float maxheight;
+ mf.read(&maxheight, 4);
+
+ for(int j=0;j<9;j++)
+ for(int i=0;i<9;i++)
+ {
+ mf.read(&h, 4);
+ mf.read(&h, 4);
+ if(h > maxheight)
+ _chunk->waterlevel[i][j]=-999999;
+ else
+ _chunk->waterlevel[i][j]=h;
+ }
+
+ if(chunkflags & 4 || chunkflags & 8)
+ _chunk->flag |=1;
+ if(chunkflags & 16)
+ _chunk->flag |=2;
+
+ }
+ break;
+ }
+ else if (fourcc==0x4d434c59) // MCLY
+ {
+ // texture info
+ nTextures = (int)size;
+ }
+ else if (fourcc==0x4d43414c) // MCAL
+ {
+ if (nTextures<=0)
+ continue;
+ }
+
+ mf.seek(nextpos);
+ }
+}
+
+double solve (vec *v,vec *p)
+{
+ 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);
+ 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);
+ 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);
+ 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);
+ //-d
+
+ //plane equation ax+by+cz+d=0
+ return ((a*p->x+c*p->z-d)/b);
+}
+
+inline
+double GetZ(double x,double z)
+{
+ vec v[3];
+ vec p;
+
+ //bool inWMO=false;
+
+ //if(!inWMO)
+ {
+ //find out quadrant
+ int xc=(int)(x/UNITSIZE);
+ int zc=(int)(z/UNITSIZE);
+ if(xc>127)xc=127;
+ if(zc>127)zc=127;
+
+ double lx=x-xc*UNITSIZE;
+ double lz=z-zc*UNITSIZE;
+ p.x=lx;
+ p.z=lz;
+
+ v[0].x=UNITSIZE/2;
+ v[0].y =cell->v8[xc][zc];
+ v[0].z=UNITSIZE/2;
+
+ if(lx>lz)
+ {
+ v[1].x=UNITSIZE;
+ v[1].y =cell->v9[xc+1][zc];
+ v[1].z=0;
+ }
+ else
+ {
+ v[1].x=0.0;
+ v[1].y =cell->v9[xc][zc+1];
+ v[1].z=UNITSIZE;
+ }
+
+ if(lz>UNITSIZE-lx)
+ {
+ v[2].x=UNITSIZE;
+ v[2].y =cell->v9[xc+1][zc+1];
+ v[2].z=UNITSIZE;
+ }
+ else
+ {
+ v[2].x=0;
+ v[2].y=cell->v9[xc][zc];
+ v[2].z=0;
+ }
+
+ return -solve(v,&p);
+ }
+}
+
+inline
+void TransformWaterData()
+{
+ cell= new Cell;
+
+ for(int x=0;x<128;x++)
+ for(int y=0;y<128;y++)
+ cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8];
+
+ //and the last 1
+ cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8];
+}
+
+inline
+void TransformData()
+{
+ cell= new Cell;
+
+ for(int x=0;x<128;x++)
+ {
+ for(int y=0;y<128;y++)
+ {
+ cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8];
+ cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8];
+ }
+
+ //extra 1 point on bounds
+ cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8];
+ //x==y
+ cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8];
+
+ }
+
+ //and the last 1
+ cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
+
+ delete mcells;
+}
+
+const char MAP_MAGIC[] = "MAP_2.00";
+
+bool ConvertADT(char * filename,char * filename2)
+{
+ //if(!strstr(filename,"oth_32_48"))return false;
+ if(!LoadADT(filename))
+ return false;
+
+ FILE *output=fopen(filename2,"wb");
+ if(!output)
+ {
+ printf("Can't create the output file '%s'\n",filename2);
+ return false;
+ }
+
+ // write magic header
+ fwrite(MAP_MAGIC,1,8,output);
+
+ for(unsigned int x=0;x<16;x++)
+ {
+ for(unsigned int y=0;y<16;y++)
+ {
+ if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D)
+ {
+ if(areas[mcells->ch[y][x].area_id]==0xffff)
+ printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id);
+
+ fwrite(&areas[mcells->ch[y][x].area_id],1,2,output);
+ }
+ else
+ {
+ uint16 flag=0xffff;
+ fwrite(&flag,1,2,output);
+ }
+ }
+ }
+
+ for(unsigned int x=0;x<16;x++)
+ for(unsigned int y=0;y<16;y++)
+ fwrite(&mcells->ch[y][x].flag,1,1,output);
+
+ TransformWaterData();
+
+ for(unsigned int x=0;x<128;x++)
+ for(unsigned int y=0;y<128;y++)
+ fwrite(&cell->v9[y][x],1,sizeof(float),output);
+
+ delete cell;
+ TransformData();
+
+ for(unsigned int x=0;x<iRes;x++)
+ for(unsigned int y=0;y<iRes;y++)
+ {
+ float z=(float)GetZ(
+ (((double)(y))*TILESIZE)/((double)(iRes-1)),
+ (((double)(x))*TILESIZE)/((double)(iRes-1)));
+
+ fwrite(&z,1,sizeof(z),output);
+ }
+
+ fclose(output);
+ delete cell;
+/*
+ for (std::vector<std::string>::iterator it = wmos.begin(); it != wmos.end(); ++it)
+ wmomanager.delbyname(*it);
+
+ wmos.clear();
+ wmois.clear();
+
+ for (std::vector<model>::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it)
+ {
+ it->tr.clear();
+
+ }
+ //printf("\n %d \n",in);
+ wmomodel.clear();
+ //polygons.clear();*/
+ return true;
+}