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

  1. struct md3;
  2.  
  3. md3 *loadingmd3 = NULL;
  4.  
  5. string md3dir;
  6.  
  7. struct md3tag
  8. {
  9.     char name[64];
  10.     vec pos;
  11.     float rotation[3][3];
  12. };
  13.  
  14. struct md3vertex
  15. {
  16.     short vertex[3];
  17.     short normal;
  18. };
  19.  
  20. struct md3triangle
  21. {
  22.     int vertexindices[3];
  23. };
  24.  
  25. struct md3header
  26. {
  27.     char id[4];
  28.     int version;
  29.     char name[64];
  30.     int flags;
  31.     int numframes, numtags, nummeshes, numskins;
  32.     int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets
  33. };
  34.  
  35. struct md3meshheader
  36. {
  37.     char id[4];
  38.     char name[64];
  39.     int flags;
  40.     int numframes, numshaders, numvertices, numtriangles;
  41.     int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets
  42. };
  43.  
  44. struct md3 : vertmodel
  45. {
  46.     md3(const char *name) : vertmodel(name) {}
  47.  
  48.     int type() { return MDL_MD3; }
  49.  
  50.     struct md3part : part
  51.     {
  52.         bool load(char *path)
  53.         {
  54.             if(filename) return true;
  55.  
  56.             FILE *f = fopen(path, "rb");
  57.             if(!f) return false;
  58.             md3header header;
  59.             fread(&header, sizeof(md3header), 1, f);
  60.             endianswap(&header.version, sizeof(int), 1);
  61.             endianswap(&header.flags, sizeof(int), 9);
  62.             if(strncmp(header.id, "IDP3", 4) != 0 || header.version != 15) // header check
  63.             { 
  64.                 fclose(f);
  65.                 conoutf("md3: corrupted header"); 
  66.                 return false; 
  67.             }
  68.  
  69.             numframes = header.numframes;
  70.             numtags = header.numtags;        
  71.             if(numtags)
  72.             {
  73.                 tags = new tag[numframes*numtags];
  74.                 fseek(f, header.ofs_tags, SEEK_SET);
  75.                 md3tag tag;
  76.                 
  77.                 loopi(header.numframes*header.numtags) 
  78.                 {
  79.                     fread(&tag, sizeof(md3tag), 1, f);
  80.                     endianswap(&tag.pos, sizeof(float), 12);
  81.                     if(tag.name[0] && i<header.numtags) tags[i].name = newstring(tag.name);
  82.                     tags[i].pos = vec(tag.pos.x, -tag.pos.y, tag.pos.z);
  83.                     memcpy(tags[i].transform, tag.rotation, sizeof(tag.rotation));
  84.                     // undo the -y
  85.                     loopj(3) tags[i].transform[1][j] *= -1;
  86.                     // then restore it
  87.                     loopj(3) tags[i].transform[j][1] *= -1;
  88.                 }
  89.                 links = new part *[numtags];
  90.                 loopi(numtags) links[i] = NULL;
  91.             }
  92.  
  93.             int mesh_offset = header.ofs_meshes;
  94.             loopi(header.nummeshes)
  95.             {
  96.                 mesh &m = *meshes.add(new mesh);
  97.                 md3meshheader mheader;
  98.                 fseek(f, mesh_offset, SEEK_SET);
  99.                 fread(&mheader, sizeof(md3meshheader), 1, f);
  100.                 endianswap(&mheader.flags, sizeof(int), 10); 
  101.  
  102.                 m.name = newstring(mheader.name);
  103.                
  104.                 m.numtris = mheader.numtriangles; 
  105.                 m.tris = new tri[m.numtris];
  106.                 fseek(f, mesh_offset + mheader.ofs_triangles, SEEK_SET);
  107.                 loopj(mheader.numtriangles)
  108.                 {
  109.                     md3triangle tri;
  110.                     fread(&tri, sizeof(md3triangle), 1, f); // read the triangles
  111.                     endianswap(&tri, sizeof(int), 3);
  112.                     loopk(3) m.tris[j].vert[k] = (ushort)tri.vertexindices[k];
  113.                 }
  114.  
  115.                 m.numtcverts = mheader.numvertices;
  116.                 m.tcverts = new tcvert[m.numtcverts];
  117.                 fseek(f, mesh_offset + mheader.ofs_uv , SEEK_SET); 
  118.                 loopj(mheader.numvertices)
  119.                 {
  120.                     fread(&m.tcverts[j].u, sizeof(float), 2, f); // read the UV data
  121.                     endianswap(&m.tcverts[j].u, sizeof(float), 2);
  122.                     m.tcverts[j].index = j;
  123.                 }
  124.                 
  125.                 m.numverts = mheader.numvertices;
  126.                 m.verts = new vec[numframes*m.numverts];
  127.                 fseek(f, mesh_offset + mheader.ofs_vertices, SEEK_SET); 
  128.                 loopj(numframes*mheader.numvertices)
  129.                 {
  130.                     md3vertex v;
  131.                     fread(&v, sizeof(md3vertex), 1, f); // read the vertices
  132.                     endianswap(&v, sizeof(short), 4);
  133.  
  134.                     m.verts[j].x = v.vertex[0]/64.0f;
  135.                     m.verts[j].y = -v.vertex[1]/64.0f;
  136.                     m.verts[j].z = v.vertex[2]/64.0f;
  137.                 }
  138.  
  139.                 mesh_offset += mheader.meshsize;
  140.             }
  141.             fclose(f);
  142.  
  143.             filename = newstring(path); 
  144.             return true;
  145.         }
  146.  
  147.         void begingenshadow()
  148.         {
  149.             glRotatef(180, 0, 0, 1);
  150.         }
  151.     };
  152.    
  153.     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)
  154.     {
  155.         if(!loaded) return;
  156.  
  157.         if(vwepmdl) // cross link the vwep to this model
  158.         {
  159.             part *vwep = ((md3 *)vwepmdl)->parts[0];
  160.             if(link(vwep, "tag_weapon")) vwep->index = parts.length();
  161.         }
  162.  
  163.         glPushMatrix();
  164.         glTranslatef(x, y, z);
  165.         glRotatef(yaw+180, 0, 0, 1);
  166.         glRotatef(pitch, 0, -1, 0);
  167.         glRotatef(90, 0, 0, 1);
  168.  
  169.         if(anim&ANIM_MIRROR || scale!=1) glScalef(anim&ANIM_MIRROR ? -scale : scale, scale, scale);
  170.         parts[0]->render(anim, varseed, speed, basetime, d);
  171.         glPopMatrix();
  172.     }
  173.  
  174.     void rendershadow(int anim, int varseed, float speed, int basetime, const vec &o, float yaw, model *vwepmdl)
  175.     {
  176.         if(parts.length()>1) return;
  177.         parts[0]->rendershadow(anim, varseed, speed, basetime, o, yaw);
  178.     }
  179.  
  180.     bool load()
  181.     {
  182.         if(loaded) return true;
  183.         s_sprintf(md3dir)("packages/models/%s", loadname);
  184.  
  185.         char *pname = parentdir(loadname);
  186.         s_sprintfd(cfgname)("packages/models/%s/md3.cfg", loadname);
  187.  
  188.         loadingmd3 = this;
  189.         if(execfile(cfgname) && parts.length()) // configured md3, will call the md3* commands below
  190.         {
  191.             delete[] pname;
  192.             loadingmd3 = NULL;
  193.             if(parts.empty()) return false;
  194.             loopv(parts) if(!parts[i]->filename) return false;
  195.         }
  196.         else // md3 without configuration, try default tris and skin
  197.         {
  198.             loadingmd3 = NULL;
  199.             md3part &mdl = *new md3part;
  200.             parts.add(&mdl);
  201.             mdl.model = this;
  202.             mdl.index = 0; 
  203.             s_sprintfd(name1)("packages/models/%s/tris.md3", loadname);
  204.             if(!mdl.load(path(name1)))
  205.             {
  206.                 s_sprintf(name1)("packages/models/%s/tris.md3", pname);    // try md3 in parent folder (vert sharing)
  207.                 if(!mdl.load(path(name1))) { delete[] pname; return false; };
  208.             };
  209.             Texture *skin;
  210.             loadskin(loadname, pname, skin);
  211.             loopv(mdl.meshes) mdl.meshes[i]->skin  = skin;
  212.             if(skin==crosshair) conoutf("could not load model skin for %s", name1);
  213.         }
  214.         loopv(parts) parts[i]->scaleverts(scale/16.0f, vec(translate.x, -translate.y, translate.z));
  215.  
  216.         return loaded = true;
  217.     }
  218. };
  219.  
  220. void md3load(char *model)
  221. {   
  222.     if(!loadingmd3) { conoutf("not loading an md3"); return; };
  223.     s_sprintfd(filename)("%s/%s", md3dir, model);
  224.     md3::md3part &mdl = *new md3::md3part;
  225.     loadingmd3->parts.add(&mdl);
  226.     mdl.model = loadingmd3;
  227.     mdl.index = loadingmd3->parts.length()-1;
  228.     if(!mdl.load(path(filename))) conoutf("could not load %s", filename); // ignore failure
  229. }  
  230.     
  231. void md3skin(char *objname, char *skin)
  232. {   
  233.     if(!objname || !skin) return;
  234.     if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; };
  235.     md3::part &mdl = *loadingmd3->parts.last();
  236.     loopv(mdl.meshes)
  237.     {   
  238.         md3::mesh &m = *mdl.meshes[i];
  239.         if(!strcmp(objname, "*") || !strcmp(m.name, objname))
  240.         {
  241.             s_sprintfd(spath)("%s/%s", md3dir, skin);
  242.             m.skin = textureload(spath);
  243.         }
  244.     }
  245. }
  246.  
  247. void md3anim(char *anim, char *startframe, char *range, char *speed)
  248. {
  249.     if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; };
  250.     int num = findanim(anim);
  251.     if(num<0) { conoutf("could not find animation %s", anim); return; };
  252.     loadingmd3->parts.last()->setanim(num, atoi(startframe), atoi(range), atof(speed));
  253. }
  254.  
  255. void md3link(char *parentno, char *childno, char *tagname)
  256. {
  257.     if(!loadingmd3) { conoutf("not loading an md3"); return; };
  258.     int parent = ATOI(parentno), child = ATOI(childno);
  259.     if(!loadingmd3->parts.inrange(parent) || !loadingmd3->parts.inrange(child)) { conoutf("no models loaded to link"); return; }
  260.     if(!loadingmd3->parts[parent]->link(loadingmd3->parts[child], tagname)) conoutf("could not link model %s", loadingmd3->loadname);
  261. }
  262.  
  263. COMMAND(md3load, ARG_1STR);
  264. COMMAND(md3skin, ARG_3STR);
  265. COMMAND(md3anim, ARG_4STR);
  266. COMMAND(md3link, ARG_3STR);
  267.             
  268.