home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / md2.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-02  |  8.8 KB  |  248 lines

  1. struct md2;
  2.  
  3. md2 *loadingmd2 = 0;
  4.  
  5. static inline bool htcmp(const vertmodel::tcvert &x, const vertmodel::tcvert &y)
  6. {
  7.     return x.u==y.u && x.v==y.v && x.index==y.index;
  8. }
  9.  
  10. static inline uint hthash(const vertmodel::tcvert &x)
  11. {
  12.     return x.index;
  13. }
  14.  
  15. struct md2 : vertmodel
  16. {
  17.     struct md2_header
  18.     {
  19.         int magic;
  20.         int version;
  21.         int skinwidth, skinheight;
  22.         int framesize;
  23.         int numskins, numvertices, numtexcoords;
  24.         int numtriangles, numglcommands, numframes;
  25.         int offsetskins, offsettexcoords, offsettriangles;
  26.         int offsetframes, offsetglcommands, offsetend;
  27.     };
  28.  
  29.     struct md2_vertex
  30.     {
  31.         uchar vertex[3], normalindex;
  32.     };
  33.  
  34.     struct md2_frame
  35.     {
  36.         float      scale[3];
  37.         float      translate[3];
  38.         char       name[16];
  39.     };
  40.     
  41.     md2(const char *name) : vertmodel(name) {}
  42.  
  43.     int type() { return MDL_MD2; }
  44.  
  45.     struct md2part : part
  46.     {
  47.         void gentcverts(int *glcommands, vector<tcvert> &tcverts, vector<tri> &tris)
  48.         {
  49.             hashtable<tcvert, int> tchash;
  50.             vector<ushort> idxs;
  51.             for(int *command = glcommands; (*command)!=0;)
  52.             {
  53.                 int numvertex = *command++;
  54.                 bool isfan;
  55.                 if(isfan = (numvertex<0)) numvertex = -numvertex;
  56.                 idxs.setsizenodelete(0);
  57.                 loopi(numvertex)
  58.                 {
  59.                     union { int i; float f; } u, v;
  60.                     u.i = *command++;
  61.                     v.i = *command++;
  62.                     tcvert tckey = { u.f, v.f, (ushort)*command++ };
  63.                     int *idx = tchash.access(tckey);
  64.                     if(!idx)
  65.                     {
  66.                         idx = &tchash[tckey];
  67.                         *idx = tcverts.length();
  68.                         tcverts.add(tckey);
  69.                     }        
  70.                     idxs.add(*idx);
  71.                 }
  72.                 loopi(numvertex-2) 
  73.                 { 
  74.                     tri &t = tris.add();
  75.                     if(isfan)
  76.                     {
  77.                         t.vert[0] = idxs[0];
  78.                         t.vert[1] = idxs[i+1];
  79.                         t.vert[2] = idxs[i+2];
  80.                     }
  81.                     else loopk(3) t.vert[k] = idxs[i&1 && k ? i+(1-(k-1))+1 : i+k];
  82.                 }
  83.             }
  84.         }
  85.         
  86.         bool load(char *path)
  87.         {
  88.             if(filename) return true;
  89.  
  90.             FILE *file = fopen(path, "rb");
  91.             if(!file) return false;
  92.  
  93.             md2_header header;
  94.             fread(&header, sizeof(md2_header), 1, file);
  95.             endianswap(&header, sizeof(int), sizeof(md2_header)/sizeof(int));
  96.  
  97.             if(header.magic!=844121161 || header.version!=8) 
  98.             {
  99.                 fclose(file);
  100.                 return false;
  101.             }
  102.            
  103.             numframes = header.numframes;
  104.  
  105.             mesh &m = *new mesh;
  106.             meshes.add(&m);
  107.  
  108.             int *glcommands = new int[header.numglcommands];
  109.             fseek(file, header.offsetglcommands, SEEK_SET);
  110.             int numglcommands = (int)fread(glcommands, sizeof(int), header.numglcommands, file);
  111.             endianswap(glcommands, sizeof(int), numglcommands);
  112.             if(numglcommands < header.numglcommands) memset(&glcommands[numglcommands], 0, (header.numglcommands-numglcommands)*sizeof(int));
  113.  
  114.             vector<tcvert> tcgen;
  115.             vector<tri> trigen;
  116.             gentcverts(glcommands, tcgen, trigen);
  117.             delete[] glcommands;
  118.  
  119.             m.numtcverts = tcgen.length();
  120.             m.tcverts = new tcvert[m.numtcverts];
  121.             memcpy(m.tcverts, tcgen.getbuf(), m.numtcverts*sizeof(tcvert));
  122.             m.numtris = trigen.length();
  123.             m.tris = new tri[m.numtris];
  124.             memcpy(m.tris, trigen.getbuf(), m.numtris*sizeof(tri));
  125.  
  126.             m.numverts = header.numvertices;
  127.             m.verts = new vec[m.numverts*numframes];
  128.  
  129.             int frame_offset = header.offsetframes;
  130.             vec *curvert = m.verts;
  131.             loopi(header.numframes)
  132.             {
  133.                 md2_frame frame;
  134.                 fseek(file, frame_offset, SEEK_SET);
  135.                 fread(&frame, sizeof(md2_frame), 1, file);
  136.                 endianswap(&frame, sizeof(float), 6);
  137.                 loopj(header.numvertices)
  138.                 {
  139.                     md2_vertex v;
  140.                     fread(&v, sizeof(md2_vertex), 1, file);
  141.                     *curvert++ = vec(v.vertex[0]*frame.scale[0]+frame.translate[0],
  142.                                    -(v.vertex[1]*frame.scale[1]+frame.translate[1]),
  143.                                      v.vertex[2]*frame.scale[2]+frame.translate[2]);
  144.                 }
  145.                 frame_offset += header.framesize;
  146.             }
  147.                  
  148.             fclose(file);
  149.           
  150.             filename = newstring(path);
  151.             return true;
  152.         }
  153.  
  154.         void getdefaultanim(animstate &as, int anim, int varseed)
  155.         {
  156.             //                      0   1   2   3   4   5   6   7   8   9  10  11  12   13  14  15  16  17 18  19  20   21  21  23  24     
  157.             //                      I   R   A   P   P   P   J   L   F   S   T   W   P   CI  CW  CA  CP  CD  D   D   D   LD  LD  LD   F
  158.             static int frame[] =  { 0,  40, 46, 54, 58, 62, 66, 69, 72, 84, 95, 112,123,135,154,160,169,173,178,184,190,183,189,197, 0 };
  159.             static int range[] =  { 40, 6,  8,  4,  4,  4,  3,  3,  12, 11, 17, 11, 12, 19, 6,  9,  4,  5,  6,  6,  8,  1,  1,  1,   7 };
  160.             static int animfr[] = { 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 24 };
  161.  
  162.             if((size_t)anim >= sizeof(animfr)/sizeof(animfr[0]))
  163.             {
  164.                 as.frame = 0;
  165.                 as.range = 1;
  166.                 return;
  167.             }
  168.             int n = animfr[anim];
  169.             if(anim==ANIM_PAIN || anim==ANIM_DEATH || anim==ANIM_LYING_DEAD) n += varseed%3;
  170.             as.frame = frame[n];
  171.             as.range = range[n];
  172.         }
  173.  
  174.         void begingenshadow()
  175.         {
  176.             glRotatef(180, 0, 0, 1);
  177.         }
  178.     };
  179.  
  180.     void render(int anim, int varseed, float speed, int basetime, float x, float y, float z, float yaw, float pitch, dynent *d, model *vwepmdl, float scale)
  181.     {
  182.         if(!loaded) return;
  183.  
  184.         glPushMatrix();
  185.         glTranslatef(x, y, z);
  186.         glRotatef(yaw+180, 0, 0, 1);
  187.         glRotatef(pitch, 0, -1, 0);
  188.         if(anim&ANIM_MIRROR || scale!=1) glScalef(anim&ANIM_MIRROR ? -scale : scale, scale, scale);
  189.         parts[0]->render(anim, varseed, speed, basetime, d);
  190.         glPopMatrix();
  191.  
  192.         if(vwepmdl)
  193.         {
  194.             ((md2 *)vwepmdl)->parts[0]->index = parts.length();
  195.             vwepmdl->setskin();
  196.             vwepmdl->render(anim, varseed, speed, basetime, x, y, z, yaw, pitch, d, NULL, scale);
  197.         }
  198.     }
  199.  
  200.     void rendershadow(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, model *vwepmdl)
  201.     {
  202.         parts[0]->rendershadow(anim, varseed, speed, basetime, o, yaw);
  203.         if(vwepmdl) ((md2 *)vwepmdl)->parts[0]->rendershadow(anim, varseed, speed, basetime, o, yaw);
  204.     }
  205.  
  206.     bool load()
  207.     { 
  208.         if(loaded) return true;
  209.         md2part &mdl = *new md2part;
  210.         parts.add(&mdl);
  211.         mdl.model = this;
  212.         mdl.index = 0;
  213.         char *pname = parentdir(loadname);
  214.         s_sprintfd(name1)("packages/models/%s/tris.md2", loadname);
  215.         if(!mdl.load(path(name1)))
  216.         {
  217.             s_sprintf(name1)("packages/models/%s/tris.md2", pname);    // try md2 in parent folder (vert sharing)
  218.             if(!mdl.load(path(name1))) { delete[] pname; return false; }
  219.         }
  220.         Texture *skin;
  221.         loadskin(loadname, pname, skin);
  222.         loopv(mdl.meshes) mdl.meshes[i]->skin  = skin;
  223.         if(skin==crosshair) conoutf("could not load model skin for %s", name1);
  224.         loadingmd2 = this;
  225.         s_sprintfd(name2)("packages/models/%s/md2.cfg", loadname);
  226.         if(!execfile(name2))
  227.         {
  228.             s_sprintf(name2)("packages/models/%s/md2.cfg", pname);
  229.             execfile(name2);
  230.         }
  231.         delete[] pname;
  232.         loadingmd2 = 0;
  233.         loopv(parts) parts[i]->scaleverts(scale/16.0f, vec(translate.x, -translate.y, translate.z));
  234.         return loaded = true;
  235.     }
  236. };
  237.  
  238. void md2anim(char *anim, char *frame, char *range, char *speed)
  239. {
  240.     if(!loadingmd2 || loadingmd2->parts.empty()) { conoutf("not loading an md2"); return; }
  241.     int num = findanim(anim);
  242.     if(num<0) { conoutf("could not find animation %s", anim); return; }
  243.     loadingmd2->parts.last()->setanim(num, atoi(frame), atoi(range), atof(speed));
  244. }
  245.  
  246. COMMAND(md2anim, ARG_4STR);
  247.  
  248.