/ source / tools / src / md2tool.cpp
md2tool.cpp
  1  
  2  #include "compat.h"
  3  #include "build.h"
  4  #include "glad/glad.h"
  5  #include "mdsprite.h"
  6  
  7  
  8  static md2head_t head;
  9  
 10  
 11  static void quit(int32_t status)
 12  {
 13      exit(status);
 14  }
 15  
 16  static md2model_t *md2load(int *fd, const char *filename, int32_t ronly)
 17  {
 18      md2model_t *m;
 19      int fil;
 20  
 21      fil = Bopen(filename, ronly?BO_RDONLY:BO_RDWR);
 22      if (fil<0)
 23      {
 24          Bfprintf(stderr, "Couldn't open `%s': %s\n", filename, strerror(errno));
 25          quit(2);
 26      }
 27  
 28      m = (md2model_t *)Bcalloc(1,sizeof(md2model_t)); if (!m) quit(1);
 29      m->mdnum = 2; m->scale = .01f;
 30  
 31      Bread(fil,(char *)&head,sizeof(md2head_t));
 32  
 33      head.id = B_LITTLE32(head.id);                 head.vers = B_LITTLE32(head.vers);
 34      head.skinxsiz = B_LITTLE32(head.skinxsiz);     head.skinysiz = B_LITTLE32(head.skinysiz);
 35      head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins);
 36      head.numverts = B_LITTLE32(head.numverts);     head.numuv = B_LITTLE32(head.numuv);
 37      head.numtris = B_LITTLE32(head.numtris);       head.numglcmds = B_LITTLE32(head.numglcmds);
 38      head.numframes = B_LITTLE32(head.numframes);   head.ofsskins = B_LITTLE32(head.ofsskins);
 39      head.ofsuv = B_LITTLE32(head.ofsuv);           head.ofstris = B_LITTLE32(head.ofstris);
 40      head.ofsframes = B_LITTLE32(head.ofsframes);   head.ofsglcmds = B_LITTLE32(head.ofsglcmds);
 41      head.ofseof = B_LITTLE32(head.ofseof);
 42  
 43      if ((head.id != 0x32504449) || (head.vers != 8))
 44      {
 45          Bfprintf(stderr, "File `%s' is not an md2 file.\n", filename);
 46          quit(3);
 47      } //"IDP2"
 48  
 49      m->numskins = head.numskins;
 50      m->numframes = head.numframes;
 51      m->numverts = head.numverts;
 52      m->numglcmds = head.numglcmds;
 53      m->framebytes = head.framebytes;
 54  
 55      m->frames = (char *)Bmalloc(m->numframes*m->framebytes); if (!m->frames) quit(1);
 56      m->tris = (md2tri_t *)Bmalloc(head.numtris*sizeof(md2tri_t)); if (!m->tris) quit(1);
 57      m->uv = (md2uv_t *)Bmalloc(head.numuv*sizeof(md2uv_t)); if (!m->uv) quit(1);
 58  
 59      Blseek(fil,head.ofsframes,SEEK_SET);
 60      if (Bread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes)
 61          quit(1);
 62  
 63      Blseek(fil,head.ofstris,SEEK_SET);
 64      if (Bread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t)))
 65          quit(1);
 66  
 67      Blseek(fil,head.ofsuv,SEEK_SET);
 68      if (Bread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t)))
 69          quit(1);
 70  
 71  #if B_BIG_ENDIAN != 0
 72      {
 73          char *f = (char *)m->frames;
 74          int32_t *l,i,j;
 75          md2frame_t *fr;
 76  
 77          for (i = m->numframes-1; i>=0; i--)
 78          {
 79              fr = (md2frame_t *)f;
 80              l = (int32_t *)&fr->mul;
 81              for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]);
 82              f += m->framebytes;
 83          }
 84  
 85          for (i = head.numtris-1; i>=0; i--)
 86          {
 87              m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]);
 88              m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]);
 89              m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]);
 90              m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]);
 91              m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]);
 92              m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]);
 93          }
 94          for (i = head.numuv-1; i>=0; i--)
 95          {
 96              m->uv[i].u = B_LITTLE16(m->uv[i].u);
 97              m->uv[i].v = B_LITTLE16(m->uv[i].v);
 98          }
 99      }
100  #endif
101  
102      *fd = fil;
103      return(m);
104  }
105  
106  
107  static void usage_and_quit()
108  {
109      Bfprintf(stderr,
110              "Usage:\n"
111              "   md2tool <modelfile>.md2:  display info about model\n"
112              "   md2tool -minmax <minx>,<miny>,<minz>:<maxx>,<maxy>,<maxz> <modelfile>.md2:\n"
113              "      modify `scale' and `translate' fields of MD2 (in-place) to produce given bounds\n"
114          );
115      quit(1);
116  }
117  
118  int main(int argc, char **argv)
119  {
120      char *fn=NULL, *cp;
121      int32_t fd=-1, i, j;
122  
123      int32_t doinfo=1;
124  
125      // md2 mul[x,y,z], add[x,y,z]
126      float mx,my,mz, ax,ay,az;
127  
128      // desired model bounds
129      float dminx=0,dminy=0,dminz=0, dmaxx=1,dmaxy=1,dmaxz=1;
130  
131      // md2 uint8-coordinate bounds
132      uint8_t maxv[3]={0,0,0};
133      uint8_t minv[3]={255,255,255};
134  
135      md2frame_t *fr;
136      uint8_t *vp;
137  
138      md2model_t *m;
139  
140      if (argc<=1)
141          usage_and_quit();
142  
143      for (i=1; i<argc; i++)
144      {
145          cp = argv[i];
146  
147          if (cp[0]=='-')
148          {
149              if (!strcmp(cp, "-minmax"))
150              {
151                  doinfo=0;
152                  if (i+1 >= argc)
153                      usage_and_quit();
154                  if (Bsscanf(argv[i+1], "%f,%f,%f:%f,%f,%f", &dminx,&dminy,&dminz, &dmaxx,&dmaxy,&dmaxz)!=6)
155                      usage_and_quit();
156                  i++;
157              }
158              else
159              {
160                  Bfprintf(stderr, "unrecognized option `%s'\n", cp);
161                  quit(2);
162              }
163          }
164          else
165              fn = cp;
166      }
167  
168      if (!fn)
169          usage_and_quit();
170  
171      m = md2load(&fd, fn, doinfo);
172  
173      fr = (md2frame_t *)m->frames;
174      mx=fr->mul.x; my=fr->mul.y; mz=fr->mul.z;
175      ax=fr->add.x; ay=fr->add.y; az=fr->add.z;
176  
177      for (i=0, vp=fr->verts->v; i<m->numverts; i++, vp+=sizeof(md2vert_t))
178      {
179          for (j=0; j<3; j++)
180          {
181              maxv[j] = max(maxv[j], vp[j]);
182              minv[j] = min(minv[j], vp[j]);
183          }
184      }
185  
186      if (doinfo)
187      {
188          Bprintf("------ %s ------\n", fn);
189          Bprintf("numframes: %d\n", m->numframes);
190          Bprintf("numverts: %d\n", m->numverts);
191          Bprintf("numtris: %d\n", head.numtris);
192          Bprintf("\n");
193          Bprintf("ofsframes: %x\n", head.ofsframes);
194          Bprintf("framebytes: %d\n", head.framebytes);
195  //        Bprintf("framebytes: %d, calculated=%d\n", head.framebytes, sizeof(md2frame_t)+(m->numverts-1)*sizeof(md2vert_t));
196          Bprintf("\n");
197  
198          Bprintf("mul=%f %f %f\n", mx, my, mz);
199          Bprintf("add=%f %f %f\n", ax, ay, az);
200  
201          Bprintf("min xyz (s+t) = %f %f %f\n", minv[0]*mx+ax, minv[1]*my+ay, minv[2]*mz+az);
202          Bprintf("max xyz (s+t) = %f %f %f\n", maxv[0]*mx+ax, maxv[1]*my+ay, maxv[2]*mz+az);
203  
204          Bprintf("\n");
205      }
206      else
207      {
208          if (maxv[0]-minv[0]>0) mx = (dmaxx-dminx)/(maxv[0]-minv[0]); else mx=0;
209          if (maxv[1]-minv[1]>0) my = (dmaxy-dminy)/(maxv[1]-minv[1]); else my=0;
210          if (maxv[2]-minv[2]>0) mz = (dmaxz-dminz)/(maxv[2]-minv[2]); else mz=0;
211  
212          if (mx==0||my==0||mz==0)
213          {
214              Bfprintf(stderr, "max[x,y,z]-min[x,y,z] must each be grater 0!\n");
215              quit(2);
216          }
217  
218          ax = dmaxx-maxv[0]*mx;
219          ay = dmaxy-maxv[1]*my;
220          az = dmaxz-maxv[2]*mz;
221  
222  #define ISNAN(x) ((x)!=(x))
223  #define ISINF(x) ((x!=0)&&(x/2==x))
224  
225          if (ISNAN(mx)||ISNAN(my)||ISNAN(mz)||ISNAN(ax)||ISNAN(ay)||ISNAN(az)||
226              ISINF(mx)||ISINF(my)||ISINF(mz)||ISINF(ax)||ISINF(ay)||ISINF(az))
227          {
228              Bfprintf(stderr, "Calculation resulted in NaN or Inf.\n");
229              quit(2);
230          }
231  
232          Blseek(fd,head.ofsframes,SEEK_SET);
233          if (Bwrite(fd, &mx, sizeof(mx))!=sizeof(mx)) { perror("write"); quit(3); }
234          if (Bwrite(fd, &my, sizeof(my))!=sizeof(my)) { perror("write"); quit(3); }
235          if (Bwrite(fd, &mz, sizeof(mz))!=sizeof(mz)) { perror("write"); quit(3); }
236          if (Bwrite(fd, &ax, sizeof(ax))!=sizeof(ax)) { perror("write"); quit(3); }
237          if (Bwrite(fd, &ay, sizeof(ay))!=sizeof(ay)) { perror("write"); quit(3); }
238          if (Bwrite(fd, &az, sizeof(az))!=sizeof(az)) { perror("write"); quit(3); }
239          Bclose(fd);
240  
241          Bprintf("wrote scale and translate of `%s'.\n", fn);
242      }
243  
244      return 0;
245  }